1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/lib/rdoc/rdoc.rb
dave 87762adcb0 Add RDoc
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5073 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-12-01 07:12:49 +00:00

219 lines
5.6 KiB
Ruby

# See README.
#
RDOC_VERSION = "1.0pr1"
rcs = '$Date$ $Revision$'.
gsub(/\$/, '').
sub(/Date: /, ': ').
sub(/ Revision: (\S+)/) { "(#$1)" }
VERSION_STRING = %{RDoc V} + RDOC_VERSION + rcs
require 'rdoc/parsers/parse_rb.rb'
require 'rdoc/parsers/parse_c.rb'
require 'rdoc/parsers/parse_f95.rb'
require 'rdoc/parsers/parse_simple.rb'
require 'rdoc/options'
require 'rdoc/diagram'
require 'find'
require 'ftools'
# We put rdoc stuff in the RDoc module to avoid namespace
# clutter.
#
# ToDo: This isn't universally true.
module RDoc
# Exception thrown by any rdoc error. Only the #message part is
# of use externally.
class RDocError < Exception
end
# Encapsulate the production of rdoc documentation. Basically
# you can use this as you would invoke rdoc from the command
# line:
#
# rdoc = RDoc::RDoc.new
# rdoc.document(args)
#
# where _args_ is an array of strings, each corresponding to
# an argument you'd give rdoc on the command line. See rdoc/rdoc.rb
# for details.
class RDoc
##
# This is the list of output generators that we
# support
Generator = Struct.new(:file_name, :class_name, :key)
GENERATORS = {}
$:.collect {|d|
File::expand_path(d)
}.find_all {|d|
File::directory?("#{d}/rdoc/generators")
}.each {|dir|
Dir::entries("#{dir}/rdoc/generators").each {|gen|
next unless /(\w+)_generator.rb$/ =~ gen
type = $1
unless GENERATORS.has_key? type
GENERATORS[type] = Generator.new("rdoc/generators/#{gen}",
"#{type.upcase}Generator".intern,
type)
end
}
}
#######
private
#######
##
# Report an error message and exit
def error(msg)
raise RDocError.new(msg)
end
##
# Create an output dir if it doesn't exist. If it does
# exist, but doesn't contain the flag file <tt>created.rid</tt>
# then we refuse to use it, as we may clobber some
# manually generated documentation
def setup_output_dir(op_dir)
flag_file = File.join(op_dir, "created.rid")
if File.exist?(op_dir)
unless File.directory?(op_dir)
error "'#{op_dir}' exists, and is not a directory"
end
unless File.file?(flag_file)
error "\nDirectory #{op_dir} already exists, but it looks like it\n" +
"isn't an RDoc directory. Because RDoc doesn't want to risk\n" +
"destroying any of your existing files, you'll need to\n" +
"specify a different output directory name (using the\n" +
"--op <dir> option).\n\n"
end
else
File.makedirs(op_dir)
end
File.open(flag_file, "w") {|f| f.puts Time.now }
end
# Given a list of files and directories, create a list
# of all the Ruby files they contain.
def normalized_file_list(options, *relative_files)
file_list = []
relative_files.each do |rel_file_name|
case type = File.stat(rel_file_name).ftype
when "file"
file_list << rel_file_name
when "directory"
next if options.exclude && options.exclude =~ rel_file_name
Find.find(rel_file_name) do |fn|
next if options.exclude && options.exclude =~ fn
next unless ParserFactory.can_parse(fn)
next unless File.file?(fn)
file_list << fn.sub(%r{\./}, '')
end
else
raise RDocError.new("I can't deal with a #{type} #{rel_file_name}")
end
end
file_list
end
# Parse each file on the command line, recursively entering
# directories
def parse_files(options)
file_info = []
files = options.files
files = ["."] if files.empty?
file_list = normalized_file_list(options, *files)
file_list.each do |fn|
$stderr.printf("\n%35s: ", File.basename(fn)) unless options.quiet
content = File.open(fn, "r") {|f| f.read}
top_level = TopLevel.new(fn)
parser = ParserFactory.parser_for(top_level, fn, content, options)
file_info << parser.scan
end
file_info
end
public
###################################################################
#
# Format up one or more files according to the given arguments.
# For simplicity, _argv_ is an array of strings, equivalent to the
# strings that would be passed on the command line. (This isn't a
# coincidence, as we _do_ pass in ARGV when running
# interactively). For a list of options, see rdoc/rdoc.rb. By
# default, output will be stored in a directory called +doc+ below
# the current directory, so make sure you're somewhere writable
# before invoking.
#
# Throws: RDocError on error
def document(argv)
TopLevel::reset
options = Options.instance
options.parse(argv, GENERATORS)
file_info = parse_files(options)
gen = options.generator
$stderr.puts "\nGenerating #{gen.key.upcase}..." unless options.quiet
require gen.file_name
gen_class = Generators.const_get(gen.class_name)
unless file_info.empty?
gen = gen_class.for(options)
pwd = Dir.pwd
unless options.all_one_file
setup_output_dir(options.op_dir)
Dir.chdir(options.op_dir)
end
begin
Diagram.new(file_info, options).draw if options.diagram
gen.generate(file_info)
ensure
Dir.chdir(pwd)
end
end
end
end
end