Class: Boson::OptionParser
- Inherits:
-
Object
- Object
- Boson::OptionParser
- Defined in:
- lib/boson/option_parser.rb
Overview
This class concisely defines commandline options that when parsed produce a Hash of option keys and values. Additional points:
-
Setting option values should follow conventions in *nix environments. See examples below.
-
By default, there are 5 option types, each which produce different objects for option values.
-
The default option types can produce objects for one or more of the following Ruby classes: String, Integer, Float, Array, Hash, FalseClass, TrueClass.
-
Users can define their own option types which create objects for any Ruby class. See Options.
-
Each option type can have attributes to enable more features (see OptionParser.new).
-
When options are parsed by parse(), an IndifferentAccessHash hash is returned.
-
Options are also called switches, parameters, flags etc.
-
Option parsing stops when it comes across a ‘–’.
Default option types:
- :boolean
-
This option has no passed value. To toogle a boolean, prepend with ‘–no-’. Multiple booleans can be joined together.
'--debug' -> {:debug=>true} '--no-debug' -> {:debug=>false} '--no-d' -> {:debug=>false} '-d -f -t' same as '-dft'
- :string
-
Sets values by separating name from value with space or ‘=’.
'--color red' -> {:color=>'red'} '--color=red' -> {:color=>'red'} '--color "gotta love spaces"' -> {:color=>'gotta love spaces'}
- :numeric
-
Sets values as :string does or by appending number right after aliased name. Shortened form can be appended to joined booleans.
'-n3' -> {:num=>3} '-dn3' -> {:debug=>true, :num=>3}
- :array
-
Sets values as :string does. Multiple values are split by a configurable character Default is ‘,’ (see OptionParser.new). Passing ‘*’ refers to all known :values.
'--fields 1,2,3' -> {:fields=>['1','2','3']} '--fields *' -> {:fields=>['1','2','3']}
- :hash
-
Sets values as :string does. Key-value pairs are split by ‘:’ and pairs are split by a configurable character (default ‘,’). Multiple keys can be joined to one value. Passing ‘*’ as a key refers to all known :keys.
'--fields a:b,c:d' -> {:fields=>{'a'=>'b', 'c'=>'d'} } '--fields a,b:d' -> {:fields=>{'a'=>'d', 'b'=>'d'} } '--fields *:d' -> {:fields=>{'a'=>'d', 'b'=>'d', 'c'=>'d'} }
This is a modified version of Yehuda Katz’s Thor::Options class which is a modified version of Daniel Berger’s Getopt::Long class (licensed under Ruby’s license).
Defined Under Namespace
Classes: Error
Constant Summary collapse
- NUMERIC =
/(\d*\.\d+|\d+)/
- LONG_RE =
/^(--\w+[-\w+]*)$/
- SHORT_RE =
/^(-[a-zA-Z])$/i
- EQ_RE =
/^(--\w+[-\w+]*|-[a-zA-Z])=(.*)$/i
- SHORT_SQ_RE =
Allow either -x -v or -xv style for single char args
/^-([a-zA-Z]{2,})$/i
- SHORT_NUM =
/^(-[a-zA-Z])#{NUMERIC}$/i
- STOP_STRINGS =
%w{-- -}
Instance Attribute Summary collapse
-
#leading_non_opts ⇒ Object
readonly
Returns the value of attribute leading_non_opts.
-
#opt_aliases ⇒ Object
readonly
Returns the value of attribute opt_aliases.
-
#trailing_non_opts ⇒ Object
readonly
Returns the value of attribute trailing_non_opts.
Class Method Summary collapse
-
.make_mergeable!(opts) ⇒ Object
:nodoc:.
-
.parse(options, args = ARGV) ⇒ Object
Given options to pass to OptionParser.new, this method parses ARGV and returns the remaining arguments and a hash of parsed options.
-
.usage ⇒ Object
Usage string summarizing options defined in parse.
Instance Method Summary collapse
-
#aliases ⇒ Object
List of option aliases.
-
#all_options_with_fields(fields) ⇒ Object
:nodoc:.
-
#current_attributes ⇒ Object
Hash of option attributes for the currently parsed option.
-
#dasherize(str) ⇒ Object
Adds dashes to an option name i.e.
-
#default_render_options ⇒ Object
:nodoc:.
-
#default_usage(opt, val) ⇒ Object
Helper method to generate usage.
-
#formatted_usage ⇒ Object
(also: #to_s)
Generates one-line usage of all options.
-
#get_usage_fields(fields) ⇒ Object
:nodoc:.
-
#initialize(opts) ⇒ OptionParser
constructor
Takes a hash of options.
-
#names ⇒ Object
List of option names.
-
#non_opts ⇒ Object
Array of arguments left after defined options have been parsed out by parse.
-
#option_attributes ⇒ Object
Hash of option names mapped to hash of its external attributes.
- #option_type(opt) ⇒ Object
-
#parse(args, flags = {}) ⇒ Object
Parses an array of arguments for defined options to return an IndifferentAccessHash.
-
#print_usage_table(render_options = {}) ⇒ Object
More verbose option help in the form of a table.
-
#types ⇒ Object
List of option types.
-
#undasherize(str) ⇒ Object
Removes dashes from a dashed option i.e.
Constructor Details
#initialize(opts) ⇒ OptionParser
Takes a hash of options. Each option, a key-value pair, must provide the option’s name and type. Names longer than one character are accessed with ‘–’ while one character names are accessed with ‘-’. Names can be symbols, strings or even dasherized strings:
Boson::OptionParser.new :debug=>:boolean, 'level'=>:numeric,
'--fields'=>:array
Options can have default values and implicit types simply by changing the option type for the default value:
Boson::OptionParser.new :debug=>true, 'level'=>3.1, :fields=>%w{f1 f2}
By default every option name longer than one character is given an alias, the first character from its name. For example, the –fields option has -f as its alias. You can override the default alias by providing your own option aliases as an array in the option’s key.
Boson::OptionParser.new [:debug, :damnit, :D]=>true
Note that aliases are accessed the same way as option names. For the above, –debug, –damnit and -D all refer to the same option.
Options can have additional attributes by passing a hash to the option value instead of a type or default:
Boson::OptionParser.new :fields=>{:type=>:array, :values=>%w{f1 f2 f3},
:enum=>false}
These attributes are available when an option is parsed via current_attributes(). Here are the available option attributes for the default option types:
- :type
-
This or :default is required. Available types are :string, :boolean, :array, :numeric, :hash.
- :default
-
This or :type is required. This is the default value an option has when not passed.
- :bool_default
-
This is the value an option has when passed as a boolean. However, by enabling this an option can only have explicit values with ‘=’ i.e. ‘–index=alias’ and no ‘–index alias’. If this value is a string, it is parsed as any option value would be. Otherwise, the value is passed directly without parsing.
- :required
-
Boolean indicating if option is required. Option parses raises error if value not given. Default is false.
- :alias
-
Alternative way to define option aliases with an option name or an array of them. Useful in yaml files. Setting to false will prevent creating an automatic alias.
- :values
-
An array of values an option can have. Available for :array and :string options. Values here can be aliased by typing a unique string it starts with or underscore aliasing (see Util.underscore_search). For example, for values foo, odd and obnoxiously_long, f refers to foo, od to odd and o_l to obnoxiously_long.
- :enum
-
Boolean indicating if an option enforces values in :values or :keys. Default is true. For :array, :hash and :string options.
- :split
-
For :array and :hash options. A string or regular expression on which an array value splits to produce an array of values. Default is ‘,’.
- :keys
-
:hash option only. An array of values a hash option’s keys can have. Keys can be aliased just like :values.
- :default_keys
-
For :hash option only. Default keys to assume when only a value is given. Multiple keys can be joined by the :split character. Defaults to first key of :keys if :keys given.
- :regexp
-
For :array option with a :values attribute. Boolean indicating that each option value does a regular expression search of :values. If there are values that match, they replace the original option value. If none, then the original option value is used.
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 |
# File 'lib/boson/option_parser.rb', line 165 def initialize(opts) @defaults = {} @opt_aliases = {} @leading_non_opts, @trailing_non_opts = [], [] # build hash of dashed options to option types # type can be a hash of opt attributes, a default value or a type symbol @opt_types = opts.inject({}) do |mem, (name, type)| name, *aliases = name if name.is_a?(Array) name = name.to_s # we need both nice and dasherized form of option name if name.index('-') == 0 nice_name = undasherize name else nice_name = name name = dasherize name end # store for later @opt_aliases[nice_name] = aliases || [] if type.is_a?(Hash) @option_attributes ||= {} @option_attributes[nice_name] = type @opt_aliases[nice_name] = Array(type[:alias]) if type.key?(:alias) @defaults[nice_name] = type[:default] if type[:default] @option_attributes[nice_name][:enum] = true if (type.key?(:values) || type.key?(:keys)) && !type.key?(:enum) @option_attributes[nice_name][:default_keys] ||= type[:keys][0] if type.key?(:keys) type = type[:type] || (!type[:default].nil? ? determine_option_type(type[:default]) : :boolean) end # set defaults case type when TrueClass then @defaults[nice_name] = true when FalseClass then @defaults[nice_name] = false else @defaults[nice_name] = type unless type.is_a?(Symbol) end mem[name] = !type.nil? ? determine_option_type(type) : type mem end # generate hash of dashed aliases to dashed options @opt_aliases = @opt_aliases.sort.inject({}) {|h, (nice_name, aliases)| name = dasherize nice_name # allow for aliases as symbols aliases.map! {|e| e.to_s.index('-') == 0 || e == false ? e : dasherize(e.to_s) } if aliases.empty? and nice_name.length > 1 opt_alias = nice_name[0,1] opt_alias = h.key?("-"+opt_alias) ? "-"+opt_alias.capitalize : "-"+opt_alias h[opt_alias] ||= name unless @opt_types.key?(opt_alias) else aliases.each {|e| h[e] = name if !@opt_types.key?(e) && e != false } end h } end |
Instance Attribute Details
#leading_non_opts ⇒ Object (readonly)
Returns the value of attribute leading_non_opts.
82 83 84 |
# File 'lib/boson/option_parser.rb', line 82 def leading_non_opts @leading_non_opts end |
#opt_aliases ⇒ Object (readonly)
Returns the value of attribute opt_aliases.
82 83 84 |
# File 'lib/boson/option_parser.rb', line 82 def opt_aliases @opt_aliases end |
#trailing_non_opts ⇒ Object (readonly)
Returns the value of attribute trailing_non_opts.
82 83 84 |
# File 'lib/boson/option_parser.rb', line 82 def trailing_non_opts @trailing_non_opts end |
Class Method Details
.make_mergeable!(opts) ⇒ Object
:nodoc:
97 98 99 100 101 102 103 |
# File 'lib/boson/option_parser.rb', line 97 def self.make_mergeable!(opts) #:nodoc: opts.each {|k,v| if !v.is_a?(Hash) && !v.is_a?(Symbol) opts[k] = {:default=>v} end } end |
.parse(options, args = ARGV) ⇒ Object
Given options to pass to OptionParser.new, this method parses ARGV and returns the remaining arguments and a hash of parsed options. This is useful for scripts outside of Boson.
86 87 88 89 90 |
# File 'lib/boson/option_parser.rb', line 86 def self.parse(, args=ARGV) @opt_parser ||= new() = @opt_parser.parse(args) [@opt_parser.non_opts, ] end |
.usage ⇒ Object
Usage string summarizing options defined in parse
93 94 95 |
# File 'lib/boson/option_parser.rb', line 93 def self.usage @opt_parser.to_s end |
Instance Method Details
#aliases ⇒ Object
List of option aliases
349 350 351 |
# File 'lib/boson/option_parser.rb', line 349 def aliases @opt_aliases.keys.map {|e| undasherize e } end |
#all_options_with_fields(fields) ⇒ Object
:nodoc:
293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/boson/option_parser.rb', line 293 def (fields) #:nodoc: aliases = @opt_aliases.invert @opt_types.keys.sort.inject([]) {|t,e| nice_name = undasherize(e) h = {:name=>e, :type=>@opt_types[e], :alias=>aliases[e] || '' } h[:default] = @defaults[nice_name] if fields.include?(:default) (fields - h.keys).each {|f| h[f] = (option_attributes[nice_name] || {})[f] } t << h } end |
#current_attributes ⇒ Object
Hash of option attributes for the currently parsed option. Any hash keys passed to an option are available here. This means that an option type can have any user-defined attributes available during option parsing and object creation.
324 325 326 |
# File 'lib/boson/option_parser.rb', line 324 def current_attributes @option_attributes && @option_attributes[@current_option] || {} end |
#dasherize(str) ⇒ Object
Adds dashes to an option name i.e. ‘date’ -> ‘–date’ and ‘d’ -> ‘-d’.
334 335 336 |
# File 'lib/boson/option_parser.rb', line 334 def dasherize(str) (str.length > 1 ? "--" : "-") + str end |
#default_render_options ⇒ Object
:nodoc:
306 307 308 309 |
# File 'lib/boson/option_parser.rb', line 306 def #:nodoc: {:header_filter=>:capitalize, :description=>false, :filter_any=>true, :filter_classes=>{Array=>[:join, ',']}, :hide_empty=>true} end |
#default_usage(opt, val) ⇒ Object
Helper method to generate usage. Takes a dashed option and a string value indicating an option value’s format.
267 268 269 |
# File 'lib/boson/option_parser.rb', line 267 def default_usage(opt, val) opt + "=" + (@defaults[undasherize(opt)] || val).to_s end |
#formatted_usage ⇒ Object Also known as: to_s
Generates one-line usage of all options.
272 273 274 275 276 277 278 |
# File 'lib/boson/option_parser.rb', line 272 def formatted_usage return "" if @opt_types.empty? @opt_types.map do |opt, type| val = respond_to?("usage_for_#{type}", true) ? send("usage_for_#{type}", opt) : "#{opt}=:#{type}" "[" + val + "]" end.join(" ") end |
#get_usage_fields(fields) ⇒ Object
:nodoc:
316 317 318 319 |
# File 'lib/boson/option_parser.rb', line 316 def get_usage_fields(fields) #:nodoc: fields || ([:name, :alias, :type] + [:desc, :values, :keys].select {|e| option_attributes.values.any? {|f| f.key?(e) } }).uniq end |
#names ⇒ Object
List of option names
344 345 346 |
# File 'lib/boson/option_parser.rb', line 344 def names @opt_types.keys.map {|e| undasherize e } end |
#non_opts ⇒ Object
Array of arguments left after defined options have been parsed out by parse.
106 107 108 |
# File 'lib/boson/option_parser.rb', line 106 def non_opts leading_non_opts + trailing_non_opts end |
#option_attributes ⇒ Object
Hash of option names mapped to hash of its external attributes
312 313 314 |
# File 'lib/boson/option_parser.rb', line 312 def option_attributes @option_attributes || {} end |
#option_type(opt) ⇒ Object
353 354 355 356 357 358 359 |
# File 'lib/boson/option_parser.rb', line 353 def option_type(opt) if opt =~ /^--no-(\w+)$/ @opt_types[opt] || @opt_types[dasherize($1)] || @opt_types[original_no_opt($1)] else @opt_types[opt] end end |
#parse(args, flags = {}) ⇒ Object
Parses an array of arguments for defined options to return an IndifferentAccessHash. Once the parser recognizes a valid option, it continues to parse until an non option argument is detected. Flags that can be passed to the parser:
-
:opts_before_args: When true options must come before arguments. Default is false.
-
:delete_invalid_opts: When true deletes any invalid options left after parsing. Will stop deleting if it comes across - or –. Default is false.
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/boson/option_parser.rb', line 228 def parse(args, flags={}) @args = args # start with defaults hash = IndifferentAccessHash.new @defaults @leading_non_opts = [] unless flags[:opts_before_args] @leading_non_opts << shift until current_is_option? || @args.empty? || STOP_STRINGS.include?(peek) end while current_is_option? case @original_current_option = shift when SHORT_SQ_RE unshift $1.split('').map { |f| "-#{f}" } next when EQ_RE, SHORT_NUM unshift $2 option = $1 when LONG_RE, SHORT_RE option = $1 end dashed_option = normalize_option(option) @current_option = undasherize(dashed_option) type = option_type(dashed_option) validate_option_value(type) value = create_option_value(type) # set on different line since current_option may change hash[@current_option.to_sym] = value end @trailing_non_opts = @args check_required! hash delete_invalid_opts if flags[:delete_invalid_opts] hash end |
#print_usage_table(render_options = {}) ⇒ Object
More verbose option help in the form of a table.
283 284 285 286 287 288 289 290 291 |
# File 'lib/boson/option_parser.rb', line 283 def print_usage_table(={}) user_fields = .delete(:fields) fields = get_usage_fields user_fields (fields << :default).uniq! if .delete(:local) || user_fields == '*' opts = fields fields.delete(:default) if fields.include?(:default) && opts.all? {|e| e[:default].nil? } = .merge(:fields=>fields).merge() View.render opts, end |
#types ⇒ Object
List of option types
339 340 341 |
# File 'lib/boson/option_parser.rb', line 339 def types @opt_types.values end |
#undasherize(str) ⇒ Object
Removes dashes from a dashed option i.e. ‘–date’ -> ‘date’ and ‘-d’ -> ‘d’.
329 330 331 |
# File 'lib/boson/option_parser.rb', line 329 def undasherize(str) str.sub(/^-{1,2}/, '') end |