argparse: Only print stacktrace when it's an error in argparse usage

A broken/missing optspec or `--` is a bug in the script using
argparse, an unknown option or invalid argument is a bug in using that script.

So in the former case print a stacktrace, because the person writing
the `argparse` call is at fault, in the latter don't.

Fixes #6703.
This commit is contained in:
Fabian Homborg 2020-06-17 20:05:48 +02:00
parent 4660be372a
commit a121833e88
3 changed files with 68 additions and 21 deletions

View file

@ -563,12 +563,6 @@ static int argparse_parse_flags(parser_t &parser, argparse_cmd_opts_t &opts,
streams);
} else if (!opts.ignore_unknown) {
streams.err.append_format(BUILTIN_ERR_UNKNOWN, cmd, argv[w.woptind - 1]);
// We don't use builtin_print_error_trailer as that
// says to use the cmd help,
// which doesn't work if it's a command that does not belong to fish.
//
// Plus this particular error is not an error in argparse usage.
streams.err.append(parser.current_line());
retval = STATUS_INVALID_ARGS;
} else {
// Any unrecognized option is put back if ignore_unknown is used.
@ -697,7 +691,13 @@ int builtin_argparse(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
int optind;
int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams);
if (retval != STATUS_CMD_OK) return retval;
if (retval != STATUS_CMD_OK) {
// This is an error in argparse usage, so we append the error trailer with a stack trace.
// The other errors are an error in using *the command* that is using argparse,
// so our help doesn't apply.
builtin_print_error_trailer(parser, streams.err, cmd);
return retval;
}
if (opts.print_help) {
builtin_print_help(parser, streams, cmd);

View file

@ -4,18 +4,32 @@
set -g LANG C
# Start by verifying a bunch of error conditions.
# These are *argparse* errors, and therefore bugs in the script,
# so they print a stack trace.
# No args is an error
argparse
#CHECKERR: argparse: No option specs were provided
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
# Missing -- is an error
argparse h/help
#CHECKERR: argparse: Missing -- separator
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse h/help
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
# Flags but no option specs is an error
argparse -s -- hello
#CHECKERR: argparse: No option specs were provided
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse -s -- hello
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
# Invalid option specs
argparse h-
@ -24,10 +38,30 @@ argparse h/help:
argparse h-help::
argparse h-help=x
#CHECKERR: argparse: Invalid option spec 'h-' at char '-'
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse h-
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
#CHECKERR: argparse: Short flag '+' invalid, must be alphanum or '#'
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse +help
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
#CHECKERR: argparse: Invalid option spec 'h/help:' at char ':'
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse h/help:
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
#CHECKERR: argparse: Invalid option spec 'h-help::' at char ':'
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse h-help::
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
#CHECKERR: argparse: Invalid option spec 'h-help=x' at char 'x'
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse h-help=x
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
# --max-args and --min-args work
begin
@ -48,39 +82,56 @@ end
begin
argparse '#-val=' -- abc -x def
# CHECKERR: argparse: Implicit int short flag '#' does not allow modifiers like '='
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse '#-val=' -- abc -x def
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
end
# Invalid arg in the face of a \"#-val\" spec
begin
argparse '#-val' -- abc -x def
# CHECKERR: argparse: Unknown option '-x'
# CHECKERR: {{.*}}argparse.fish (line {{\d+}}):
# CHECKERR: argparse '#-val' -- abc -x def
# CHECKERR: {{\s*\^\s*}}
end
# Defining a short flag more than once
begin
argparse s/short x/xray s/long -- -s -x --long
# CHECKERR: argparse: Short flag 's' already defined
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse s/short x/xray s/long -- -s -x --long
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
end
# Defining a long flag more than once
begin
argparse s/short x/xray l/short -- -s -x --long
# CHECKERR: argparse: Long flag 'short' already defined
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse s/short x/xray l/short -- -s -x --long
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
end
# Defining an implicit int flag more than once
begin
argparse '#-val' x/xray 'v#val' -- -s -x --long
# CHECKERR: argparse: Implicit int flag '#' already defined
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse '#-val' x/xray 'v#val' -- -s -x --long
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
end
# Defining an implicit int flag with modifiers
begin
argparse 'v#val=' --
# CHECKERR: argparse: Implicit int short flag 'v' does not allow modifiers like '='
#CHECKERR: checks/argparse.fish (line {{\d+}}):
#CHECKERR: argparse 'v#val=' --
#CHECKERR: ^
#CHECKERR: (Type 'help argparse' for related documentation)
end
##########
@ -255,11 +306,6 @@ function notargparse
end
notargparse
# CHECKERR: notargparse: Unknown option '--banana'
# CHECKERR: {{.*}}argparse.fish (line {{\d+}}):
# CHECKERR: argparse a/alpha -- --banana
# CHECKERR: ^
# CHECKERR: in function 'notargparse'
# CHECKERR: called on line {{\d+}} of file {{.*}}argparse.fish
true
@ -388,3 +434,9 @@ fish_opt -s h --multiple-vals --long-only
or echo unexpected status $status
#CHECK: h=+
#CHECK: h=+
function wrongargparse
argparse -foo -- banana
argparse a-b
argparse
end

View file

@ -15,15 +15,10 @@ emit linenumber
type --nonexistent-option-so-we-get-a-backtrace
# CHECKERR: type: Unknown option '--nonexistent-option-so-we-get-a-backtrace'
# CHECKERR: {{.*/type.fish}} (line 7):
# CHECKERR: argparse -n type -x t,p,P $options -- $argv
# CHECKERR: ^
# CHECKERR: in function 'type' with arguments '--nonexistent-option-so-we-get-a-backtrace'
# CHECKERR: called on line 16 of file {{.*}}line-number.fish
function line-number
status line-number
end
line-number
# CHECK: 25
# CHECK: 20