class RDoc::RI::Driver

The RI driver implements the command-line ri tool.

The driver supports:

  • loading RI data from:

    • Ruby's standard library

    • RubyGems

    • ~/.rdoc

    • A user-supplied directory

  • Paging output (uses RI_PAGER environment variable, PAGER environment variable or the less, more and pager programs)

  • Interactive mode with tab-completion

  • Abbreviated names (ri Zl shows Zlib documentation)

  • Colorized output

  • Merging output from multiple RI data sources

Attributes

show_all[RW]

Show all method documentation following a class or module

stores[RW]

An RDoc::RI::Store for each entry in the RI path

use_stdout[RW]

Controls the user of the pager vs $stdout

Public Class Methods

default_options() click to toggle source

Default options for ri

# File lib/rdoc/ri/driver.rb, line 77
def self.default_options
 options = {}
 options[:interactive] = false
 options[:profile] = false
 options[:show_all] = false
 options[:use_cache] = true
 options[:use_stdout] = !$stdout.tty?
 options[:width] = 72
 # By default all standard paths are used.
 options[:use_system] = true
 options[:use_site] = true
 options[:use_home] = true
 options[:use_gems] = true
 options[:extra_doc_dirs] = []
 return options
end
dump(data_path) click to toggle source

Dump data_path using pp

# File lib/rdoc/ri/driver.rb, line 99
def self.dump data_path
 require 'pp'
 open data_path, 'rb' do |io|
 pp Marshal.load(io.read)
 end
end
new(initial_options = {}) click to toggle source

Creates a new driver using initial_options from ::process_args

# File lib/rdoc/ri/driver.rb, line 369
def initialize initial_options = {}
 @paging = false
 @classes = nil
 options = self.class.default_options.update(initial_options)
 @formatter_klass = options[:formatter]
 require 'profile' if options[:profile]
 @names = options[:names]
 @list = options[:list]
 @doc_dirs = []
 @stores = []
 RDoc::RI::Paths.each(options[:use_system], options[:use_site],
 options[:use_home], options[:use_gems],
 *options[:extra_doc_dirs]) do |path, type|
 @doc_dirs << path
 store = RDoc::RI::Store.new path, type
 store.load_cache
 @stores << store
 end
 @list_doc_dirs = options[:list_doc_dirs]
 @interactive = options[:interactive]
 @server = options[:server]
 @use_stdout = options[:use_stdout]
 @show_all = options[:show_all]
 # pager process for jruby
 @jruby_pager_process = nil
end
process_args(argv) click to toggle source

Parses argv and returns a Hash of options

# File lib/rdoc/ri/driver.rb, line 110
 def self.process_args argv
 options = default_options
 opts = OptionParser.new do |opt|
 opt.accept File do |file,|
 File.readable?(file) and not File.directory?(file) and file
 end
 opt.program_name = File.basename 0ドル
 opt.version = RDoc::VERSION
 opt.release = nil
 opt.summary_indent = ' ' * 4
 opt.banner = <<-EOT
Usage: #{opt.program_name} [options] [names...]
Where name can be:
 Class | Module | Module::Class
 Class::method | Class#method | Class.method | method
 gem_name: | gem_name:README | gem_name:History
All class names may be abbreviated to their minimum unambiguous form. If a name
is ambiguous, all valid options will be listed.
A '.' matches either class or instance methods, while #method
matches only instance and ::method matches only class methods.
README and other files may be displayed by prefixing them with the gem name
they're contained in. If the gem name is followed by a ':' all files in the
gem will be shown. The file name extension may be omitted where it is
unambiguous.
For example:
 #{opt.program_name} Fil
 #{opt.program_name} File
 #{opt.program_name} File.new
 #{opt.program_name} zip
 #{opt.program_name} rdoc:README
Note that shell quoting or escaping may be required for method names containing
punctuation:
 #{opt.program_name} 'Array.[]'
 #{opt.program_name} compact\\!
To see the default directories ri will search, run:
 #{opt.program_name} --list-doc-dirs
Specifying the --system, --site, --home, --gems or --doc-dir options will
limit ri to searching only the specified directories.
ri options may be set in the 'RI' environment variable.
The ri pager can be set with the 'RI_PAGER' environment variable or the
'PAGER' environment variable.
 EOT
 opt.separator nil
 opt.separator "Options:"
 opt.separator nil
 opt.on("--[no-]interactive", "-i",
 "In interactive mode you can repeatedly",
 "look up methods with autocomplete.") do |interactive|
 options[:interactive] = interactive
 end
 opt.separator nil
 opt.on("--[no-]all", "-a",
 "Show all documentation for a class or",
 "module.") do |show_all|
 options[:show_all] = show_all
 end
 opt.separator nil
 opt.on("--[no-]list", "-l",
 "List classes ri knows about.") do |list|
 options[:list] = list
 end
 opt.separator nil
 opt.on("--[no-]pager",
 "Send output directly to stdout,",
 "rather than to a pager.") do |use_pager|
 options[:use_stdout] = !use_pager
 end
 opt.separator nil
 opt.on("-T",
 "Synonym for --no-pager") do
 options[:use_stdout] = true
 end
 opt.separator nil
 opt.on("--width=WIDTH", "-w", OptionParser::DecimalInteger,
 "Set the width of the output.") do |width|
 options[:width] = width
 end
 opt.separator nil
 opt.on("--server [PORT]", Integer,
 "Run RDoc server on the given port.",
 "The default port is 8214.") do |port|
 options[:server] = port || 8214
 end
 opt.separator nil
 formatters = RDoc::Markup.constants.grep(/^To[A-Z][a-z]+$/).sort
 formatters = formatters.sort.map do |formatter|
 formatter.to_s.sub('To', '').downcase
 end
 formatters -= %w[html label test] # remove useless output formats
 opt.on("--format=NAME", "-f",
 "Uses the selected formatter. The default",
 "formatter is bs for paged output and ansi",
 "otherwise. Valid formatters are:",
 formatters.join(' '), formatters) do |value|
 options[:formatter] = RDoc::Markup.const_get "To#{value.capitalize}"
 end
 opt.separator nil
 opt.separator "Data source options:"
 opt.separator nil
 opt.on("--[no-]list-doc-dirs",
 "List the directories from which ri will",
 "source documentation on stdout and exit.") do |list_doc_dirs|
 options[:list_doc_dirs] = list_doc_dirs
 end
 opt.separator nil
 opt.on("--doc-dir=DIRNAME", "-d", Array,
 "List of directories from which to source",
 "documentation in addition to the standard",
 "directories. May be repeated.") do |value|
 value.each do |dir|
 unless File.directory? dir then
 raise OptionParser::InvalidArgument, "#{dir} is not a directory"
 end
 options[:extra_doc_dirs] << File.expand_path(dir)
 end
 end
 opt.separator nil
 opt.on("--no-standard-docs",
 "Do not include documentation from",
 "the Ruby standard library, site_lib,",
 "installed gems, or ~/.rdoc.",
 "Use with --doc-dir") do
 options[:use_system] = false
 options[:use_site] = false
 options[:use_gems] = false
 options[:use_home] = false
 end
 opt.separator nil
 opt.on("--[no-]system",
 "Include documentation from Ruby's standard",
 "library. Defaults to true.") do |value|
 options[:use_system] = value
 end
 opt.separator nil
 opt.on("--[no-]site",
 "Include documentation from libraries",
 "installed in site_lib.",
 "Defaults to true.") do |value|
 options[:use_site] = value
 end
 opt.separator nil
 opt.on("--[no-]gems",
 "Include documentation from RubyGems.",
 "Defaults to true.") do |value|
 options[:use_gems] = value
 end
 opt.separator nil
 opt.on("--[no-]home",
 "Include documentation stored in ~/.rdoc.",
 "Defaults to true.") do |value|
 options[:use_home] = value
 end
 opt.separator nil
 opt.separator "Debug options:"
 opt.separator nil
 opt.on("--[no-]profile",
 "Run with the ruby profiler") do |value|
 options[:profile] = value
 end
 opt.separator nil
 opt.on("--dump=CACHE", File,
 "Dumps data from an ri cache or data file") do |value|
 options[:dump_path] = value
 end
 end
 argv = ENV['RI'].to_s.split.concat argv
 opts.parse! argv
 options[:names] = argv
 options[:use_stdout] ||= !$stdout.tty?
 options[:use_stdout] ||= options[:interactive]
 options[:width] ||= 72
 options
 rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e
 puts opts
 puts
 puts e
 exit 1
 end
run(argv = ARGV) click to toggle source

Runs the ri command line executable using argv

# File lib/rdoc/ri/driver.rb, line 354
def self.run argv = ARGV
 options = process_args argv
 if options[:dump_path] then
 dump options[:dump_path]
 return
 end
 ri = new options
 ri.run
end

Public Instance Methods

add_also_in(out, also_in) click to toggle source

Adds paths for undocumented classes also_in to out

# File lib/rdoc/ri/driver.rb, line 409
def add_also_in out, also_in
 return if also_in.empty?
 out << RDoc::Markup::Rule.new(1)
 out << RDoc::Markup::Paragraph.new("Also found in:")
 paths = RDoc::Markup::Verbatim.new
 also_in.each do |store|
 paths.parts.push store.friendly_path, "\n"
 end
 out << paths
end
add_class(out, name, classes) click to toggle source

Adds a class header to out for class name which is described in classes.

# File lib/rdoc/ri/driver.rb, line 426
def add_class out, name, classes
 heading = if classes.all? { |klass| klass.module? } then
 name
 else
 superclass = classes.map do |klass|
 klass.superclass unless klass.module?
 end.compact.shift || 'Object'
 superclass = superclass.full_name unless String === superclass
 "#{name} < #{superclass}"
 end
 out << RDoc::Markup::Heading.new(1, heading)
 out << RDoc::Markup::BlankLine.new
end
add_extends(out, extends) click to toggle source

Adds extends to out

# File lib/rdoc/ri/driver.rb, line 453
def add_extends out, extends
 add_extension_modules out, 'Extended by', extends
end
add_extension_modules(out, type, extensions) click to toggle source

Adds a list of extensions to this module of the given type to out. #add_includes and #add_extends call this, so you should use those directly.

# File lib/rdoc/ri/driver.rb, line 461
def add_extension_modules out, type, extensions
 return if extensions.empty?
 out << RDoc::Markup::Rule.new(1)
 out << RDoc::Markup::Heading.new(1, "#{type}:")
 extensions.each do |modules, store|
 if modules.length == 1 then
 add_extension_modules_single out, store, modules.first
 else
 add_extension_modules_multiple out, store, modules
 end
 end
end
add_from(out, store) click to toggle source

Adds "(from ...)" to out for store

# File lib/rdoc/ri/driver.rb, line 446
def add_from out, store
 out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})")
end
add_includes(out, includes) click to toggle source

Adds includes to out

# File lib/rdoc/ri/driver.rb, line 520
def add_includes out, includes
 add_extension_modules out, 'Includes', includes
end
add_method(out, name) click to toggle source

Looks up the method name and adds it to out

# File lib/rdoc/ri/driver.rb, line 527
def add_method out, name
 filtered = lookup_method name
 method_out = method_document name, filtered
 out.concat method_out.parts
end
add_method_documentation(out, klass) click to toggle source

Adds documentation for all methods in klass to out

# File lib/rdoc/ri/driver.rb, line 538
def add_method_documentation out, klass
 klass.method_list.each do |method|
 begin
 add_method out, method.full_name
 rescue NotFoundError
 next
 end
 end
end
add_method_list(out, methods, name) click to toggle source

Adds a list of methods to out with a heading of name

# File lib/rdoc/ri/driver.rb, line 551
def add_method_list out, methods, name
 return if methods.empty?
 out << RDoc::Markup::Heading.new(1, "#{name}:")
 out << RDoc::Markup::BlankLine.new
 if @use_stdout and !@interactive then
 out.concat methods.map { |method|
 RDoc::Markup::Verbatim.new method
 }
 else
 out << RDoc::Markup::IndentedParagraph.new(2, methods.join(', '))
 end
 out << RDoc::Markup::BlankLine.new
end
ancestors_of(klass) click to toggle source

Returns ancestor classes of klass

# File lib/rdoc/ri/driver.rb, line 571
def ancestors_of klass
 ancestors = []
 unexamined = [klass]
 seen = []
 loop do
 break if unexamined.empty?
 current = unexamined.shift
 seen << current
 stores = classes[current]
 break unless stores and not stores.empty?
 klasses = stores.map do |store|
 store.ancestors[current]
 end.flatten.uniq
 klasses = klasses - seen
 ancestors.concat klasses
 unexamined.concat klasses
 end
 ancestors.reverse
end
class_document(name, found, klasses, includes, extends) click to toggle source

Builds a RDoc::Markup::Document from found, klasess and includes

# File lib/rdoc/ri/driver.rb, line 608
def class_document name, found, klasses, includes, extends
 also_in = []
 out = RDoc::Markup::Document.new
 add_class out, name, klasses
 add_includes out, includes
 add_extends out, extends
 found.each do |store, klass|
 render_class out, store, klass, also_in
 end
 add_also_in out, also_in
 out
end
classes() click to toggle source

Hash mapping a known class or module to the stores it can be loaded from

# File lib/rdoc/ri/driver.rb, line 674
def classes
 return @classes if @classes
 @classes = {}
 @stores.each do |store|
 store.cache[:modules].each do |mod|
 # using default block causes searched-for modules to be added
 @classes[mod] ||= []
 @classes[mod] << store
 end
 end
 @classes
end
classes_and_includes_and_extends_for(name) click to toggle source

Returns the stores wherein name is found along with the classes, extends and includes that match it

# File lib/rdoc/ri/driver.rb, line 694
def classes_and_includes_and_extends_for name
 klasses = []
 extends = []
 includes = []
 found = @stores.map do |store|
 begin
 klass = store.load_class name
 klasses << klass
 extends << [klass.extends, store] if klass.extends
 includes << [klass.includes, store] if klass.includes
 [store, klass]
 rescue RDoc::Store::MissingFileError
 end
 end.compact
 extends.reject! do |modules,| modules.empty? end
 includes.reject! do |modules,| modules.empty? end
 [found, klasses, includes, extends]
end
complete(name) click to toggle source

Completes name based on the caches. For Readline

# File lib/rdoc/ri/driver.rb, line 719
def complete name
 completions = []
 klass, selector, method = parse_name name
 complete_klass name, klass, selector, method, completions
 complete_method name, klass, selector, completions
 completions.sort.uniq
end
display(document) click to toggle source

Converts document to text and writes it to the pager

# File lib/rdoc/ri/driver.rb, line 769
def display document
 page do |io|
 text = document.accept formatter(io)
 io.write text
 end
end
display_class(name) click to toggle source

Outputs formatted RI data for class name. Groups undocumented classes

# File lib/rdoc/ri/driver.rb, line 780
def display_class name
 return if name =~ /#|\./
 found, klasses, includes, extends =
 classes_and_includes_and_extends_for name
 return if found.empty?
 out = class_document name, found, klasses, includes, extends
 display out
end
display_method(name) click to toggle source

Outputs formatted RI data for method name

# File lib/rdoc/ri/driver.rb, line 796
def display_method name
 out = RDoc::Markup::Document.new
 add_method out, name
 display out
end
display_name(name) click to toggle source

Outputs formatted RI data for the class or method name.

Returns true if name was found, false if it was not an alternative could be guessed, raises an error if name couldn't be guessed.

# File lib/rdoc/ri/driver.rb, line 810
def display_name name
 if name =~ /\w:(\w|$)/ then
 display_page name
 return true
 end
 return true if display_class name
 display_method name if name =~ /::|#|\./
 true
rescue NotFoundError
 matches = list_methods_matching name if name =~ /::|#|\./
 matches = classes.keys.grep(/^#{Regexp.escape name}/) if matches.empty?
 raise if matches.empty?
 page do |io|
 io.puts "#{name} not found, maybe you meant:"
 io.puts
 io.puts matches.sort.join("\n")
 end
 false
end
display_names(names) click to toggle source

Displays each name in name

# File lib/rdoc/ri/driver.rb, line 839
def display_names names
 names.each do |name|
 name = expand_name name
 display_name name
 end
end
display_page(name) click to toggle source

Outputs formatted RI data for page name.

# File lib/rdoc/ri/driver.rb, line 850
def display_page name
 store_name, page_name = name.split ':', 2
 store = @stores.find { |s| s.source == store_name }
 return display_page_list store if page_name.empty?
 pages = store.cache[:pages]
 unless pages.include? page_name then
 found_names = pages.select do |n|
 n =~ /#{Regexp.escape page_name}\.[^.]+$/
 end
 if found_names.length.zero? then
 return display_page_list store, pages
 elsif found_names.length > 1 then
 return display_page_list store, found_names, page_name
 end
 page_name = found_names.first
 end
 page = store.load_page page_name
 display page.comment
end
display_page_list(store, pages = store.cache[:pages], search = nil) click to toggle source

Outputs a formatted RI page list for the pages in store.

# File lib/rdoc/ri/driver.rb, line 881
def display_page_list store, pages = store.cache[:pages], search = nil
 out = RDoc::Markup::Document.new
 title = if search then
 "#{search} pages"
 else
 'Pages'
 end
 out << RDoc::Markup::Heading.new(1, "#{title} in #{store.friendly_path}")
 out << RDoc::Markup::BlankLine.new
 list = RDoc::Markup::List.new(:BULLET)
 pages.each do |page|
 list << RDoc::Markup::Paragraph.new(page)
 end
 out << list
 display out
end
expand_class(klass) click to toggle source

Expands abbreviated klass klass into a fully-qualified class. "Zl::Da" will be expanded to Zlib::DataError.

# File lib/rdoc/ri/driver.rb, line 908
def expand_class klass
 klass.split('::').inject '' do |expanded, klass_part|
 expanded << '::' unless expanded.empty?
 short = expanded << klass_part
 subset = classes.keys.select do |klass_name|
 klass_name =~ /^#{expanded}[^:]*$/
 end
 abbrevs = Abbrev.abbrev subset
 expanded = abbrevs[short]
 raise NotFoundError, short unless expanded
 expanded.dup
 end
end
expand_name(name) click to toggle source

Expands the class portion of name into a fully-qualified class. See expand_class.

# File lib/rdoc/ri/driver.rb, line 931
def expand_name name
 klass, selector, method = parse_name name
 return [selector, method].join if klass.empty?
 case selector
 when ':' then
 [find_store(klass), selector, method]
 else
 [expand_class(klass), selector, method]
 end.join
end
filter_methods(found, name) click to toggle source

Filters the methods in found trying to find a match for name.

# File lib/rdoc/ri/driver.rb, line 947
def filter_methods found, name
 regexp = name_regexp name
 filtered = found.find_all do |store, methods|
 methods.any? { |method| method.full_name =~ regexp }
 end
 return filtered unless filtered.empty?
 found
end
find_methods(name) { |*item| ... } click to toggle source

Yields items matching name including the store they were found in, the class being searched for, the class they were found in (an ancestor) the types of methods to look up (from method_type), and the method name being searched for

# File lib/rdoc/ri/driver.rb, line 965
def find_methods name
 klass, selector, method = parse_name name
 types = method_type selector
 klasses = nil
 ambiguous = klass.empty?
 if ambiguous then
 klasses = classes.keys
 else
 klasses = ancestors_of klass
 klasses.unshift klass
 end
 methods = []
 klasses.each do |ancestor|
 ancestors = classes[ancestor]
 next unless ancestors
 klass = ancestor if ambiguous
 ancestors.each do |store|
 methods << [store, klass, ancestor, types, method]
 end
 end
 methods = methods.sort_by do |_, k, a, _, m|
 [k, a, m].compact
 end
 methods.each do |item|
 yield(*item) # :yields: store, klass, ancestor, types, method
 end
 self
end
find_pager_jruby(pager) click to toggle source

Finds the given pager for jruby. Returns an IO if pager was found.

Returns false if pager does not exist.

Returns nil if the jruby JVM doesn't support ProcessBuilder redirection (1.6 and older).

# File lib/rdoc/ri/driver.rb, line 1013
def find_pager_jruby pager
 require 'java'
 require 'shellwords'
 return nil unless java.lang.ProcessBuilder.constants.include? :Redirect
 pager = Shellwords.split pager
 pb = java.lang.ProcessBuilder.new(*pager)
 pb = pb.redirect_output java.lang.ProcessBuilder::Redirect::INHERIT
 @jruby_pager_process = pb.start
 input = @jruby_pager_process.output_stream
 io = input.to_io
 io.sync = true
 io
rescue java.io.IOException
 false
end
find_store(name) click to toggle source

Finds a store that matches name which can be the name of a gem, "ruby", "home" or "site".

See also RDoc::Store#source

# File lib/rdoc/ri/driver.rb, line 1041
def find_store name
 @stores.each do |store|
 source = store.source
 return source if source == name
 return source if
 store.type == :gem and source =~ /^#{Regexp.escape name}-\d/
 end
 raise RDoc::RI::Driver::NotFoundError, name
end
formatter(io) click to toggle source

Creates a new RDoc::Markup::Formatter. If a formatter is given with -f, use it. If we're outputting to a pager, use bs, otherwise ansi.

# File lib/rdoc/ri/driver.rb, line 1058
def formatter(io)
 if @formatter_klass then
 @formatter_klass.new
 elsif paging? or !io.tty? then
 RDoc::Markup::ToBs.new
 else
 RDoc::Markup::ToAnsi.new
 end
end
in_path?(file) click to toggle source

Is file in ENV?

# File lib/rdoc/ri/driver.rb, line 1107
def in_path? file
 return true if file =~ %r%\A/% and File.exist? file
 ENV['PATH'].split(File::PATH_SEPARATOR).any? do |path|
 File.exist? File.join(path, file)
 end
end
interactive() click to toggle source

Runs ri interactively using Readline if it is available.

# File lib/rdoc/ri/driver.rb, line 1071
def interactive
 puts "\nEnter the method name you want to look up."
 if defined? Readline then
 Readline.completion_proc = method :complete
 puts "You can use tab to autocomplete."
 end
 puts "Enter a blank line to exit.\n\n"
 loop do
 name = if defined? Readline then
 Readline.readline ">> "
 else
 print ">> "
 $stdin.gets
 end
 return if name.nil? or name.empty?
 name = expand_name name.strip
 begin
 display_name name
 rescue NotFoundError => e
 puts e.message
 end
 end
rescue Interrupt
 exit
end
list_known_classes(names = []) click to toggle source

Lists classes known to ri starting with names. If names is empty all known classes are shown.

# File lib/rdoc/ri/driver.rb, line 1119
def list_known_classes names = []
 classes = []
 stores.each do |store|
 classes << store.module_names
 end
 classes = classes.flatten.uniq.sort
 unless names.empty? then
 filter = Regexp.union names.map { |name| /^#{name}/ }
 classes = classes.grep filter
 end
 page do |io|
 if paging? or io.tty? then
 if names.empty? then
 io.puts "Classes and Modules known to ri:"
 else
 io.puts "Classes and Modules starting with #{names.join ', '}:"
 end
 io.puts
 end
 io.puts classes.join("\n")
 end
end
list_methods_matching(name) click to toggle source

Returns an Array of methods matching name

# File lib/rdoc/ri/driver.rb, line 1151
def list_methods_matching name
 found = []
 find_methods name do |store, klass, ancestor, types, method|
 if types == :instance or types == :both then
 methods = store.instance_methods[ancestor]
 if methods then
 matches = methods.grep(/^#{Regexp.escape method.to_s}/)
 matches = matches.map do |match|
 "#{klass}##{match}"
 end
 found.concat matches
 end
 end
 if types == :class or types == :both then
 methods = store.class_methods[ancestor]
 next unless methods
 matches = methods.grep(/^#{Regexp.escape method.to_s}/)
 matches = matches.map do |match|
 "#{klass}::#{match}"
 end
 found.concat matches
 end
 end
 found.uniq
end
load_method(store, cache, klass, type, name) click to toggle source

Loads RI data for method name on klass from store. type and cache indicate if it is a class or instance method.

# File lib/rdoc/ri/driver.rb, line 1190
def load_method store, cache, klass, type, name
 methods = store.send(cache)[klass]
 return unless methods
 method = methods.find do |method_name|
 method_name == name
 end
 return unless method
 store.load_method klass, "#{type}#{method}"
rescue RDoc::Store::MissingFileError => e
 comment = RDoc::Comment.new("missing documentation at #{e.file}").parse
 method = RDoc::AnyMethod.new nil, name
 method.comment = comment
 method
end
load_methods_matching(name) click to toggle source

Returns an Array of RI data for methods matching name

# File lib/rdoc/ri/driver.rb, line 1213
def load_methods_matching name
 found = []
 find_methods name do |store, klass, ancestor, types, method|
 methods = []
 methods << load_method(store, :class_methods, ancestor, '::', method) if
 [:class, :both].include? types
 methods << load_method(store, :instance_methods, ancestor, '#', method) if
 [:instance, :both].include? types
 found << [store, methods.compact]
 end
 found.reject do |path, methods| methods.empty? end
end
lookup_method(name) click to toggle source

Returns a filtered list of methods matching name

# File lib/rdoc/ri/driver.rb, line 1234
def lookup_method name
 found = load_methods_matching name
 raise NotFoundError, name if found.empty?
 filter_methods found, name
end
method_document(name, filtered) click to toggle source

Builds a RDoc::Markup::Document from found, klasses and includes

# File lib/rdoc/ri/driver.rb, line 1245
def method_document name, filtered
 out = RDoc::Markup::Document.new
 out << RDoc::Markup::Heading.new(1, name)
 out << RDoc::Markup::BlankLine.new
 filtered.each do |store, methods|
 methods.each do |method|
 render_method out, store, method, name
 end
 end
 out
end
method_type(selector) click to toggle source

Returns the type of method (:both, :instance, :class) for selector

# File lib/rdoc/ri/driver.rb, line 1263
def method_type selector
 case selector
 when '.', nil then :both
 when '#' then :instance
 else :class
 end
end
name_regexp(name) click to toggle source

Returns a regular expression for name that will match an RDoc::AnyMethod's name.

# File lib/rdoc/ri/driver.rb, line 1275
def name_regexp name
 klass, type, name = parse_name name
 case type
 when '#', '::' then
 /^#{klass}#{type}#{Regexp.escape name}$/
 else
 /^#{klass}(#|::)#{Regexp.escape name}$/
 end
end
page() { |pager| ... } click to toggle source

Paginates output through a pager program.

# File lib/rdoc/ri/driver.rb, line 1289
def page
 if pager = setup_pager then
 begin
 yield pager
 ensure
 pager.close
 @jruby_pager_process.wait_for if @jruby_pager_process
 end
 else
 yield $stdout
 end
rescue Errno::EPIPE
ensure
 @paging = false
end
paging?() click to toggle source

Are we using a pager?

# File lib/rdoc/ri/driver.rb, line 1308
def paging?
 @paging
end
parse_name(name) click to toggle source

Extracts the class, selector and method name parts from name like Foo::Bar#baz.

NOTE: Given Foo::Bar, Bar is considered a class even though it may be a method

# File lib/rdoc/ri/driver.rb, line 1319
def parse_name name
 parts = name.split(/(::?|#|\.)/)
 if parts.length == 1 then
 if parts.first =~ /^[a-z]|^([%&*+\/<>^`|~-]|\+@|-@|<<|<=>?|===?|=>|=~|>>|\[\]=?|~@)$/ then
 type = '.'
 meth = parts.pop
 else
 type = nil
 meth = nil
 end
 elsif parts.length == 2 or parts.last =~ /::|#|\./ then
 type = parts.pop
 meth = nil
 elsif parts[1] == ':' then
 klass = parts.shift
 type = parts.shift
 meth = parts.join
 elsif parts[-2] != '::' or parts.last !~ /^[A-Z]/ then
 meth = parts.pop
 type = parts.pop
 end
 klass ||= parts.join
 [klass, type, meth]
end
run() click to toggle source

Looks up and displays ri data according to the options given.

# File lib/rdoc/ri/driver.rb, line 1422
def run
 if @list_doc_dirs then
 puts @doc_dirs
 elsif @list then
 list_known_classes @names
 elsif @server then
 start_server
 elsif @interactive or @names.empty? then
 interactive
 else
 display_names @names
 end
rescue NotFoundError => e
 abort e.message
end
setup_pager() click to toggle source

Sets up a pager program to pass output through. Tries the RI_PAGER and PAGER environment variables followed by pager, less then more.

# File lib/rdoc/ri/driver.rb, line 1442
def setup_pager
 return if @use_stdout
 jruby = Object.const_defined?(:RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
 pagers = [ENV['RI_PAGER'], ENV['PAGER'], 'pager', 'less', 'more']
 pagers.compact.uniq.each do |pager|
 next unless pager
 pager_cmd = pager.split.first
 next unless in_path? pager_cmd
 if jruby then
 case io = find_pager_jruby(pager)
 when nil then break
 when false then next
 else io
 end
 else
 io = IO.popen(pager, 'w') rescue next
 end
 next if $? and $?.pid == io.pid and $?.exited? # pager didn't work
 @paging = true
 return io
 end
 @use_stdout = true
 nil
end
start_server() click to toggle source

Starts a WEBrick server for ri.

# File lib/rdoc/ri/driver.rb, line 1481
def start_server
 require 'webrick'
 server = WEBrick::HTTPServer.new :Port => @server
 extra_doc_dirs = @stores.map {|s| s.type == :extra ? s.path : nil}.compact
 server.mount '/', RDoc::Servlet, nil, extra_doc_dirs
 trap 'INT' do server.shutdown end
 trap 'TERM' do server.shutdown end
 server.start
end