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.)
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 help "String#reverse" help "String.reverse" a.method(:reverse).help # gets help for Method help "Hash#map"
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' class IHelp::Renderer def print_name(info) puts info.full_name end end 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::WWW_BROWSER rubydoc_org -- opens the corresponding www.ruby-doc.org class documentation page with the program named in IHelp::WWW_BROWSER rubytoruby_src -- uses RubyToRuby to print the source for the method (highly experimental)
License: Ruby’s
Author: Ilmari Heikkinen <kig misfiring net>
HELP_VERSION | = | "0.3.1" |
WWW_BROWSER | = | 'firefox' |
RI_ARGS | = | [] |
RI_ARGS | = | ENV["RI"].split.concat(ARGV) |
renderer | [RW] |
Return RI::ClassDescription / RI::MethodDescription for klass or its method meth, or its instance method meth if instance == true.
# File lib/ihelp.rb, line 230 230: def generate_help_description(klass, meth=nil, instance=nil) 231: meth_str = nil 232: double_colon = false 233: if meth 234: meth_str = meth.to_s 235: if /::|\.|#/ === meth_str # called with e.g."Array#str","String.new" 236: meth_str, klass_name, instance_help, double_colon = 237: get_help_klass_info_for_name(meth_str) 238: klass_ancs = find_ancestors(klass_name, instance) 239: else 240: klass_name, klass_ancs, instance_help = 241: get_help_klass_info(klass, instance) 242: end 243: else 244: klass_name, klass_ancs, instance_help = 245: get_help_klass_info(klass, instance) 246: end 247: info = get_help_info(meth_str, klass_name, klass_ancs, instance_help, 248: instance) 249: # Retry with method as class if double_colon-splitted and no info 250: if info.nil? and double_colon 251: klass_name = [klass_name, meth_str].join("::") 252: meth_str = nil 253: klass_ancs = find_ancestors(klass_name, instance) 254: info = get_help_info( 255: meth_str, klass_name, klass_ancs, instance_help, instance) 256: end 257: info 258: 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 219 219: def render(info) 220: IHelp::Renderer.new.send(renderer, info) 221: end
# File lib/ihelp.rb, line 223 223: def ri_driver 224: @ri_driver ||= IHelpDriver.new(RI_ARGS) 225: end
Find ancestors for klass_name (works if the class has been loaded)
# File lib/ihelp.rb, line 302 302: def find_ancestors(klass_name, instance) 303: similarily_named_class = nil 304: ObjectSpace.each_object(Class){|k| 305: similarily_named_class = k if k.name == klass_name 306: break if similarily_named_class 307: } 308: if similarily_named_class 309: klass_ancs = similarily_named_class.ancestors 310: klass_ancs += similarily_named_class.class.ancestors unless instance 311: else 312: klass_ancs = [] 313: end 314: klass_ancs 315: end
# File lib/ihelp.rb, line 317 317: def get_help_info(meth_str, klass_name, klass_ancs, instance_help, instance) 318: info = get_help_info_str(meth_str, klass_name, klass_ancs, instance_help) 319: # If instance is undefined, try both the class methods and instance 320: # methods. 321: if info.nil? and instance.nil? 322: info = get_help_info_str( 323: meth_str, klass_name, klass_ancs, (not instance_help)) 324: end 325: info 326: end
# File lib/ihelp.rb, line 328 328: def get_help_info_str(meth_str, klass_name, klass_ancs, instance) 329: info_str = ri_driver.get_info_str(klass_name, meth_str, instance) 330: if not info_str 331: # Walk through class hierarchy to find an inherited method 332: ancest = klass_ancs.find{|anc| 333: info_str = ri_driver.get_info_str(anc.name, meth_str, instance) 334: } 335: # Avoid returning Object in case of no help. 336: if ancest == Object and meth_str.nil? and klass_name != Object.name 337: info_str = nil 338: end 339: end 340: info_str 341: end
# File lib/ihelp.rb, line 261 261: def get_help_klass_info(klass,instance) 262: if klass.is_a? Class or klass.is_a? Module 263: klass_ancs = klass.ancestors + klass.class.ancestors 264: klass_ancs -= [klass, klass.class] 265: instance = false if instance.nil? 266: # If we are an instance, set klass to our class 267: # 268: else 269: klass = klass.class 270: klass_ancs = klass.ancestors - [klass] 271: instance = true if instance.nil? 272: end 273: klass_name = klass.name 274: [klass_name, klass_ancs, instance] 275: end
# File lib/ihelp.rb, line 277 277: def get_help_klass_info_for_name(meth_str) 278: double_colon = false 279: # Maybe we are being called with something like "Array#slice" 280: if /#/ === meth_str 281: klass_name, meth_str = meth_str.split(/#/, 2) 282: instance = true 283: 284: # Or maybe the requested item is "Ri::RiDriver.new" 285: elsif /\./ === meth_str 286: klass_name, meth_str = meth_str.reverse.split(/\./, 2). 287: reverse.map{|i| i.reverse} 288: instance = false 289: 290: # And the problematic case of "Test::Unit" (is Unit a class name or 291: # a method name? Why does Ri even care?) 292: else 293: klass_name, meth_str = meth_str.reverse.split(/::/, 2). 294: reverse.map{|i| i.reverse} 295: double_colon = true 296: instance = false 297: end 298: [meth_str, klass_name, instance, double_colon] 299: 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 154 154: def help(method_name=nil, instance=nil) 155: info = help_description(method_name, instance) 156: if not info 157: puts "No help found." 158: return 159: end 160: IHelp.render(info) 161: 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 199 199: def help_description(method_name=nil, instance=nil) 200: IHelp.generate_help_description(self, method_name, instance) 201: 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 191 191: def help_html(method_name=nil, instance=nil) 192: info = help_description(method_name, instance) 193: info.to_html if info 194: 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 178 178: def help_yaml(method_name=nil, instance=nil) 179: info = help_description(method_name, instance) 180: info.to_yaml if info 181: end