[前][次][番号順一覧][スレッド一覧]

ruby-changes:3457

From: ko1@a...
Date: 8 Jan 2008 18:07:53 +0900
Subject: [ruby-changes:3457] drbrain - Ruby:r14950 (trunk): Replace ri with Ryan Davis' cached ri

drbrain	2008-01-08 18:07:31 +0900 (Tue, 08 Jan 2008)

  New Revision: 14950

  Added files:
    trunk/lib/rdoc/ri.rb
    trunk/lib/rdoc.rb
  Removed files:
    trunk/lib/rdoc/ri/ri_options.rb
  Modified files:
    trunk/ChangeLog
    trunk/bin/ri
    trunk/lib/rdoc/rdoc.rb
    trunk/lib/rdoc/ri/ri_display.rb
    trunk/lib/rdoc/ri/ri_driver.rb
    trunk/lib/rdoc/ri/ri_formatter.rb
    trunk/lib/rdoc/ri/ri_paths.rb
    trunk/lib/rdoc/template.rb

  Log:
    Replace ri with Ryan Davis' cached ri

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc/ri/ri_options.rb
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc/ri/ri_driver.rb?r1=14950&r2=14949&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=14950&r2=14949&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc/template.rb?r1=14950&r2=14949&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc/ri/ri_paths.rb?r1=14950&r2=14949&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bin/ri?r1=14950&r2=14949&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc/ri.rb?revision=14950&view=markup
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc.rb?revision=14950&view=markup
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc/ri/ri_formatter.rb?r1=14950&r2=14949&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc/ri/ri_display.rb?r1=14950&r2=14949&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rdoc/rdoc.rb?r1=14950&r2=14949&diff_format=u

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 14949)
+++ ChangeLog	(revision 14950)
@@ -1,3 +1,7 @@
+Tue Jan  8 18:05:35 2008  Eric Hodel  <drbrain@s...>
+
+	* bin/ri, lib/rdoc/ri/*: Replace with Ryan Davis' cached ri.
+
 Tue Jan  8 15:47:43 2008  NAKAMURA Usaku  <usa@r...>
 
 	* enc/utf{16,32}_{be,le}.c: use &OnigEncodingName(*) instead of
Index: lib/rdoc.rb
===================================================================
--- lib/rdoc.rb	(revision 0)
+++ lib/rdoc.rb	(revision 14950)
@@ -0,0 +1,18 @@
+##
+# :include: rdoc/README
+
+module RDoc
+
+  ##
+  # RDoc version you are using
+
+  VERSION = "2.0.0"
+
+  ##
+  # Name of the dotfile that contains the description of files to be processed
+  # in the current directory
+
+  DOT_DOC_FILENAME = ".document"
+
+end
+
Index: lib/rdoc/rdoc.rb
===================================================================
--- lib/rdoc/rdoc.rb	(revision 14949)
+++ lib/rdoc/rdoc.rb	(revision 14950)
@@ -1,3 +1,5 @@
+require 'rdoc'
+
 require 'rdoc/parsers/parse_rb.rb'
 require 'rdoc/parsers/parse_c.rb'
 require 'rdoc/parsers/parse_f95.rb'
@@ -11,23 +13,9 @@
 require 'fileutils'
 require 'time'
 
-##
-# :include: README
-
 module RDoc
 
   ##
-  # RDoc version you are using
-
-  VERSION = "2.0.0"
-
-  ##
-  # Name of the dotfile that contains the description of files to be processed
-  # in the current directory
-
-  DOT_DOC_FILENAME = ".document"
-
-  ##
   # Simple stats collector
 
   class Stats
Index: lib/rdoc/ri/ri_options.rb
===================================================================
--- lib/rdoc/ri/ri_options.rb	(revision 14949)
+++ lib/rdoc/ri/ri_options.rb	(revision 14950)
@@ -1,319 +0,0 @@
-# We handle the parsing of options, and subsequently as a singleton
-# object to be queried for option values
-
-module RI
-
-  require 'rdoc/ri/ri_paths'
-  require 'rdoc/ri/ri_display'
-
-  VERSION_STRING = "ri v1.0.1 - 20041108"
-
-  class Options
-    
-    require 'singleton'
-    require 'getoptlong'
-    
-    include Singleton
-
-    # No not use a pager. Writable, because ri sets it if it
-    # can't find a pager
-    attr_accessor :use_stdout
-
-    # should we just display a class list and exit
-    attr_reader :list_classes
-
-    # should we display a list of all names
-    attr_reader :list_names
-
-    # The width of the output line
-    attr_reader :width
-
-    # the formatting we apply to the output
-    attr_reader :formatter
-
-    # the directory we search for original documentation
-    attr_reader :doc_dir
-
-    module OptionList
-      
-      OPTION_LIST = [
-        [ "--help",          "-h",   nil,
-          "you're looking at it" ],
-
-        [ "--classes",      "-c",   nil,
-          "Display the names of classes and modules we\n" +
-          "know about"],
-
-        [ "--doc-dir",      "-d",   "<dirname>",
-          "A directory to search for documentation. If not\n" +
-          "specified, we search the standard rdoc/ri directories.\n" +
-          "May be repeated."],
-
-        [ "--system",       nil,    nil,
-          "Include documentation from Ruby's standard library:\n  " +
-          RI::Paths::SYSDIR ],
-
-        [ "--site",         nil,    nil,
-          "Include documentation from libraries installed in site_lib:\n  " +
-          RI::Paths::SITEDIR ],
-
-        [ "--home",         nil,    nil,
-          "Include documentation stored in ~/.rdoc:\n  " +
-          (RI::Paths::HOMEDIR || "No ~/.rdoc found") ],
-
-        [ "--gems",         nil,    nil,
-          "Include documentation from RubyGems:\n" +
-          (RI::Paths::GEMDIRS ?
-           Gem.path.map { |dir| "  #{dir}/doc/*/ri" }.join("\n") :
-           "No Rubygems ri found.") ],
-
-        [ "--format",       "-f",   "<name>",
-          "Format to use when displaying output:\n" +
-          "   " + RI::TextFormatter.list + "\n" +
-          "Use 'bs' (backspace) with most pager programs.\n" +
-          "To use ANSI, either also use the -T option, or\n" +
-          "tell your pager to allow control characters\n" +
-          "(for example using the -R option to less)"],
-
-        [ "--list-names",    "-l",   nil,
-          "List all the names known to RDoc, one per line"
-        ],
-
-        [ "--no-pager",      "-T",   nil,
-          "Send output directly to stdout." 
-        ],
-
-        [ "--width",         "-w",   "output width",
-        "Set the width of the output" ],
-
-        [ "--version",       "-v",   nil,
-         "Display the version of ri"
-        ],
-
-      ]
-
-      def OptionList.options
-        OPTION_LIST.map do |long, short, arg,|
-          option = []
-          option << long
-          option << short unless short.nil?
-          option << (arg ? GetoptLong::REQUIRED_ARGUMENT :
-                           GetoptLong::NO_ARGUMENT)
-          option
-        end
-      end
-
-
-      def OptionList.strip_output(text)
-        text =~ /^\s+/
-        leading_spaces = $&
-        text.gsub!(/^#{leading_spaces}/, '')
-        $stdout.puts text
-      end
-      
-      
-      # Show an error and exit
-      
-      def OptionList.error(msg)
-        $stderr.puts
-        $stderr.puts msg
-        name = File.basename $PROGRAM_NAME
-        $stderr.puts "\nFor help on options, try '#{name} --help'\n\n"
-        exit 1
-      end
-      
-      # Show usage and exit
-      
-      def OptionList.usage(short_form=false)
-        
-        puts
-        puts(RI::VERSION_STRING)
-        puts
-        
-        name = File.basename($0)
-
-        directories = [
-          RI::Paths::SYSDIR,
-          RI::Paths::SITEDIR,
-          RI::Paths::HOMEDIR
-        ]
-
-        if RI::Paths::GEMDIRS then
-          Gem.path.each do |dir|
-            directories << "#{dir}/doc/*/ri"
-          end
-        end
-
-        directories = directories.join("\n    ")
-
-        OptionList.strip_output(<<-EOT)
-          Usage:
-
-            #{name} [options]  [names...]
-
-          Display information on Ruby classes, modules, and methods.
-          Give the names of classes or methods to see their documentation.
-          Partial names may be given: if the names match more than
-          one entity, a list will be shown, otherwise details on
-          that entity will be displayed.
-
-          Nested classes and modules can be specified using the normal
-          Name::Name notation, and instance methods can be distinguished
-          from class methods using "." (or "#") instead of "::".
-
-          For example:
-
-              #{name}  File
-              #{name}  File.new
-              #{name}  F.n
-              #{name}  zip
-
-          Note that shell quoting may be required for method names
-          containing punctuation:
-
-              #{name} 'Array.[]'
-              #{name} compact\\!
-
-          By default ri searches for documentation in the following
-          directories:
-
-              #{directories}
-
-          Specifying the --system, --site, --home, --gems or --doc-dir
-          options will limit ri to searching only the specified
-          directories.
-
-        EOT
-
-        if short_form
-          puts "For help on options, type '#{name} -h'"
-          puts "For a list of classes I know about, type '#{name} -c'"
-        else
-          puts "Options:\n\n"
-          OPTION_LIST.each do|long, short, arg, desc|
-            opt = ''
-            opt << (short ? sprintf("%15s", "#{long}, #{short}") :
-                            sprintf("%15s", long))
-            if arg
-              opt << " " << arg
-            end
-            print opt
-            desc = desc.split("\n")
-            if opt.size < 17
-              print " "*(18-opt.size)
-              puts desc.shift
-            else
-              puts
-            end
-            desc.each do |line|
-              puts(" "*18 + line)
-            end
-            puts
-          end
-          puts "Options may also be passed in the 'RI' environment variable"
-          exit 0
-        end
-      end
-    end
-
-    # Show the version and exit
-    def show_version
-      puts VERSION_STRING
-      exit(0)
-    end
-
-    def initialize
-      @use_stdout   = !STDOUT.tty?
-      @width        = 72
-      @formatter    = RI::TextFormatter.for("plain") 
-      @list_classes = false
-      @list_names   = false
-
-      # By default all paths are used.  If any of these are true, only those
-      # directories are used.
-      @use_system = false
-      @use_site = false
-      @use_home = false
-      @use_gems = false
-      @doc_dirs = []
-    end
-
-    # Parse command line options.
-
-    def parse(args)
-    
-      old_argv = ARGV.dup
-
-      ARGV.replace(args)
-
-      begin
-
-        go = GetoptLong.new(*OptionList.options)
-        go.quiet = true
-
-        go.each do |opt, arg|
-          case opt
-          when "--help"       then OptionList.usage
-          when "--version"    then show_version
-          when "--list-names" then @list_names = true
-          when "--no-pager"   then @use_stdout = true
-          when "--classes"    then @list_classes = true
-
-          when "--system"     then @use_system = true
-          when "--site"       then @use_site = true
-          when "--home"       then @use_home = true
-          when "--gems"       then @use_gems = true
-
-          when "--doc-dir"
-            if File.directory?(arg)
-              @doc_dirs << arg
-            else
-              $stderr.puts "Invalid directory: #{arg}"
-              exit 1
-            end
-
-          when "--format"
-            @formatter = RI::TextFormatter.for(arg)
-            unless @formatter
-              $stderr.print "Invalid formatter (should be one of "
-              $stderr.puts RI::TextFormatter.list + ")"
-              exit 1
-            end
-          when "--width"
-            begin
-              @width = Integer(arg)
-            rescue 
-              $stderr.puts "Invalid width: '#{arg}'"
-              exit 1
-            end
-          end
-        end
-
-      rescue GetoptLong::InvalidOption, GetoptLong::MissingArgument => error
-        OptionList.error(error.message)
-
-      end
-    end
-
-    # Return the selected documentation directories.
-
-    def path
-      RI::Paths.path(@use_system, @use_site, @use_home, @use_gems, *@doc_dirs)
-    end
-
-    def raw_path
-      RI::Paths.raw_path(@use_system, @use_site, @use_home, @use_gems,
-                         *@doc_dirs)
-    end
-
-    # Return an instance of the displayer (the thing that actually writes
-    # the information). This allows us to load in new displayer classes
-    # at runtime (for example to help with IDE integration)
-    
-    def displayer
-      ::RiDisplay.new(self)
-    end
-  end
-
-end
-
Index: lib/rdoc/ri/ri_formatter.rb
===================================================================
--- lib/rdoc/ri/ri_formatter.rb	(revision 14949)
+++ lib/rdoc/ri/ri_formatter.rb	(revision 14950)
@@ -2,29 +2,28 @@
   class TextFormatter
 
     attr_reader :indent
-    
-    def initialize(options, indent)
-      @options = options
-      @width   = options.width
+
+    def initialize(width, indent)
+      @width   = width
       @indent  = indent
     end
-    
-    
+
+
     ######################################################################
-    
+
     def draw_line(label=nil)
       len = @width
       len -= (label.size+1) if label
       print "-"*len
       if label
         print(" ")
-        bold_print(label) 
+        bold_print(label)
       end
       puts
     end
-    
+
     ######################################################################
-    
+
     def wrap(txt,  prefix=@indent, linelen=@width)
       return unless txt && !txt.empty?
       work = conv_markup(txt)
@@ -51,7 +50,7 @@
     def blankline
       puts
     end
-    
+
     ######################################################################
 
     # called when we want to ensure a nbew 'wrap' starts on a newline
@@ -60,7 +59,7 @@
 
     def break_to_newline
     end
-    
+
     ######################################################################
 
     def bold_print(txt)
@@ -82,7 +81,7 @@
           gsub(/&lt;/, '<').
           gsub(/&quot;/, '"').
           gsub(/&amp;/, '&')
-          
+
     end
 
     # convert markup into display form
@@ -99,7 +98,7 @@
     def display_list(list)
       case list.type
 
-      when SM::ListBase::BULLET 
+      when SM::ListBase::BULLET
         prefixer = proc { |ignored| @indent + "*   " }
 
       when SM::ListBase::NUMBER,
@@ -116,7 +115,7 @@
           start = start.succ
           res
         end
-        
+
       when SM::ListBase::LABELED
         prefixer = proc do |li|
           li.label
@@ -156,7 +155,7 @@
       when SM::Flow::P, SM::Flow::LI
         wrap(conv_html(item.body), prefix)
         blankline
-        
+
       when SM::Flow::LIST
         display_list(item)
 
@@ -194,7 +193,7 @@
         puts text.upcase
         puts ul
 #        puts
-        
+
       when 2
         ul = "-" * text.length
         puts
@@ -215,7 +214,7 @@
 
     def strip_attributes(txt)
       tokens = txt.split(%r{(</?(?:b|code|em|i|tt)>)})
-      text = [] 
+      text = []
       attributes = 0
       tokens.each do |tok|
         case tok
@@ -230,16 +229,16 @@
 
 
   end
-  
-  
+
+
   ######################################################################
   # Handle text with attributes. We're a base class: there are
   # different presentation classes (one, for example, uses overstrikes
   # to handle bold and underlining, while another using ANSI escape
   # sequences
-  
+
   class AttributeFormatter < TextFormatter
-    
+
     BOLD      = 1
     ITALIC    = 2
     CODE      = 4
@@ -263,7 +262,7 @@
       end
     end
 
-    
+
     class AttributeString
       attr_reader :txt
 
@@ -363,7 +362,7 @@
 
 
   ##################################################
-  
+
   # This formatter generates overstrike-style formatting, which
   # works with pagers such as man and less.
 
@@ -395,7 +394,7 @@
   end
 
   ##################################################
-  
+
   # This formatter uses ANSI escape sequences
   # to colorize stuff
   # works with pages such as man and less.
@@ -441,7 +440,7 @@
       print strip_attributes(text)
       puts heading[1]
     end
-    
+
     private
 
     ATTR_MAP = {
@@ -462,7 +461,7 @@
   end
 
   ##################################################
-  
+
   # This formatter uses HTML.
 
   class HtmlFormatter < AttributeFormatter
@@ -508,13 +507,13 @@
       tag("h#{level}") { text }
       puts
     end
-    
+
     ######################################################################
 
     def display_list(list)
 
       case list.type
-      when SM::ListBase::BULLET 
+      when SM::ListBase::BULLET
         list_type = "ul"
         prefixer = proc { |ignored| "<li>" }
 
@@ -523,7 +522,7 @@
       SM::ListBase::LOWERALPHA
         list_type = "ol"
         prefixer = proc { |ignored| "<li>" }
-        
+
       when SM::ListBase::LABELED
         list_type = "dl"
         prefixer = proc do |li|
@@ -554,7 +553,9 @@
 
     def display_verbatim_flow_item(item, prefix=@indent)
         print("<pre>")
-        puts item.body
+        item.body.split(/\n/).each do |line|
+          puts conv_html(line)
+        end
         puts("</pre>")
     end
 
@@ -602,7 +603,7 @@
   end
 
   ##################################################
-  
+
   # This formatter reduces extra lines for a simpler output.
   # It improves way output looks for tools like IRC bots.
 
@@ -621,7 +622,7 @@
 
     def draw_line(label=nil)
       unless label.nil? then
-        bold_print(label) 
+        bold_print(label)
         puts
       end
     end
@@ -656,7 +657,7 @@
       "plain"  => TextFormatter,
       "simple" => SimpleFormatter,
     }
-      
+
     def TextFormatter.list
       FORMATTERS.keys.sort.join(", ")
     end
Index: lib/rdoc/ri/ri_display.rb
===================================================================
--- lib/rdoc/ri/ri_display.rb	(revision 14949)
+++ lib/rdoc/ri/ri_display.rb	(revision 14950)
@@ -1,13 +1,8 @@
-require 'rdoc/ri/ri_util'
-require 'rdoc/ri/ri_formatter'
-require 'rdoc/ri/ri_options'
-
-
 # This is a kind of 'flag' module. If you want to write your
 # own 'ri' display module (perhaps because you'r writing
 # an IDE or somesuch beast), you simply write a class
 # which implements the various 'display' methods in 'DefaultDisplay',
-# and include the 'RiDisplay' module in that class. 
+# and include the 'RiDisplay' module in that class.
 #
 # To access your class from the command line, you can do
 #
@@ -34,18 +29,17 @@
 # actual presentation
 #
 
-class  DefaultDisplay
+class DefaultDisplay
 
   include RiDisplay
 
-  def initialize(options)
-    @options = options
-    @formatter = @options.formatter.new(@options, "     ")
-  end    
-  
-  
+  def initialize(formatter, width, use_stdout)
+    @use_stdout = use_stdout
+    @formatter = formatter.new width, "     "
+  end
+
   ######################################################################
-  
+
   def display_usage
     page do
       RI::Options::OptionList.usage(short_form=true)
@@ -54,7 +48,7 @@
 
 
   ######################################################################
-  
+
   def display_method_info(method)
     page do
       @formatter.draw_line(method.full_name)
@@ -64,31 +58,31 @@
       if method.aliases && !method.aliases.empty?
         @formatter.blankline
         aka = "(also known as "
-        aka << method.aliases.map {|a| a.name }.join(", ") 
+        aka << method.aliases.map {|a| a.name }.join(", ")
         aka << ")"
         @formatter.wrap(aka)
       end
     end
   end
-  
+
   ######################################################################
-  
+
   def display_class_info(klass, ri_reader)
-    page do 
+    page do
       superclass = klass.superclass_string
-      
+
       if superclass
         superclass = " < " + superclass
       else
         superclass = ""
       end
-      
+
       @formatter.draw_line(klass.display_name + ": " +
                            klass.full_name + superclass)
-      
+
       display_flow(klass.comment)
-      @formatter.draw_line 
-    
+      @formatter.draw_line
+
       unless klass.includes.empty?
         @formatter.blankline
         @formatter.display_heading("Includes:", 2, "")
@@ -106,7 +100,7 @@
       end
         @formatter.wrap(incs.sort.join(', '))
       end
-      
+
       unless klass.constants.empty?
         @formatter.blankline
         @formatter.display_heading("Constants:", 2, "")
@@ -114,23 +108,35 @@
         klass.constants.each { |c| len = c.name.length if c.name.length > len }
         len += 2
         klass.constants.each do |c|
-          @formatter.wrap(c.value, 
+          @formatter.wrap(c.value,
                           @formatter.indent+((c.name+":").ljust(len)))
-        end 
+        end
       end
-      
+
       unless klass.class_methods.empty?
         @formatter.blankline
         @formatter.display_heading("Class methods:", 2, "")
         @formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
       end
-      
+
+      unless klass.class_method_extensions.empty?
+        @formatter.blankline
+        @formatter.display_heading("Class Method Extensions:", 2, "")
+        @formatter.wrap(klass.class_method_extensions.map{|m| m.name}.sort.join(', '))
+      end
+
       unless klass.instance_methods.empty?
         @formatter.blankline
         @formatter.display_heading("Instance methods:", 2, "")
         @formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
       end
-      
+
+      unless klass.instance_method_extensions.empty?
+        @formatter.blankline
+        @formatter.display_heading("Instance Method Extensions:", 2, "")
+        @formatter.wrap(klass.instance_method_extensions.map{|m| m.name}.sort.join(', '))
+      end
+
       unless klass.attributes.empty?
         @formatter.blankline
         @formatter.wrap("Attributes:", "")
@@ -138,11 +144,11 @@
       end
     end
   end
-  
+
   ######################################################################
-  
+
   # Display a list of method names
-  
+
   def display_method_list(methods)
     page do
       puts "More than one method matched your request. You can refine"
@@ -150,9 +156,9 @@
       @formatter.wrap(methods.map {|m| m.full_name} .join(", "))
     end
   end
-  
+
   ######################################################################
-  
+
   def display_class_list(namespaces)
     page do
       puts "More than one class or module matched your request. You can refine"
@@ -160,14 +166,14 @@
       @formatter.wrap(namespaces.map {|m| m.full_name}.join(", "))
     end
   end
-  
+
   ######################################################################
 
   def list_known_classes(classes)
     if classes.empty?
       warn_no_database
     else
-      page do 
+      page do
         @formatter.draw_line("Known classes and modules")
         @formatter.blankline
         @formatter.wrap(classes.sort.join(", "))
@@ -181,7 +187,7 @@
     if names.empty?
       warn_no_database
     else
-      page do 
+      page do
         names.each {|n| @formatter.raw_print_line(n)}
       end
     end
@@ -194,34 +200,36 @@
   ######################################################################
 
   def page
-    return yield unless pager = setup_pager
-    begin
-      save_stdout = STDOUT.clone
-      STDOUT.reopen(pager)
+    if pager = setup_pager then
+      begin
+        orig_stdout = $stdout
+        $stdout = pager
+        yield
+      ensure
+        $stdout = orig_stdout
+        pager.close
+      end
+    else
       yield
-    ensure
-      STDOUT.reopen(save_stdout)
-      save_stdout.close
-      pager.close
     end
+  rescue Errno::EPIPE
   end
 
   ######################################################################
 
   def setup_pager
-    unless @options.use_stdout
+    unless @use_stdout then
       for pager in [ ENV['PAGER'], "less", "more", 'pager' ].compact.uniq
         return IO.popen(pager, "w") rescue nil
       end
-      @options.use_stdout = true
+      @use_stdout = true
       nil
     end
   end
 
   ######################################################################
-  
+
   def display_params(method)
-
     params = method.params
 
     if params[0,1] == "("
@@ -232,13 +240,16 @@
       end
     end
     params.split(/\n/).each do |p|
-      @formatter.wrap(p) 
+      @formatter.wrap(p)
       @formatter.break_to_newline
     end
+    if method.source_path then
+      @formatter.blankline
+      @formatter.wrap("Extension from #{method.source_path}")
+    end
   end
+  ######################################################################
 
-  ######################################################################
-  
   def display_flow(flow)
     if !flow || flow.empty?
       @formatter.wrap("(no description...)")
@@ -248,9 +259,17 @@
   end
 
   ######################################################################
-  
+
   def warn_no_database
-    puts "Before using ri, you need to generate documentation"
-    puts "using 'rdoc' with the --ri option"
+    puts "No ri data found"
+    puts
+    puts "If you've installed Ruby yourself, you need to generate documentation using:"
+    puts
+    puts "  make install-doc"
+    puts
+    puts "from the same place you ran `make` to build ruby."
+    puts
+    puts "If you installed Ruby from a packaging system, then you may need to"
+    puts "install an additional package, or ask the packager to enable ri generation."
   end
 end  # class RiDisplay
Index: lib/rdoc/ri/ri_driver.rb
===================================================================
--- lib/rdoc/ri/ri_driver.rb	(revision 14949)
+++ lib/rdoc/ri/ri_driver.rb	(revision 14950)
@@ -1,143 +1,424 @@
+require 'optparse'
+require 'yaml'
+
+require 'rdoc/ri'
 require 'rdoc/ri/ri_paths'
-require 'rdoc/usage'
-require 'rdoc/ri/ri_cache'
-require 'rdoc/ri/ri_util'
-require 'rdoc/ri/ri_reader'
 require 'rdoc/ri/ri_formatter'
-require 'rdoc/ri/ri_options'
+require 'rdoc/ri/ri_display'
+require 'fileutils'
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_flow'
 
+class RDoc::RI::RiDriver
+  
+  def self.process_args(argv)
+    options = {}
+    options[:use_stdout] = !$stdout.tty?
+    options[:width] = 72
+    options[:formatter] = RI::TextFormatter.for 'plain'
+    options[:list_classes] = false
+    options[:list_names] = false
 
-######################################################################
+    # By default all paths are used.  If any of these are true, only those
+    # directories are used.
+    use_system = false
+    use_site = false
+    use_home = false
+    use_gems = false
+    doc_dirs = []
 
-class  RiDriver
+    opts = OptionParser.new do |opt|
+      opt.program_name = File.basename $0
+      opt.version = RDoc::VERSION
+      opt.summary_indent = ' ' * 4
 
-  def initialize
-    @options = RI::Options.instance
+      directories = [
+        RI::Paths::SYSDIR,
+        RI::Paths::SITEDIR,
+        RI::Paths::HOMEDIR
+      ]
 
-    args = ARGV
-    if ENV["RI"]
-      args = ENV["RI"].split.concat(ARGV)
+      if RI::Paths::GEMDIRS then
+        Gem.path.each do |dir|
+          directories << "#{dir}/doc/*/ri"
+        end
+      end
+
+      opt.banner = <<-EOT
+Usage: #{opt.program_name} [options] [names...]
+
+Where name can be:
+
+  Class | Class::method | Class#method | Class.method | method
+
+All class names may be abbreviated to their minimum unambiguous form. If a name
+is ambiguous, all valid options will be listed.
+
+The form '.' method matches either class or instance methods, while 
+#method matches only instance and ::method matches only class methods.
+
+For example:
+
+    #{opt.program_name} Fil
+    #{opt.program_name} File
+    #{opt.program_name} File.new
+    #{opt.program_name} zip
+
+Note that shell quoting may be required for method names containing
+punctuation:
+
+    #{opt.program_name} 'Array.[]'
+    #{opt.program_name} compact\\!
+
+By default ri searches for documentation in the following directories:
+
+    #{directories.join "\n    "}
+
+Specifying the --system, --site, --home, --gems or --doc-dir options will
+limit ri to searching only the specified directories.
+
+Options may also be set in the 'RI' environment variable.
+      EOT
+
+      opt.separator nil
+      opt.separator "Options:"
+      opt.separator nil
+
+      opt.on("--classes", "-c",
+             "Display the names of classes and modules we",
+             "know about.") do |value|
+        options[:list_classes] = value
+      end
+
+      opt.separator nil
+
+      opt.on("--doc-dir=DIRNAME", "-d", Array,
+             "List of directories to search for",
+             "documentation. If not specified, we search",
+             "the standard rdoc/ri directories. May be",
+             "repeated.") do |value|
+        value.each do |dir|
+          unless File.directory? dir then
+            raise OptionParser::InvalidArgument, "#{dir} is not a directory"
+          end
+        end
+
+        doc_dirs.concat value
+      end
+
+      opt.separator nil
+
+      opt.on("--fmt=FORMAT", "--format=FORMAT", "-f",
+             RI::TextFormatter.list.split(', '), # HACK
+             "Format to use when displaying output:",
+             "   #{RI::TextFormatter.list}",
+             "Use 'bs' (backspace) with most pager",
+             "programs. To use ANSI, either disable the",
+             "pager or tell the pager to allow control",
+             "characters.") do |value|
+        options[:formatter] = RI::TextFormatter.for value
+      end
+
+      opt.separator nil
+
+      if RI::Paths::GEMDIRS then
+        opt.on("--[no-]gems",
+               "Include documentation from RubyGems.") do |value|
+          use_gems = value
+        end
+      end
+
+      opt.separator nil
+
+      opt.on("--[no-]home",
+             "Include documentation stored in ~/.rdoc.") do |value|
+        use_home = value
+      end
+
+      opt.separator nil
+
+      opt.on("--[no-]list-names", "-l",
+             "List all the names known to RDoc, one per",
+             "line.") do |value|
+        options[:list_names] = value
+      end
+
+      opt.separator nil
+
+      opt.on("--no-pager", "-T",
+             "Send output directly to stdout.") do |value|
+        options[:use_stdout] = !value
+      end
+
+      opt.separator nil
+
+      opt.on("--[no-]site",
+             "Include documentation from libraries",
+             "installed in site_lib.") do |value|
+        use_site = value
+      end
+
+      opt.separator nil
+
+      opt.on("--[no-]system",
+             "Include documentation from Ruby's standard",
+             "library.") do |value|
+        use_system = value
+      end
+
+      opt.separator nil
+
+      opt.on("--width=WIDTH", "-w", OptionParser::DecimalInteger,
+             "Set the width of the output.") do |value|
+        options[:width] = value
+      end
     end
 
-    @options.parse(args)
+    argv = ENV['RI'].to_s.split.concat argv
 
-    path = @options.path
-    report_missing_documentation @options.raw_path if path.empty?
+    opts.parse! argv
 
-    @ri_reader = RI::RiReader.new(RI::RiCache.new(path))
-    @display   = @options.displayer
+    options[:names] = argv
+
+    options[:path] = RI::Paths.path(use_system, use_site, use_home, use_gems,
+                                    *doc_dirs)
+    options[:raw_path] = RI::Paths.raw_path(use_system, use_site, use_home,
+                                            use_gems, *doc_dirs)
+
+    options
+
+  rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e
+    puts opts
+    puts
+    puts e
+    exit 1
   end
-  
-  # Couldn't find documentation in +path+, so tell the user what to do
 
-  def report_missing_documentation(path)
-    STDERR.puts "No ri documentation found in:"
-    path.each do |d|
-      STDERR.puts "     #{d}"
-    end
-    STDERR.puts "\nWas rdoc run to create documentation?\n\n"
-    RDoc::usage("Installing Documentation")
+  def self.run(argv = ARGV)
+    options = process_args argv
+    ri = new options
+    ri.run
   end
-  
-  ######################################################################
-  
-  # If the list of matching methods contains exactly one entry, or
-  # if it contains an entry that exactly matches the requested method,
-  # then display that entry, otherwise display the list of
-  # matching method names
-  
-  def report_method_stuff(requested_method_name, methods)
-    if methods.size == 1
-      method = @ri_reader.get_method(methods[0])
-      @display.display_method_info(method)
-    else
-      entries = methods.find_all {|m| m.name == requested_method_name}
-      if entries.size == 1
-        method = @ri_reader.get_method(entries[0])
-        @display.display_method_info(method)
-      else
-        @display.display_method_list(methods)
-      end
-    end
+
+  def initialize(options)
+    @names = options[:names]
+
+    @class_cache_name = 'classes'
+    @all_dirs = RI::Paths.path(true, true, true, true)
+    @homepath = RI::Paths.raw_path(false, false, true, false).first
+    @homepath = @homepath.sub(/\.rdoc/, '.ri')
+    @sys_dirs = RI::Paths.raw_path(true, false, false, false)
+
+    FileUtils.mkdir_p cache_file_path unless File.directory? cache_file_path
+
+    @class_cache = nil
+
+    @display = DefaultDisplay.new(options[:formatter], options[:width],
+                                  options[:use_stdout])
   end
-  
-  ######################################################################
-  
-  def report_class_stuff(namespaces)
-    if namespaces.size == 1
-      klass = @ri_reader.get_class(namespaces[0])
-      @display.display_class_info(klass, @ri_reader)
-    else 
-#      entries = namespaces.find_all {|m| m.full_name == requested_class_name}
-#      if entries.size == 1
-#        klass = @ri_reader.get_class(entries[0])
-#        @display.display_class_info(klass, @ri_reader)
-#      else
-        @display.display_class_list(namespaces)
-#      end
-    end
+
+  def class_cache
+    return @class_cache if @class_cache
+
+    newest = map_dirs('created.rid', :all) do |f|
+      File.mtime f if test ?f, f 
+    end.max
+
+    up_to_date = (File.exist?(class_cache_file_path) and
+                  newest < File.mtime(class_cache_file_path))
+
+    @class_cache = if up_to_date then
+                     load_cache_for @class_cache_name
+                   else
+                     class_cache = {}
+
+                     classes = map_dirs('**/cdesc*.yaml', :sys) { |f| Dir[f] }
+                     populate_class_cache class_cache, classes
+
+                     classes = map_dirs('**/cdesc*.yaml') { |f| Dir[f] }
+                     warn "Updating class cache with #{classes.size} classes..."
+
+                     populate_class_cache class_cache, classes, true
+                     write_cache class_cache, class_cache_file_path
+                   end
   end
-  
-  ######################################################################
-  
-  
-  def get_info_for(arg)
-    desc = NameDescriptor.new(arg)
 
-    namespaces = @ri_reader.top_level_namespace
-    
-    for class_name in desc.class_names
-      namespaces = @ri_reader.lookup_namespace_in(class_name, namespaces)
-      if namespaces.empty?
-        raise RiError.new("Nothing known about #{arg}")
+  def class_cache_file_path
+    File.join cache_file_path, @class_cache_name
+  end
+
+  def cache_file_for(klassname)
+    File.join cache_file_path, klassname
+  end
+
+  def cache_file_path
+    File.join @homepath, 'cache'
+  end
+
+  def display_class(name)
+    klass = class_cache[name]
+    @display.display_class_info klass, class_cache
+  end
+
+  def load_cache_for(klassname)
+    path = cache_file_for klassname
+
+    if File.exist? path and
+       File.mtime(path) >= File.mtime(class_cache_file_path) then
+      File.open path, 'rb' do |fp|
+        Marshal.load fp
       end
+    else
+      class_cache = nil
+
+      File.open class_cache_file_path, 'rb' do |fp|
+        class_cache = Marshal.load fp
+      end
+
+      klass = class_cache[klassname]
+      return nil unless klass
+
+      method_files = klass["sources"]
+      cache = {}
+
+      sys_dir = @sys_dirs.first
+      method_files.each do |f|
+        system_file = f.index(sys_dir) == 0
+        Dir[File.join(File.dirname(f), "*")].each do |yaml|
+          next unless yaml =~ /yaml$/
+          next if yaml =~ /cdesc-[^\/]+yaml$/
+          method = read_yaml yaml
+          name = method["full_name"]
+          ext_path = f
+          ext_path = "gem #{$1}" if f =~ %r%gems/[\d.]+/doc/([^/]+)%
+          method["source_path"] = ext_path unless system_file
+          cache[name] = method
+        end
+      end
+
+      write_cache cache, path
     end
+  end
 
-    # at this point, if we have multiple possible namespaces, but one
-    # is an exact match for our requested class, prune down to just it
+  def map_dirs(file_name, system=false)
+    dirs = if system == :all then
+             @all_dirs
+           else
+             if system then
+               @sys_dirs
+             else
+               @all_dirs - @sys_dirs
+             end
+           end
 
-    full_class_name = desc.full_class_name
-    entries = namespaces.find_all {|m| m.full_name == full_class_name}
-    namespaces = entries if entries.size == 1
+    dirs.map { |dir| yield File.join(dir, file_name) }.flatten.compact
+  end
 
-    if desc.method_name.nil?
-      report_class_stuff(namespaces)
-    else
-      methods = @ri_reader.find_methods(desc.method_name, 
-                                        desc.is_class_method,
-                                        namespaces)
+  def populate_class_cache(class_cache, classes, extension = false)
+    classes.each do |cdesc|
+      desc = read_yaml cdesc
+      klassname = desc["full_name"]
 
-      if methods.empty?
-        raise RiError.new("Nothing known about #{arg}")
+      unless class_cache.has_key? klassname then
+        desc["display_name"] = "Class"
+        desc["sources"] = [cdesc]
+        desc["instance_method_extensions"] = []
+        desc["class_method_extensions"] = []
+        class_cache[klassname] = desc
       else
-        report_method_stuff(desc.method_name, methods)
+        klass = class_cache[klassname]
+
+        if extension then
+          desc["instance_method_extensions"] = desc.delete "instance_methods"
+          desc["class_method_extensions"] = desc.delete "class_methods"
+        end
+
+        klass.merge_enums desc
+        klass["sources"] << cdesc
       end
     end
   end
 
-  ######################################################################
+  def read_yaml(path)
+    YAML.load File.read(path).gsub(/ \!ruby\/(object|struct):RI.*/, '')
+  end
 
-  def process_args
-    if @options.list_classes
-      classes = @ri_reader.full_class_names
-      @display.list_known_classes(classes)
-    elsif @options.list_names
-      names = @ri_reader.all_names
-      @display.list_known_names(names)
+  def run
+    if @names.empty? then
+      @display.list_known_classes select_classes
     else
-      if ARGV.size.zero?
-        @display.display_usage
-      else
-        begin
-          ARGV.each do |arg|
-            get_info_for(arg)
+      @names.each do |name|
+        case name
+        when /::|\#|\./ then
+          if class_cache.key? name then
+            display_class name
+          else
+            klass, meth = name.split(/::|\#|\./)
+            cache = load_cache_for klass
+            # HACK Does not support F.n
+            abort "Nothing known about #{name}" unless cache
+            method = cache[name.gsub(/\./, '#')]
+            abort "Nothing known about #{name}" unless method
+            @display.display_method_info method
           end
-        rescue RiError => e
-          STDERR.puts(e.message)
-          exit(1)
+        else
+          if class_cache.key? name then
+            display_class name
+          else
+            @display.list_known_classes select_classes(/^#{name}/)
+          end
         end
       end
     end
   end
+  
+  def select_classes(pattern = nil)
+    classes = class_cache.keys.sort
+    classes = classes.grep pattern if pattern
+    classes
+  end
 
-end  # class RiDriver
+  def write_cache(cache, path)
+    File.open path, "wb" do |cache_file|
+      Marshal.dump cache, cache_file
+    end
+
+    cache
+  end
+
+  # Couldn't find documentation in +path+, so tell the user what to do
+
+  def report_missing_documentation(path)
+    STDERR.puts "No ri documentation found in:"
+    path.each do |d|
+      STDERR.puts "     #{d}"
+    end
+    STDERR.puts "\nWas rdoc run to create documentation?\n\n"
+    RDoc::usage("Installing Documentation")
+  end
+
+end
+
+class Hash
+  def method_missing method, *args
+    self[method.to_s]
+  end
+
+  def merge_enums(other)
+    other.each do |k,v|
+      if self[k] then
+        case v
+        when Array then
+          self[k] += v
+        when Hash then
+          self[k].merge! v
+        else
+          # do nothing
+        end
+      else
+        self[k] = v
+      end
+    end
+  end
+end
+
Index: lib/rdoc/ri/ri_paths.rb
===================================================================
--- lib/rdoc/ri/ri_paths.rb	(revision 14949)
+++ lib/rdoc/ri/ri_paths.rb	(revision 14950)
@@ -23,7 +23,7 @@
 
     #:stopdoc:
     require 'rbconfig'
-    
+
     DOC_DIR  = "doc/rdoc"
 
     version = RbConfig::CONFIG['ruby_version']
@@ -42,7 +42,7 @@
     # This is the search path for 'ri'
     PATH = [ SYSDIR, SITEDIR, HOMEDIR ].find_all {|p| p && File.directory?(p)}
 
-    require 'rubygems'
+    require 'rubygems' unless defined?(Gem) and Gem::Enable
 
     # HACK dup'd from Gem.latest_partials and friends
     all_paths = []
Index: lib/rdoc/ri.rb
===================================================================
--- lib/rdoc/ri.rb	(revision 0)
+++ lib/rdoc/ri.rb	(revision 14950)
@@ -0,0 +1,4 @@
+require 'rdoc'
+
+module RDoc::RI; end
+
Index: lib/rdoc/template.rb
===================================================================
--- lib/rdoc/template.rb	(revision 14949)
+++ lib/rdoc/template.rb	(revision 14950)
@@ -48,10 +48,9 @@
   # Process the template using +values+, writing the result to +io+.
 
   def write_html_on(io, values)
+    b = binding
     template_include = ""
 
-    b = binding
-
     @templates.reverse_each do |template|
       template_include = ERB.new(template).result b
     end
Index: bin/ri
===================================================================
--- bin/ri	(revision 14949)
+++ bin/ri	(revision 14950)
@@ -1,49 +1,6 @@
-#!/usr/bin/env ruby
-# usage:
-#
-#   ri  name...
-#
-# where name can be 
-#
-#   Class | Class::method | Class#method | Class.method | method
-#
-# All names may be abbreviated to their minimum unambiguous form. If a name
-# _is_ ambiguous, all valid options will be listed.
-#
-# The form '.' method matches either class or instance methods, while 
-# #method matches only instance and ::method matches only class methods.
-#
-#
-# == Installing Documentation
-#
-# 'ri' uses a database of documentation built by the RDoc utility.
-# 
-# So, how do you install this documentation on your system?
-# It depends on how you installed Ruby.
-#
-# <em>If you installed Ruby from source files</em> (that is, if it some point
-# you typed 'make' during the process :), you can install the RDoc
-# documentation yourself. Just go back to the place where you have 
-# your Ruby source and type
-#
-#    make install-doc
-#
-# You'll probably need to do this as a superuser, as the documentation
-# is installed in the Ruby target tree (normally somewhere under 
-# <tt>/usr/local</tt>.
-#
-# <em>If you installed Ruby from a binary distribution</em> (perhaps
-# using a one-click installer, or using some other packaging system),
-# then the team that produced the package probably forgot to package
-# the documentation as well. Contact them, and see if they can add
-# it to the next release.
-#
+#!/usr//bin/env ruby
 
-
 require 'rdoc/ri/ri_driver'
 
-######################################################################
+RDoc::RI::RiDriver.run ARGV
 
-ri = RiDriver.new
-ri.process_args
-

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧]