Class: GetoptLong
- Inherits:
-
Object
- Object
- GetoptLong
- Defined in:
- lib/getoptlong.rb
Overview
The GetoptLong class allows you to parse command line options similarly to the GNU getopt_long() C library call. Note, however, that GetoptLong is a pure Ruby implementation.
GetoptLong allows for POSIX-style options like --file
as well as single letter options like -f
The empty option --
(two minus symbols) is used to end option processing. This can be particularly important if options have optional arguments.
Here is a simple example of usage:
require 'getoptlong'
opts = GetoptLong.new(
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
[ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
)
dir = nil
name = nil
repetitions = 1
opts.each do |opt, arg|
case opt
when '--help'
puts <<-EOF
hello [OPTION] ... DIR
-h, --help:
show help
--repeat x, -n x:
repeat x times
--name [name]:
greet user by name, if name not supplied default is John
DIR: The directory in which to issue the greeting.
EOF
when '--repeat'
repetitions = arg.to_i
when '--name'
if arg == ''
name = 'John'
else
name = arg
end
end
end
if ARGV.length != 1
puts "Missing dir argument (try --help)"
exit 0
end
dir = ARGV.shift
Dir.chdir(dir)
for i in (1..repetitions)
print "Hello"
if name
print ", #{name}"
end
puts
end
Example command line:
hello -n 6 --name -- /tmp
Defined Under Namespace
Classes: AmbiguousOption, Error, InvalidOption, MissingArgument, NeedlessArgument
Constant Summary collapse
- ORDERINGS =
Orderings.
[REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
- ARGUMENT_FLAGS =
Argument flags.
[NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1, OPTIONAL_ARGUMENT = 2]
Instance Attribute Summary collapse
-
#error ⇒ Object
(also: #error?)
readonly
Examine whether an option processing is failed.
-
#ordering ⇒ Object
Return ordering.
-
#quiet ⇒ Object
(also: #quiet?)
Return the flag of ‘quiet’ mode.
Instance Method Summary collapse
-
#each ⇒ Object
(also: #each_option)
Iterator version of ‘get’.
-
#error_message ⇒ Object
Return the appropriate error message in POSIX-defined format.
-
#get ⇒ Object
(also: #get_option)
Get next option name and its argument, as an Array of two elements.
-
#initialize(*arguments) ⇒ GetoptLong
constructor
Set up option processing.
-
#set_options(*arguments) ⇒ Object
Set options.
-
#terminate ⇒ Object
Explicitly terminate option processing.
-
#terminated? ⇒ Boolean
Returns true if option processing has terminated, false otherwise.
Constructor Details
#initialize(*arguments) ⇒ GetoptLong
Set up option processing.
The options to support are passed to new() as an array of arrays. Each sub-array contains any number of String option names which carry the same meaning, and one of the following flags:
- GetoptLong::NO_ARGUMENT
-
Option does not take an argument.
- GetoptLong::REQUIRED_ARGUMENT
-
Option always takes an argument.
- GetoptLong::OPTIONAL_ARGUMENT
-
Option may or may not take an argument.
The first option name is considered to be the preferred (canonical) name. Other than that, the elements of each sub-array can be in any order.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/getoptlong.rb', line 129 def initialize(*arguments) # # Current ordering. # if ENV.include?('POSIXLY_CORRECT') @ordering = REQUIRE_ORDER else @ordering = PERMUTE end # # Hash table of option names. # Keys of the table are option names, and their values are canonical # names of the options. # @canonical_names = Hash.new # # Hash table of argument flags. # Keys of the table are option names, and their values are argument # flags of the options. # @argument_flags = Hash.new # # Whether error messages are output to $stderr. # @quiet = FALSE # # Status code. # @status = STATUS_YET # # Error code. # @error = nil # # Error message. # @error_message = nil # # Rest of catenated short options. # @rest_singles = '' # # List of non-option-arguments. # Append them to ARGV when option processing is terminated. # @non_option_arguments = Array.new if 0 < arguments.length (*arguments) end end |
Instance Attribute Details
#error ⇒ Object (readonly) Also known as: error?
Examine whether an option processing is failed.
402 403 404 |
# File 'lib/getoptlong.rb', line 402 def error @error end |
#ordering ⇒ Object
Return ordering.
264 265 266 |
# File 'lib/getoptlong.rb', line 264 def ordering @ordering end |
#quiet ⇒ Object Also known as: quiet?
Return the flag of ‘quiet’ mode.
348 349 350 |
# File 'lib/getoptlong.rb', line 348 def quiet @quiet end |
Instance Method Details
#each ⇒ Object Also known as: each_option
Iterator version of ‘get’.
The block is called repeatedly with two arguments: The first is the option name. The second is the argument which followed it (if any). Example: (‘–opt’, ‘value’)
The option name is always converted to the first (preferred) name given in the original options to GetoptLong.new.
601 602 603 604 605 606 607 |
# File 'lib/getoptlong.rb', line 601 def each loop do option_name, option_argument = get_option break if option_name == nil yield option_name, option_argument end end |
#error_message ⇒ Object
Return the appropriate error message in POSIX-defined format. If no error has occurred, returns nil.
412 413 414 |
# File 'lib/getoptlong.rb', line 412 def return @error_message end |
#get ⇒ Object Also known as: get_option
Get next option name and its argument, as an Array of two elements.
The option name is always converted to the first (preferred) name given in the original options to GetoptLong.new.
Example: [‘–option’, ‘value’]
Returns nil if the processing is complete (as determined by STATUS_TERMINATED).
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 |
# File 'lib/getoptlong.rb', line 427 def get option_name, option_argument = nil, '' # # Check status. # return nil if @error != nil case @status when STATUS_YET @status = STATUS_STARTED when STATUS_TERMINATED return nil end # # Get next option argument. # if 0 < @rest_singles.length argument = '-' + @rest_singles elsif (ARGV.length == 0) terminate return nil elsif @ordering == PERMUTE while 0 < ARGV.length && ARGV[0] !~ /^-./ @non_option_arguments.push(ARGV.shift) end if ARGV.length == 0 terminate return nil end argument = ARGV.shift elsif @ordering == REQUIRE_ORDER if (ARGV[0] !~ /^-./) terminate return nil end argument = ARGV.shift else argument = ARGV.shift end # # Check the special argument `--'. # `--' indicates the end of the option list. # if argument == '--' && @rest_singles.length == 0 terminate return nil end # # Check for long and short options. # if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0 # # This is a long style option, which start with `--'. # pattern = $1 if @canonical_names.include?(pattern) option_name = pattern else # # The option `option_name' is not registered in `@canonical_names'. # It may be an abbreviated. # matches = [] @canonical_names.each_key do |key| if key.index(pattern) == 0 option_name = key matches << key end end if 2 <= matches.length set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}") elsif matches.length == 0 set_error(InvalidOption, "unrecognized option `#{argument}'") end end # # Check an argument to the option. # if @argument_flags[option_name] == REQUIRED_ARGUMENT if argument =~ /=(.*)$/ option_argument = $1 elsif 0 < ARGV.length option_argument = ARGV.shift else set_error(MissingArgument, "option `#{argument}' requires an argument") end elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT if argument =~ /=(.*)$/ option_argument = $1 elsif 0 < ARGV.length && ARGV[0] !~ /^-./ option_argument = ARGV.shift else option_argument = '' end elsif argument =~ /=(.*)$/ set_error(NeedlessArgument, "option `#{option_name}' doesn't allow an argument") end elsif argument =~ /^(-(.))(.*)/ # # This is a short style option, which start with `-' (not `--'). # Short options may be catenated (e.g. `-l -g' is equivalent to # `-lg'). # option_name, ch, @rest_singles = $1, $2, $3 if @canonical_names.include?(option_name) # # The option `option_name' is found in `@canonical_names'. # Check its argument. # if @argument_flags[option_name] == REQUIRED_ARGUMENT if 0 < @rest_singles.length option_argument = @rest_singles @rest_singles = '' elsif 0 < ARGV.length option_argument = ARGV.shift else # 1003.2 specifies the format of this message. set_error(MissingArgument, "option requires an argument -- #{ch}") end elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT if 0 < @rest_singles.length option_argument = @rest_singles @rest_singles = '' elsif 0 < ARGV.length && ARGV[0] !~ /^-./ option_argument = ARGV.shift else option_argument = '' end end else # # This is an invalid option. # 1003.2 specifies the format of this message. # if ENV.include?('POSIXLY_CORRECT') set_error(InvalidOption, "invalid option -- #{ch}") else set_error(InvalidOption, "invalid option -- #{ch}") end end else # # This is a non-option argument. # Only RETURN_IN_ORDER fell into here. # return '', argument end return @canonical_names[option_name], option_argument end |
#set_options(*arguments) ⇒ Object
Set options. Takes the same argument as GetoptLong.new.
Raises a RuntimeError if option processing has already started.
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/getoptlong.rb', line 271 def (*arguments) # # The method is failed if option processing has already started. # if @status != STATUS_YET raise RuntimeError, "invoke set_options, but option processing has already started" end # # Clear tables of option names and argument flags. # @canonical_names.clear @argument_flags.clear arguments.each do |arg| if !arg.is_a?(Array) raise ArgumentError, "the option list contains non-Array argument" end # # Find an argument flag and it set to `argument_flag'. # argument_flag = nil arg.each do |i| if ARGUMENT_FLAGS.include?(i) if argument_flag != nil raise ArgumentError, "too many argument-flags" end argument_flag = i end end raise ArgumentError, "no argument-flag" if argument_flag == nil canonical_name = nil arg.each do |i| # # Check an option name. # next if i == argument_flag begin if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/ raise ArgumentError, "an invalid option `#{i}'" end if (@canonical_names.include?(i)) raise ArgumentError, "option redefined `#{i}'" end rescue @canonical_names.clear @argument_flags.clear raise end # # Register the option (`i') to the `@canonical_names' and # `@canonical_names' Hashes. # if canonical_name == nil canonical_name = i end @canonical_names[i] = canonical_name @argument_flags[i] = argument_flag end raise ArgumentError, "no option name" if canonical_name == nil end return self end |
#terminate ⇒ Object
Explicitly terminate option processing.
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
# File 'lib/getoptlong.rb', line 358 def terminate return nil if @status == STATUS_TERMINATED raise RuntimeError, "an error has occurred" if @error != nil @status = STATUS_TERMINATED @non_option_arguments.reverse_each do |argument| ARGV.unshift(argument) end @canonical_names = nil @argument_flags = nil @rest_singles = nil @non_option_arguments = nil return self end |
#terminated? ⇒ Boolean
Returns true if option processing has terminated, false otherwise.
378 379 380 |
# File 'lib/getoptlong.rb', line 378 def terminated? return @status == STATUS_TERMINATED end |