Class | RDoc::RDoc |
In: |
lib/rdoc/rdoc.rb
|
Parent: | Object |
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.
Generator | = | Struct.new(:file_name, :class_name, :key) | This is the list of output generators that we support | |
GENERATORS | = | {} |
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.
# File lib/rdoc/rdoc.rb, line 249 249: def document(argv) 250: 251: TopLevel::reset 252: 253: @stats = Stats.new 254: 255: options = Options.instance 256: options.parse(argv, GENERATORS) 257: 258: @last_created = nil 259: unless options.all_one_file 260: @last_created = setup_output_dir(options.op_dir, options.force_update) 261: end 262: start_time = Time.now 263: 264: file_info = parse_files(options) 265: 266: if file_info.empty? 267: $stderr.puts "\nNo newer files." unless options.quiet 268: else 269: gen = options.generator 270: 271: $stderr.puts "\nGenerating #{gen.key.upcase}..." unless options.quiet 272: 273: require gen.file_name 274: 275: gen_class = Generators.const_get(gen.class_name) 276: gen = gen_class.for(options) 277: 278: pwd = Dir.pwd 279: 280: Dir.chdir(options.op_dir) unless options.all_one_file 281: 282: begin 283: Diagram.new(file_info, options).draw if options.diagram 284: gen.generate(file_info) 285: update_output_dir(".", start_time) 286: ensure 287: Dir.chdir(pwd) 288: end 289: end 290: 291: unless options.quiet 292: puts 293: @stats.print 294: end 295: end
Return a list of the files to be processed in a directory. We know that this directory doesn‘t have a .document file, so we‘re looking for real files. However we may well contain subdirectories which must be tested for .document files
# File lib/rdoc/rdoc.rb, line 202 202: def list_files_in_directory(dir, options) 203: normalized_file_list(options, Dir.glob(File.join(dir, "*")), false, options.exclude) 204: end
Given a list of files and directories, create a list of all the Ruby files they contain.
If force_doc is true, we always add the given files. If false, only add files that we guarantee we can parse It is true when looking at files given on the command line, false when recursing through subdirectories.
The effect of this is that if you want a file with a non- standard extension parsed, you must name it explicity.
# File lib/rdoc/rdoc.rb, line 172 172: def normalized_file_list(options, relative_files, force_doc = false, exclude_pattern=nil) 173: file_list = [] 174: 175: relative_files.each do |rel_file_name| 176: next if exclude_pattern && exclude_pattern =~ rel_file_name 177: stat = File.stat(rel_file_name) 178: case type = stat.ftype 179: when "file" 180: next if @last_created and stat.mtime < @last_created 181: file_list << rel_file_name.sub(/^\.\//, '') if force_doc || ParserFactory.can_parse(rel_file_name) 182: when "directory" 183: next if rel_file_name == "CVS" || rel_file_name == ".svn" 184: dot_doc = File.join(rel_file_name, DOT_DOC_FILENAME) 185: if File.file?(dot_doc) 186: file_list.concat(parse_dot_doc_file(rel_file_name, dot_doc, options)) 187: else 188: file_list.concat(list_files_in_directory(rel_file_name, options)) 189: end 190: else 191: raise RDocError.new("I can't deal with a #{type} #{rel_file_name}") 192: end 193: end 194: file_list 195: end
Return the path name of the flag file in an output directory.
# File lib/rdoc/rdoc.rb, line 139 139: def output_flag_file(op_dir) 140: File.join(op_dir, "created.rid") 141: end
The .document file contains a list of file and directory name patterns, representing candidates for documentation. It may also contain comments (starting with ’#’)
# File lib/rdoc/rdoc.rb, line 146 146: def parse_dot_doc_file(in_dir, filename, options) 147: # read and strip comments 148: patterns = File.read(filename).gsub(/#.*/, '') 149: 150: result = [] 151: 152: patterns.split.each do |patt| 153: candidates = Dir.glob(File.join(in_dir, patt)) 154: result.concat(normalized_file_list(options, candidates)) 155: end 156: result 157: end
Parse each file on the command line, recursively entering directories
# File lib/rdoc/rdoc.rb, line 210 210: def parse_files(options) 211: 212: file_info = [] 213: 214: files = options.files 215: files = ["."] if files.empty? 216: 217: file_list = normalized_file_list(options, files, true) 218: 219: file_list.each do |fn| 220: $stderr.printf("\n%35s: ", File.basename(fn)) unless options.quiet 221: 222: content = File.open(fn, "r") {|f| f.read} 223: 224: top_level = TopLevel.new(fn) 225: parser = ParserFactory.parser_for(top_level, fn, content, options, @stats) 226: file_info << parser.scan 227: @stats.num_files += 1 228: end 229: 230: file_info 231: end
Create an output dir if it doesn‘t exist. If it does exist, but doesn‘t contain the flag file created.rid then we refuse to use it, as we may clobber some manually generated documentation
# File lib/rdoc/rdoc.rb, line 110 110: def setup_output_dir(op_dir, force) 111: flag_file = output_flag_file(op_dir) 112: if File.exist?(op_dir) 113: unless File.directory?(op_dir) 114: error "'#{op_dir}' exists, and is not a directory" 115: end 116: begin 117: created = File.read(flag_file) 118: rescue SystemCallError 119: error "\nDirectory #{op_dir} already exists, but it looks like it\n" + 120: "isn't an RDoc directory. Because RDoc doesn't want to risk\n" + 121: "destroying any of your existing files, you'll need to\n" + 122: "specify a different output directory name (using the\n" + 123: "--op <dir> option).\n\n" 124: else 125: last = (Time.parse(created) unless force rescue nil) 126: end 127: else 128: File.makedirs(op_dir) 129: end 130: last 131: end