lib/optparse.rb in optparse-0.2.0 vs lib/optparse.rb in optparse-0.3.0

- old
+ new

@@ -48,11 +48,11 @@ # # == OptionParser # # === New to \OptionParser? # -# See the {Tutorial}[./doc/optparse/tutorial_rdoc.html]. +# See the {Tutorial}[optparse/tutorial.rdoc]. # # === Introduction # # OptionParser is a class for command-line option analysis. It is much more # advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented @@ -418,16 +418,16 @@ # completion for command line options. # # === Further documentation # # The above examples, along with the accompanying -# {Tutorial}[./doc/optparse/tutorial_rdoc.html], +# {Tutorial}[optparse/tutorial.rdoc], # should be enough to learn how to use this class. # If you have any questions, file a ticket at http://bugs.ruby-lang.org. # class OptionParser - OptionParser::Version = "0.2.0" + OptionParser::Version = "0.3.0" # :stopdoc: NoArgument = [NO_ARGUMENT = :NONE, nil].freeze RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze OptionalArgument = [OPTIONAL_ARGUMENT = :OPTIONAL, false].freeze @@ -672,10 +672,33 @@ yield("#{opt}", desc.join("")) end end end + def pretty_print_contents(q) # :nodoc: + if @block + q.text ":" + @block.source_location.join(":") + ":" + first = false + else + first = true + end + [@short, @long].each do |list| + list.each do |opt| + if first + q.text ":" + first = false + end + q.breakable + q.text opt + end + end + end + + def pretty_print(q) # :nodoc: + q.object_group(self) {pretty_print_contents(q)} + end + # # Switch that takes no arguments. # class NoArgument < self @@ -691,10 +714,14 @@ end def self.pattern Object end + + def pretty_head # :nodoc: + "NoArgument" + end end # # Switch that takes an argument. # @@ -708,10 +735,14 @@ raise MissingArgument if argv.empty? arg = argv.shift end conv_arg(*parse_arg(arg, &method(:raise))) end + + def pretty_head # :nodoc: + "Required" + end end # # Switch that can omit argument. # @@ -725,22 +756,26 @@ conv_arg(*parse_arg(arg, &error)) else conv_arg(arg) end end + + def pretty_head # :nodoc: + "Optional" + end end # - # Switch that takes an argument, which does not begin with '-'. + # Switch that takes an argument, which does not begin with '-' or is '-'. # class PlacedArgument < self # - # Returns nil if argument is not present or begins with '-'. + # Returns nil if argument is not present or begins with '-' and is not '-'. # def parse(arg, argv, &error) - if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0])) + if !(val = arg) and (argv.empty? or /\A-./ =~ (val = argv[0])) return nil, block, nil end opt = (val = parse_arg(val, &error))[1] val = conv_arg(*val) if opt and !arg @@ -748,10 +783,14 @@ else val[0] = nil end val end + + def pretty_head # :nodoc: + "Placed" + end end end # # Simple option list providing mapping from short and/or long option @@ -779,10 +818,21 @@ @short = OptionMap.new @long = OptionMap.new @list = [] end + def pretty_print(q) # :nodoc: + q.group(1, "(", ")") do + @list.each do |sw| + next unless Switch === sw + q.group(1, "(" + sw.pretty_head, ")") do + sw.pretty_print_contents(q) + end + end + end + end + # # See OptionParser.accept. # def accept(t, pat = /.*/m, &block) if pat @@ -1096,10 +1146,11 @@ @banner = banner @summary_width = width @summary_indent = indent @default_argv = ARGV @require_exact = false + @raise_unknown = true add_officious yield self if block_given? end def add_officious # :nodoc: @@ -1173,10 +1224,13 @@ # Whether to require that options match exactly (disallows providing # abbreviated long option as short option). attr_accessor :require_exact + # Whether to raise at unknown option. + attr_accessor :raise_unknown + # # Heading banner preceding summary. # def banner unless @banner @@ -1291,10 +1345,33 @@ # Returns option summary string. # def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end alias to_s help + def pretty_print(q) # :nodoc: + q.object_group(self) do + first = true + if @stack.size > 2 + @stack.each_with_index do |s, i| + next if i < 2 + next if s.list.empty? + if first + first = false + q.text ":" + end + q.breakable + s.pretty_print(q) + end + end + end + end + + def inspect # :nodoc: + require 'pp' + pretty_print_inspect + end + # # Returns option summary list. # def to_a; summarize("#{banner}".split(/^/)) end @@ -1427,11 +1504,11 @@ short << q when /^=/ style = notwice(default_style.guess(arg = o), style, 'style') default_pattern, conv = search(:atype, Object) unless default_pattern else - desc.push(o) + desc.push(o) if o && !o.empty? end end default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern if !(short.empty? and long.empty?) @@ -1564,13 +1641,15 @@ opt, rest = $1, $2 opt.tr!('_', '-') begin sw, = complete(:long, opt, true) if require_exact && !sw.long.include?(arg) + throw :terminate, arg unless raise_unknown raise InvalidOption, arg end rescue ParseError + throw :terminate, arg unless raise_unknown raise $!.set_option(arg, true) end begin opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)} val = cb.call(val) if cb @@ -1598,10 +1677,11 @@ sw, = complete(:long, opt) eq ||= !rest end end rescue ParseError + throw :terminate, arg unless raise_unknown raise $!.set_option(arg, true) end begin opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq} rescue ParseError @@ -1828,14 +1908,17 @@ # # +filename+ defaults to basename of the program without suffix in a # directory ~/.options, then the basename with '.options' suffix # under XDG and Haiku standard places. # - def load(filename = nil) + # The optional +into+ keyword argument works exactly like that accepted in + # method #parse. + # + def load(filename = nil, into: nil) unless filename basename = File.basename($0, '.*') - return true if load(File.expand_path(basename, '~/.options')) rescue nil + return true if load(File.expand_path(basename, '~/.options'), into: into) rescue nil basename << ".options" return [ # XDG ENV['XDG_CONFIG_HOME'], '~/.config', @@ -1843,14 +1926,14 @@ # Haiku '~/config/settings', ].any? {|dir| next if !dir or dir.empty? - load(File.expand_path(basename, dir)) rescue nil + load(File.expand_path(basename, dir), into: into) rescue nil } end begin - parse(*IO.readlines(filename).each {|s| s.chomp!}) + parse(*File.readlines(filename, chomp: true), into: into) true rescue Errno::ENOENT, Errno::ENOTDIR false end end