class OptimistXL::Option
Attributes
Public Class Methods
Determines which type of object to create based on arguments passed to OptimistXL::opt
. This is trickier in OptimistXL
, than other cmdline parsers (e.g. Slop) because we allow the default:
to be able to set the option's type.
# File lib/optimist_xl.rb, line 1034 def self.create(name, _desc="", opts={}, _settings={}) opttype = OptimistXL::Parser.registry_getopttype(opts[:type]) opttype_from_default = get_klass_from_default(opts, opttype) #DEBUG# puts "\nopt:#{opttype||'nil'} ofd:#{opttype_from_default}" if opttype_from_default if opttype && opttype_from_default && !opttype.compatible_with?(opttype_from_default) # opttype.is_a? opttype_from_default.class raise ArgumentError, ":type specification (#{opttype.class}) and default type don't match (default type is #{opttype_from_default.class})" end opt_inst = (opttype || opttype_from_default || OptimistXL::BooleanOption.new) ## fill in :long opt_inst.long.set(name, opts[:long], opts[:alt]) ## fill in :short opt_inst.short.add opts[:short] ## fill in :multi multi_given = opts[:multi] || false opt_inst.multi_given = multi_given ## fill in :default for flags defvalue = opts[:default] || opt_inst.default ## fill in permitted values permitted = opts[:permitted] || nil ## autobox :default for :multi (multi-occurrence) arguments defvalue = [defvalue] if defvalue && multi_given && !defvalue.kind_of?(Array) opt_inst.permitted = permitted opt_inst.permitted_response = opts[:permitted_response] if opts[:permitted_response] opt_inst.default = defvalue opt_inst.name = name opt_inst.opts = opts opt_inst end
# File lib/optimist_xl.rb, line 1105 def self.handle_long_opt(lopt, name) lopt = lopt ? lopt.to_s : name.to_s.gsub("_", "-") lopt = case lopt when /^--([^-].*)$/ then $1 when /^[^-]/ then lopt else raise ArgumentError, "invalid long option name #{lopt.inspect}" end end
# File lib/optimist_xl.rb, line 1114 def self.handle_short_opt(sopt) sopt = sopt.to_s if sopt && sopt != :none sopt = case sopt when /^-(.)$/ then $1 when nil, :none, /^.$/ then sopt else raise ArgumentError, "invalid short option name '#{sopt.inspect}'" end if sopt raise ArgumentError, "a short option name can't be a number or a dash" if sopt =~ ::OptimistXL::Parser::INVALID_SHORT_ARG_REGEX end return sopt end
# File lib/optimist_xl.rb, line 866 def initialize @long = LongNames.new @short = ShortNames.new # can be an Array of one-char strings, a one-char String, nil or :none @name = nil @multi_given = false @hidden = false @default = nil @permitted = nil @permitted_response = "option '%{arg}' only accepts %{valid_string}" @optshash = Hash.new() @min_args = 1 @max_args = 1 # maximum max_args is likely ~~ 128*1024, as linux MAX_ARG_STRLEN is 128kiB end
Provide a way to register symbol aliases to the Parser
# File lib/optimist_xl.rb, line 1021 def self.register_alias(*alias_keys) alias_keys.each do |alias_key| # pass in the alias-key and the class Parser.register(alias_key, self) end end
Private Class Methods
# File lib/optimist_xl.rb, line 1085 def self.get_klass_from_default(opts, opttype) ## 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) && opttype.nil? opts[:default].first else opts[:default] end return nil if disambiguated_default.nil? type_from_default = get_type_from_disdef(opts[:default], opttype, disambiguated_default) return OptimistXL::Parser.registry_getopttype(type_from_default) end
# File lib/optimist_xl.rb, line 1072 def self.get_type_from_disdef(optdef, opttype, disambiguated_default) if disambiguated_default.is_a? Array return(optdef.first.class.name.downcase + "s") if !optdef.empty? if opttype raise ArgumentError, "multiple argument type must be plural" unless opttype.max_args > 1 return nil else raise ArgumentError, "multiple argument type cannot be deduced from an empty array" end end return disambiguated_default.class.name.downcase end
Public Instance Methods
|@min_args | @max_args | ----------
———–+ | 0 | 0 | formerly flag?==true (option without any arguments) | 1 | 1 | formerly single_arg?==true (single-parameter/normal option) | 1 | >1 | formerly multi_arg?==true | ? | ? | presumably illegal condition. untested.
# File lib/optimist_xl.rb, line 909 def array_default? ; self.default.kind_of?(Array) ; end
# File lib/optimist_xl.rb, line 913 def callback ; opts(:callback) ; end
Check that an option is compatible with another option. By default, checking that they are the same class, but we can override this in the subclass as needed.
# File lib/optimist_xl.rb, line 885 def compatible_with?(other_option) self.is_a? other_option.class end
# File lib/optimist_xl.rb, line 915 def desc ; opts(:desc) ; end
Format the educate-line description including the default-value(s)
# File lib/optimist_xl.rb, line 952 def description_with_default(str) return str unless default default_s = case default when Array default.join(', ') else format_stdio(default).to_s end return "#{str} (Default: #{default_s})" end
Format the educate-line description including the permitted-value(s)
# File lib/optimist_xl.rb, line 964 def description_with_permitted(str) permitted_s = case permitted when Array permitted.map do |p| format_stdio(p).to_s end.join(', ') when Range permitted.to_a.map(&:to_s).join(', ') when Regexp permitted.to_s end return "#{str} (Permitted: #{permitted_s})" end
# File lib/optimist_xl.rb, line 911 def doesnt_need_autogen_short ; !short.auto || !short.chars.empty? ; end
# File lib/optimist_xl.rb, line 926 def educate optionlist = [] optionlist.concat(short.chars.map { |o| "-#{o}" }) optionlist.concat(long.names.map { |o| "--#{o}" }) optionlist.compact.join(', ') + type_format + (min_args==0 && default ? ", --no-#{long}" : "") end
Format stdio like objects to a string
# File lib/optimist_xl.rb, line 942 def format_stdio(obj) case obj when $stdout then '<stdout>' when $stdin then '<stdin>' when $stderr then '<stderr>' else obj # pass-through-case end end
Format the educate-line description including the default and permitted value(s)
# File lib/optimist_xl.rb, line 934 def full_description desc_str = desc desc_str = description_with_default desc_str if default desc_str = description_with_permitted desc_str if permitted desc_str end
# File lib/optimist_xl.rb, line 898 def multi ; @multi_given ; end
# File lib/optimist_xl.rb, line 889 def opts(key) @optshash[key] end
# File lib/optimist_xl.rb, line 893 def opts=(o) @optshash = o end
# File lib/optimist_xl.rb, line 919 def parse(_paramlist, _neg_given) raise NotImplementedError, "parse must be overridden for newly registered type" end
# File lib/optimist_xl.rb, line 990 def permitted_type_valid? return true if permitted.nil? return true if permitted.is_a? Array return true if permitted.is_a? Range return true if permitted.is_a? Regexp false end
# File lib/optimist_xl.rb, line 978 def permitted_valid_string case permitted when Array return "one of: " + permitted.to_a.map(&:to_s).join(', ') when Range return "value in range of: #{permitted}" when Regexp return "value matching: #{permitted.inspect}" end raise StandardError, "invalid branch" end
incoming values from the command-line should be strings, so we should stringify any permitted types as the basis of comparison.
# File lib/optimist_xl.rb, line 1009 def permitted_value?(val) case permitted when nil then true when Regexp then val.match permitted when Range then permitted.to_a.map(&:to_s).include? val when Array then permitted.map(&:to_s).include? val else false end end
# File lib/optimist_xl.rb, line 917 def required? ; opts(:required) ; end
provide type-format string. default to empty, but user should probably override it
# File lib/optimist_xl.rb, line 924 def type_format ; "" ; end
# File lib/optimist_xl.rb, line 998 def validate_permitted(arg, value) return true if permitted.nil? unless permitted_value?(value) format_hash = {arg: arg, given: value, value: value, valid_string: permitted_valid_string(), permitted: permitted } raise CommandlineError, permitted_response % format_hash end true end