ruby--ruby/lib/rdoc/ri/display.rb

275 lines
6.5 KiB
Ruby

require 'rdoc/ri'
##
# This is a kind of 'flag' module. If you want to write your own 'ri' display
# module (perhaps because you're writing an IDE), you write a class which
# implements the various 'display' methods in RDoc::RI::DefaultDisplay, and
# include the RDoc::RI::Display module in that class.
#
# To access your class from the command line, you can do
#
# ruby -r <your source file> ../ri ....
module RDoc::RI::Display
@@display_class = nil
def self.append_features(display_class)
@@display_class = display_class
end
def self.new(*args)
@@display_class.new(*args)
end
end
##
# A paging display module. Uses the RDoc::RI::Formatter class to do the actual
# presentation.
class RDoc::RI::DefaultDisplay
include RDoc::RI::Display
def initialize(formatter, width, use_stdout, output = $stdout)
@use_stdout = use_stdout
@formatter = formatter.new output, width, " "
end
##
# Display information about +klass+. Fetches additional information from
# +ri_reader+ as necessary.
def display_class_info(klass, ri_reader)
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
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, "")
constants = klass.constants.sort_by { |constant| constant.name }
constants.each do |constant|
if constant.comment then
@formatter.wrap "#{constant.name}:"
@formatter.indent do
@formatter.display_flow constant.comment
end
else
@formatter.wrap constant.name
end
end
end
class_data = [
:class_methods,
:class_method_extensions,
:instance_methods,
:instance_method_extensions,
]
class_data.each do |data_type|
data = klass.send data_type
unless data.empty? then
@formatter.blankline
heading = data_type.to_s.split('_').join(' ').capitalize << ':'
@formatter.display_heading heading, 2, ''
data = data.map { |item| item.name }.sort.join ', '
@formatter.wrap data
end
end
unless klass.attributes.empty? then
@formatter.blankline
@formatter.display_heading 'Attributes:', 2, ''
attributes = klass.attributes.sort_by { |attribute| attribute.name }
attributes.each do |attribute|
if attribute.comment then
@formatter.wrap "#{attribute.name} (#{attribute.rw}):"
@formatter.indent do
@formatter.display_flow attribute.comment
end
else
@formatter.wrap "#{attribute.name} (#{attribute.rw})"
end
end
end
end
end
##
# Display an Array of RDoc::Markup::Flow objects, +flow+.
def display_flow(flow)
if flow and not flow.empty? then
@formatter.display_flow flow
else
@formatter.wrap '[no description]'
end
end
##
# Display information about +method+.
def display_method_info(method)
page do
@formatter.draw_line(method.full_name)
display_params(method)
@formatter.draw_line
display_flow(method.comment)
if method.aliases and not method.aliases.empty? then
@formatter.blankline
aka = "(also known as #{method.aliases.map { |a| a.name }.join(', ')})"
@formatter.wrap aka
end
end
end
##
# Display the list of +methods+.
def display_method_list(methods)
page do
@formatter.wrap "More than one method matched your request. You can refine your search by asking for information on one of:"
@formatter.blankline
@formatter.wrap methods.map { |m| m.full_name }.join(", ")
end
end
##
# Display the params for +method+.
def display_params(method)
params = method.params
if params[0,1] == "(" then
if method.is_singleton
params = method.full_name + params
else
params = method.name + params
end
end
params.split(/\n/).each do |param|
@formatter.wrap param
@formatter.break_to_newline
end
if method.source_path then
@formatter.blankline
@formatter.wrap("Extension from #{method.source_path}")
end
end
##
# List the classes in +classes+.
def list_known_classes(classes)
if classes.empty?
warn_no_database
else
page do
@formatter.draw_line "Known classes and modules"
@formatter.blankline
@formatter.wrap classes.sort.join(', ')
end
end
end
##
# Paginates output through a pager program.
def page
if pager = setup_pager then
begin
orig_output = @formatter.output
@formatter.output = pager
yield
ensure
@formatter.output = orig_output
pager.close
end
else
yield
end
rescue Errno::EPIPE
end
##
# Sets up a pager program to pass output through.
def setup_pager
unless @use_stdout then
for pager in [ ENV['PAGER'], "less", "more", 'pager' ].compact.uniq
return IO.popen(pager, "w") rescue nil
end
@use_stdout = true
nil
end
end
##
# Displays a message that describes how to build RI data.
def warn_no_database
output = @formatter.output
output.puts "No ri data found"
output.puts
output.puts "If you've installed Ruby yourself, you need to generate documentation using:"
output.puts
output.puts " make install-doc"
output.puts
output.puts "from the same place you ran `make` to build ruby."
output.puts
output.puts "If you installed Ruby from a packaging system, then you may need to"
output.puts "install an additional package, or ask the packager to enable ri generation."
end
end