Method: Trollop::Parser#opt
- Defined in:
- lib/amp/dependencies/trollop.rb
#opt(name, desc = "", opts = {}) ⇒ Object
Define an option. name is the option name, a unique identifier
for the option that you will use internally, which should be a
symbol or a string. desc is a string description which will be
displayed in help messages.
Takes the following optional arguments:
[+:long+] Specify the long form of the argument, i.e. the form with two dashes. If unspecified, will be automatically derived based on the argument name by turning the name option into a string, and replacing any _'s by -'s.
[+:short+] Specify the short form of the argument, i.e. the form with one dash. If unspecified, will be automatically derived from name.
[+:type+] Require that the argument take a parameter or parameters of type type. For a single parameter, the value can be a member of SINGLE_ARG_TYPES, or a corresponding Ruby class (e.g. Integer for :int). For multiple-argument parameters, the value can be any member of MULTI_ARG_TYPES constant. If unset, the default argument type is :flag, meaning that the argument does not take a parameter. The specification of :type is not necessary if a :default is given.
[+:default+] Set the default value for an argument. Without a default value, the hash returned by #parse (and thus Trollop::options) will have a nil value for this key unless the argument is given on the commandline. The argument type is derived automatically from the class of the default value given, so specifying a :type is not necessary if a :default is given. (But see below for an important caveat when :multi: is specified too.) If the argument is a flag, and the default is set to true, then if it is specified on the the commandline the value will be false.
[+:required+] If set to true, the argument must be provided on the commandline.
[+:multi+] If set to true, allows multiple occurrences of the option on the commandline. Otherwise, only a single instance of the option is allowed. (Note that this is different from taking multiple parameters. See below.)
Note that there are two types of argument multiplicity: an argument can take multiple values, e.g. "--arg 1 2 3". An argument can also be allowed to occur multiple times, e.g. "--arg 1 --arg 2".
Arguments that take multiple values should have a :type parameter
drawn from MULTI_ARG_TYPES (e.g. :strings), or a :default:
value of an array of the correct type (e.g. [String]). The
value of this argument will be an array of the parameters on the
commandline.
Arguments that can occur multiple times should be marked with
:multi => true. The value of this argument will also be an array.
These two attributes can be combined (e.g. :type => :strings,
:multi => true), in which case the value of the argument will be
an array of arrays.
There's one ambiguous case to be aware of: when :multi: is true and a
:default is set to an array (of something), it's ambiguous whether this
is a multi-value argument as well as a multi-occurrence argument.
In thise case, Trollop assumes that it's not a multi-value argument.
If you want a multi-value, multi-occurrence argument with a default
value, you must specify :type as well.
119 120 121 122 123 124 125 126 127 128 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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/amp/dependencies/trollop.rb', line 119 def opt name, desc="", opts={} raise ArgumentError, "you already have an argument named '#{name}'" if @specs.member? name ## fill in :type opts[:type] = # normalize case opts[:type] when :boolean, :bool; :flag when :integer; :int when :integers; :ints when :double; :float when :doubles; :floats when Class case opts[:type].to_s # sigh... there must be a better way to do this when 'TrueClass', 'FalseClass'; :flag when 'String'; :string when 'Integer'; :int when 'Float'; :float when 'IO'; :io else raise ArgumentError, "unsupported argument type '#{opts[:type].class.name}'" end when nil; nil else raise ArgumentError, "unsupported argument type '#{opts[:type]}'" unless TYPES.include?(opts[:type]) opts[:type] end ## for options with :multi => true, an array default doesn't imply ## a multi-valued argument. for that you have to specify a :type ## as well. (this is how we disambiguate an ambiguous situation; ## see the docs for Parser#opt for details.) disambiguated_default = if opts[:multi] && opts[:default].is_a?(Array) && !opts[:type] opts[:default].first else opts[:default] end type_from_default = case disambiguated_default when Integer; :int when Numeric; :float when TrueClass, FalseClass; :flag when String; :string when IO; :io when Array if opts[:default].empty? raise ArgumentError, "multiple argument type cannot be deduced from an empty array for '#{opts[:default][0].class.name}'" end case opts[:default][0] # the first element determines the types when Integer; :ints when Numeric; :floats when String; :strings when IO; :ios else raise ArgumentError, "unsupported multiple argument type '#{opts[:default][0].class.name}'" end when nil; nil else raise ArgumentError, "unsupported argument type '#{opts[:default].class.name}'" end raise ArgumentError, ":type specification and default type don't match" if opts[:type] && type_from_default && opts[:type] != type_from_default opts[:type] = opts[:type] || type_from_default || :flag ## fill in :long opts[:long] = opts[:long] ? opts[:long].to_s : name.to_s.gsub("_", "-") opts[:long] = case opts[:long] when /^--([^-].*)$/ $1 when /^[^-]/ opts[:long] else raise ArgumentError, "invalid long option name #{opts[:long].inspect}" end raise ArgumentError, "long option name #{opts[:long].inspect} is already taken; please specify a (different) :long" if @long[opts[:long]] ## fill in :short opts[:short] = opts[:short].to_s if opts[:short] unless opts[:short] == :none opts[:short] = case opts[:short] when /^-(.)$/; $1 when nil, :none, /^.$/; opts[:short] else raise ArgumentError, "invalid short option name '#{opts[:short].inspect}'" end if opts[:short] raise ArgumentError, "short option name #{opts[:short].inspect} is already taken; please specify a (different) :short" if @short[opts[:short]] raise ArgumentError, "a short option name can't be a number or a dash" if opts[:short] =~ INVALID_SHORT_ARG_REGEX end ## fill in :default for flags opts[:default] = false if opts[:type] == :flag && opts[:default].nil? ## autobox :default for :multi (multi-occurrence) arguments opts[:default] = [opts[:default]] if opts[:default] && opts[:multi] && !opts[:default].is_a?(Array) ## fill in :multi opts[:multi] ||= false opts[:desc] ||= desc @long[opts[:long]] = name @short[opts[:short]] = name if opts[:short] && opts[:short] != :none @specs[name] = opts @order << [:opt, name] end |