Module | IHelp |
In: |
lib/ihelp.rb
|
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'
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>
HELP_VERSION | = | "0.4.5" |
Return RI::ClassDescription / RI::MethodDescription for klass or its method meth, or its instance method meth if instance == true.
# 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
# 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=.
# File lib/ihelp.rb, line 358 358: def render(info) 359: IHelp::Renderer.new.send(renderer, info) 360: 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.
# 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
Find ancestors for klass_name (works if the class has been loaded)
# 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
# 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
# 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
# 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
# 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
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).
# 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.
# 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.
# 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.
# 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.
# 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