Module IHelp
In: lib/ihelp.rb
Ferret::Analysis::StandardAnalyzer IHelpAnalyzer RiDriver IHelpDriver IHelpIndex Renderer lib/ihelp.rb IHelp dot/m_0_1.png

Ri bindings for interactive use from within Ruby. Does a bit of second-guessing (Instance method? Class method? Try both unless explicitly defined. Not found in this class? Try the ancestor classes.)

The goal is that help is given for all methods that have help.

Examples:

  require 'ihelp'

  a = "string"
  a.help
  a.help :reverse
  a.help :map
  String.help
  String.help :new
  String.help :reverse
  String.help :map
  String.instance_help :reverse
  String.instance_help :new # => No help found.
  a.help :new
  ihelp "String#reverse"
  ihelp "String.reverse"
  a.method(:reverse).help # gets help for Method
  ihelp "Hash#map"

You can also search for terms in the documentation:

  ihelp 'domain name lookup'
  String.help 'byte order'

Custom help renderers:

The help-method calls IHelp::Renderer‘s method defined by IHelp.renderer with the RI info object. You can print help out the way you want by defining your own renderer method in IHelp::Renderer and setting IHelp.renderer to the name of the method.

Example:

  require 'ihelp'

  IHelp.renderers
  # => ["emacs", "rubydoc", "ri", "source", "html"]

  class IHelp::Renderer
    def print_name(info)
      puts info.full_name
    end
  end

  IHelp.renderers
  # => ["emacs", "rubydoc", "ri", "source", "print_name", "html"]

  IHelp.renderer = :print_name

  [1,2,3].help:reject
  # Array#reject
  # => nil

The current renderers are:

  ri -- the default renderer
  html -- creates a HTML document for the help and opens it
          with the program named in IHelp.web_browser
  rubydoc -- opens the corresponding www.ruby-doc.org class
             documentation page with the program named in
             IHelp.web_browser
  emacs -- uses gnudoit and ri-emacs to display help in an Emacs buffer.
           The Emacs commands that I got it running with were:
              ;; make ri-emacs autoload according to its instructions
              M-x ruby-mode
              M-x gnuserv-start
              M-x run-ruby
              > IHelp.renderer = :emacs
              > String.help:center
  source -- uses RubyToRuby to print the source for the method
            (experimental)

Changelog:

0.4.5

  Use RI environment variable to pass config to ri (thanks to Parragh Szabolcs.)
  Bugfix for missing stringio (thanks to Marcel M. Cary.)
  Show first thousand hits instead of a mere ten.

0.4.0

  Full-text documentation search using Ferret.

0.3.2

  Added support for ruby 1.8.5, added emacs renderer from
  rubykitch <rubykitch@ruby-lang.org>, made source renderer use the
  released version of RubyToRuby.

License: Ruby‘s

Author: Ilmari Heikkinen <kig misfiring net>

Methods

Classes and Modules

Class IHelp::IHelpAnalyzer
Class IHelp::IHelpDriver
Class IHelp::IHelpIndex
Class IHelp::Renderer

Constants

HELP_VERSION = "0.4.5"

Attributes

help_index  [RW] 
no_colors  [RW]  Don‘t use colors for highlighting search results.
renderer  [RW]  Help renderer to use.
web_browser  [RW]  Web browser to use for html and rubydoc renderers.

Public Class methods

Return RI::ClassDescription / RI::MethodDescription for klass or its method meth, or its instance method meth if instance == true.

[Source]

     # File lib/ihelp.rb, line 369
369:     def generate_help_description(klass, meth=nil, instance=nil)
370:       meth_str = nil
371:       double_colon = false
372:       if meth
373:         meth_str = meth.to_s
374:         if /::|\.|#/ === meth_str # called with e.g."Array#str","String.new"
375:           meth_str, klass_name, instance_help, double_colon =
376:             get_help_klass_info_for_name(meth_str)
377:             klass_ancs = find_ancestors(klass_name, instance)
378:         elsif (/\A[A-Z][a-zA-Z0-9_]*\Z/ === meth_str and # called with e.g. "Array"
379:                not (klass.methods+Kernel.methods).include? meth_str)
380:           meth_str, klass_name, instance_help, double_colon =
381:             get_help_klass_info_for_name(meth_str)
382:             klass_ancs = find_ancestors(klass_name, instance)
383:         else
384:           klass_name, klass_ancs, instance_help =
385:             get_help_klass_info(klass, instance)
386:         end
387:       else
388:         klass_name, klass_ancs, instance_help =
389:           get_help_klass_info(klass, instance)
390:       end
391:       info = get_help_info(meth_str, klass_name, klass_ancs, instance_help,
392:                            instance)
393:       # Retry with method as class if double_colon-splitted and no info
394:       if info.nil? and double_colon
395:         klass_name = [klass_name, meth_str].join("::")
396:         meth_str = nil
397:         klass_ancs = find_ancestors(klass_name, instance)
398:         info = get_help_info(
399:                  meth_str, klass_name, klass_ancs, instance_help, instance)
400:       end
401:       info
402:     end

[Source]

     # File lib/ihelp.rb, line 350
350:     def help_index
351:       @help_index ||= IHelpIndex.new
352:     end

[Source]

     # File lib/ihelp.rb, line 340
340:     def intersect_search_query(str)
341:       a = IHelpAnalyzer.new
342:       t = a.token_stream :content, str.to_s
343:       c = []
344:       n = nil
345:       c << n.text while n = t.next
346:       "(#{c.join(" AND ")})"
347:     end

Render the RI info object a renderer method in IHelp::Renderer. The name of the renderer method to use is returned by IHelp.renderer, and can be set with IHelp.renderer=.

[Source]

     # File lib/ihelp.rb, line 358
358:     def render(info)
359:       IHelp::Renderer.new.send(renderer, info)
360:     end

Returns list of available renderers.

[Source]

     # File lib/ihelp.rb, line 126
126:   def self.renderers
127:     Renderer.instance_methods(false)
128:   end

[Source]

     # File lib/ihelp.rb, line 362
362:     def ri_driver
363:       @ri_driver ||= IHelpDriver.new
364:     end

Searches for str from available documentation and prints out the results.

Creates a search index if you don‘t already have one. Creating the index may take a couple of minutes.

See IHelpIndex.

[Source]

     # File lib/ihelp.rb, line 330
330:     def search(str, escape_query=true)
331:       raise "No search capability, do you have ferret installed? (gem install ferret)" unless $ihelp_full_text_search
332:       if escape_query
333:         help_index.search(intersect_search_query(str.to_s))
334:       else
335:         help_index.search(str)
336:       end
337:       nil
338:     end

Private Class methods

Find ancestors for klass_name (works if the class has been loaded)

[Source]

     # File lib/ihelp.rb, line 446
446:     def find_ancestors(klass_name, instance)
447:       similarily_named_class = nil
448:       ObjectSpace.each_object(Class){|k|
449:         similarily_named_class = k if k.name == klass_name
450:         break if similarily_named_class
451:       }
452:       if similarily_named_class
453:         klass_ancs = similarily_named_class.ancestors
454:         klass_ancs += similarily_named_class.class.ancestors unless instance
455:       else
456:         klass_ancs = []
457:       end
458:       klass_ancs
459:     end

[Source]

     # File lib/ihelp.rb, line 461
461:     def get_help_info(meth_str, klass_name, klass_ancs, instance_help, instance)
462:       info = get_help_info_str(meth_str, klass_name, klass_ancs, instance_help)
463:       # If instance is undefined, try both the class methods and instance
464:       # methods.
465:       if info.nil? and instance.nil?
466:         info = get_help_info_str(
467:                  meth_str, klass_name, klass_ancs, (not instance_help))
468:       end
469:       info
470:     end

[Source]

     # File lib/ihelp.rb, line 472
472:     def get_help_info_str(meth_str, klass_name, klass_ancs, instance)
473:         info_str = ri_driver.get_info_str(klass_name, meth_str, instance)
474:         if not info_str
475:           # Walk through class hierarchy to find an inherited method
476:           ancest = klass_ancs.find{|anc|
477:             info_str = ri_driver.get_info_str(anc.name, meth_str, instance)
478:           }
479:           # Avoid returning Object in case of no help.
480:           if ((ancest == Object and meth_str.nil? and klass_name != 'Object') or 
481:               (ancest == IHelp and meth_str.nil? and klass_name != 'IHelp'))
482:             info_str = nil
483:           end
484:         end
485:         info_str
486:     end

[Source]

     # File lib/ihelp.rb, line 405
405:     def get_help_klass_info(klass,instance)
406:         if klass.is_a? Class or klass.is_a? Module
407:           klass_ancs = klass.ancestors + klass.class.ancestors
408:           klass_ancs -= [klass, klass.class]
409:           instance = false if instance.nil?
410:         # If we are an instance, set klass to our class
411:         #
412:         else
413:           klass = klass.class
414:           klass_ancs = klass.ancestors - [klass]
415:           instance = true if instance.nil?
416:         end
417:         klass_name = klass.name
418:         [klass_name, klass_ancs, instance]
419:     end

[Source]

     # File lib/ihelp.rb, line 421
421:     def get_help_klass_info_for_name(meth_str)
422:       double_colon = false
423:       # Maybe we are being called with something like "Array#slice"
424:       if /#/ === meth_str
425:         klass_name, meth_str = meth_str.split(/#/, 2)
426:         instance = true
427: 
428:       # Or maybe the requested item is "Ri::RiDriver.new"
429:       elsif /\./ === meth_str
430:         klass_name, meth_str = meth_str.reverse.split(/\./, 2).
431:                                         reverse.map{|i| i.reverse}
432:         instance = false
433: 
434:       # And the problematic case of "Test::Unit" (is Unit a class name or
435:       # a method name? Why does Ri even care?)
436:       else
437:         klass_name, meth_str = meth_str.reverse.split(/::/, 2).
438:                                         reverse.map{|i| i.reverse}
439:         double_colon = true
440:         instance = false
441:       end
442:       [meth_str, klass_name, instance, double_colon]
443:     end

Public Instance methods

Print out help for self.

  If method_name is given, prints help for that method.
  If instance is true, tries to find help only for the instance method.
  If instance is false, tries to find help for the object's method only.
  If instance is nil, checks object's method first, then instance method.

Uses help_description(method_name, instance).

[Source]

     # File lib/ihelp.rb, line 215
215:   def help(method_name=nil, instance=nil)
216:     if $ihelp_full_text_search and (
217:         method_name and method_name.class == String and
218:         self.class == Object and to_s == 'main' and
219:         not method_name =~ /::|\.|#/ and
220:         not method_name =~ /\A[A-Z][a-z0-9A-Z]*\Z/
221:       ) # calling for main
222:       IHelp.search method_name
223:       return
224:     end
225:     if $ihelp_full_text_search and method_name and method_name.to_s.include? " " # phrase search
226:       puts "Searching from docs..."
227:       help_search method_name
228:       return
229:     end
230:     info = help_description(method_name, instance)
231:     if not info
232:       if $ihelp_full_text_search and method_name
233:         puts "No help found for method of that name, searching from docs..."
234:         help_search method_name
235:       else
236:         puts "No help found."
237:       end
238:       return
239:     end
240:     IHelp.render(info)
241:   end

Return RI::ClassDescription / RI::MethodDescription for self or its method meth, or its instance method meth if instance == true.

[Source]

     # File lib/ihelp.rb, line 281
281:   def help_description(method_name=nil, instance=nil)
282:     IHelp.generate_help_description(self, method_name, instance)
283:   end

Returns help string as a HTML REXML::Document with a DIV element as the root.

  If method_name is given, prints help for that method.
  If instance is true, tries to find help only for the instance method.
  If instance is false, tries to find help for the object's method only.
  If instance is nil, checks object's method first, then instance method.
  Returns nil if there is no help to be found.

[Source]

     # File lib/ihelp.rb, line 273
273:   def help_html(method_name=nil, instance=nil)
274:     info = help_description(method_name, instance)
275:     info.to_html if info
276:   end

Searches for str in the documentation of this object.

[Source]

     # File lib/ihelp.rb, line 287
287:   def help_search(str)
288:     raise "No search capability, do you have ferret installed? (gem install ferret)" unless $ihelp_full_text_search
289:     ms = if is_a? Module
290:       instance_methods.map{|im| instance_method im } +
291:       methods.map{|m| method m }
292:     else
293:       methods.map{|m| method m }
294:     end
295:     phrases = ms.map do |m|
296:       mod, met = m.inspect.split(" ",2)[1][0..-2].split(/#|\./)
297:       rmod = mod.scan(/\(([^\)]+)\)/).flatten[0]
298:       rmod ||= mod
299:       rmod.gsub(/[^a-z0-9]/i){|c| "\\"+c }
300:     end.uniq
301:     phrases.delete ""
302:     name_query = phrases.join(" OR ")
303:     query = "(name:(#{name_query})) AND (*:#{IHelp.intersect_search_query str})"
304:     IHelp.search query, false
305:   end

Returns help string in YAML for self.

  If method_name is given, prints help for that method.
  If instance is true, tries to find help only for the instance method.
  If instance is false, tries to find help for the object's method only.
  If instance is nil, checks object's method first, then instance method.
  Returns nil if there is no help to be found.

[Source]

     # File lib/ihelp.rb, line 260
260:   def help_yaml(method_name=nil, instance=nil)
261:     info = help_description(method_name, instance)
262:     info.to_yaml if info
263:   end
ihelp(method_name=nil, instance=nil)

Alias for help

Print out help for instance method method_name. If no method_name given, behaves like help.

[Source]

     # File lib/ihelp.rb, line 248
248:   def instance_help(method_name = nil)
249:     help(method_name, true)
250:   end

[Validate]