Class: RDoc::RI::Driver

### Home Classes Methods

### In Files

- lib/rdoc/ri/driver.rb

### Parent

Object

### Namespace

- CLASS RDoc::RI::Driver::Error
- CLASS RDoc::RI::Driver::NotFoundError

### Methods

- ::default_options
- ::dump
- ::new
- ::process_args
- ::run
- #add_also_in
- #add_class
- #add_extends
- #add_extension_modules
- #add_from
- #add_includes
- #add_method
- #add_method_documentation
- #add_method_list
- #ancestors_of
- #class_document
- #classes
- #classes_and_includes_and_extends_for
- #complete
- #display
- #display_class
- #display_method
- #display_name
- #display_names
- #display_page
- #display_page_list
- #expand_class
- #expand_name
- #filter_methods
- #find_methods
- #find_pager_jruby
- #find_store
- #formatter
- #in_path?
- #interactive
- #list_known_classes
- #list_methods_matching
- #load_method
- #load_methods_matching
- #lookup_method
- #method_document
- #method_type
- #name_regexp
- #page
- #paging?
- #parse_name
- #run
- #setup_pager
- #start_server

### Files

- CVE-2013-0256.rdoc
- DEVELOPERS.rdoc
- LICENSE.rdoc
- Manifest.txt
- README.rdoc
- RI.rdoc
- Rakefile
- TODO.rdoc

### Class/Module Index

Quicksearch

- RDoc
- RDoc::Alias
- RDoc::AnonClass
- RDoc::AnyMethod
- RDoc::Attr
- RDoc::ClassModule
- RDoc::CodeObject
- RDoc::Comment
- RDoc::Constant
- RDoc::Context
- RDoc::Context::Section
- RDoc::CrossReference
- RDoc::ERBIO
- RDoc::ERBPartial
- RDoc::Encoding
- RDoc::Error
- RDoc::Extend
- RDoc::Gauntlet
- RDoc::Generator
- RDoc::Generator::Darkfish
- RDoc::Generator::JsonIndex
- RDoc::Generator::Markup
- RDoc::Generator::RI
- RDoc::GhostMethod
- RDoc::Include
- RDoc::Markdown
- RDoc::Markdown::Literals
- RDoc::Markup
- RDoc::Markup::AttrChanger
- RDoc::Markup::AttrSpan
- RDoc::Markup::AttributeManager
- RDoc::Markup::Attributes
- RDoc::Markup::BlankLine
- RDoc::Markup::BlockQuote
- RDoc::Markup::Document
- RDoc::Markup::Formatter
- RDoc::Markup::FormatterTestCase
- RDoc::Markup::HardBreak
- RDoc::Markup::Include
- RDoc::Markup::IndentedParagraph
- RDoc::Markup::List
- RDoc::Markup::ListItem
- RDoc::Markup::Paragraph
- RDoc::Markup::Parser
- RDoc::Markup::Parser::Error
- RDoc::Markup::Parser::ParseError
- RDoc::Markup::PreProcess
- RDoc::Markup::Raw
- RDoc::Markup::Rule
- RDoc::Markup::Special
- RDoc::Markup::TextFormatterTestCase
- RDoc::Markup::ToAnsi
- RDoc::Markup::ToBs
- RDoc::Markup::ToHtml
- RDoc::Markup::ToHtmlCrossref
- RDoc::Markup::ToHtmlSnippet
- RDoc::Markup::ToJoinedParagraph
- RDoc::Markup::ToLabel
- RDoc::Markup::ToMarkdown
- RDoc::Markup::ToRdoc
- RDoc::Markup::ToTableOfContents
- RDoc::Markup::ToTest
- RDoc::Markup::ToTtOnly
- RDoc::Markup::Verbatim
- RDoc::MetaMethod
- RDoc::MethodAttr
- RDoc::NormalClass
- RDoc::NormalModule
- RDoc::Options
- RDoc::Parser
- RDoc::Parser::C
- RDoc::Parser::ChangeLog
- RDoc::Parser::Markdown
- RDoc::Parser::RD
- RDoc::Parser::Ruby
- RDoc::Parser::RubyTools
- RDoc::Parser::Simple
- RDoc::Parser::Text
- RDoc::RD
- RDoc::RD::BlockParser
- RDoc::RD::Inline
- RDoc::RD::InlineParser
- RDoc::RDoc
- RDoc::RI
- RDoc::RI::Driver
- RDoc::RI::Driver::Error
- RDoc::RI::Driver::NotFoundError
- RDoc::RI::Error
- RDoc::RI::Paths
- RDoc::Require
- RDoc::RubyLex
- RDoc::RubyLex::Error
- RDoc::RubyToken
- RDoc::RubygemsHook
- RDoc::Servlet
- RDoc::SingleClass
- RDoc::Stats
- RDoc::Stats::Normal
- RDoc::Stats::Quiet
- RDoc::Stats::Verbose
- RDoc::Store
- RDoc::Store::Error
- RDoc::Store::MissingFileError
- RDoc::Task
- RDoc::Task
- RDoc::TestCase
- RDoc::TokenStream
- RDoc::TomDoc
- RDoc::TopLevel
- Object

No matching classes.

# 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 362
    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 = 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:HistoryAll class names may be abbreviated to their minimum unambiguous form. If a nameis ambiguous, all valid options will be listed.A '.' matches either class or instance methods, while #methodmatches only instance and ::method matches only class methods.README and other files may be displayed by prefixing them with the gem namethey're contained in.  If the gem name is followed by a ':' all files in thegem will be shown.  The file name extension may be omitted where it isunambiguous.For example:    #{opt.program_name} Fil    #{opt.program_name} File    #{opt.program_name} File.new    #{opt.program_name} zip    #{opt.program_name} rdoc:READMENote that shell quoting or escaping may be required for method names containingpunctuation:    #{opt.program_name} 'Array.[]'    #{opt.program_name} compact\\!To see the default directories ri will search, run:    #{opt.program_name} --list-doc-dirsSpecifying the --system, --site, --home, --gems or --doc-dir options willlimit 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.

        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", "-T",
               "Send output directly to stdout,",
               "rather than to a pager.") do |use_pager|
          options[:use_stdout] = !use_pager
        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 -= ]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 347
    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 402
    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 419
    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 446
    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 454
    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
          include = modules.first
          name = include.name
          path = store.friendly_path
          out << RDoc::Markup::Paragraph.new("#{name} (from #{path})")

          if include.comment then
            out << RDoc::Markup::BlankLine.new
            out << include.comment
          end
        else
          out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})")

          wout, with = modules.partition { |incl| incl.comment.empty? }

          out << RDoc::Markup::BlankLine.new unless with.empty?

          with.each do |incl|
            out << RDoc::Markup::Paragraph.new(incl.name)
            out << RDoc::Markup::BlankLine.new
            out << incl.comment
          end

          unless wout.empty? then
            verb = RDoc::Markup::Verbatim.new

            wout.each do |incl|
              verb.push incl.name, "\n"
            end

            out << verb
          end
        end
      end
    end

add_from(out, store) click to toggle source

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

    # File lib/rdoc/ri/driver.rb, line 439
    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 500
    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 507
    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 518
    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 531
    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 551
    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 588
    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|
        comment = klass.comment
        # TODO the store's cache should always return an empty Array
        class_methods    = store.class_methods[klass.full_name]    || []
        instance_methods = store.instance_methods[klass.full_name] || []
        attributes       = store.attributes[klass.full_name]       || []

        if comment.empty? and
           instance_methods.empty? and class_methods.empty? then
          also_in << store
          next
        end

        add_from out, store

        unless comment.empty? then
          out << RDoc::Markup::Rule.new(1)

          if comment.merged? then
            parts = comment.parts
            parts = parts.zip [RDoc::Markup::BlankLine.new] * parts.length
            parts.flatten!
            parts.pop

            out.concat parts
          else
            out << comment
          end
        end

        if class_methods or instance_methods or not klass.constants.empty? then
          out << RDoc::Markup::Rule.new(1)
        end

        unless klass.constants.empty? then
          out << RDoc::Markup::Heading.new(1, "Constants:")
          out << RDoc::Markup::BlankLine.new
          list = RDoc::Markup::List.new :NOTE

          constants = klass.constants.sort_by { |constant| constant.name }

          list.items.concat constants.map { |constant|
            parts = constant.comment.parts if constant.comment
            parts << RDoc::Markup::Paragraph.new('[not documented]') if
              parts.empty?

            RDoc::Markup::ListItem.new(constant.name, *parts)
          }

          out << list
          out << RDoc::Markup::BlankLine.new
        end

        add_method_list out, class_methods,    'Class methods'
        add_method_list out, instance_methods, 'Instance methods'
        add_method_list out, attributes,       'Attributes'

        add_method_documentation out, klass if @show_all
      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 666
    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 686
    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 711
    def complete name
      klasses = classes.keys
      completions = []

      klass, selector, method = parse_name name

      # may need to include Foo when given Foo::
      klass_name = method ? name : klass

      if name !~ /#|\./ then
        completions = klasses.grep(/^#{Regexp.escape klass_name}[^:]*$/)
        completions.concat klasses.grep(/^#{Regexp.escape name}[^:]*$/) if
          name =~ /::$/

        completions << klass if classes.key? klass # to complete a method name
      elsif selector then
        completions << klass if classes.key? klass
      elsif classes.key? klass_name then
        completions << klass_name
      end

      if completions.include? klass and name =~ /#|\.|::/ then
        methods = list_methods_matching name

        if not methods.empty? then
          # remove Foo if given Foo:: and a method was found
          completions.delete klass
        elsif selector then
          # replace Foo with Foo:: as given
          completions.delete klass
          completions << "#{klass}#{selector}"
        end

        completions.concat methods
      end

      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 753
    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 764
    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 780
    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 794
    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(/^#{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 823
    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 834
    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 865
    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 892
    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 915
    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 931
    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) 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 949
    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 997
    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 1025
    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 1042
    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 1091
    def in_path? file
      return true if file =~ %\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 1055
    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 1103
    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 1135
    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 1174
    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}"
    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 1191
    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 1212
    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 1223
    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|
          out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})")

          unless name =~ /^#{Regexp.escape method.parent_name}/ then
            out << RDoc::Markup::Heading.new(3, "Implementation from #{method.parent_name}")
          end

          out << RDoc::Markup::Rule.new(1)

          if method.arglists then
            arglists = method.arglists.chomp.split "\n"
            arglists = arglists.map { |line| line + "\n" }
            out << RDoc::Markup::Verbatim.new(*arglists)
            out << RDoc::Markup::Rule.new(1)
          end

          if method.respond_to?(:superclass_method) and method.superclass_method
            out << RDoc::Markup::BlankLine.new
            out << RDoc::Markup::Heading.new(4, "(Uses superclass method #{method.superclass_method})")
            out << RDoc::Markup::Rule.new(1)
          end

          out << RDoc::Markup::BlankLine.new
          out << method.comment
          out << RDoc::Markup::BlankLine.new
        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 1264
    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 1276
    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() click to toggle source

Paginates output through a pager program.

    # File lib/rdoc/ri/driver.rb, line 1290
    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 1309
    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 1320
    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 1351
    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 1371
    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 1410
    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

[Validate]

Generated with the Darkfish Rdoc Generator 2.