/tools/Ruby/lib/ruby/1.8/getoptlong.rb

http://github.com/agross/netopenspace · Ruby · 621 lines · 244 code · 49 blank · 328 comment · 69 complexity · 1d9afade1330b02bd0ff31ced760aa3a MD5 · raw file

  1. #
  2. # GetoptLong for Ruby
  3. #
  4. # Copyright (C) 1998, 1999, 2000 Motoyuki Kasahara.
  5. #
  6. # You may redistribute and/or modify this library under the same license
  7. # terms as Ruby.
  8. #
  9. # See GetoptLong for documentation.
  10. #
  11. # Additional documents and the latest version of `getoptlong.rb' can be
  12. # found at http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
  13. # The GetoptLong class allows you to parse command line options similarly to
  14. # the GNU getopt_long() C library call. Note, however, that GetoptLong is a
  15. # pure Ruby implementation.
  16. #
  17. # GetoptLong allows for POSIX-style options like <tt>--file</tt> as well
  18. # as single letter options like <tt>-f</tt>
  19. #
  20. # The empty option <tt>--</tt> (two minus symbols) is used to end option
  21. # processing. This can be particularly important if options have optional
  22. # arguments.
  23. #
  24. # Here is a simple example of usage:
  25. #
  26. # # == Synopsis
  27. # #
  28. # # hello: greets user, demonstrates command line parsing
  29. # #
  30. # # == Usage
  31. # #
  32. # # hello [OPTION] ... DIR
  33. # #
  34. # # -h, --help:
  35. # # show help
  36. # #
  37. # # --repeat x, -n x:
  38. # # repeat x times
  39. # #
  40. # # --name [name]:
  41. # # greet user by name, if name not supplied default is John
  42. # #
  43. # # DIR: The directory in which to issue the greeting.
  44. #
  45. # require 'getoptlong'
  46. # require 'rdoc/usage'
  47. #
  48. # opts = GetoptLong.new(
  49. # [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
  50. # [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
  51. # [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
  52. # )
  53. #
  54. # dir = nil
  55. # name = nil
  56. # repetitions = 1
  57. # opts.each do |opt, arg|
  58. # case opt
  59. # when '--help'
  60. # RDoc::usage
  61. # when '--repeat'
  62. # repetitions = arg.to_i
  63. # when '--name'
  64. # if arg == ''
  65. # name = 'John'
  66. # else
  67. # name = arg
  68. # end
  69. # end
  70. # end
  71. #
  72. # if ARGV.length != 1
  73. # puts "Missing dir argument (try --help)"
  74. # exit 0
  75. # end
  76. #
  77. # dir = ARGV.shift
  78. #
  79. # Dir.chdir(dir)
  80. # for i in (1..repetitions)
  81. # print "Hello"
  82. # if name
  83. # print ", #{name}"
  84. # end
  85. # puts
  86. # end
  87. #
  88. # Example command line:
  89. #
  90. # hello -n 6 --name -- /tmp
  91. #
  92. class GetoptLong
  93. #
  94. # Orderings.
  95. #
  96. ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
  97. #
  98. # Argument flags.
  99. #
  100. ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
  101. OPTIONAL_ARGUMENT = 2]
  102. #
  103. # Status codes.
  104. #
  105. STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
  106. #
  107. # Error types.
  108. #
  109. class Error < StandardError; end
  110. class AmbigousOption < Error; end
  111. class NeedlessArgument < Error; end
  112. class MissingArgument < Error; end
  113. class InvalidOption < Error; end
  114. #
  115. # Set up option processing.
  116. #
  117. # The options to support are passed to new() as an array of arrays.
  118. # Each sub-array contains any number of String option names which carry
  119. # the same meaning, and one of the following flags:
  120. #
  121. # GetoptLong::NO_ARGUMENT :: Option does not take an argument.
  122. #
  123. # GetoptLong::REQUIRED_ARGUMENT :: Option always takes an argument.
  124. #
  125. # GetoptLong::OPTIONAL_ARGUMENT :: Option may or may not take an argument.
  126. #
  127. # The first option name is considered to be the preferred (canonical) name.
  128. # Other than that, the elements of each sub-array can be in any order.
  129. #
  130. def initialize(*arguments)
  131. #
  132. # Current ordering.
  133. #
  134. if ENV.include?('POSIXLY_CORRECT')
  135. @ordering = REQUIRE_ORDER
  136. else
  137. @ordering = PERMUTE
  138. end
  139. #
  140. # Hash table of option names.
  141. # Keys of the table are option names, and their values are canonical
  142. # names of the options.
  143. #
  144. @canonical_names = Hash.new
  145. #
  146. # Hash table of argument flags.
  147. # Keys of the table are option names, and their values are argument
  148. # flags of the options.
  149. #
  150. @argument_flags = Hash.new
  151. #
  152. # Whether error messages are output to $deferr.
  153. #
  154. @quiet = FALSE
  155. #
  156. # Status code.
  157. #
  158. @status = STATUS_YET
  159. #
  160. # Error code.
  161. #
  162. @error = nil
  163. #
  164. # Error message.
  165. #
  166. @error_message = nil
  167. #
  168. # Rest of catenated short options.
  169. #
  170. @rest_singles = ''
  171. #
  172. # List of non-option-arguments.
  173. # Append them to ARGV when option processing is terminated.
  174. #
  175. @non_option_arguments = Array.new
  176. if 0 < arguments.length
  177. set_options(*arguments)
  178. end
  179. end
  180. #
  181. # Set the handling of the ordering of options and arguments.
  182. # A RuntimeError is raised if option processing has already started.
  183. #
  184. # The supplied value must be a member of GetoptLong::ORDERINGS. It alters
  185. # the processing of options as follows:
  186. #
  187. # <b>REQUIRE_ORDER</b> :
  188. #
  189. # Options are required to occur before non-options.
  190. #
  191. # Processing of options ends as soon as a word is encountered that has not
  192. # been preceded by an appropriate option flag.
  193. #
  194. # For example, if -a and -b are options which do not take arguments,
  195. # parsing command line arguments of '-a one -b two' would result in
  196. # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being
  197. # processed as an option/arg pair.
  198. #
  199. # This is the default ordering, if the environment variable
  200. # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
  201. #
  202. # <b>PERMUTE</b> :
  203. #
  204. # Options can occur anywhere in the command line parsed. This is the
  205. # default behavior.
  206. #
  207. # Every sequence of words which can be interpreted as an option (with or
  208. # without argument) is treated as an option; non-option words are skipped.
  209. #
  210. # For example, if -a does not require an argument and -b optionally takes
  211. # an argument, parsing '-a one -b two three' would result in ('-a','') and
  212. # ('-b', 'two') being processed as option/arg pairs, and 'one','three'
  213. # being left in ARGV.
  214. #
  215. # If the ordering is set to PERMUTE but the environment variable
  216. # POSIXLY_CORRECT is set, REQUIRE_ORDER is used instead. This is for
  217. # compatibility with GNU getopt_long.
  218. #
  219. # <b>RETURN_IN_ORDER</b> :
  220. #
  221. # All words on the command line are processed as options. Words not
  222. # preceded by a short or long option flag are passed as arguments
  223. # with an option of '' (empty string).
  224. #
  225. # For example, if -a requires an argument but -b does not, a command line
  226. # of '-a one -b two three' would result in option/arg pairs of ('-a', 'one')
  227. # ('-b', ''), ('', 'two'), ('', 'three') being processed.
  228. #
  229. def ordering=(ordering)
  230. #
  231. # The method is failed if option processing has already started.
  232. #
  233. if @status != STATUS_YET
  234. set_error(ArgumentError, "argument error")
  235. raise RuntimeError,
  236. "invoke ordering=, but option processing has already started"
  237. end
  238. #
  239. # Check ordering.
  240. #
  241. if !ORDERINGS.include?(ordering)
  242. raise ArgumentError, "invalid ordering `#{ordering}'"
  243. end
  244. if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
  245. @ordering = REQUIRE_ORDER
  246. else
  247. @ordering = ordering
  248. end
  249. end
  250. #
  251. # Return ordering.
  252. #
  253. attr_reader :ordering
  254. #
  255. # Set options. Takes the same argument as GetoptLong.new.
  256. #
  257. # Raises a RuntimeError if option processing has already started.
  258. #
  259. def set_options(*arguments)
  260. #
  261. # The method is failed if option processing has already started.
  262. #
  263. if @status != STATUS_YET
  264. raise RuntimeError,
  265. "invoke set_options, but option processing has already started"
  266. end
  267. #
  268. # Clear tables of option names and argument flags.
  269. #
  270. @canonical_names.clear
  271. @argument_flags.clear
  272. arguments.each do |arg|
  273. #
  274. # Each argument must be an Array.
  275. #
  276. if !arg.is_a?(Array)
  277. raise ArgumentError, "the option list contains non-Array argument"
  278. end
  279. #
  280. # Find an argument flag and it set to `argument_flag'.
  281. #
  282. argument_flag = nil
  283. arg.each do |i|
  284. if ARGUMENT_FLAGS.include?(i)
  285. if argument_flag != nil
  286. raise ArgumentError, "too many argument-flags"
  287. end
  288. argument_flag = i
  289. end
  290. end
  291. raise ArgumentError, "no argument-flag" if argument_flag == nil
  292. canonical_name = nil
  293. arg.each do |i|
  294. #
  295. # Check an option name.
  296. #
  297. next if i == argument_flag
  298. begin
  299. if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
  300. raise ArgumentError, "an invalid option `#{i}'"
  301. end
  302. if (@canonical_names.include?(i))
  303. raise ArgumentError, "option redefined `#{i}'"
  304. end
  305. rescue
  306. @canonical_names.clear
  307. @argument_flags.clear
  308. raise
  309. end
  310. #
  311. # Register the option (`i') to the `@canonical_names' and
  312. # `@canonical_names' Hashes.
  313. #
  314. if canonical_name == nil
  315. canonical_name = i
  316. end
  317. @canonical_names[i] = canonical_name
  318. @argument_flags[i] = argument_flag
  319. end
  320. raise ArgumentError, "no option name" if canonical_name == nil
  321. end
  322. return self
  323. end
  324. #
  325. # Set/Unset `quiet' mode.
  326. #
  327. attr_writer :quiet
  328. #
  329. # Return the flag of `quiet' mode.
  330. #
  331. attr_reader :quiet
  332. #
  333. # `quiet?' is an alias of `quiet'.
  334. #
  335. alias quiet? quiet
  336. #
  337. # Explicitly terminate option processing.
  338. #
  339. def terminate
  340. return nil if @status == STATUS_TERMINATED
  341. raise RuntimeError, "an error has occured" if @error != nil
  342. @status = STATUS_TERMINATED
  343. @non_option_arguments.reverse_each do |argument|
  344. ARGV.unshift(argument)
  345. end
  346. @canonical_names = nil
  347. @argument_flags = nil
  348. @rest_singles = nil
  349. @non_option_arguments = nil
  350. return self
  351. end
  352. #
  353. # Returns true if option processing has terminated, false otherwise.
  354. #
  355. def terminated?
  356. return @status == STATUS_TERMINATED
  357. end
  358. #
  359. # Set an error (protected).
  360. #
  361. def set_error(type, message)
  362. $deferr.print("#{$0}: #{message}\n") if !@quiet
  363. @error = type
  364. @error_message = message
  365. @canonical_names = nil
  366. @argument_flags = nil
  367. @rest_singles = nil
  368. @non_option_arguments = nil
  369. raise type, message
  370. end
  371. protected :set_error
  372. #
  373. # Examine whether an option processing is failed.
  374. #
  375. attr_reader :error
  376. #
  377. # `error?' is an alias of `error'.
  378. #
  379. alias error? error
  380. # Return the appropriate error message in POSIX-defined format.
  381. # If no error has occurred, returns nil.
  382. #
  383. def error_message
  384. return @error_message
  385. end
  386. #
  387. # Get next option name and its argument, as an Array of two elements.
  388. #
  389. # The option name is always converted to the first (preferred)
  390. # name given in the original options to GetoptLong.new.
  391. #
  392. # Example: ['--option', 'value']
  393. #
  394. # Returns nil if the processing is complete (as determined by
  395. # STATUS_TERMINATED).
  396. #
  397. def get
  398. option_name, option_argument = nil, ''
  399. #
  400. # Check status.
  401. #
  402. return nil if @error != nil
  403. case @status
  404. when STATUS_YET
  405. @status = STATUS_STARTED
  406. when STATUS_TERMINATED
  407. return nil
  408. end
  409. #
  410. # Get next option argument.
  411. #
  412. if 0 < @rest_singles.length
  413. argument = '-' + @rest_singles
  414. elsif (ARGV.length == 0)
  415. terminate
  416. return nil
  417. elsif @ordering == PERMUTE
  418. while 0 < ARGV.length && ARGV[0] !~ /^-./
  419. @non_option_arguments.push(ARGV.shift)
  420. end
  421. if ARGV.length == 0
  422. terminate
  423. return nil
  424. end
  425. argument = ARGV.shift
  426. elsif @ordering == REQUIRE_ORDER
  427. if (ARGV[0] !~ /^-./)
  428. terminate
  429. return nil
  430. end
  431. argument = ARGV.shift
  432. else
  433. argument = ARGV.shift
  434. end
  435. #
  436. # Check the special argument `--'.
  437. # `--' indicates the end of the option list.
  438. #
  439. if argument == '--' && @rest_singles.length == 0
  440. terminate
  441. return nil
  442. end
  443. #
  444. # Check for long and short options.
  445. #
  446. if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0
  447. #
  448. # This is a long style option, which start with `--'.
  449. #
  450. pattern = $1
  451. if @canonical_names.include?(pattern)
  452. option_name = pattern
  453. else
  454. #
  455. # The option `option_name' is not registered in `@canonical_names'.
  456. # It may be an abbreviated.
  457. #
  458. match_count = 0
  459. @canonical_names.each_key do |key|
  460. if key.index(pattern) == 0
  461. option_name = key
  462. match_count += 1
  463. end
  464. end
  465. if 2 <= match_count
  466. set_error(AmbigousOption, "option `#{argument}' is ambiguous")
  467. elsif match_count == 0
  468. set_error(InvalidOption, "unrecognized option `#{argument}'")
  469. end
  470. end
  471. #
  472. # Check an argument to the option.
  473. #
  474. if @argument_flags[option_name] == REQUIRED_ARGUMENT
  475. if argument =~ /=(.*)$/
  476. option_argument = $1
  477. elsif 0 < ARGV.length
  478. option_argument = ARGV.shift
  479. else
  480. set_error(MissingArgument,
  481. "option `#{argument}' requires an argument")
  482. end
  483. elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
  484. if argument =~ /=(.*)$/
  485. option_argument = $1
  486. elsif 0 < ARGV.length && ARGV[0] !~ /^-./
  487. option_argument = ARGV.shift
  488. else
  489. option_argument = ''
  490. end
  491. elsif argument =~ /=(.*)$/
  492. set_error(NeedlessArgument,
  493. "option `#{option_name}' doesn't allow an argument")
  494. end
  495. elsif argument =~ /^(-(.))(.*)/
  496. #
  497. # This is a short style option, which start with `-' (not `--').
  498. # Short options may be catenated (e.g. `-l -g' is equivalent to
  499. # `-lg').
  500. #
  501. option_name, ch, @rest_singles = $1, $2, $3
  502. if @canonical_names.include?(option_name)
  503. #
  504. # The option `option_name' is found in `@canonical_names'.
  505. # Check its argument.
  506. #
  507. if @argument_flags[option_name] == REQUIRED_ARGUMENT
  508. if 0 < @rest_singles.length
  509. option_argument = @rest_singles
  510. @rest_singles = ''
  511. elsif 0 < ARGV.length
  512. option_argument = ARGV.shift
  513. else
  514. # 1003.2 specifies the format of this message.
  515. set_error(MissingArgument, "option requires an argument -- #{ch}")
  516. end
  517. elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
  518. if 0 < @rest_singles.length
  519. option_argument = @rest_singles
  520. @rest_singles = ''
  521. elsif 0 < ARGV.length && ARGV[0] !~ /^-./
  522. option_argument = ARGV.shift
  523. else
  524. option_argument = ''
  525. end
  526. end
  527. else
  528. #
  529. # This is an invalid option.
  530. # 1003.2 specifies the format of this message.
  531. #
  532. if ENV.include?('POSIXLY_CORRECT')
  533. set_error(InvalidOption, "illegal option -- #{ch}")
  534. else
  535. set_error(InvalidOption, "invalid option -- #{ch}")
  536. end
  537. end
  538. else
  539. #
  540. # This is a non-option argument.
  541. # Only RETURN_IN_ORDER falled into here.
  542. #
  543. return '', argument
  544. end
  545. return @canonical_names[option_name], option_argument
  546. end
  547. #
  548. # `get_option' is an alias of `get'.
  549. #
  550. alias get_option get
  551. # Iterator version of `get'.
  552. #
  553. # The block is called repeatedly with two arguments:
  554. # The first is the option name.
  555. # The second is the argument which followed it (if any).
  556. # Example: ('--opt', 'value')
  557. #
  558. # The option name is always converted to the first (preferred)
  559. # name given in the original options to GetoptLong.new.
  560. #
  561. def each
  562. loop do
  563. option_name, option_argument = get_option
  564. break if option_name == nil
  565. yield option_name, option_argument
  566. end
  567. end
  568. #
  569. # `each_option' is an alias of `each'.
  570. #
  571. alias each_option each
  572. end