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 -- /tmpConstants
Argument flags.
Orderings.
Version.
error[R]
Examine whether an option processing is failed.
error?[R]
Examine whether an option processing is failed.
ordering[R]
Return ordering.
quiet[RW]
Set/Unset `quiet' mode.
quiet?[RW]
Set/Unset `quiet' mode.
Public Class Methodsnew(*arguments) click to toggle source
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:
Option does not take an argument.
Option always takes an 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.
def initialize(*arguments) if ENV.include?('POSIXLY_CORRECT') @ordering = REQUIRE_ORDER else @ordering = PERMUTE end @canonical_names = Hash.new @argument_flags = Hash.new @quiet = false @status = STATUS_YET @error = nil @error_message = nil @rest_singles = '' @non_option_arguments = Array.new if 0 < arguments.length set_options(*arguments) end endPublic Instance Methods
each() { |option_name, option_argument| ... } click to toggle source
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
.
def each loop do option_name, option_argument = get_option break if option_name == nil yield option_name, option_argument end end
each_option()
`each_option' is an alias of `each'.
error_message() click to toggle source
Return the appropriate error message in POSIX-defined format. If no error has occurred, returns nil.
def error_message return @error_message end
get() click to toggle source
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
).
def get option_name, option_argument = nil, '' return nil if @error != nil case @status when STATUS_YET @status = STATUS_STARTED when STATUS_TERMINATED return nil end if 0 < @rest_singles.length argument = '-' + @rest_singles elsif (ARGV.length == 0) terminate return nil elsif @ordering == PERMUTE while 0 < ARGV.length && ARGV[0] !~ /\A-./ @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] !~ /\A-./) terminate return nil end argument = ARGV.shift else argument = ARGV.shift end if argument == '--' && @rest_singles.length == 0 terminate return nil end if argument =~ /\A(--[^=]+)/ && @rest_singles.length == 0 pattern = $1 if @canonical_names.include?(pattern) option_name = pattern else 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 if @argument_flags[option_name] == REQUIRED_ARGUMENT if argument =~ /=(.*)/m 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 =~ /=(.*)/m option_argument = $1 elsif 0 < ARGV.length && ARGV[0] !~ /\A-./ option_argument = ARGV.shift else option_argument = '' end elsif argument =~ /=(.*)/m set_error(NeedlessArgument, "option `#{option_name}' doesn't allow an argument") end elsif argument =~ /\A(-(.))(.*)/m option_name, ch, @rest_singles = $1, $2, $3 if @canonical_names.include?(option_name) 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 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] !~ /\A-./ option_argument = ARGV.shift else option_argument = '' end end else if ENV.include?('POSIXLY_CORRECT') set_error(InvalidOption, "invalid option -- #{ch}") else set_error(InvalidOption, "invalid option -- #{ch}") end end else return '', argument end return @canonical_names[option_name], option_argument end
get_option()
`get_option' is an alias of `get'.
ordering=(ordering) click to toggle source
Set
the handling of the ordering of options and arguments. A RuntimeError
is raised if option processing has already started.
The supplied value must be a member of GetoptLong::ORDERINGS
. It alters the processing of options as follows:
REQUIRE_ORDER :
Options are required to occur before non-options.
Processing of options ends as soon as a word is encountered that has not been preceded by an appropriate option flag.
For example, if -a and -b are options which do not take arguments, parsing command line arguments of '-a one -b two' would result in 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being processed as an option/arg pair.
This is the default ordering, if the environment variable POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
PERMUTE :
Options can occur anywhere in the command line parsed. This is the default behavior.
Every sequence of words which can be interpreted as an option (with or without argument) is treated as an option; non-option words are skipped.
For example, if -a does not require an argument and -b optionally takes an argument, parsing '-a one -b two three' would result in ('-a','') and ('-b', 'two') being processed as option/arg pairs, and 'one','three' being left in ARGV.
If the ordering is set to PERMUTE but the environment variable POSIXLY_CORRECT is set, REQUIRE_ORDER is used instead. This is for compatibility with GNU getopt_long.
RETURN_IN_ORDER :
All words on the command line are processed as options. Words not preceded by a short or long option flag are passed as arguments with an option of '' (empty string).
For example, if -a requires an argument but -b does not, a command line of '-a one -b two three' would result in option/arg pairs of ('-a', 'one') ('-b', ''), ('', 'two'), ('', 'three') being processed.
def ordering=(ordering) if @status != STATUS_YET set_error(ArgumentError, "argument error") raise RuntimeError, "invoke ordering=, but option processing has already started" end if !ORDERINGS.include?(ordering) raise ArgumentError, "invalid ordering `#{ordering}'" end if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT') @ordering = REQUIRE_ORDER else @ordering = ordering end end
set_options(*arguments) click to toggle source
Set
options. Takes the same argument as GetoptLong.new
.
Raises a RuntimeError
if option processing has already started.
def set_options(*arguments) if @status != STATUS_YET raise RuntimeError, "invoke set_options, but option processing has already started" end @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 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| next if i == argument_flag begin if !i.is_a?(String) || i !~ /\A-([^-]|-.+)\z/ 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 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() click to toggle source
Explicitly terminate option processing.
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?() click to toggle source
Returns true if option processing has terminated, false otherwise.
def terminated? return @status == STATUS_TERMINATED endProtected Instance Methods
set_error(type, message) click to toggle source
Set
an error (a protected method).
def set_error(type, message) $stderr.print("#{$0}: #{message}\n") if !@quiet @error = type @error_message = message @canonical_names = nil @argument_flags = nil @rest_singles = nil @non_option_arguments = nil raise type, message end
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4