vendor/gems/trollop/lib/trollop.rb in auser-poolparty-1.2.12 vs vendor/gems/trollop/lib/trollop.rb in auser-poolparty-1.3.0

- old
+ new

@@ -1,15 +1,13 @@ ## lib/trollop.rb -- trollop command-line processing library ## Author:: William Morgan (mailto: wmorgan-trollop@masanjin.net) ## Copyright:: Copyright 2007 William Morgan ## License:: GNU GPL version 2 -require 'date' - module Trollop -VERSION = "1.13" +VERSION = "1.10.2" ## Thrown by Parser in the event of a commandline error. Not needed if ## you're using the Trollop::options entry. class CommandlineError < StandardError; end @@ -44,15 +42,15 @@ ## The set of values that indicate a single-parameter option when ## passed as the +:type+ parameter of #opt. ## ## A value of +io+ corresponds to a readable IO resource, including ## a filename, URI, or the strings 'stdin' or '-'. - SINGLE_ARG_TYPES = [:int, :integer, :string, :double, :float, :io, :date] + SINGLE_ARG_TYPES = [:int, :integer, :string, :double, :float, :io] ## The set of values that indicate a multiple-parameter option when ## passed as the +:type+ parameter of #opt. - MULTI_ARG_TYPES = [:ints, :integers, :strings, :doubles, :floats, :ios, :dates] + MULTI_ARG_TYPES = [:ints, :integers, :strings, :doubles, :floats, :ios] ## The complete set of legal values for the +:type+ parameter of #opt. TYPES = FLAG_TYPES + SINGLE_ARG_TYPES + MULTI_ARG_TYPES INVALID_SHORT_ARG_REGEX = /[\d-]/ #:nodoc: @@ -128,17 +126,16 @@ when :integer; :int when :integers; :ints when :double; :float when :doubles; :floats when Class - case opts[:type].name + 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 - when 'Date'; :date else raise ArgumentError, "unsupported argument type '#{opts[:type].class.name}'" end when nil; nil else @@ -162,21 +159,19 @@ when Integer; :int when Numeric; :float when TrueClass, FalseClass; :flag when String; :string when IO; :io - when Date; :date 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 - when Date; :dates else raise ArgumentError, "unsupported multiple argument type '#{opts[:default][0].class.name}'" end when nil; nil else @@ -200,16 +195,25 @@ 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 - + opts[:short] = + case opts[:short] + when nil + c = opts[:long].split(//).find { |c| c !~ INVALID_SHORT_ARG_REGEX && !@short.member?(c) } + raise ArgumentError, "can't generate a short option name for #{opts[:long].inspect}: out of unique characters" unless c + c + when /^-(.)$/ + $1 + when /^.$/ + opts[:short] + when :none + nil + 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 @@ -222,11 +226,11 @@ ## fill in :multi opts[:multi] ||= false opts[:desc] ||= desc @long[opts[:long]] = name - @short[opts[:short]] = name if opts[:short] && opts[:short] != :none + @short[opts[:short]] = name if opts[:short] @specs[name] = opts @order << [:opt, name] end ## Sets the version string. If set, the user can request the version @@ -272,10 +276,82 @@ ## i.e., without first parsing the global options. def stop_on_unknown @stop_on_unknown = true end + ## yield successive arg, parameter pairs + def each_arg args # :nodoc: + remains = [] + i = 0 + + until i >= args.length + if @stop_words.member? args[i] + remains += args[i .. -1] + return remains + end + case args[i] + when /^--$/ # arg terminator + remains += args[(i + 1) .. -1] + return remains + when /^--(\S+?)=(\S+)$/ # long argument with equals + yield "--#{$1}", [$2] + i += 1 + when /^--(\S+)$/ # long argument + params = collect_argument_parameters(args, i + 1) + unless params.empty? + num_params_taken = yield args[i], params + unless num_params_taken + if @stop_on_unknown + remains += args[i + 1 .. -1] + return remains + else + remains += params + end + end + i += 1 + num_params_taken + else # long argument no parameter + yield args[i], nil + i += 1 + end + when /^-(\S+)$/ # one or more short arguments + shortargs = $1.split(//) + shortargs.each_with_index do |a, j| + if j == (shortargs.length - 1) + params = collect_argument_parameters(args, i + 1) + unless params.empty? + num_params_taken = yield "-#{a}", params + unless num_params_taken + if @stop_on_unknown + remains += args[i + 1 .. -1] + return remains + else + remains += params + end + end + i += 1 + num_params_taken + else # argument no parameter + yield "-#{a}", nil + i += 1 + end + else + yield "-#{a}", nil + end + end + else + if @stop_on_unknown + remains += args[i .. -1] + return remains + else + remains << args[i] + i += 1 + end + end + end + + remains + end + ## Parses the commandline. Typically called by Trollop::options. def parse cmdline=ARGV vals = {} required = {} @@ -285,23 +361,22 @@ @specs.each do |sym, opts| required[sym] = true if opts[:required] vals[sym] = opts[:default] end - resolve_default_short_options - ## resolve symbols given_args = {} @leftovers = each_arg cmdline do |arg, params| - sym = case arg - when /^-([^-])$/ - @short[$1] - when /^--([^-]\S*)$/ - @long[$1] - else - raise CommandlineError, "invalid argument syntax: '#{arg}'" - end + sym = + case arg + when /^-([^-])$/ + @short[$1] + when /^--([^-]\S*)$/ + @long[$1] + else + raise CommandlineError, "invalid argument syntax: '#{arg}'" + end raise CommandlineError, "unknown argument '#{arg}'" unless sym if given_args.include?(sym) && !@specs[sym][:multi] raise CommandlineError, "option '#{arg}' specified multiple times" end @@ -354,12 +429,10 @@ params = given_data[:params] opts = @specs[sym] raise CommandlineError, "option '#{arg}' needs a parameter" if params.empty? && opts[:type] != :flag - vals["#{sym}_given".intern] = true # mark argument as specified on the commandline - case opts[:type] when :flag vals[sym] = !opts[:default] when :int, :ints vals[sym] = params.map { |pg| pg.map { |p| parse_integer_parameter p, arg } } @@ -367,12 +440,10 @@ vals[sym] = params.map { |pg| pg.map { |p| parse_float_parameter p, arg } } when :string, :strings vals[sym] = params.map { |pg| pg.map { |p| p.to_s } } when :io, :ios vals[sym] = params.map { |pg| pg.map { |p| parse_io_parameter p, arg } } - when :date, :dates - vals[sym] = params.map { |pg| pg.map { |p| parse_date_parameter p, arg } } end if SINGLE_ARG_TYPES.include?(opts[:type]) unless opts[:multi] # single parameter vals[sym] = vals[sym][0][0] @@ -392,44 +463,79 @@ end end vals end - def parse_date_parameter param, arg #:nodoc: - begin + def parse_integer_parameter param, arg #:nodoc: + raise CommandlineError, "option '#{arg}' needs an integer" unless param =~ /^\d+$/ + param.to_i + end + + def parse_float_parameter param, arg #:nodoc: + raise CommandlineError, "option '#{arg}' needs a floating-point number" unless param =~ FLOAT_RE + param.to_f + end + + def parse_io_parameter param, arg #:nodoc: + case param + when /^(stdin|-)$/i; $stdin + else + require 'open-uri' begin - time = Chronic.parse(param) - rescue NameError - # chronic is not available + open param + rescue SystemCallError => e + raise CommandlineError, "file or url for option '#{arg}' cannot be opened: #{e.message}" end - time ? Date.new(time.year, time.month, time.day) : Date.parse(param) - rescue ArgumentError => e - raise CommandlineError, "option '#{arg}' needs a date" end end + def collect_argument_parameters args, start_at #:nodoc: + params = [] + pos = start_at + while args[pos] && args[pos] !~ PARAM_RE && !@stop_words.member?(args[pos]) do + params << args[pos] + pos += 1 + end + params + end + + def width #:nodoc: + @width ||= + if $stdout.tty? + begin + require 'curses' + Curses::init_screen + x = Curses::cols + Curses::close_screen + x + rescue Exception + 80 + end + else + 80 + end + end + ## Print the help message to +stream+. def educate stream=$stdout width # just calculate it now; otherwise we have to be careful not to # call this unless the cursor's at the beginning of a line. left = {} @specs.each do |name, spec| left[name] = "--#{spec[:long]}" + - (spec[:short] && spec[:short] != :none ? ", -#{spec[:short]}" : "") + + (spec[:short] ? ", -#{spec[:short]}" : "") + case spec[:type] when :flag; "" when :int; " <i>" when :ints; " <i+>" when :string; " <s>" when :strings; " <s+>" when :float; " <f>" when :floats; " <f+>" when :io; " <filename/uri>" when :ios; " <filename/uri+>" - when :date; " <date>" - when :dates; " <date+>" end end leftcol_width = left.values.map { |s| s.length }.max || 0 rightcol_start = leftcol_width + 6 # spaces @@ -470,156 +576,11 @@ end stream.puts wrap(desc, :width => width - rightcol_start - 1, :prefix => rightcol_start) end end - def width #:nodoc: - @width ||= if $stdout.tty? - begin - require 'curses' - Curses::init_screen - x = Curses::cols - Curses::close_screen - x - rescue Exception - 80 - end - else - 80 - end - end - - def wrap str, opts={} # :nodoc: - if str == "" - [""] - else - str.split("\n").map { |s| wrap_line s, opts }.flatten - end - end - -private - - ## yield successive arg, parameter pairs - def each_arg args - remains = [] - i = 0 - - until i >= args.length - if @stop_words.member? args[i] - remains += args[i .. -1] - return remains - end - case args[i] - when /^--$/ # arg terminator - remains += args[(i + 1) .. -1] - return remains - when /^--(\S+?)=(.*)$/ # long argument with equals - yield "--#{$1}", [$2] - i += 1 - when /^--(\S+)$/ # long argument - params = collect_argument_parameters(args, i + 1) - unless params.empty? - num_params_taken = yield args[i], params - unless num_params_taken - if @stop_on_unknown - remains += args[i + 1 .. -1] - return remains - else - remains += params - end - end - i += 1 + num_params_taken - else # long argument no parameter - yield args[i], nil - i += 1 - end - when /^-(\S+)$/ # one or more short arguments - shortargs = $1.split(//) - shortargs.each_with_index do |a, j| - if j == (shortargs.length - 1) - params = collect_argument_parameters(args, i + 1) - unless params.empty? - num_params_taken = yield "-#{a}", params - unless num_params_taken - if @stop_on_unknown - remains += args[i + 1 .. -1] - return remains - else - remains += params - end - end - i += 1 + num_params_taken - else # argument no parameter - yield "-#{a}", nil - i += 1 - end - else - yield "-#{a}", nil - end - end - else - if @stop_on_unknown - remains += args[i .. -1] - return remains - else - remains << args[i] - i += 1 - end - end - end - - remains - end - - def parse_integer_parameter param, arg - raise CommandlineError, "option '#{arg}' needs an integer" unless param =~ /^\d+$/ - param.to_i - end - - def parse_float_parameter param, arg - raise CommandlineError, "option '#{arg}' needs a floating-point number" unless param =~ FLOAT_RE - param.to_f - end - - def parse_io_parameter param, arg - case param - when /^(stdin|-)$/i; $stdin - else - require 'open-uri' - begin - open param - rescue SystemCallError => e - raise CommandlineError, "file or url for option '#{arg}' cannot be opened: #{e.message}" - end - end - end - - def collect_argument_parameters args, start_at - params = [] - pos = start_at - while args[pos] && args[pos] !~ PARAM_RE && !@stop_words.member?(args[pos]) do - params << args[pos] - pos += 1 - end - params - end - - def resolve_default_short_options - @order.each do |type, name| - next unless type == :opt - opts = @specs[name] - next if opts[:short] - - c = opts[:long].split(//).find { |d| d !~ INVALID_SHORT_ARG_REGEX && !@short.member?(d) } - raise ArgumentError, "can't generate a default short option name for #{opts[:long].inspect}: out of unique characters" unless c - - opts[:short] = c - @short[c] = name - end - end - - def wrap_line str, opts={} + def wrap_line str, opts={} # :nodoc: prefix = opts[:prefix] || 0 width = opts[:width] || (self.width - 1) start = 0 ret = [] until start > str.length @@ -635,13 +596,21 @@ start = nextt + 1 end ret end + def wrap str, opts={} # :nodoc: + if str == "" + [""] + else + str.split("\n").map { |s| wrap_line s, opts }.flatten + end + end + ## instance_eval but with ability to handle block arguments ## thanks to why: http://redhanded.hobix.com/inspect/aBlockCostume.html - def cloaker &b + def cloaker &b #:nodoc: (class << self; self; end).class_eval do define_method :cloaker_, &b meth = instance_method :cloaker_ remove_method :cloaker_ meth @@ -657,32 +626,22 @@ ## ## The block passed in should contain zero or more calls to +opt+ ## (Parser#opt), zero or more calls to +text+ (Parser#text), and ## probably a call to +version+ (Parser#version). ## -## The returned block contains a value for every option specified with -## +opt+. The value will be the value given on the commandline, or the -## default value if the option was not specified on the commandline. For -## every option specified on the commandline, a key "<option -## name>_given" will also be set in the hash. -## ## Example: ## ## require 'trollop' ## opts = Trollop::options do ## opt :monkey, "Use monkey mode" # a flag --monkey, defaulting to false ## opt :goat, "Use goat mode", :default => true # a flag --goat, defaulting to true ## opt :num_limbs, "Number of limbs", :default => 4 # an integer --num-limbs <i>, defaulting to 4 ## opt :num_thumbs, "Number of thumbs", :type => :int # an integer --num-thumbs <i>, defaulting to nil ## end ## -## ## if called with no arguments -## p opts # => { :monkey => false, :goat => true, :num_limbs => 4, :num_thumbs => nil } +## p opts # returns a hash: { :monkey => false, :goat => true, :num_limbs => 4, :num_thumbs => nil } ## -## ## if called with --monkey -## p opts # => {:monkey_given=>true, :monkey=>true, :goat=>true, :num_limbs=>4, :help=>false, :num_thumbs=>nil} -## ## See more examples at http://trollop.rubyforge.org. def options args = ARGV, *a, &b @p = Parser.new(*a, &b) begin vals = @p.parse args @@ -731,5 +690,6 @@ end module_function :options, :die end # module +