In Files

Parent

Files

IHelp::IHelpIndex

IHelpIndex uses Ferret to index all available RI documentation and lets you do full text searches over the index.

E.g. IHelpIndex.new.search("domain name lookup")

See Ferret::QueryParser for query string format.

Constants

DEFAULT_LOG_LEVEL
GLOBAL_INDEX_PATH

Default place to save and load the index from.

LOCAL_INDEX_PATH

Attributes

reindex_when_needed[RW]
index[RW]

The search index, is a Ferret::Index::Index

log_level[RW]

Public Class Methods

new(use_global_index = (ENV["USER"] == "root")) click to toggle source
# File lib/ihelp.rb, line 600
def initialize(use_global_index = (ENV["USER"] == "root"))
  @log_level = DEFAULT_LOG_LEVEL
  if use_global_index
    @index_path = GLOBAL_INDEX_PATH
  else
    @index_path = LOCAL_INDEX_PATH
    if not File.exist?(@index_path) and File.exist?(GLOBAL_INDEX_PATH)
      FileUtils.cp_r(GLOBAL_INDEX_PATH, @index_path) rescue nil
    elsif not File.exist?(@index_path)
      self.class.reindex_when_needed = true
    end
  end
  analyzer = IHelpAnalyzer.new
  have_index = File.exist? @index_path
  if have_index
    log "Loading existing index from #{@index_path}", 1
    @index = Ferret::I.new(
      :key => :full_name,
      :path => @index_path,
      :analyzer => analyzer
    )
  else
    log "Creating new index in #{@index_path}", 2
    field_infos = Ferret::Index::FieldInfos.new(:term_vector => :no)
    field_infos.add_field(:name,
                      :store => :yes,
                      :index => :yes,
                      :boost => 10.0)
    field_infos.add_field(:full_name,
                      :store => :yes,
                      :index => :untokenized,
                      :boost => 0.0)
    field_infos.add_field(:content,
                      :boost => 1.0,
                      :store => :yes,
                      :index => :yes,
                      :term_vector => :with_positions_offsets)
    @index = Ferret::I.new(
      :key => :full_name,
      :field_infos => field_infos,
      :analyzer => analyzer
    )
  end
  if self.class.reindex_when_needed and need_reindexing?
    reindex!
  end
  unless have_index
    @index.persist(@index_path)
    log "\nSaved index.", 2
  end
end

Public Instance Methods

all_names() click to toggle source
# File lib/ihelp.rb, line 683
def all_names
  IHelp.ri_driver.ri_reader.all_names.uniq
end
already_indexed?(full_name) click to toggle source

Returns true if there already is an object named full_name

# File lib/ihelp.rb, line 669
def already_indexed? full_name
  @index[full_name]
end
display() click to toggle source
# File lib/ihelp.rb, line 741
def display
  return @display if @display
  @display = IHelp.ri_driver.display
  if ENV["PAGER"].to_s.size > 0
    unless ENV["PAGER"] =~ /(^|\/)less\b.* -[a-zA-Z]*[rR]/
      IHelp.no_colors = true
    end
  else
    ENV["PAGER"] = "less -R"
  end
  class << @display
    public :page
    attr_accessor :formatter
  end
  @display
end
format_time(t) click to toggle source
# File lib/ihelp.rb, line 673
def format_time(t)
  sec = t % 60
  min = (t / 60) % 60
  hour = (t / 3600)
  str = sec.to_i.to_s.rjust(2,'0')
  str = min.to_i.to_s.rjust(2,'0') + ":" + str
  str = hour.to_i.to_s.rjust(2,'0') + ":" + str if hour >= 1
  str
end
init_display() click to toggle source
# File lib/ihelp.rb, line 775
def init_display
  display
end
log(str, level = 1) click to toggle source
# File lib/ihelp.rb, line 652
def log str, level = 1
  STDERR.puts str if level >= @log_level
end
need_reindexing?() click to toggle source
# File lib/ihelp.rb, line 687
def need_reindexing?
  all_names.size > @index.size
end
page(*a,&b) click to toggle source
# File lib/ihelp.rb, line 758
def page(*a,&b)
  display.page(*a,&b)
end
path() click to toggle source
# File lib/ihelp.rb, line 656
def path
  @index_path
end
reindex!() click to toggle source

Reindexes any non-indexed help documents.

# File lib/ihelp.rb, line 693
def reindex!
  start_size = @index.size
  names = all_names
  log "Indexing...", 2
  nsz = names.size.to_s
  i = 0
  names.each{|n|
    i += 1
    next if (start_size > 0) and (already_indexed?(n))
    if @log_level == DEFAULT_LOG_LEVEL
      amt_done = (i.to_f / names.size)
      pct = ("%.1f" % [100*amt_done]).rjust(5)
      STDERR.write "\r #{pct}% (#{i.to_s.rjust(nsz.size)}/#{nsz}) #{n}".ljust(80)[0,80]
      STDERR.flush
    end
    hd = if n.include? "#"
      IHelp.ri_driver.get_info_str(*(n.split("#") + [true]))
    elsif n.include? "::"
      IHelp.ri_driver.get_info_str(n) or
      IHelp.ri_driver.get_info_str(*n.reverse.split("::",2).reverse.map{|r| r.reverse })
    else
      IHelp.ri_driver.get_info_str n
    end
    if hd.nil?
      log "skipping #{n} (not found)"
      next
    else
      log "indexing #{n}"
    end
    @index << {
      :name => hd.full_name,
      :full_name => n,
      :content => wrap_str(hd.to_text)
    }
  }
  if @log_level == DEFAULT_LOG_LEVEL
    amt_done = (i.to_f / names.size)
    pct = ("%.1f" % [100*amt_done]).rjust(5)
    STDERR.write "\r #{pct}% (#{i.to_s.rjust(nsz.size)}/#{nsz}) #{names.last}".ljust(80)[0,80]
    STDERR.flush
    STDERR.puts
  end
  if start_size != @index.size
    log "Optimizing index... (old size #{start_size}, current size #{@index.size})"
    @index.optimize
  end
end
search(query) click to toggle source

Searches for the terms in query and prints out first ten hits

See Ferret::QueryParser for query string format.

# File lib/ihelp.rb, line 783
def search(query)
  result = @index.search(query, :limit => 1000)
  init_display
  if IHelp.no_colors or `which less`.strip.empty?
    pre_tag = "<<"
    post_tag = ">>"
  else
    name_start = "\0033[32m"
    name_end = "\0033[0m"
    pre_tag = "\0033[36m"
    post_tag = "\0033[0m"
  end
  page do
    puts
    puts "=== #{result.total_hits} hits#{", showing first 1000" if result.total_hits > 1000} ".ljust(72,"=")
    puts
    result.hits.each_with_index do |hit, i|
      id, score = hit.doc, hit.score
      #puts hit.score
      puts "#{name_start}#{@index[id][:full_name]}#{name_end}"
      puts
      puts @index.highlight(query, id, :field => :content,
                            :pre_tag => pre_tag,
                            :post_tag => post_tag,
                            :ellipsis => "...\n").to_s
      puts
      display.formatter.draw_line
      puts
    end
    puts "#{result.total_hits} hits"
  end
  p result.hits.map{|hit| @index[hit.doc][:full_name] }
  result
end
time() click to toggle source
# File lib/ihelp.rb, line 660
def time
  t = Time.now
  rv = yield
  log "Took #{Time.now - t}"
  rv
end
wrap(str) click to toggle source
# File lib/ihelp.rb, line 762
def wrap(str)
  display.formatter.wrap(str)
end
wrap_str(str) click to toggle source
# File lib/ihelp.rb, line 766
def wrap_str(str)
  $stdout = StringIO.new
  wrap(str)
  $stdout.rewind
  s = $stdout.read
  $stdout = STDOUT
  s
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.