diff options
Diffstat (limited to 'lib/optparse.rb')
| -rw-r--r-- | lib/optparse.rb | 109 |
1 files changed, 62 insertions, 47 deletions
diff --git a/lib/optparse.rb b/lib/optparse.rb index e1069b3505..97178e284b 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -7,6 +7,7 @@ # # See OptionParser for documentation. # +require 'set' unless defined?(Set) #-- # == Developer Documentation (not for RDoc output) @@ -425,7 +426,9 @@ # class OptionParser # The version string - OptionParser::Version = "0.7.0.dev.2" + VERSION = "0.8.1" + # An alias for compatibility + Version = VERSION # :stopdoc: NoArgument = [NO_ARGUMENT = :NONE, nil].freeze @@ -469,7 +472,6 @@ class OptionParser Completion.candidate(key, icase, pat, &method(:each)) end - public def complete(key, icase = false, pat = nil) candidates = candidate(key, icase, pat, &method(:each)).sort_by {|k, v, kn| kn.size} if candidates.size == 1 @@ -559,7 +561,7 @@ class OptionParser # Parses +arg+ and returns rest of +arg+ and matched portion to the # argument pattern. Yields when the pattern doesn't match substring. # - def parse_arg(arg) # :nodoc: + private def parse_arg(arg) # :nodoc: pattern or return nil, [arg] unless m = pattern.match(arg) yield(InvalidArgument, arg) @@ -577,14 +579,13 @@ class OptionParser yield(InvalidArgument, arg) # didn't match whole arg return arg[s.length..-1], m end - private :parse_arg # # Parses argument, converts and returns +arg+, +block+ and result of # conversion. Yields at semi-error condition instead of raising an # exception. # - def conv_arg(arg, val = []) # :nodoc: + private def conv_arg(arg, val = []) # :nodoc: v, = *val if conv val = conv.call(*val) @@ -596,7 +597,6 @@ class OptionParser end return arg, block, val end - private :conv_arg # # Produces the summary text. Each line of the summary is yielded to the @@ -880,14 +880,13 @@ class OptionParser # +lopts+:: Long style option list. # +nlopts+:: Negated long style options list. # - def update(sw, sopts, lopts, nsw = nil, nlopts = nil) # :nodoc: + private def update(sw, sopts, lopts, nsw = nil, nlopts = nil) # :nodoc: sopts.each {|o| @short[o] = sw} if sopts lopts.each {|o| @long[o] = sw} if lopts nlopts.each {|o| @long[o] = nsw} if nsw and nlopts used = @short.invert.update(@long.invert) @list.delete_if {|o| Switch === o and !used[o]} end - private :update # # Inserts +switch+ at the head of the list, and associates short, long @@ -1293,7 +1292,15 @@ XXX # to $0. # def program_name - @program_name || File.basename($0, '.*') + @program_name || strip_ext(File.basename($0)) + end + + private def strip_ext(name) # :nodoc: + exts = /#{ + require "rbconfig" + Regexp.union(*RbConfig::CONFIG["EXECUTABLE_EXTS"]&.split(" ")) + }\z/o + name.sub(exts, "") end # for experimental cascading :-) @@ -1448,14 +1455,13 @@ XXX # +prv+:: Previously specified argument. # +msg+:: Exception message. # - def notwice(obj, prv, msg) # :nodoc: + private def notwice(obj, prv, msg) # :nodoc: unless !prv or prv == obj raise(ArgumentError, "argument #{msg} given twice: #{obj}", ParseError.filter_backtrace(caller(2))) end obj end - private :notwice SPLAT_PROC = proc {|*a| a.length <= 1 ? a.first : a} # :nodoc: @@ -1500,7 +1506,7 @@ XXX case o when Proc, Method block = notwice(o, block, 'block') - when Array, Hash + when Array, Hash, Set if Array === o o, v = o.partition {|v,| Completion.completable?(v)} values = notwice(v, values, 'values') unless v.empty? @@ -1722,7 +1728,7 @@ XXX parse_in_order(argv, setter, **keywords, &nonopt) end - def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc: + private def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc: opt, arg, val, rest = nil nonopt ||= proc {|a| throw :terminate, a} argv.unshift(arg) if arg = catch(:terminate) { @@ -1813,10 +1819,9 @@ XXX argv end - private :parse_in_order # Calls callback with _val_. - def callback!(cb, max_arity, *args) # :nodoc: + private def callback!(cb, max_arity, *args) # :nodoc: args.compact! if (size = args.size) < max_arity and cb.to_proc.lambda? @@ -1826,7 +1831,6 @@ XXX end cb.call(*args) end - private :callback! # # Parses command line arguments +argv+ in permutation mode and returns @@ -1846,7 +1850,7 @@ XXX # def permute!(argv = default_argv, **keywords) nonopts = [] - order!(argv, **keywords, &nonopts.method(:<<)) + order!(argv, **keywords) {|nonopt| nonopts << nonopt} argv[0, 0] = nonopts argv end @@ -1899,13 +1903,16 @@ XXX single_options, *long_options = *args result = {} + setter = (symbolize_names ? + ->(name, val) {result[name.to_sym] = val} + : ->(name, val) {result[name] = val}) single_options.scan(/(.)(:)?/) do |opt, val| if val - result[opt] = nil + setter[opt, nil] define("-#{opt} VAL") else - result[opt] = false + setter[opt, false] define("-#{opt}") end end if single_options @@ -1914,16 +1921,16 @@ XXX arg, desc = arg.split(';', 2) opt, val = arg.split(':', 2) if val - result[opt] = val.empty? ? nil : val + setter[opt, (val unless val.empty?)] define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact) else - result[opt] = false + setter[opt, false] define("--#{opt}", *[desc].compact) end end - parse_in_order(argv, result.method(:[]=), **keywords) - symbolize_names ? result.transform_keys(&:to_sym) : result + parse_in_order(argv, setter, **keywords) + result end # @@ -1937,24 +1944,22 @@ XXX # Traverses @stack, sending each element method +id+ with +args+ and # +block+. # - def visit(id, *args, &block) # :nodoc: + private def visit(id, *args, &block) # :nodoc: @stack.reverse_each do |el| el.__send__(id, *args, &block) end nil end - private :visit # # Searches +key+ in @stack for +id+ hash and returns or yields the result. # - def search(id, key) # :nodoc: + private def search(id, key) # :nodoc: block_given = block_given? visit(:search, id, key) do |k| return block_given ? yield(k) : k end end - private :search # # Completes shortened long style option switch and returns pair of @@ -1965,7 +1970,7 @@ XXX # +icase+:: Search case insensitive if true. # +pat+:: Optional pattern for completion. # - def complete(typ, opt, icase = false, *pat) # :nodoc: + private def complete(typ, opt, icase = false, *pat) # :nodoc: if pat.empty? search(typ, opt) {|sw| return [sw, opt]} # exact match or... end @@ -1973,9 +1978,8 @@ XXX visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw} } exc = ambiguous ? AmbiguousOption : InvalidOption - raise exc.new(opt, additional: self.method(:additional_message).curry[typ]) + raise exc.new(opt, additional: proc {|o| additional_message(typ, o)}) end - private :complete # # Returns additional info. @@ -2038,19 +2042,27 @@ XXX def load(filename = nil, **keywords) unless filename basename = File.basename($0, '.*') - return true if load(File.expand_path(basename, '~/.options'), **keywords) rescue nil + return true if load(File.expand_path("~/.options/#{basename}"), **keywords) rescue nil basename << ".options" + if !(xdg = ENV['XDG_CONFIG_HOME']) or xdg.empty? + # https://specifications.freedesktop.org/basedir-spec/latest/#variables + # + # If $XDG_CONFIG_HOME is either not set or empty, a default + # equal to $HOME/.config should be used. + xdg = ['~/.config', true] + end return [ - # XDG - ENV['XDG_CONFIG_HOME'], - '~/.config', + xdg, + *ENV['XDG_CONFIG_DIRS']&.split(File::PATH_SEPARATOR), # Haiku - '~/config/settings', - ].any? {|dir| + ['~/config/settings', true], + ].any? {|dir, expand| next if !dir or dir.empty? - load(File.expand_path(basename, dir), **keywords) rescue nil + filename = File.join(dir, basename) + filename = File.expand_path(filename) if expand + load(filename, **keywords) rescue nil } end begin @@ -2256,9 +2268,10 @@ XXX argv end + DIR = File.join(__dir__, '') def self.filter_backtrace(array) unless $DEBUG - array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~)) + array.delete_if {|bt| bt.start_with?(DIR)} end array end @@ -2301,42 +2314,42 @@ XXX # Raises when ambiguously completable string is encountered. # class AmbiguousOption < ParseError - const_set(:Reason, 'ambiguous option') + Reason = 'ambiguous option' # :nodoc: end # # Raises when there is an argument for a switch which takes no argument. # class NeedlessArgument < ParseError - const_set(:Reason, 'needless argument') + Reason = 'needless argument' # :nodoc: end # # Raises when a switch with mandatory argument has no argument. # class MissingArgument < ParseError - const_set(:Reason, 'missing argument') + Reason = 'missing argument' # :nodoc: end # # Raises when switch is undefined. # class InvalidOption < ParseError - const_set(:Reason, 'invalid option') + Reason = 'invalid option' # :nodoc: end # # Raises when the given argument does not match required format. # class InvalidArgument < ParseError - const_set(:Reason, 'invalid argument') + Reason = 'invalid argument' # :nodoc: end # # Raises when the given argument word can't be completed uniquely. # class AmbiguousArgument < InvalidArgument - const_set(:Reason, 'ambiguous argument') + Reason = 'ambiguous argument' # :nodoc: end # @@ -2435,9 +2448,11 @@ XXX # and DecimalNumeric. See Acceptable argument classes (in source code). # module Acceptables - const_set(:DecimalInteger, OptionParser::DecimalInteger) - const_set(:OctalInteger, OptionParser::OctalInteger) - const_set(:DecimalNumeric, OptionParser::DecimalNumeric) + # :stopdoc: + DecimalInteger = OptionParser::DecimalInteger + OctalInteger = OptionParser::OctalInteger + DecimalNumeric = OptionParser::DecimalNumeric + # :startdoc: end end |
