Skip to content

Commit

Permalink
Allow multi-flag parameters
Browse files Browse the repository at this point in the history
Some tools need to allow the repeated input of certain valueless parameters. One such example is the use of `v` for `verbose`, where the addition of more v's increases the verbosity of the output. This behavior can be seen in tools such as curl and ssh.

Prior to this change, when the `:multi` option was passed in to a `:flag` or `:boolean` parameter, the parser would return either a a `true` value or an empty array depending on if the flag was passed in the command line or not.

After this change, the `:flag` with `:multi` set will instead count the number of times the flag was passed. Flag options without `:multi` set still exhibit the original behavior of simple `true`/`false` values.

Example config:
```ruby
opts = Optimist::options do
    opt :verbose, "Enables verbose output. Twice will enable very-verbose output", multi: true
end
```

Before change:
```
$ mytool
{:verbose => []}

$ mytool -vvv
{:verbose => true}
```

After change:
```
$ mytool
{:verbose => 0}

$ mytool -vv
{:verbose => 3}
```
  • Loading branch information
akhoury6 committed Apr 18, 2024
1 parent 30b3b84 commit 07e97f0
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion lib/optimist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ def parse(cmdline = ARGV)
@specs.each do |sym, opts|
required[sym] = true if opts.required?
vals[sym] = opts.default
vals[sym] = [] if opts.multi && !opts.default # multi arguments default to [], not nil
vals[sym] = [] if opts.multi && !opts.default && !opts.flag? # multi arguments default to [], not nil
vals[sym] = 0 if opts.multi && !opts.default && opts.flag? # multi argument flags default to 0 because they return a count
end

resolve_default_short_options!
Expand Down Expand Up @@ -283,6 +284,11 @@ def parse(cmdline = ARGV)
# The block returns the number of parameters taken.
num_params_taken = 0

if @specs[sym].multi? && @specs[sym].flag?
given_args[sym][:params][0] ||= 0
given_args[sym][:params][0] += 1
end

unless params.empty?
if @specs[sym].single_arg?
given_args[sym][:params] << params[0, 1] # take the first parameter
Expand Down Expand Up @@ -765,6 +771,7 @@ def initialize
end
def flag? ; true ; end
def parse(_paramlist, neg_given)
return _paramlist[0] if @multi_given
return(self.name.to_s =~ /^no_/ ? neg_given : !neg_given)
end
end
Expand Down

0 comments on commit 07e97f0

Please sign in to comment.