mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-10 23:24:39 +00:00
implement fish_opt
helper command
This implements a `fish_opt` command that provides a way for people to create option specs for the `argparse` command as an alternative to creating such strings by hand. Fixes #4190
This commit is contained in:
parent
9adf500cf3
commit
a4dc2b872b
5 changed files with 193 additions and 0 deletions
54
doc_src/fish_opt.txt
Normal file
54
doc_src/fish_opt.txt
Normal file
|
@ -0,0 +1,54 @@
|
|||
\section fish_opt fish_opt - create an option spec for the argparse command
|
||||
|
||||
\subsection fish_opt-synopsis Synopsis
|
||||
\fish{synopsis}
|
||||
fish_opt [ -h | --help ]
|
||||
fish_opt ( -s X | --short=X ) [ -l LONG | --long=LONG ] [ --long-only ] \
|
||||
[ -o | --optional-val ] [ -r | --required-val ] [ --multiple-vals ]
|
||||
\endfish
|
||||
|
||||
\subsection fish_opt-description Description
|
||||
|
||||
This command provides a way to produce option specifications suitable for use with the <a href="#argparse">`argparse`</a> command. You can, of course, write the option specs by hand without using this command. But you might prefer to use this for the clarity it provides.
|
||||
|
||||
The following `argparse` options are available:
|
||||
|
||||
- `-s` or `--short` takes a single letter that is used as the short flag in the option being defined. This option is mandatory.
|
||||
|
||||
- `-l` or `--long` takes a string that is used as the long flag in the option being defined. This option is optional and has no default. If no long flag is defined then only the short flag will be allowed when parsing arguments using the option spec.
|
||||
|
||||
- `--long-only` means the option spec being defined will only allow the long flag name to be used. The short flag name must still be defined (i.e., `--short` must be specified) but it cannot be used when parsing args using this option spec.
|
||||
|
||||
- `-o` or `--optional` means the option being defined can take a value but it is optional rather than required. If the option is seen more than once when parsing arguments only the last value seen is saved. This means the resulting flag variable created by `argparse` will zero elements if no value was given with the option else it will have exactly one element.
|
||||
|
||||
- `-r` or `--required` means the option being defined requires a value. If the option is seen more than once when parsing arguments only the last value seen is saved. This means the resulting flag variable created by `argparse` will have exactly one element.
|
||||
|
||||
- `--multiple-vals` means the option being defined requires a value each time it is seen. Each instance is stored. This means the resulting flag variable created by `argparse` will have one element for each instance of this option in the args.
|
||||
|
||||
- `-h` or `--help` displays help about using this command.
|
||||
|
||||
\subsection fish_opt-examples Examples
|
||||
|
||||
Define a single option spec for the boolean help flag:
|
||||
|
||||
\fish
|
||||
set -l options (fish_opt -s h -l help)
|
||||
argparse $options -- $argv
|
||||
\endfish
|
||||
|
||||
Same as above but with a second flag that requires a value:
|
||||
|
||||
\fish
|
||||
set -l options (fish_opt -s h -l help)
|
||||
set options $options (fish_opt -s m -l max --required-val)
|
||||
argparse $options -- $argv
|
||||
\endfish
|
||||
|
||||
Same as above but with a third flag that can be given multiple times saving the value of each instance seen and only the long flag name (`--token`) can be used:
|
||||
|
||||
\fish
|
||||
set -l options (fish_opt --short=h --long=help)
|
||||
set options $options (fish_opt --short=m --long=max --required-val)
|
||||
set options $options (fish_opt --short=t --long=token --multiple-vals --long-only)
|
||||
argparse $options -- $argv
|
||||
\endfish
|
47
share/functions/fish_opt.fish
Normal file
47
share/functions/fish_opt.fish
Normal file
|
@ -0,0 +1,47 @@
|
|||
# This is a helper function for `fish_opt`. It does some basic validation of the arguments.
|
||||
function __fish_opt_validate_args --no-scope-shadowing
|
||||
if not set -q _flag_short
|
||||
or test 1 -ne (string length -- $_flag_short)
|
||||
printf (_ "%s: The --short flag is required and must be a single character\n") fish_opt >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
# The `fish_opt` command.
|
||||
function fish_opt -d 'Produce an option specification suitable for use with `argparse`.'
|
||||
set -l options 'h/help' 's/short=' 'l/long=' 'o/optional-val' 'r/required-val'
|
||||
set options $options 'L-long-only' 'M-multiple-vals'
|
||||
argparse -n fish_opt --max-args=0 --exclusive=r,o --exclusive=M,o $options -- $argv
|
||||
or return
|
||||
|
||||
if set -q _flag_help
|
||||
__fish_print_help nextd
|
||||
return 0
|
||||
end
|
||||
|
||||
__fish_opt_validate_args
|
||||
or return
|
||||
|
||||
set -l opt_spec $_flag_short
|
||||
|
||||
if set -q _flag_long
|
||||
if set -q _flag_long_only
|
||||
set opt_spec "$opt_spec-"
|
||||
else
|
||||
set opt_spec "$opt_spec/"
|
||||
end
|
||||
set opt_spec "$opt_spec$_flag_long"
|
||||
end
|
||||
|
||||
if set -q _flag_multiple_vals
|
||||
set opt_spec "$opt_spec=+"
|
||||
else if set -q _flag_required_val
|
||||
set opt_spec "$opt_spec="
|
||||
else if set -q _flag_optional_val
|
||||
and set opt_spec "$opt_spec=?"
|
||||
end
|
||||
|
||||
echo $opt_spec
|
||||
end
|
11
tests/fish_opt.err
Normal file
11
tests/fish_opt.err
Normal file
|
@ -0,0 +1,11 @@
|
|||
# no args is an error
|
||||
fish_opt: The --short flag is required and must be a single character
|
||||
# no short flag or an invalid short flag is an error
|
||||
fish_opt: The --short flag is required and must be a single character
|
||||
fish_opt: The --short flag is required and must be a single character
|
||||
# a required and optional arg makes no sense
|
||||
fish_opt: Mutually exclusive flags 'o/optional-val' and `r/required-val` seen
|
||||
# a repeated and optional arg makes no sense
|
||||
fish_opt: Mutually exclusive flags 'multiple-vals' and `o/optional-val` seen
|
||||
# an unexpected arg not associated with a flag is an error
|
||||
fish_opt: Expected at most 0 args, got 1
|
62
tests/fish_opt.in
Normal file
62
tests/fish_opt.in
Normal file
|
@ -0,0 +1,62 @@
|
|||
# Start by testing a bunch of error conditions.
|
||||
|
||||
echo '# no args is an error' >&2
|
||||
fish_opt
|
||||
and echo unexpected status $status
|
||||
|
||||
echo '# no short flag or an invalid short flag is an error' >&2
|
||||
fish_opt -l help
|
||||
and echo unexpected status $status
|
||||
fish_opt -s help
|
||||
and echo unexpected status $status
|
||||
|
||||
echo '# a required and optional arg makes no sense' >&2
|
||||
fish_opt -s h -l help -r --optional-val
|
||||
and echo unexpected status $status
|
||||
|
||||
echo '# a repeated and optional arg makes no sense' >&2
|
||||
fish_opt -s h -l help --multiple-vals --optional-val
|
||||
and echo unexpected status $status
|
||||
|
||||
echo '# an unexpected arg not associated with a flag is an error' >&2
|
||||
fish_opt -s h -l help hello
|
||||
and echo unexpected status $status
|
||||
|
||||
# Now verify that valid combinations of options produces the correct output.
|
||||
|
||||
echo '# bool, short only'
|
||||
fish_opt -s h
|
||||
or echo unexpected status $status
|
||||
|
||||
echo '# bool, short and long'
|
||||
fish_opt --short h --long help
|
||||
or echo unexpected status $status
|
||||
|
||||
echo '# bool, short and long but the short var cannot be used'
|
||||
fish_opt --short h --long help --long-only
|
||||
|
||||
echo '# required val, short and long but the short var cannot be used'
|
||||
fish_opt --short h --long help -r --long-only
|
||||
or echo unexpected status $status
|
||||
|
||||
echo '# optional val, short and long valid'
|
||||
fish_opt --short h -l help --optional-val
|
||||
or echo unexpected status $status
|
||||
|
||||
echo '# optional val, short and long but the short var cannot be used'
|
||||
fish_opt --short h -l help --optional-val --long-only
|
||||
or echo unexpected status $status
|
||||
|
||||
echo '# repeated val, short and long valid'
|
||||
fish_opt --short h -l help --multiple-vals
|
||||
or echo unexpected status $status
|
||||
|
||||
echo '# repeated val, short and long but short not valid'
|
||||
fish_opt --short h -l help --multiple-vals --long-only
|
||||
or echo unexpected status $status
|
||||
|
||||
echo '# repeated val, short only'
|
||||
fish_opt -s h --multiple-vals
|
||||
or echo unexpected status $status
|
||||
fish_opt -s h --multiple-vals --long-only
|
||||
or echo unexpected status $status
|
19
tests/fish_opt.out
Normal file
19
tests/fish_opt.out
Normal file
|
@ -0,0 +1,19 @@
|
|||
# bool, short only
|
||||
h
|
||||
# bool, short and long
|
||||
h/help
|
||||
# bool, short and long but the short var cannot be used
|
||||
h-help
|
||||
# required val, short and long but the short var cannot be used
|
||||
h-help=
|
||||
# optional val, short and long valid
|
||||
h/help=?
|
||||
# optional val, short and long but the short var cannot be used
|
||||
h-help=?
|
||||
# repeated val, short and long valid
|
||||
h/help=+
|
||||
# repeated val, short and long but short not valid
|
||||
h-help=+
|
||||
# repeated val, short only
|
||||
h=+
|
||||
h=+
|
Loading…
Reference in a new issue