# frozen_string_literal: true
# Copyright (C) 1998, 1999, 2000 Motoyuki Kasahara.
# You may redistribute and/or modify this library under the same license
# \Class \GetoptLong provides parsing both for options
# and for regular arguments.
# Using \GetoptLong, you can define options for your program.
# The program can then capture and respond to whatever options
# are included in the command that executes the program.
# A simple example: file <tt>simple.rb</tt>:
# :include: ../sample/getoptlong/simple.rb
# If you are somewhat familiar with options,
# you may want to skip to this
# {full example}[#class-GetoptLong-label-Full+Example].
# A \GetoptLong option has:
# - A string <em>option name</em>.
# - Zero or more string <em>aliases</em> for the name.
# - An <em>option type</em>.
# Options may be defined by calling singleton method GetoptLong.new,
# which returns a new \GetoptLong object.
# Options may then be processed by calling other methods
# such as GetoptLong#each.
# === Option Name and Aliases
# In the array that defines an option,
# the first element is the string option name.
# Often the name takes the 'long' form, beginning with two hyphens.
# The option name may have any number of aliases,
# which are defined by additional string elements.
# The name and each alias must be of one of two forms:
# - Two hyphens, followed by one or more letters.
# - One hyphen, followed by a single letter.
# File <tt>aliases.rb</tt>:
# :include: ../sample/getoptlong/aliases.rb
# An option may be cited by its name,
# or by any of its aliases;
# the parsed option always reports the name, not an alias:
# $ ruby aliases.rb -a -p --xxx --aaa -x
# An option may also be cited by an abbreviation of its name or any alias,
# as long as that abbreviation is unique among the options.
# File <tt>abbrev.rb</tt>:
# :include: ../sample/getoptlong/abbrev.rb
# $ ruby abbrev.rb --xxx --xx --xyz --xy
# This command line raises GetoptLong::AmbiguousOption:
# An option may be cited more than once:
# $ ruby abbrev.rb --xxx --xyz --xxx --xyz
# === Treating Remaining Options as Arguments
# A option-like token that appears
# anywhere after the token <tt>--</tt> is treated as an ordinary argument,
# and is not processed as an option:
# $ ruby abbrev.rb --xxx --xyz -- --xxx --xyz
# Each option definition includes an option type,
# which controls whether the option takes an argument.
# File <tt>types.rb</tt>:
# :include: ../sample/getoptlong/types.rb
# Note that an option type has to do with the <em>option argument</em>
# (whether it is required, optional, or forbidden),
# not with whether the option itself is required.
# ==== Option with Required Argument
# An option of type <tt>GetoptLong::REQUIRED_ARGUMENT</tt>
# must be followed by an argument, which is associated with that option:
# $ ruby types.rb --xxx foo
# If the option is not last, its argument is whatever follows it
# (even if the argument looks like another option):
# $ ruby types.rb --xxx --yyy
# If the option is last, an exception is raised:
# # Raises GetoptLong::MissingArgument
# ==== Option with Optional Argument
# An option of type <tt>GetoptLong::OPTIONAL_ARGUMENT</tt>
# may be followed by an argument, which if given is associated with that option.
# If the option is last, it does not have an argument:
# If the option is followed by another option, it does not have an argument:
# $ ruby types.rb --yyy --zzz
# Otherwise the option is followed by its argument, which is associated
# $ ruby types.rb --yyy foo
# ==== Option with No Argument
# An option of type <tt>GetoptLong::NO_ARGUMENT</tt> takes no argument:
# ruby types.rb --zzz foo
# You can process options either with method #each and a block,
# During processing, each found option is removed, along with its argument
# After processing, each remaining element was neither an option
# nor the argument for an option.
# :include: ../sample/getoptlong/argv.rb
# $ ruby argv.rb --xxx Foo --yyy Bar Baz --zzz Bat Bam
# Original ARGV: ["--xxx", "Foo", "--yyy", "Bar", "Baz", "--zzz", "Bat", "Bam"]
# Remaining ARGV: ["Baz", "Bat", "Bam"]
# There are three settings that control the way the options
# The initial setting for a new \GetoptLong object is +REQUIRE_ORDER+
# if environment variable +POSIXLY_CORRECT+ is defined, +PERMUTE+ otherwise.
# In the +PERMUTE+ ordering, options and other, non-option,
# arguments may appear in any order and any mixture.
# File <tt>permute.rb</tt>:
# :include: ../sample/getoptlong/permute.rb
# $ ruby permute.rb Foo --zzz Bar --xxx Baz --yyy Bat Bam --xxx Bag Bah
# Original ARGV: ["Foo", "--zzz", "Bar", "--xxx", "Baz", "--yyy", "Bat", "Bam", "--xxx", "Bag", "Bah"]
# Remaining ARGV: ["Foo", "Bar", "Bam", "Bah"]
# ==== REQUIRE_ORDER Ordering
# In the +REQUIRE_ORDER+ ordering, all options precede all non-options;
# that is, each word after the first non-option word
# is treated as a non-option word (even if it begins with a hyphen).
# File <tt>require_order.rb</tt>:
# :include: ../sample/getoptlong/require_order.rb
# $ ruby require_order.rb --xxx Foo Bar --xxx Baz --yyy Bat -zzz
# Original ARGV: ["--xxx", "Foo", "Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"]
# Remaining ARGV: ["Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"]
# ==== RETURN_IN_ORDER Ordering
# In the +RETURN_IN_ORDER+ ordering, every word is treated as an option.
# A word that begins with a hyphen (or two) is treated in the usual way;
# a word +word+ that does not so begin is treated as an option
# whose name is an empty string, and whose value is +word+.
# File <tt>return_in_order.rb</tt>:
# :include: ../sample/getoptlong/return_in_order.rb
# $ ruby return_in_order.rb Foo --xxx Bar Baz --zzz Bat Bam
# Original ARGV: ["Foo", "--xxx", "Bar", "Baz", "--zzz", "Bat", "Bam"]
# File <tt>fibonacci.rb</tt>:
# :include: ../sample/getoptlong/fibonacci.rb
# Option --number is required.
# Compute Fibonacci number for n.
# -v [boolean], --verbose [boolean]:
# Show intermediate results; default is 'false'.
# $ ruby fibonacci.rb --number
# Raises GetoptLong::MissingArgument:
# fibonacci.rb: option `--number' requires an argument
# $ ruby fibonacci.rb --number 6
# $ ruby fibonacci.rb --number 6 --verbose
# $ ruby fibonacci.rb --number 6 --verbose yes
# --verbose argument must be true or false
# Compute Fibonacci number for n.
# -v [boolean], --verbose [boolean]:
# Show intermediate results; default is 'false'.
ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
class Error < StandardError; end
class AmbiguousOption < Error; end
class NeedlessArgument < Error; end
class MissingArgument < Error; end
class InvalidOption < Error; end
# Returns a new \GetoptLong object based on the given +arguments+.
# See {Options}[#class-GetoptLong-label-Options].
# :include: ../sample/getoptlong/simple.rb
# Raises an exception if:
# - Any of +arguments+ is not an array.
# - Any option name or alias is not a string.
# - Any option type is invalid.
def initialize(*arguments)
if ENV.include?('POSIXLY_CORRECT')
@ordering = REQUIRE_ORDER
# Hash table of option names.
# Keys of the table are option names, and their values are canonical
@canonical_names = Hash.new
# Hash table of argument flags.
# Keys of the table are option names, and their values are argument
@argument_flags = Hash.new
# Whether error messages are output to $stderr.
# Rest of catenated short options.
# List of non-option-arguments.
# Append them to ARGV when option processing is terminated.
@non_option_arguments = Array.new
# Sets the ordering; see {Ordering}[#class-GetoptLong-label-Ordering];
# returns the new ordering.
# If the given +ordering+ is +PERMUTE+ and environment variable
# +POSIXLY_CORRECT+ is defined, sets the ordering to +REQUIRE_ORDER+;
# otherwise sets the ordering to +ordering+:
# options = GetoptLong.new
# options.ordering == GetoptLong::PERMUTE # => true
# options.ordering = GetoptLong::RETURN_IN_ORDER
# options.ordering == GetoptLong::RETURN_IN_ORDER # => true
# ENV['POSIXLY_CORRECT'] = 'true'
# options.ordering = GetoptLong::PERMUTE
# options.ordering == GetoptLong::REQUIRE_ORDER # => true
# Raises an exception if +ordering+ is invalid.
# The method is failed if option processing has already started.
set_error(ArgumentError, "argument error")
"invoke ordering=, but option processing has already started"