1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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:
drbrain 2008-01-08 09:07:31 +00:00
parent cc22700b90
commit e539dc6080
11 changed files with 535 additions and 583 deletions

View file

@ -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>
* enc/utf{16,32}_{be,le}.c: use &OnigEncodingName(*) instead of

47
bin/ri
View file

@ -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'
######################################################################
ri = RiDriver.new
ri.process_args
RDoc::RI::RiDriver.run ARGV

18
lib/rdoc.rb Normal file
View 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

View file

@ -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,22 +13,8 @@ require 'find'
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

4
lib/rdoc/ri.rb Normal file
View file

@ -0,0 +1,4 @@
require 'rdoc'
module RDoc::RI; end

View file

@ -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 @@ end
# 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 @@ class DefaultDisplay
######################################################################
def display_method_info(method)
page do
@formatter.draw_line(method.full_name)
@ -64,31 +58,31 @@ class DefaultDisplay
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 @@ class DefaultDisplay
end
@formatter.wrap(incs.sort.join(', '))
end
unless klass.constants.empty?
@formatter.blankline
@formatter.display_heading("Constants:", 2, "")
@ -114,23 +108,35 @@ class DefaultDisplay
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 @@ class DefaultDisplay
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 @@ class DefaultDisplay
@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 @@ class DefaultDisplay
@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 @@ class DefaultDisplay
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 @@ class DefaultDisplay
######################################################################
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)
def display_params(method)
params = method.params
if params[0,1] == "("
@ -232,13 +240,16 @@ class DefaultDisplay
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 @@ class DefaultDisplay
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

View file

@ -1,33 +1,391 @@
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
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
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
def report_missing_documentation(path)
@ -38,106 +396,29 @@ class RiDriver
STDERR.puts "\nWas rdoc run to create documentation?\n\n"
RDoc::usage("Installing Documentation")
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
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
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
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
class Hash
def method_missing method, *args
self[method.to_s]
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)
else
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)
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
end # class RiDriver

View file

@ -2,29 +2,28 @@ module RI
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 @@ module RI
def blankline
puts
end
######################################################################
# called when we want to ensure a nbew 'wrap' starts on a newline
@ -60,7 +59,7 @@ module RI
def break_to_newline
end
######################################################################
def bold_print(txt)
@ -82,7 +81,7 @@ module RI
gsub(/&lt;/, '<').
gsub(/&quot;/, '"').
gsub(/&amp;/, '&')
end
# convert markup into display form
@ -99,7 +98,7 @@ module RI
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 @@ module RI
start = start.succ
res
end
when SM::ListBase::LABELED
prefixer = proc do |li|
li.label
@ -156,7 +155,7 @@ module RI
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 @@ module RI
puts text.upcase
puts ul
# puts
when 2
ul = "-" * text.length
puts
@ -215,7 +214,7 @@ module RI
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 @@ module RI
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 @@ module RI
end
end
class AttributeString
attr_reader :txt
@ -363,7 +362,7 @@ module RI
##################################################
# This formatter generates overstrike-style formatting, which
# works with pagers such as man and less.
@ -395,7 +394,7 @@ module RI
end
##################################################
# This formatter uses ANSI escape sequences
# to colorize stuff
# works with pages such as man and less.
@ -441,7 +440,7 @@ module RI
print strip_attributes(text)
puts heading[1]
end
private
ATTR_MAP = {
@ -462,7 +461,7 @@ module RI
end
##################################################
# This formatter uses HTML.
class HtmlFormatter < AttributeFormatter
@ -508,13 +507,13 @@ module RI
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 @@ module RI
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 @@ module RI
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 @@ module RI
end
##################################################
# This formatter reduces extra lines for a simpler output.
# It improves way output looks for tools like IRC bots.
@ -621,7 +622,7 @@ module RI
def draw_line(label=nil)
unless label.nil? then
bold_print(label)
bold_print(label)
puts
end
end
@ -656,7 +657,7 @@ module RI
"plain" => TextFormatter,
"simple" => SimpleFormatter,
}
def TextFormatter.list
FORMATTERS.keys.sort.join(", ")
end

View file

@ -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

View file

@ -23,7 +23,7 @@ module RI
#:stopdoc:
require 'rbconfig'
DOC_DIR = "doc/rdoc"
version = RbConfig::CONFIG['ruby_version']
@ -42,7 +42,7 @@ module RI
# 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 = []

View file

@ -48,9 +48,8 @@ class RDoc::TemplatePage
# Process the template using +values+, writing the result to +io+.
def write_html_on(io, values)
template_include = ""
b = binding
template_include = ""
@templates.reverse_each do |template|
template_include = ERB.new(template).result b