mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	Finish documenting internal stuff. See Changelog for other details
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5364 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									eee1377a60
								
							
						
					
					
						commit
						88c127c19b
					
				
					 20 changed files with 1453 additions and 266 deletions
				
			
		
							
								
								
									
										407
									
								
								bin/ri
									
										
									
									
									
								
							
							
						
						
									
										407
									
								
								bin/ri
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -20,17 +20,6 @@ require 'rdoc/ri/ri_reader'
 | 
			
		|||
require 'rdoc/ri/ri_formatter'
 | 
			
		||||
require 'rdoc/ri/ri_options'
 | 
			
		||||
 | 
			
		||||
######################################################################
 | 
			
		||||
 | 
			
		||||
def display_usage
 | 
			
		||||
  RI::Options::OptionList.usage(short_form=true)
 | 
			
		||||
#  File.open(__FILE__) do |f|
 | 
			
		||||
#    f.gets
 | 
			
		||||
#    puts $1 while (f.gets =~ /^# ?(.*)/)
 | 
			
		||||
#  end
 | 
			
		||||
#  exit
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
######################################################################
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -53,31 +42,43 @@ class  RiDisplay
 | 
			
		|||
  end    
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  ######################################################################
 | 
			
		||||
  
 | 
			
		||||
  def display_usage
 | 
			
		||||
    setup_pager
 | 
			
		||||
    RI::Options::OptionList.usage(short_form=true)
 | 
			
		||||
    page_output
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ######################################################################
 | 
			
		||||
 | 
			
		||||
  def setup_pager
 | 
			
		||||
    require 'tempfile'
 | 
			
		||||
    unless @options.use_stdout
 | 
			
		||||
      require 'tempfile'
 | 
			
		||||
 | 
			
		||||
    @save_stdout = STDOUT.clone
 | 
			
		||||
    STDOUT.reopen(Tempfile.new("ri_"))
 | 
			
		||||
      @save_stdout = STDOUT.clone
 | 
			
		||||
      STDOUT.reopen(Tempfile.new("ri_"))
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ######################################################################
 | 
			
		||||
 | 
			
		||||
  def page_output
 | 
			
		||||
    path = STDOUT.path
 | 
			
		||||
    STDOUT.reopen(@save_stdout)
 | 
			
		||||
    @save_stdout = nil
 | 
			
		||||
    paged = false
 | 
			
		||||
    for pager in [ ENV['PAGER'], "less", "more <", 'pager' ].compact.uniq
 | 
			
		||||
      if system("#{pager} #{path}")
 | 
			
		||||
        paged = true
 | 
			
		||||
        break
 | 
			
		||||
    unless @options.use_stdout
 | 
			
		||||
      path = STDOUT.path
 | 
			
		||||
      STDOUT.reopen(@save_stdout)
 | 
			
		||||
      @save_stdout = nil
 | 
			
		||||
      paged = false
 | 
			
		||||
      for pager in [ ENV['PAGER'], "less", "more <", 'pager' ].compact.uniq
 | 
			
		||||
        if system("#{pager} #{path}")
 | 
			
		||||
          paged = true
 | 
			
		||||
          break
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      if !paged
 | 
			
		||||
        @options.use_stdout = true
 | 
			
		||||
        puts File.read(path)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    if !paged
 | 
			
		||||
      @options.use_stdout = true
 | 
			
		||||
      puts File.read(path)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -107,171 +108,209 @@ class  RiDisplay
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
######################################################################
 | 
			
		||||
 | 
			
		||||
def display_method_info(method_entry)
 | 
			
		||||
  method = @ri_reader.get_method(method_entry)
 | 
			
		||||
  @formatter.draw_line(method.full_name)
 | 
			
		||||
  display_params(method)
 | 
			
		||||
  @formatter.draw_line
 | 
			
		||||
  display_flow(method.comment)
 | 
			
		||||
  if method.aliases && !method.aliases.empty?
 | 
			
		||||
    @formatter.blankline
 | 
			
		||||
    aka = "(also known as "
 | 
			
		||||
    aka << method.aliases.map {|a| a.name }.join(", ") 
 | 
			
		||||
    aka << ")"
 | 
			
		||||
    @formatter.wrap(aka)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
######################################################################
 | 
			
		||||
 | 
			
		||||
def display_class_info(class_entry)
 | 
			
		||||
  klass = @ri_reader.get_class(class_entry)
 | 
			
		||||
  @formatter.draw_line(klass.display_name + ": " + klass.full_name)
 | 
			
		||||
  display_flow(klass.comment)
 | 
			
		||||
  @formatter.draw_line
 | 
			
		||||
 | 
			
		||||
  unless klass.includes.empty?
 | 
			
		||||
    @formatter.blankline
 | 
			
		||||
    @formatter.display_heading("Includes:", 2, "")
 | 
			
		||||
    incs = []
 | 
			
		||||
    klass.includes.each do |inc|
 | 
			
		||||
      inc_desc = @ri_reader.find_class_by_name(inc.name)
 | 
			
		||||
      if inc_desc
 | 
			
		||||
        str = inc.name + "("
 | 
			
		||||
        str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
 | 
			
		||||
        str << ")"
 | 
			
		||||
        incs << str
 | 
			
		||||
      else
 | 
			
		||||
        incs << inc.name
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    @formatter.wrap(incs.sort.join(', '))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  unless klass.constants.empty?
 | 
			
		||||
    @formatter.blankline
 | 
			
		||||
    @formatter.display_heading("Constants:", 2, "")
 | 
			
		||||
    len = 0
 | 
			
		||||
    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.indent+((c.name+":").ljust(len)))
 | 
			
		||||
    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.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.attributes.empty?
 | 
			
		||||
    @formatter.blankline
 | 
			
		||||
    @formatter.wrap("Attributes:", "")
 | 
			
		||||
    @formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
 | 
			
		||||
  end
 | 
			
		||||
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
 | 
			
		||||
    display_method_info(methods[0])
 | 
			
		||||
  else
 | 
			
		||||
    entries = methods.find_all {|m| m.name == requested_method_name}
 | 
			
		||||
    if entries.size == 1
 | 
			
		||||
      display_method_info(entries[0])
 | 
			
		||||
    else
 | 
			
		||||
      puts "More than one method matched your request. You can refine"
 | 
			
		||||
      puts "your search by asking for information on one of:\n\n"
 | 
			
		||||
      @formatter.wrap(methods.map {|m| m.full_name} .join(", "))
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
######################################################################
 | 
			
		||||
 | 
			
		||||
def report_class_stuff(requested_class_name, namespaces)
 | 
			
		||||
  if namespaces.size == 1
 | 
			
		||||
    display_class_info(namespaces[0])
 | 
			
		||||
  else 
 | 
			
		||||
    entries = namespaces.find_all {|m| m.full_name == requested_class_name}
 | 
			
		||||
    if entries.size == 1
 | 
			
		||||
      display_class_info(entries[0])
 | 
			
		||||
    else
 | 
			
		||||
      puts "More than one class or module matched your request. You can refine"
 | 
			
		||||
      puts "your search by asking for information on one of:\n\n"
 | 
			
		||||
      @formatter.wrap(namespaces.map {|m| m.full_name}.join(", "))
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
######################################################################
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def display_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}")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  setup_pager unless @options.use_stdout
 | 
			
		||||
  ######################################################################
 | 
			
		||||
  
 | 
			
		||||
  begin
 | 
			
		||||
    if desc.method_name.nil?
 | 
			
		||||
      report_class_stuff(desc.class_names.join('::'), namespaces)
 | 
			
		||||
  def display_method_info(method_entry)
 | 
			
		||||
    method = @ri_reader.get_method(method_entry)
 | 
			
		||||
    @formatter.draw_line(method.full_name)
 | 
			
		||||
    display_params(method)
 | 
			
		||||
    @formatter.draw_line
 | 
			
		||||
    display_flow(method.comment)
 | 
			
		||||
    if method.aliases && !method.aliases.empty?
 | 
			
		||||
      @formatter.blankline
 | 
			
		||||
      aka = "(also known as "
 | 
			
		||||
      aka << method.aliases.map {|a| a.name }.join(", ") 
 | 
			
		||||
      aka << ")"
 | 
			
		||||
      @formatter.wrap(aka)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  ######################################################################
 | 
			
		||||
  
 | 
			
		||||
  def display_class_info(class_entry)
 | 
			
		||||
    klass = @ri_reader.get_class(class_entry)
 | 
			
		||||
    superclass = klass.superclass_string
 | 
			
		||||
    
 | 
			
		||||
    if superclass
 | 
			
		||||
      superclass = " < " + superclass
 | 
			
		||||
    else
 | 
			
		||||
      methods = @ri_reader.find_methods(desc.method_name, 
 | 
			
		||||
                                        desc.is_class_method,
 | 
			
		||||
                                        namespaces)
 | 
			
		||||
      
 | 
			
		||||
      if methods.empty?
 | 
			
		||||
        raise RiError.new("Nothing known about #{arg}")
 | 
			
		||||
      superclass = ""
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    @formatter.draw_line(klass.display_name + ": " +
 | 
			
		||||
                         klass.full_name + superclass)
 | 
			
		||||
    
 | 
			
		||||
    display_flow(klass.comment)
 | 
			
		||||
    @formatter.draw_line
 | 
			
		||||
    
 | 
			
		||||
    unless klass.includes.empty?
 | 
			
		||||
      @formatter.blankline
 | 
			
		||||
      @formatter.display_heading("Includes:", 2, "")
 | 
			
		||||
      incs = []
 | 
			
		||||
      klass.includes.each do |inc|
 | 
			
		||||
        inc_desc = @ri_reader.find_class_by_name(inc.name)
 | 
			
		||||
        if inc_desc
 | 
			
		||||
          str = inc.name + "("
 | 
			
		||||
          str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
 | 
			
		||||
          str << ")"
 | 
			
		||||
          incs << str
 | 
			
		||||
        else
 | 
			
		||||
          incs << inc.name
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    @formatter.wrap(incs.sort.join(', '))
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    unless klass.constants.empty?
 | 
			
		||||
      @formatter.blankline
 | 
			
		||||
      @formatter.display_heading("Constants:", 2, "")
 | 
			
		||||
      len = 0
 | 
			
		||||
      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.indent+((c.name+":").ljust(len)))
 | 
			
		||||
      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.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.attributes.empty?
 | 
			
		||||
      @formatter.blankline
 | 
			
		||||
      @formatter.wrap("Attributes:", "")
 | 
			
		||||
      @formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
 | 
			
		||||
    end
 | 
			
		||||
  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
 | 
			
		||||
      display_method_info(methods[0])
 | 
			
		||||
    else
 | 
			
		||||
      entries = methods.find_all {|m| m.name == requested_method_name}
 | 
			
		||||
      if entries.size == 1
 | 
			
		||||
        display_method_info(entries[0])
 | 
			
		||||
      else
 | 
			
		||||
        report_method_stuff(desc.method_name, methods)
 | 
			
		||||
        puts "More than one method matched your request. You can refine"
 | 
			
		||||
        puts "your search by asking for information on one of:\n\n"
 | 
			
		||||
        @formatter.wrap(methods.map {|m| m.full_name} .join(", "))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    page_output unless @options.use_stdout
 | 
			
		||||
  ensure
 | 
			
		||||
    STDOUT.reopen(@save_stdout) if @save_stdout
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  ######################################################################
 | 
			
		||||
  
 | 
			
		||||
  def report_class_stuff(requested_class_name, namespaces)
 | 
			
		||||
    if namespaces.size == 1
 | 
			
		||||
      display_class_info(namespaces[0])
 | 
			
		||||
    else 
 | 
			
		||||
      entries = namespaces.find_all {|m| m.full_name == requested_class_name}
 | 
			
		||||
      if entries.size == 1
 | 
			
		||||
        display_class_info(entries[0])
 | 
			
		||||
      else
 | 
			
		||||
        puts "More than one class or module matched your request. You can refine"
 | 
			
		||||
        puts "your search by asking for information on one of:\n\n"
 | 
			
		||||
        @formatter.wrap(namespaces.map {|m| m.full_name}.join(", "))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  ######################################################################
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  def display_info_for(arg)
 | 
			
		||||
    desc = NameDescriptor.new(arg)
 | 
			
		||||
    
 | 
			
		||||
end
 | 
			
		||||
end
 | 
			
		||||
    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}")
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    setup_pager
 | 
			
		||||
    
 | 
			
		||||
    begin
 | 
			
		||||
      if desc.method_name.nil?
 | 
			
		||||
        report_class_stuff(desc.class_names.join('::'), namespaces)
 | 
			
		||||
      else
 | 
			
		||||
        methods = @ri_reader.find_methods(desc.method_name, 
 | 
			
		||||
                                          desc.is_class_method,
 | 
			
		||||
                                          namespaces)
 | 
			
		||||
        
 | 
			
		||||
        if methods.empty?
 | 
			
		||||
          raise RiError.new("Nothing known about #{arg}")
 | 
			
		||||
        else
 | 
			
		||||
          report_method_stuff(desc.method_name, methods)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      
 | 
			
		||||
      page_output
 | 
			
		||||
    ensure
 | 
			
		||||
      STDOUT.reopen(@save_stdout) if @save_stdout
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ######################################################################
 | 
			
		||||
 | 
			
		||||
  def process_args
 | 
			
		||||
    if @options.list_classes
 | 
			
		||||
      display_class_list
 | 
			
		||||
    else
 | 
			
		||||
      if ARGV.size.zero?
 | 
			
		||||
        display_usage
 | 
			
		||||
      else
 | 
			
		||||
        begin
 | 
			
		||||
          ARGV.each do |arg|
 | 
			
		||||
            display_info_for(arg)
 | 
			
		||||
          end
 | 
			
		||||
        rescue RiError => e
 | 
			
		||||
          $stderr.puts(e.message)
 | 
			
		||||
          exit(1)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ######################################################################
 | 
			
		||||
 | 
			
		||||
  def display_class_list
 | 
			
		||||
    classes = @ri_reader.class_names
 | 
			
		||||
    if classes.empty?
 | 
			
		||||
      puts "Before using ri, you need to generate documentation"
 | 
			
		||||
      puts "using 'rdoc' with the --ri option"
 | 
			
		||||
    else
 | 
			
		||||
      setup_pager
 | 
			
		||||
      @formatter.draw_line("Known classes and modules")
 | 
			
		||||
      @formatter.blankline
 | 
			
		||||
      @formatter.wrap(@ri_reader.class_names.sort.join(", "))
 | 
			
		||||
      page_output
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end  # class RiDisplay
 | 
			
		||||
 | 
			
		||||
######################################################################
 | 
			
		||||
 | 
			
		||||
if ARGV.size.zero?
 | 
			
		||||
  display_usage
 | 
			
		||||
else
 | 
			
		||||
  ri = RiDisplay.new
 | 
			
		||||
  begin
 | 
			
		||||
    ARGV.each do |arg|
 | 
			
		||||
      ri.display_info_for(arg)
 | 
			
		||||
    end
 | 
			
		||||
  rescue RiError => e
 | 
			
		||||
    $stderr.puts(e.message)
 | 
			
		||||
    exit(1)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
ri = RiDisplay.new
 | 
			
		||||
ri.process_args
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue