summaryrefslogtreecommitdiff
path: root/bin/ri
diff options
context:
space:
mode:
Diffstat (limited to 'bin/ri')
-rwxr-xr-xbin/ri201
1 files changed, 201 insertions, 0 deletions
diff --git a/bin/ri b/bin/ri
new file mode 100755
index 0000000..899fc2d
--- /dev/null
+++ b/bin/ri
@@ -0,0 +1,201 @@
+#!/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 unbiguous form. If a name
+# _is_ ambiguous, all valid options will be listed.
+#
+
+require 'rdoc/ri/ri_paths'
+require 'rdoc/ri/ri_cache'
+require 'rdoc/ri/ri_util'
+require 'rdoc/ri/ri_reader'
+require 'rdoc/ri/ri_formatter'
+
+######################################################################
+
+def display_usage
+ File.open(__FILE__) do |f|
+ f.gets
+ puts $1 while (f.gets =~ /^# ?(.*)/)
+ end
+ exit
+end
+
+
+######################################################################
+
+class RiDisplay
+
+ def initialize
+ paths = RI::Paths::PATH
+ if paths.empty?
+ $stderr.puts "No ri documentation found in:"
+ [ RI::Paths::SYSDIR, RI::Paths::SITEDIR, RI::Paths::HOMEDIR].each do |d|
+ $stderr.puts " #{d}"
+ end
+ $stderr.puts "\nIs ri correctly installed?"
+ exit 1
+ end
+ @ri_reader = RI::RiReader.new(RI::RiCache.new(paths))
+ @formatter = RI::RiFormatter.new(72, " ")
+ end
+
+ ######################################################################
+
+ def display_params(method)
+ params = method.params
+ if params[0,1] == "("
+ if method.is_singleton
+ params = method.full_name + params
+ else
+ params = method.name + params
+ end
+ end
+ @formatter.wrap(params)
+ end
+
+ ######################################################################
+
+ def display_flow(flow)
+ if !flow || flow.empty?
+ @formatter.wrap("(no description...)")
+ else
+ @formatter.display_flow(flow)
+ end
+ end
+
+######################################################################
+
+def display_method_info(method_entry)
+ method = @ri_reader.get_method(method_entry)
+ @formatter.draw_line(method.full_name)
+ display_params(method)
+ @formatter.draw_line
+ display_flow(method.comment)
+ if method.aliases && !method.aliases.empty?
+ @formatter.blankline
+ aka = "(also known as "
+ aka << method.aliases.map {|a| a.name }.join(", ")
+ aka << ")"
+ @formatter.wrap(aka)
+ end
+end
+
+######################################################################
+
+def display_class_info(class_entry)
+ klass = @ri_reader.get_class(class_entry)
+ @formatter.draw_line("Class: " + klass.full_name)
+ display_flow(klass.comment)
+ @formatter.draw_line
+
+ unless klass.constants.empty?
+ @formatter.blankline
+ @formatter.wrap("Constants:", "")
+ len = 0
+ klass.constants.each { |c| len = c.name.length if c.name.length > len }
+ len += 2
+ klass.constants.each do |c|
+ @formatter.wrap(c.value,
+ @formatter.indent+((c.name+":").ljust(len)))
+ end
+ end
+
+ unless klass.method_list.empty?
+ @formatter.blankline
+ @formatter.wrap("Methods:", "")
+ @formatter.wrap(klass.method_list.map{|m| m.name}.sort.join(', '))
+ end
+
+ unless klass.attributes.empty?
+ @formatter.blankline
+ @formatter.wrap("Attributes:", "")
+ @formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
+ end
+end
+
+######################################################################
+
+# If the list of matching methods contains exactly one entry, or
+# if it contains an entry that exactly matches the requested method,
+# then display that entry, otherwise display the list of
+# matching method names
+
+def report_method_stuff(requested_method_name, methods)
+ if methods.size == 1
+ display_method_info(methods[0])
+ elsif (entry = methods.find {|m| m.name == requested_method_name})
+ display_method_info(entry)
+ else
+ puts "More than one method matched your request. You can refine"
+ puts "your search by asking for information on one of:\n\n"
+ @formatter.wrap(methods.map {|m| m.full_name} .join(", "))
+ end
+end
+
+######################################################################
+
+def report_class_stuff(namespaces)
+ if namespaces.size > 1
+ puts "More than one class or module matched your request. You can refine"
+ puts "your search by asking for information on one of:\n\n"
+ puts @formatter.wrap("", namespaces.map {|m| m.full_name} .join(", "))
+ else
+ class_desc = @ri_reader.get_class(namespaces[0])
+ display_class_info(namespaces[0])
+ end
+end
+
+######################################################################
+
+
+def display_info_for(arg)
+ desc = NameDescriptor.new(arg)
+
+ namespaces = @ri_reader.top_level_namespace
+
+ for class_name in desc.class_names
+ namespaces = @ri_reader.lookup_namespace_in(class_name, namespaces)
+ if namespaces.empty?
+ raise RiError.new("Nothing known about #{arg}")
+ end
+ end
+
+ 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
+
+######################################################################
+
+if ARGV.size.zero?
+ display_usage
+else
+ ri = RiDisplay.new
+ begin
+ ARGV.each do |arg|
+ ri.display_info_for(arg)
+ end
+ rescue RiError => e
+ $stderr.puts(e.message)
+ exit(1)
+ end
+end