options.rb 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. require 'optparse'
  2. ##
  3. # RDoc::Options handles the parsing and storage of options
  4. #
  5. # == Saved Options
  6. #
  7. # You can save some options like the markup format in the
  8. # <tt>.rdoc_options</tt> file in your gem. The easiest way to do this is:
  9. #
  10. # rdoc --markup tomdoc --write-options
  11. #
  12. # Which will automatically create the file and fill it with the options you
  13. # specified.
  14. #
  15. # The following options will not be saved since they interfere with the user's
  16. # preferences or with the normal operation of RDoc:
  17. #
  18. # * +--coverage-report+
  19. # * +--dry-run+
  20. # * +--encoding+
  21. # * +--force-update+
  22. # * +--format+
  23. # * +--pipe+
  24. # * +--quiet+
  25. # * +--template+
  26. # * +--verbose+
  27. class RDoc::Options
  28. ##
  29. # The deprecated options.
  30. DEPRECATED = {
  31. '--accessor' => 'support discontinued',
  32. '--diagram' => 'support discontinued',
  33. '--help-output' => 'support discontinued',
  34. '--image-format' => 'was an option for --diagram',
  35. '--inline-source' => 'source code is now always inlined',
  36. '--merge' => 'ri now always merges class information',
  37. '--one-file' => 'support discontinued',
  38. '--op-name' => 'support discontinued',
  39. '--opname' => 'support discontinued',
  40. '--promiscuous' => 'files always only document their content',
  41. '--ri-system' => 'Ruby installers use other techniques',
  42. }
  43. ##
  44. # RDoc options ignored (or handled specially) by --write-options
  45. SPECIAL = %w[
  46. coverage_report
  47. dry_run
  48. encoding
  49. files
  50. force_output
  51. force_update
  52. generator
  53. generator_name
  54. generator_options
  55. generators
  56. op_dir
  57. option_parser
  58. pipe
  59. rdoc_include
  60. static_path
  61. stylesheet_url
  62. template
  63. template_dir
  64. update_output_dir
  65. verbosity
  66. write_options
  67. ]
  68. ##
  69. # Path option validator for OptionParser
  70. Path = Object.new
  71. ##
  72. # Array of Paths option validator for OptionParser
  73. PathArray = Object.new
  74. ##
  75. # Template option validator for OptionParser
  76. Template = Object.new
  77. ##
  78. # Character-set for HTML output. #encoding is preferred over #charset
  79. attr_accessor :charset
  80. ##
  81. # If true, RDoc will not write any files.
  82. attr_accessor :dry_run
  83. ##
  84. # Encoding of output where. This is set via --encoding.
  85. attr_accessor :encoding
  86. ##
  87. # Files matching this pattern will be excluded
  88. attr_accessor :exclude
  89. ##
  90. # The list of files to be processed
  91. attr_accessor :files
  92. ##
  93. # Create the output even if the output directory does not look
  94. # like an rdoc output directory
  95. attr_accessor :force_output
  96. ##
  97. # Scan newer sources than the flag file if true.
  98. attr_accessor :force_update
  99. ##
  100. # Formatter to mark up text with
  101. attr_accessor :formatter
  102. ##
  103. # Description of the output generator (set with the <tt>--fmt</tt> option)
  104. attr_accessor :generator
  105. ##
  106. # For #==
  107. attr_reader :generator_name # :nodoc:
  108. ##
  109. # Loaded generator options. Used to prevent --help from loading the same
  110. # options multiple times.
  111. attr_accessor :generator_options
  112. ##
  113. # Old rdoc behavior: hyperlink all words that match a method name,
  114. # even if not preceded by '#' or '::'
  115. attr_accessor :hyperlink_all
  116. ##
  117. # Include line numbers in the source code
  118. attr_accessor :line_numbers
  119. ##
  120. # Name of the file, class or module to display in the initial index page (if
  121. # not specified the first file we encounter is used)
  122. attr_accessor :main_page
  123. ##
  124. # The default markup format. The default is 'rdoc'. 'tomdoc' and 'rd' are
  125. # also built-in.
  126. attr_accessor :markup
  127. ##
  128. # If true, only report on undocumented files
  129. attr_accessor :coverage_report
  130. ##
  131. # The name of the output directory
  132. attr_accessor :op_dir
  133. ##
  134. # The OptionParser for this instance
  135. attr_accessor :option_parser
  136. ##
  137. # Is RDoc in pipe mode?
  138. attr_accessor :pipe
  139. ##
  140. # Array of directories to search for files to satisfy an :include:
  141. attr_accessor :rdoc_include
  142. ##
  143. # Include the '#' at the front of hyperlinked instance method names
  144. attr_accessor :show_hash
  145. ##
  146. # Directory to copy static files from
  147. attr_accessor :static_path
  148. ##
  149. # The number of columns in a tab
  150. attr_accessor :tab_width
  151. ##
  152. # Template to be used when generating output
  153. attr_accessor :template
  154. ##
  155. # Directory the template lives in
  156. attr_accessor :template_dir
  157. ##
  158. # Documentation title
  159. attr_accessor :title
  160. ##
  161. # Should RDoc update the timestamps in the output dir?
  162. attr_accessor :update_output_dir
  163. ##
  164. # Verbosity, zero means quiet
  165. attr_accessor :verbosity
  166. ##
  167. # URL of web cvs frontend
  168. attr_accessor :webcvs
  169. ##
  170. # Minimum visibility of a documented method. One of +:public+,
  171. # +:protected+, +:private+. May be overridden on a per-method
  172. # basis with the :doc: directive.
  173. attr_accessor :visibility
  174. def initialize # :nodoc:
  175. init_ivars
  176. end
  177. def init_ivars # :nodoc:
  178. @dry_run = false
  179. @exclude = []
  180. @files = nil
  181. @force_output = false
  182. @force_update = true
  183. @generator = nil
  184. @generator_name = nil
  185. @generator_options = []
  186. @generators = RDoc::RDoc::GENERATORS
  187. @hyperlink_all = false
  188. @line_numbers = false
  189. @main_page = nil
  190. @markup = 'rdoc'
  191. @coverage_report = false
  192. @op_dir = nil
  193. @pipe = false
  194. @rdoc_include = []
  195. @show_hash = false
  196. @static_path = []
  197. @stylesheet_url = nil # TODO remove in RDoc 4
  198. @tab_width = 8
  199. @template = nil
  200. @template_dir = nil
  201. @title = nil
  202. @update_output_dir = true
  203. @verbosity = 1
  204. @visibility = :protected
  205. @webcvs = nil
  206. @write_options = false
  207. if Object.const_defined? :Encoding then
  208. @encoding = Encoding.default_external
  209. @charset = @encoding.to_s
  210. else
  211. @encoding = nil
  212. @charset = 'UTF-8'
  213. end
  214. end
  215. def init_with map # :nodoc:
  216. init_ivars
  217. encoding = map['encoding']
  218. @encoding = if Object.const_defined? :Encoding then
  219. encoding ? Encoding.find(encoding) : encoding
  220. end
  221. @charset = map['charset']
  222. @exclude = map['exclude']
  223. @generator_name = map['generator_name']
  224. @hyperlink_all = map['hyperlink_all']
  225. @line_numbers = map['line_numbers']
  226. @main_page = map['main_page']
  227. @markup = map['markup']
  228. @op_dir = map['op_dir']
  229. @show_hash = map['show_hash']
  230. @tab_width = map['tab_width']
  231. @template_dir = map['template_dir']
  232. @title = map['title']
  233. @visibility = map['visibility']
  234. @webcvs = map['webcvs']
  235. @rdoc_include = sanitize_path map['rdoc_include']
  236. @static_path = sanitize_path map['static_path']
  237. end
  238. def yaml_initialize tag, map # :nodoc:
  239. init_with map
  240. end
  241. def == other # :nodoc:
  242. self.class === other and
  243. @encoding == other.encoding and
  244. @generator_name == other.generator_name and
  245. @hyperlink_all == other.hyperlink_all and
  246. @line_numbers == other.line_numbers and
  247. @main_page == other.main_page and
  248. @markup == other.markup and
  249. @op_dir == other.op_dir and
  250. @rdoc_include == other.rdoc_include and
  251. @show_hash == other.show_hash and
  252. @static_path == other.static_path and
  253. @tab_width == other.tab_width and
  254. @template == other.template and
  255. @title == other.title and
  256. @visibility == other.visibility and
  257. @webcvs == other.webcvs
  258. end
  259. ##
  260. # Check that the files on the command line exist
  261. def check_files
  262. @files.delete_if do |file|
  263. if File.exist? file then
  264. if File.readable? file then
  265. false
  266. else
  267. warn "file '#{file}' not readable"
  268. true
  269. end
  270. else
  271. warn "file '#{file}' not found"
  272. true
  273. end
  274. end
  275. end
  276. ##
  277. # Ensure only one generator is loaded
  278. def check_generator
  279. if @generator then
  280. raise OptionParser::InvalidOption,
  281. "generator already set to #{@generator_name}"
  282. end
  283. end
  284. ##
  285. # Set the title, but only if not already set. Used to set the title
  286. # from a source file, so that a title set from the command line
  287. # will have the priority.
  288. def default_title=(string)
  289. @title ||= string
  290. end
  291. ##
  292. # For dumping YAML
  293. def encode_with coder # :nodoc:
  294. encoding = @encoding ? @encoding.name : nil
  295. coder.add 'encoding', encoding
  296. coder.add 'static_path', sanitize_path(@static_path)
  297. coder.add 'rdoc_include', sanitize_path(@rdoc_include)
  298. ivars = instance_variables.map { |ivar| ivar.to_s[1..-1] }
  299. ivars -= SPECIAL
  300. ivars.sort.each do |ivar|
  301. coder.add ivar, instance_variable_get("@#{ivar}")
  302. end
  303. end
  304. ##
  305. # Completes any unfinished option setup business such as filtering for
  306. # existent files, creating a regexp for #exclude and setting a default
  307. # #template.
  308. def finish
  309. @op_dir ||= 'doc'
  310. @rdoc_include << "." if @rdoc_include.empty?
  311. if @exclude.nil? or Regexp === @exclude then
  312. # done, #finish is being re-run
  313. elsif @exclude.empty? then
  314. @exclude = nil
  315. else
  316. @exclude = Regexp.new(@exclude.join("|"))
  317. end
  318. check_files
  319. # If no template was specified, use the default template for the output
  320. # formatter
  321. unless @template then
  322. @template = @generator_name
  323. @template_dir = template_dir_for @template
  324. end
  325. self
  326. end
  327. ##
  328. # Returns a properly-space list of generators and their descriptions.
  329. def generator_descriptions
  330. lengths = []
  331. generators = RDoc::RDoc::GENERATORS.map do |name, generator|
  332. lengths << name.length
  333. description = generator::DESCRIPTION if
  334. generator.const_defined? :DESCRIPTION
  335. [name, description]
  336. end
  337. longest = lengths.max
  338. generators.sort.map do |name, description|
  339. if description then
  340. " %-*s - %s" % [longest, name, description]
  341. else
  342. " #{name}"
  343. end
  344. end.join "\n"
  345. end
  346. ##
  347. # Parses command line options.
  348. def parse argv
  349. ignore_invalid = true
  350. argv.insert(0, *ENV['RDOCOPT'].split) if ENV['RDOCOPT']
  351. opts = OptionParser.new do |opt|
  352. @option_parser = opt
  353. opt.program_name = File.basename $0
  354. opt.version = RDoc::VERSION
  355. opt.release = nil
  356. opt.summary_indent = ' ' * 4
  357. opt.banner = <<-EOF
  358. Usage: #{opt.program_name} [options] [names...]
  359. Files are parsed, and the information they contain collected, before any
  360. output is produced. This allows cross references between all files to be
  361. resolved. If a name is a directory, it is traversed. If no names are
  362. specified, all Ruby files in the current directory (and subdirectories) are
  363. processed.
  364. How RDoc generates output depends on the output formatter being used, and on
  365. the options you give.
  366. Options can be specified via the RDOCOPT environment variable, which
  367. functions similar to the RUBYOPT environment variable for ruby.
  368. $ export RDOCOPT="--show-hash"
  369. will make rdoc show hashes in method links by default. Command-line options
  370. always will override those in RDOCOPT.
  371. Available formatters:
  372. #{generator_descriptions}
  373. RDoc understands the following file formats:
  374. EOF
  375. parsers = Hash.new { |h,parser| h[parser] = [] }
  376. RDoc::Parser.parsers.each do |regexp, parser|
  377. parsers[parser.name.sub('RDoc::Parser::', '')] << regexp.source
  378. end
  379. parsers.sort.each do |parser, regexp|
  380. opt.banner << " - #{parser}: #{regexp.join ', '}\n"
  381. end
  382. opt.banner << "\n The following options are deprecated:\n\n"
  383. name_length = DEPRECATED.keys.sort_by { |k| k.length }.last.length
  384. DEPRECATED.sort_by { |k,| k }.each do |name, reason|
  385. opt.banner << " %*1$2$s %3$s\n" % [-name_length, name, reason]
  386. end
  387. opt.accept Template do |template|
  388. template_dir = template_dir_for template
  389. unless template_dir then
  390. $stderr.puts "could not find template #{template}"
  391. nil
  392. else
  393. [template, template_dir]
  394. end
  395. end
  396. opt.accept Path do |directory|
  397. directory = File.expand_path directory
  398. raise OptionParser::InvalidArgument unless File.exist? directory
  399. directory
  400. end
  401. opt.accept PathArray do |directories,|
  402. directories = if directories then
  403. directories.split(',').map { |d| d unless d.empty? }
  404. end
  405. directories.map do |directory|
  406. directory = File.expand_path directory
  407. raise OptionParser::InvalidArgument unless File.exist? directory
  408. directory
  409. end
  410. end
  411. opt.separator nil
  412. opt.separator "Parsing options:"
  413. opt.separator nil
  414. if Object.const_defined? :Encoding then
  415. opt.on("--encoding=ENCODING", "-e", Encoding.list.map { |e| e.name },
  416. "Specifies the output encoding. All files",
  417. "read will be converted to this encoding.",
  418. "Preferred over --charset") do |value|
  419. @encoding = Encoding.find value
  420. @charset = @encoding.to_s # may not be valid value
  421. end
  422. opt.separator nil
  423. end
  424. opt.on("--all", "-a",
  425. "Synonym for --visibility=private.") do |value|
  426. @visibility = :private
  427. end
  428. opt.separator nil
  429. opt.on("--exclude=PATTERN", "-x", Regexp,
  430. "Do not process files or directories",
  431. "matching PATTERN.") do |value|
  432. @exclude << value
  433. end
  434. opt.separator nil
  435. opt.on("--extension=NEW=OLD", "-E",
  436. "Treat files ending with .new as if they",
  437. "ended with .old. Using '-E cgi=rb' will",
  438. "cause xxx.cgi to be parsed as a Ruby file.") do |value|
  439. new, old = value.split(/=/, 2)
  440. unless new and old then
  441. raise OptionParser::InvalidArgument, "Invalid parameter to '-E'"
  442. end
  443. unless RDoc::Parser.alias_extension old, new then
  444. raise OptionParser::InvalidArgument, "Unknown extension .#{old} to -E"
  445. end
  446. end
  447. opt.separator nil
  448. opt.on("--[no-]force-update", "-U",
  449. "Forces rdoc to scan all sources even if",
  450. "newer than the flag file.") do |value|
  451. @force_update = value
  452. end
  453. opt.separator nil
  454. opt.on("--pipe",
  455. "Convert RDoc on stdin to HTML") do
  456. @pipe = true
  457. end
  458. opt.separator nil
  459. opt.on("--tab-width=WIDTH", "-w", OptionParser::DecimalInteger,
  460. "Set the width of tab characters.") do |value|
  461. @tab_width = value
  462. end
  463. opt.separator nil
  464. opt.on("--visibility=VISIBILITY", "-V", RDoc::VISIBILITIES,
  465. "Minimum visibility to document a method.",
  466. "One of 'public', 'protected' (the default)",
  467. "or 'private'. Can be abbreviated.") do |value|
  468. @visibility = value
  469. end
  470. opt.separator nil
  471. markup_formats = RDoc::Text::MARKUP_FORMAT.keys.sort
  472. opt.on("--markup=MARKUP", markup_formats,
  473. "The markup format for the named files.",
  474. "The default is rdoc. Valid values are:",
  475. markup_formats.join(', ')) do |value|
  476. @markup = value
  477. end
  478. opt.separator nil
  479. opt.separator "Common generator options:"
  480. opt.separator nil
  481. opt.on("--force-output", "-O",
  482. "Forces rdoc to write the output files,",
  483. "even if the output directory exists",
  484. "and does not seem to have been created",
  485. "by rdoc.") do |value|
  486. @force_output = value
  487. end
  488. opt.separator nil
  489. generator_text = @generators.keys.map { |name| " #{name}" }.sort
  490. opt.on("-f", "--fmt=FORMAT", "--format=FORMAT", @generators.keys,
  491. "Set the output formatter. One of:", *generator_text) do |value|
  492. check_generator
  493. @generator_name = value.downcase
  494. setup_generator
  495. end
  496. opt.separator nil
  497. opt.on("--include=DIRECTORIES", "-i", PathArray,
  498. "Set (or add to) the list of directories to",
  499. "be searched when satisfying :include:",
  500. "requests. Can be used more than once.") do |value|
  501. @rdoc_include.concat value.map { |dir| dir.strip }
  502. end
  503. opt.separator nil
  504. opt.on("--[no-]coverage-report=[LEVEL]", "--[no-]dcov", "-C", Integer,
  505. "Prints a report on undocumented items.",
  506. "Does not generate files.") do |value|
  507. value = 0 if value.nil? # Integer converts -C to nil
  508. @coverage_report = value
  509. @force_update = true if value
  510. end
  511. opt.separator nil
  512. opt.on("--output=DIR", "--op", "-o",
  513. "Set the output directory.") do |value|
  514. @op_dir = value
  515. end
  516. opt.separator nil
  517. opt.on("-d",
  518. "Deprecated --diagram option.",
  519. "Prevents firing debug mode",
  520. "with legacy invocation.") do |value|
  521. end
  522. opt.separator nil
  523. opt.separator 'HTML generator options:'
  524. opt.separator nil
  525. opt.on("--charset=CHARSET", "-c",
  526. "Specifies the output HTML character-set.",
  527. "Use --encoding instead of --charset if",
  528. "available.") do |value|
  529. @charset = value
  530. end
  531. opt.separator nil
  532. opt.on("--hyperlink-all", "-A",
  533. "Generate hyperlinks for all words that",
  534. "correspond to known methods, even if they",
  535. "do not start with '#' or '::' (legacy",
  536. "behavior).") do |value|
  537. @hyperlink_all = value
  538. end
  539. opt.separator nil
  540. opt.on("--main=NAME", "-m",
  541. "NAME will be the initial page displayed.") do |value|
  542. @main_page = value
  543. end
  544. opt.separator nil
  545. opt.on("--[no-]line-numbers", "-N",
  546. "Include line numbers in the source code.",
  547. "By default, only the number of the first",
  548. "line is displayed, in a leading comment.") do |value|
  549. @line_numbers = value
  550. end
  551. opt.separator nil
  552. opt.on("--show-hash", "-H",
  553. "A name of the form #name in a comment is a",
  554. "possible hyperlink to an instance method",
  555. "name. When displayed, the '#' is removed",
  556. "unless this option is specified.") do |value|
  557. @show_hash = value
  558. end
  559. opt.separator nil
  560. opt.on("--template=NAME", "-T", Template,
  561. "Set the template used when generating",
  562. "output. The default depends on the",
  563. "formatter used.") do |(template, template_dir)|
  564. @template = template
  565. @template_dir = template_dir
  566. end
  567. opt.separator nil
  568. opt.on("--title=TITLE", "-t",
  569. "Set TITLE as the title for HTML output.") do |value|
  570. @title = value
  571. end
  572. opt.separator nil
  573. opt.on("--copy-files=PATH", Path,
  574. "Specify a file or directory to copy static",
  575. "files from.",
  576. "If a file is given it will be copied into",
  577. "the output dir. If a directory is given the",
  578. "entire directory will be copied.",
  579. "You can use this multiple times") do |value|
  580. @static_path << value
  581. end
  582. opt.separator nil
  583. opt.on("--webcvs=URL", "-W",
  584. "Specify a URL for linking to a web frontend",
  585. "to CVS. If the URL contains a '\%s', the",
  586. "name of the current file will be",
  587. "substituted; if the URL doesn't contain a",
  588. "'\%s', the filename will be appended to it.") do |value|
  589. @webcvs = value
  590. end
  591. opt.separator nil
  592. opt.separator "ri generator options:"
  593. opt.separator nil
  594. opt.on("--ri", "-r",
  595. "Generate output for use by `ri`. The files",
  596. "are stored in the '.rdoc' directory under",
  597. "your home directory unless overridden by a",
  598. "subsequent --op parameter, so no special",
  599. "privileges are needed.") do |value|
  600. check_generator
  601. @generator_name = "ri"
  602. @op_dir ||= RDoc::RI::Paths::HOMEDIR
  603. setup_generator
  604. end
  605. opt.separator nil
  606. opt.on("--ri-site", "-R",
  607. "Generate output for use by `ri`. The files",
  608. "are stored in a site-wide directory,",
  609. "making them accessible to others, so",
  610. "special privileges are needed.") do |value|
  611. check_generator
  612. @generator_name = "ri"
  613. @op_dir = RDoc::RI::Paths::SITEDIR
  614. setup_generator
  615. end
  616. opt.separator nil
  617. opt.separator "Generic options:"
  618. opt.separator nil
  619. opt.on("--write-options",
  620. "Write .rdoc_options to the current",
  621. "directory with the given options. Not all",
  622. "options will be used. See RDoc::Options",
  623. "for details.") do |value|
  624. @write_options = true
  625. end
  626. opt.separator nil
  627. opt.on("--[no-]dry-run",
  628. "Don't write any files") do |value|
  629. @dry_run = value
  630. end
  631. opt.separator nil
  632. opt.on("-D", "--[no-]debug",
  633. "Displays lots on internal stuff.") do |value|
  634. $DEBUG_RDOC = value
  635. end
  636. opt.separator nil
  637. opt.on("--[no-]ignore-invalid",
  638. "Ignore invalid options and continue",
  639. "(default true).") do |value|
  640. ignore_invalid = value
  641. end
  642. opt.separator nil
  643. opt.on("--quiet", "-q",
  644. "Don't show progress as we parse.") do |value|
  645. @verbosity = 0
  646. end
  647. opt.separator nil
  648. opt.on("--verbose", "-v",
  649. "Display extra progress as RDoc parses") do |value|
  650. @verbosity = 2
  651. end
  652. opt.separator nil
  653. opt.on("--help",
  654. "Display this help") do
  655. RDoc::RDoc::GENERATORS.each_key do |generator|
  656. setup_generator generator
  657. end
  658. puts opt.help
  659. exit
  660. end
  661. opt.separator nil
  662. end
  663. setup_generator 'darkfish' if
  664. argv.grep(/\A(-f|--fmt|--format|-r|-R|--ri|--ri-site)\b/).empty?
  665. deprecated = []
  666. invalid = []
  667. begin
  668. opts.parse! argv
  669. rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e
  670. if DEPRECATED[e.args.first] then
  671. deprecated << e.args.first
  672. elsif %w[--format --ri -r --ri-site -R].include? e.args.first then
  673. raise
  674. else
  675. invalid << e.args.join(' ')
  676. end
  677. retry
  678. end
  679. unless @generator then
  680. @generator = RDoc::Generator::Darkfish
  681. @generator_name = 'darkfish'
  682. end
  683. if @pipe and not argv.empty? then
  684. @pipe = false
  685. invalid << '-p (with files)'
  686. end
  687. unless quiet then
  688. deprecated.each do |opt|
  689. $stderr.puts 'option ' << opt << ' is deprecated: ' << DEPRECATED[opt]
  690. end
  691. unless invalid.empty? then
  692. invalid = "invalid options: #{invalid.join ', '}"
  693. if ignore_invalid then
  694. $stderr.puts invalid
  695. $stderr.puts '(invalid options are ignored)'
  696. else
  697. $stderr.puts opts
  698. $stderr.puts invalid
  699. exit 1
  700. end
  701. end
  702. end
  703. @files = argv.dup
  704. finish
  705. if @write_options then
  706. write_options
  707. exit
  708. end
  709. self
  710. end
  711. ##
  712. # Don't display progress as we process the files
  713. def quiet
  714. @verbosity.zero?
  715. end
  716. ##
  717. # Set quietness to +bool+
  718. def quiet= bool
  719. @verbosity = bool ? 0 : 1
  720. end
  721. ##
  722. # Removes directories from +path+ that are outside the current directory
  723. def sanitize_path path
  724. require 'pathname'
  725. dot = Pathname.new('.').expand_path
  726. path.reject do |item|
  727. path = Pathname.new(item).expand_path
  728. relative = path.relative_path_from(dot).to_s
  729. relative.start_with? '..'
  730. end
  731. end
  732. ##
  733. # Set up an output generator for the named +generator_name+.
  734. #
  735. # If the found generator responds to :setup_options it will be called with
  736. # the options instance. This allows generators to add custom options or set
  737. # default options.
  738. def setup_generator generator_name = @generator_name
  739. @generator = @generators[generator_name]
  740. unless @generator then
  741. raise OptionParser::InvalidArgument,
  742. "Invalid output formatter #{generator_name}"
  743. end
  744. return if @generator_options.include? @generator
  745. @generator_name = generator_name
  746. @generator_options << @generator
  747. if @generator.respond_to? :setup_options then
  748. @option_parser ||= OptionParser.new
  749. @generator.setup_options self
  750. end
  751. end
  752. ##
  753. # Finds the template dir for +template+
  754. def template_dir_for template
  755. template_path = File.join 'rdoc', 'generator', 'template', template
  756. $LOAD_PATH.map do |path|
  757. File.join File.expand_path(path), template_path
  758. end.find do |dir|
  759. File.directory? dir
  760. end
  761. end
  762. ##
  763. # This is compatibility code for syck
  764. def to_yaml opts = {} # :nodoc:
  765. return super if YAML.const_defined?(:ENGINE) and not YAML::ENGINE.syck?
  766. YAML.quick_emit self, opts do |out|
  767. out.map taguri, to_yaml_style do |map|
  768. encode_with map
  769. end
  770. end
  771. end
  772. ##
  773. # Displays a warning using Kernel#warn if we're being verbose
  774. def warn message
  775. super message if @verbosity > 1
  776. end
  777. ##
  778. # Writes the YAML file .rdoc_options to the current directory containing the
  779. # parsed options.
  780. def write_options
  781. RDoc.load_yaml
  782. open '.rdoc_options', 'w' do |io|
  783. io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding
  784. YAML.dump self, io
  785. end
  786. end
  787. end