Replace ri with Ryan Davis' cached ri
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14950 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
cc22700b90
commit
e539dc6080
@ -1,3 +1,7 @@
|
|||||||
|
Tue Jan 8 18:05:35 2008 Eric Hodel <drbrain@segment7.net>
|
||||||
|
|
||||||
|
* bin/ri, lib/rdoc/ri/*: Replace with Ryan Davis' cached ri.
|
||||||
|
|
||||||
Tue Jan 8 15:47:43 2008 NAKAMURA Usaku <usa@ruby-lang.org>
|
Tue Jan 8 15:47:43 2008 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
|
|
||||||
* enc/utf{16,32}_{be,le}.c: use &OnigEncodingName(*) instead of
|
* enc/utf{16,32}_{be,le}.c: use &OnigEncodingName(*) instead of
|
||||||
|
47
bin/ri
47
bin/ri
@ -1,49 +1,6 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/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.
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
require 'rdoc/ri/ri_driver'
|
require 'rdoc/ri/ri_driver'
|
||||||
|
|
||||||
######################################################################
|
RDoc::RI::RiDriver.run ARGV
|
||||||
|
|
||||||
ri = RiDriver.new
|
|
||||||
ri.process_args
|
|
||||||
|
|
||||||
|
18
lib/rdoc.rb
Normal file
18
lib/rdoc.rb
Normal file
@ -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
|
||||||
|
|
@ -1,3 +1,5 @@
|
|||||||
|
require 'rdoc'
|
||||||
|
|
||||||
require 'rdoc/parsers/parse_rb.rb'
|
require 'rdoc/parsers/parse_rb.rb'
|
||||||
require 'rdoc/parsers/parse_c.rb'
|
require 'rdoc/parsers/parse_c.rb'
|
||||||
require 'rdoc/parsers/parse_f95.rb'
|
require 'rdoc/parsers/parse_f95.rb'
|
||||||
@ -11,22 +13,8 @@ require 'find'
|
|||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'time'
|
require 'time'
|
||||||
|
|
||||||
##
|
|
||||||
# :include: README
|
|
||||||
|
|
||||||
module RDoc
|
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
|
# Simple stats collector
|
||||||
|
|
||||||
|
4
lib/rdoc/ri.rb
Normal file
4
lib/rdoc/ri.rb
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
require 'rdoc'
|
||||||
|
|
||||||
|
module RDoc::RI; end
|
||||||
|
|
@ -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
|
# This is a kind of 'flag' module. If you want to write your
|
||||||
# own 'ri' display module (perhaps because you'r writing
|
# own 'ri' display module (perhaps because you'r writing
|
||||||
# an IDE or somesuch beast), you simply write a class
|
# an IDE or somesuch beast), you simply write a class
|
||||||
# which implements the various 'display' methods in 'DefaultDisplay',
|
# 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
|
# To access your class from the command line, you can do
|
||||||
#
|
#
|
||||||
@ -34,18 +29,17 @@ end
|
|||||||
# actual presentation
|
# actual presentation
|
||||||
#
|
#
|
||||||
|
|
||||||
class DefaultDisplay
|
class DefaultDisplay
|
||||||
|
|
||||||
include RiDisplay
|
include RiDisplay
|
||||||
|
|
||||||
def initialize(options)
|
def initialize(formatter, width, use_stdout)
|
||||||
@options = options
|
@use_stdout = use_stdout
|
||||||
@formatter = @options.formatter.new(@options, " ")
|
@formatter = formatter.new width, " "
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def display_usage
|
def display_usage
|
||||||
page do
|
page do
|
||||||
RI::Options::OptionList.usage(short_form=true)
|
RI::Options::OptionList.usage(short_form=true)
|
||||||
@ -54,7 +48,7 @@ class DefaultDisplay
|
|||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def display_method_info(method)
|
def display_method_info(method)
|
||||||
page do
|
page do
|
||||||
@formatter.draw_line(method.full_name)
|
@formatter.draw_line(method.full_name)
|
||||||
@ -64,31 +58,31 @@ class DefaultDisplay
|
|||||||
if method.aliases && !method.aliases.empty?
|
if method.aliases && !method.aliases.empty?
|
||||||
@formatter.blankline
|
@formatter.blankline
|
||||||
aka = "(also known as "
|
aka = "(also known as "
|
||||||
aka << method.aliases.map {|a| a.name }.join(", ")
|
aka << method.aliases.map {|a| a.name }.join(", ")
|
||||||
aka << ")"
|
aka << ")"
|
||||||
@formatter.wrap(aka)
|
@formatter.wrap(aka)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def display_class_info(klass, ri_reader)
|
def display_class_info(klass, ri_reader)
|
||||||
page do
|
page do
|
||||||
superclass = klass.superclass_string
|
superclass = klass.superclass_string
|
||||||
|
|
||||||
if superclass
|
if superclass
|
||||||
superclass = " < " + superclass
|
superclass = " < " + superclass
|
||||||
else
|
else
|
||||||
superclass = ""
|
superclass = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
@formatter.draw_line(klass.display_name + ": " +
|
@formatter.draw_line(klass.display_name + ": " +
|
||||||
klass.full_name + superclass)
|
klass.full_name + superclass)
|
||||||
|
|
||||||
display_flow(klass.comment)
|
display_flow(klass.comment)
|
||||||
@formatter.draw_line
|
@formatter.draw_line
|
||||||
|
|
||||||
unless klass.includes.empty?
|
unless klass.includes.empty?
|
||||||
@formatter.blankline
|
@formatter.blankline
|
||||||
@formatter.display_heading("Includes:", 2, "")
|
@formatter.display_heading("Includes:", 2, "")
|
||||||
@ -106,7 +100,7 @@ class DefaultDisplay
|
|||||||
end
|
end
|
||||||
@formatter.wrap(incs.sort.join(', '))
|
@formatter.wrap(incs.sort.join(', '))
|
||||||
end
|
end
|
||||||
|
|
||||||
unless klass.constants.empty?
|
unless klass.constants.empty?
|
||||||
@formatter.blankline
|
@formatter.blankline
|
||||||
@formatter.display_heading("Constants:", 2, "")
|
@formatter.display_heading("Constants:", 2, "")
|
||||||
@ -114,23 +108,35 @@ class DefaultDisplay
|
|||||||
klass.constants.each { |c| len = c.name.length if c.name.length > len }
|
klass.constants.each { |c| len = c.name.length if c.name.length > len }
|
||||||
len += 2
|
len += 2
|
||||||
klass.constants.each do |c|
|
klass.constants.each do |c|
|
||||||
@formatter.wrap(c.value,
|
@formatter.wrap(c.value,
|
||||||
@formatter.indent+((c.name+":").ljust(len)))
|
@formatter.indent+((c.name+":").ljust(len)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unless klass.class_methods.empty?
|
unless klass.class_methods.empty?
|
||||||
@formatter.blankline
|
@formatter.blankline
|
||||||
@formatter.display_heading("Class methods:", 2, "")
|
@formatter.display_heading("Class methods:", 2, "")
|
||||||
@formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
|
@formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
|
||||||
end
|
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?
|
unless klass.instance_methods.empty?
|
||||||
@formatter.blankline
|
@formatter.blankline
|
||||||
@formatter.display_heading("Instance methods:", 2, "")
|
@formatter.display_heading("Instance methods:", 2, "")
|
||||||
@formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
|
@formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
|
||||||
end
|
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?
|
unless klass.attributes.empty?
|
||||||
@formatter.blankline
|
@formatter.blankline
|
||||||
@formatter.wrap("Attributes:", "")
|
@formatter.wrap("Attributes:", "")
|
||||||
@ -138,11 +144,11 @@ class DefaultDisplay
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
# Display a list of method names
|
# Display a list of method names
|
||||||
|
|
||||||
def display_method_list(methods)
|
def display_method_list(methods)
|
||||||
page do
|
page do
|
||||||
puts "More than one method matched your request. You can refine"
|
puts "More than one method matched your request. You can refine"
|
||||||
@ -150,9 +156,9 @@ class DefaultDisplay
|
|||||||
@formatter.wrap(methods.map {|m| m.full_name} .join(", "))
|
@formatter.wrap(methods.map {|m| m.full_name} .join(", "))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def display_class_list(namespaces)
|
def display_class_list(namespaces)
|
||||||
page do
|
page do
|
||||||
puts "More than one class or module matched your request. You can refine"
|
puts "More than one class or module matched your request. You can refine"
|
||||||
@ -160,14 +166,14 @@ class DefaultDisplay
|
|||||||
@formatter.wrap(namespaces.map {|m| m.full_name}.join(", "))
|
@formatter.wrap(namespaces.map {|m| m.full_name}.join(", "))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def list_known_classes(classes)
|
def list_known_classes(classes)
|
||||||
if classes.empty?
|
if classes.empty?
|
||||||
warn_no_database
|
warn_no_database
|
||||||
else
|
else
|
||||||
page do
|
page do
|
||||||
@formatter.draw_line("Known classes and modules")
|
@formatter.draw_line("Known classes and modules")
|
||||||
@formatter.blankline
|
@formatter.blankline
|
||||||
@formatter.wrap(classes.sort.join(", "))
|
@formatter.wrap(classes.sort.join(", "))
|
||||||
@ -181,7 +187,7 @@ class DefaultDisplay
|
|||||||
if names.empty?
|
if names.empty?
|
||||||
warn_no_database
|
warn_no_database
|
||||||
else
|
else
|
||||||
page do
|
page do
|
||||||
names.each {|n| @formatter.raw_print_line(n)}
|
names.each {|n| @formatter.raw_print_line(n)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -194,34 +200,36 @@ class DefaultDisplay
|
|||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def page
|
def page
|
||||||
return yield unless pager = setup_pager
|
if pager = setup_pager then
|
||||||
begin
|
begin
|
||||||
save_stdout = STDOUT.clone
|
orig_stdout = $stdout
|
||||||
STDOUT.reopen(pager)
|
$stdout = pager
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
$stdout = orig_stdout
|
||||||
|
pager.close
|
||||||
|
end
|
||||||
|
else
|
||||||
yield
|
yield
|
||||||
ensure
|
|
||||||
STDOUT.reopen(save_stdout)
|
|
||||||
save_stdout.close
|
|
||||||
pager.close
|
|
||||||
end
|
end
|
||||||
|
rescue Errno::EPIPE
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def setup_pager
|
def setup_pager
|
||||||
unless @options.use_stdout
|
unless @use_stdout then
|
||||||
for pager in [ ENV['PAGER'], "less", "more", 'pager' ].compact.uniq
|
for pager in [ ENV['PAGER'], "less", "more", 'pager' ].compact.uniq
|
||||||
return IO.popen(pager, "w") rescue nil
|
return IO.popen(pager, "w") rescue nil
|
||||||
end
|
end
|
||||||
@options.use_stdout = true
|
@use_stdout = true
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def display_params(method)
|
|
||||||
|
|
||||||
|
def display_params(method)
|
||||||
params = method.params
|
params = method.params
|
||||||
|
|
||||||
if params[0,1] == "("
|
if params[0,1] == "("
|
||||||
@ -232,13 +240,16 @@ class DefaultDisplay
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
params.split(/\n/).each do |p|
|
params.split(/\n/).each do |p|
|
||||||
@formatter.wrap(p)
|
@formatter.wrap(p)
|
||||||
@formatter.break_to_newline
|
@formatter.break_to_newline
|
||||||
end
|
end
|
||||||
|
if method.source_path then
|
||||||
|
@formatter.blankline
|
||||||
|
@formatter.wrap("Extension from #{method.source_path}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def display_flow(flow)
|
def display_flow(flow)
|
||||||
if !flow || flow.empty?
|
if !flow || flow.empty?
|
||||||
@formatter.wrap("(no description...)")
|
@formatter.wrap("(no description...)")
|
||||||
@ -248,9 +259,17 @@ class DefaultDisplay
|
|||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def warn_no_database
|
def warn_no_database
|
||||||
puts "Before using ri, you need to generate documentation"
|
puts "No ri data found"
|
||||||
puts "using 'rdoc' with the --ri option"
|
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
|
||||||
end # class RiDisplay
|
end # class RiDisplay
|
||||||
|
@ -1,33 +1,391 @@
|
|||||||
|
require 'optparse'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
require 'rdoc/ri'
|
||||||
require 'rdoc/ri/ri_paths'
|
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_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
|
directories = [
|
||||||
@options = RI::Options.instance
|
RI::Paths::SYSDIR,
|
||||||
|
RI::Paths::SITEDIR,
|
||||||
|
RI::Paths::HOMEDIR
|
||||||
|
]
|
||||||
|
|
||||||
args = ARGV
|
if RI::Paths::GEMDIRS then
|
||||||
if ENV["RI"]
|
Gem.path.each do |dir|
|
||||||
args = ENV["RI"].split.concat(ARGV)
|
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
|
end
|
||||||
|
|
||||||
@options.parse(args)
|
argv = ENV['RI'].to_s.split.concat argv
|
||||||
|
|
||||||
path = @options.path
|
opts.parse! argv
|
||||||
report_missing_documentation @options.raw_path if path.empty?
|
|
||||||
|
|
||||||
@ri_reader = RI::RiReader.new(RI::RiCache.new(path))
|
options[:names] = argv
|
||||||
@display = @options.displayer
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def self.run(argv = ARGV)
|
||||||
|
options = process_args argv
|
||||||
|
ri = new options
|
||||||
|
ri.run
|
||||||
|
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 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 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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
dirs.map { |dir| yield File.join(dir, file_name) }.flatten.compact
|
||||||
|
end
|
||||||
|
|
||||||
|
def populate_class_cache(class_cache, classes, extension = false)
|
||||||
|
classes.each do |cdesc|
|
||||||
|
desc = read_yaml cdesc
|
||||||
|
klassname = desc["full_name"]
|
||||||
|
|
||||||
|
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
|
||||||
|
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 run
|
||||||
|
if @names.empty? then
|
||||||
|
@display.list_known_classes select_classes
|
||||||
|
else
|
||||||
|
@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
|
||||||
|
else
|
||||||
|
if class_cache.key? name then
|
||||||
|
display_class name
|
||||||
|
else
|
||||||
|
@display.list_known_classes select_classes(/^#{name}/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def select_classes(pattern = nil)
|
||||||
|
classes = class_cache.keys.sort
|
||||||
|
classes = classes.grep pattern if pattern
|
||||||
|
classes
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
# Couldn't find documentation in +path+, so tell the user what to do
|
||||||
|
|
||||||
def report_missing_documentation(path)
|
def report_missing_documentation(path)
|
||||||
@ -38,106 +396,29 @@ class RiDriver
|
|||||||
STDERR.puts "\nWas rdoc run to create documentation?\n\n"
|
STDERR.puts "\nWas rdoc run to create documentation?\n\n"
|
||||||
RDoc::usage("Installing Documentation")
|
RDoc::usage("Installing Documentation")
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
end
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
|
|
||||||
def get_info_for(arg)
|
|
||||||
desc = NameDescriptor.new(arg)
|
|
||||||
|
|
||||||
namespaces = @ri_reader.top_level_namespace
|
end
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
# at this point, if we have multiple possible namespaces, but one
|
class Hash
|
||||||
# is an exact match for our requested class, prune down to just it
|
def method_missing method, *args
|
||||||
|
self[method.to_s]
|
||||||
full_class_name = desc.full_class_name
|
|
||||||
entries = namespaces.find_all {|m| m.full_name == full_class_name}
|
|
||||||
namespaces = entries if entries.size == 1
|
|
||||||
|
|
||||||
if desc.method_name.nil?
|
|
||||||
report_class_stuff(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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
def merge_enums(other)
|
||||||
|
other.each do |k,v|
|
||||||
def process_args
|
if self[k] then
|
||||||
if @options.list_classes
|
case v
|
||||||
classes = @ri_reader.full_class_names
|
when Array then
|
||||||
@display.list_known_classes(classes)
|
self[k] += v
|
||||||
elsif @options.list_names
|
when Hash then
|
||||||
names = @ri_reader.all_names
|
self[k].merge! v
|
||||||
@display.list_known_names(names)
|
else
|
||||||
else
|
# do nothing
|
||||||
if ARGV.size.zero?
|
|
||||||
@display.display_usage
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
ARGV.each do |arg|
|
|
||||||
get_info_for(arg)
|
|
||||||
end
|
|
||||||
rescue RiError => e
|
|
||||||
STDERR.puts(e.message)
|
|
||||||
exit(1)
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
self[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end # class RiDriver
|
|
||||||
|
@ -2,29 +2,28 @@ module RI
|
|||||||
class TextFormatter
|
class TextFormatter
|
||||||
|
|
||||||
attr_reader :indent
|
attr_reader :indent
|
||||||
|
|
||||||
def initialize(options, indent)
|
def initialize(width, indent)
|
||||||
@options = options
|
@width = width
|
||||||
@width = options.width
|
|
||||||
@indent = indent
|
@indent = indent
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def draw_line(label=nil)
|
def draw_line(label=nil)
|
||||||
len = @width
|
len = @width
|
||||||
len -= (label.size+1) if label
|
len -= (label.size+1) if label
|
||||||
print "-"*len
|
print "-"*len
|
||||||
if label
|
if label
|
||||||
print(" ")
|
print(" ")
|
||||||
bold_print(label)
|
bold_print(label)
|
||||||
end
|
end
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def wrap(txt, prefix=@indent, linelen=@width)
|
def wrap(txt, prefix=@indent, linelen=@width)
|
||||||
return unless txt && !txt.empty?
|
return unless txt && !txt.empty?
|
||||||
work = conv_markup(txt)
|
work = conv_markup(txt)
|
||||||
@ -51,7 +50,7 @@ module RI
|
|||||||
def blankline
|
def blankline
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
# called when we want to ensure a nbew 'wrap' starts on a newline
|
# called when we want to ensure a nbew 'wrap' starts on a newline
|
||||||
@ -60,7 +59,7 @@ module RI
|
|||||||
|
|
||||||
def break_to_newline
|
def break_to_newline
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def bold_print(txt)
|
def bold_print(txt)
|
||||||
@ -82,7 +81,7 @@ module RI
|
|||||||
gsub(/</, '<').
|
gsub(/</, '<').
|
||||||
gsub(/"/, '"').
|
gsub(/"/, '"').
|
||||||
gsub(/&/, '&')
|
gsub(/&/, '&')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# convert markup into display form
|
# convert markup into display form
|
||||||
@ -99,7 +98,7 @@ module RI
|
|||||||
def display_list(list)
|
def display_list(list)
|
||||||
case list.type
|
case list.type
|
||||||
|
|
||||||
when SM::ListBase::BULLET
|
when SM::ListBase::BULLET
|
||||||
prefixer = proc { |ignored| @indent + "* " }
|
prefixer = proc { |ignored| @indent + "* " }
|
||||||
|
|
||||||
when SM::ListBase::NUMBER,
|
when SM::ListBase::NUMBER,
|
||||||
@ -116,7 +115,7 @@ module RI
|
|||||||
start = start.succ
|
start = start.succ
|
||||||
res
|
res
|
||||||
end
|
end
|
||||||
|
|
||||||
when SM::ListBase::LABELED
|
when SM::ListBase::LABELED
|
||||||
prefixer = proc do |li|
|
prefixer = proc do |li|
|
||||||
li.label
|
li.label
|
||||||
@ -156,7 +155,7 @@ module RI
|
|||||||
when SM::Flow::P, SM::Flow::LI
|
when SM::Flow::P, SM::Flow::LI
|
||||||
wrap(conv_html(item.body), prefix)
|
wrap(conv_html(item.body), prefix)
|
||||||
blankline
|
blankline
|
||||||
|
|
||||||
when SM::Flow::LIST
|
when SM::Flow::LIST
|
||||||
display_list(item)
|
display_list(item)
|
||||||
|
|
||||||
@ -194,7 +193,7 @@ module RI
|
|||||||
puts text.upcase
|
puts text.upcase
|
||||||
puts ul
|
puts ul
|
||||||
# puts
|
# puts
|
||||||
|
|
||||||
when 2
|
when 2
|
||||||
ul = "-" * text.length
|
ul = "-" * text.length
|
||||||
puts
|
puts
|
||||||
@ -215,7 +214,7 @@ module RI
|
|||||||
|
|
||||||
def strip_attributes(txt)
|
def strip_attributes(txt)
|
||||||
tokens = txt.split(%r{(</?(?:b|code|em|i|tt)>)})
|
tokens = txt.split(%r{(</?(?:b|code|em|i|tt)>)})
|
||||||
text = []
|
text = []
|
||||||
attributes = 0
|
attributes = 0
|
||||||
tokens.each do |tok|
|
tokens.each do |tok|
|
||||||
case tok
|
case tok
|
||||||
@ -230,16 +229,16 @@ module RI
|
|||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Handle text with attributes. We're a base class: there are
|
# Handle text with attributes. We're a base class: there are
|
||||||
# different presentation classes (one, for example, uses overstrikes
|
# different presentation classes (one, for example, uses overstrikes
|
||||||
# to handle bold and underlining, while another using ANSI escape
|
# to handle bold and underlining, while another using ANSI escape
|
||||||
# sequences
|
# sequences
|
||||||
|
|
||||||
class AttributeFormatter < TextFormatter
|
class AttributeFormatter < TextFormatter
|
||||||
|
|
||||||
BOLD = 1
|
BOLD = 1
|
||||||
ITALIC = 2
|
ITALIC = 2
|
||||||
CODE = 4
|
CODE = 4
|
||||||
@ -263,7 +262,7 @@ module RI
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
class AttributeString
|
class AttributeString
|
||||||
attr_reader :txt
|
attr_reader :txt
|
||||||
|
|
||||||
@ -363,7 +362,7 @@ module RI
|
|||||||
|
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
# This formatter generates overstrike-style formatting, which
|
# This formatter generates overstrike-style formatting, which
|
||||||
# works with pagers such as man and less.
|
# works with pagers such as man and less.
|
||||||
|
|
||||||
@ -395,7 +394,7 @@ module RI
|
|||||||
end
|
end
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
# This formatter uses ANSI escape sequences
|
# This formatter uses ANSI escape sequences
|
||||||
# to colorize stuff
|
# to colorize stuff
|
||||||
# works with pages such as man and less.
|
# works with pages such as man and less.
|
||||||
@ -441,7 +440,7 @@ module RI
|
|||||||
print strip_attributes(text)
|
print strip_attributes(text)
|
||||||
puts heading[1]
|
puts heading[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
ATTR_MAP = {
|
ATTR_MAP = {
|
||||||
@ -462,7 +461,7 @@ module RI
|
|||||||
end
|
end
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
# This formatter uses HTML.
|
# This formatter uses HTML.
|
||||||
|
|
||||||
class HtmlFormatter < AttributeFormatter
|
class HtmlFormatter < AttributeFormatter
|
||||||
@ -508,13 +507,13 @@ module RI
|
|||||||
tag("h#{level}") { text }
|
tag("h#{level}") { text }
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def display_list(list)
|
def display_list(list)
|
||||||
|
|
||||||
case list.type
|
case list.type
|
||||||
when SM::ListBase::BULLET
|
when SM::ListBase::BULLET
|
||||||
list_type = "ul"
|
list_type = "ul"
|
||||||
prefixer = proc { |ignored| "<li>" }
|
prefixer = proc { |ignored| "<li>" }
|
||||||
|
|
||||||
@ -523,7 +522,7 @@ module RI
|
|||||||
SM::ListBase::LOWERALPHA
|
SM::ListBase::LOWERALPHA
|
||||||
list_type = "ol"
|
list_type = "ol"
|
||||||
prefixer = proc { |ignored| "<li>" }
|
prefixer = proc { |ignored| "<li>" }
|
||||||
|
|
||||||
when SM::ListBase::LABELED
|
when SM::ListBase::LABELED
|
||||||
list_type = "dl"
|
list_type = "dl"
|
||||||
prefixer = proc do |li|
|
prefixer = proc do |li|
|
||||||
@ -554,7 +553,9 @@ module RI
|
|||||||
|
|
||||||
def display_verbatim_flow_item(item, prefix=@indent)
|
def display_verbatim_flow_item(item, prefix=@indent)
|
||||||
print("<pre>")
|
print("<pre>")
|
||||||
puts item.body
|
item.body.split(/\n/).each do |line|
|
||||||
|
puts conv_html(line)
|
||||||
|
end
|
||||||
puts("</pre>")
|
puts("</pre>")
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -602,7 +603,7 @@ module RI
|
|||||||
end
|
end
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
# This formatter reduces extra lines for a simpler output.
|
# This formatter reduces extra lines for a simpler output.
|
||||||
# It improves way output looks for tools like IRC bots.
|
# It improves way output looks for tools like IRC bots.
|
||||||
|
|
||||||
@ -621,7 +622,7 @@ module RI
|
|||||||
|
|
||||||
def draw_line(label=nil)
|
def draw_line(label=nil)
|
||||||
unless label.nil? then
|
unless label.nil? then
|
||||||
bold_print(label)
|
bold_print(label)
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -656,7 +657,7 @@ module RI
|
|||||||
"plain" => TextFormatter,
|
"plain" => TextFormatter,
|
||||||
"simple" => SimpleFormatter,
|
"simple" => SimpleFormatter,
|
||||||
}
|
}
|
||||||
|
|
||||||
def TextFormatter.list
|
def TextFormatter.list
|
||||||
FORMATTERS.keys.sort.join(", ")
|
FORMATTERS.keys.sort.join(", ")
|
||||||
end
|
end
|
||||||
|
@ -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
|
|
||||||
|
|
@ -23,7 +23,7 @@ module RI
|
|||||||
|
|
||||||
#:stopdoc:
|
#:stopdoc:
|
||||||
require 'rbconfig'
|
require 'rbconfig'
|
||||||
|
|
||||||
DOC_DIR = "doc/rdoc"
|
DOC_DIR = "doc/rdoc"
|
||||||
|
|
||||||
version = RbConfig::CONFIG['ruby_version']
|
version = RbConfig::CONFIG['ruby_version']
|
||||||
@ -42,7 +42,7 @@ module RI
|
|||||||
# This is the search path for 'ri'
|
# This is the search path for 'ri'
|
||||||
PATH = [ SYSDIR, SITEDIR, HOMEDIR ].find_all {|p| p && File.directory?(p)}
|
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
|
# HACK dup'd from Gem.latest_partials and friends
|
||||||
all_paths = []
|
all_paths = []
|
||||||
|
@ -48,9 +48,8 @@ class RDoc::TemplatePage
|
|||||||
# Process the template using +values+, writing the result to +io+.
|
# Process the template using +values+, writing the result to +io+.
|
||||||
|
|
||||||
def write_html_on(io, values)
|
def write_html_on(io, values)
|
||||||
template_include = ""
|
|
||||||
|
|
||||||
b = binding
|
b = binding
|
||||||
|
template_include = ""
|
||||||
|
|
||||||
@templates.reverse_each do |template|
|
@templates.reverse_each do |template|
|
||||||
template_include = ERB.new(template).result b
|
template_include = ERB.new(template).result b
|
||||||
|
Loading…
x
Reference in New Issue
Block a user