diff --git a/src/builtin.cpp b/src/builtin.cpp index 73458d4bf..91276b9b7 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -109,7 +109,7 @@ static const wchar_t *const short_options = L"+:h"; static const struct woption long_options[] = {{L"help", no_argument, 'h'}, {}}; int parse_help_only_cmd_opts(struct help_only_cmd_opts_t &opts, int *optind, int argc, - const wchar_t **argv, io_streams_t &streams) { + const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; wgetopter_t w; @@ -120,11 +120,11 @@ int parse_help_only_cmd_opts(struct help_only_cmd_opts_t &opts, int *optind, int break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -162,12 +162,17 @@ void builtin_print_help(parser_t &parser, const io_streams_t &streams, const wch } /// Perform error reporting for encounter with unknown option. -void builtin_unknown_option(io_streams_t &streams, const wchar_t *cmd, const wchar_t *opt) { +void builtin_unknown_option(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, + const wchar_t *opt, bool print_hints) { streams.err.append_format(BUILTIN_ERR_UNKNOWN, cmd, opt); + if (print_hints) { + builtin_print_error_trailer(parser, streams.err, cmd); + } } /// Perform error reporting for encounter with missing argument. -void builtin_missing_argument(io_streams_t &streams, const wchar_t *cmd, const wchar_t *opt) { +void builtin_missing_argument(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, + const wchar_t *opt, bool print_hints) { if (opt[0] == L'-' && opt[1] != L'-') { // if c in -qc '-qc' is missing the argument, now opt is just 'c' opt += std::wcslen(opt) - 1; @@ -175,6 +180,10 @@ void builtin_missing_argument(io_streams_t &streams, const wchar_t *cmd, const w streams.err.append_format(BUILTIN_ERR_MISSING, cmd, wcstring(L"-").append(opt).c_str()); } else streams.err.append_format(BUILTIN_ERR_MISSING, cmd, opt); + + if (print_hints) { + builtin_print_error_trailer(parser, streams.err, cmd); + } } /// Print the backtrace and call for help that we use at the end of error messages. @@ -196,7 +205,7 @@ static maybe_t builtin_generic(parser_t &parser, io_streams_t &streams, con int argc = builtin_count_args(argv); help_only_cmd_opts_t opts; int optind; - int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtin.h b/src/builtin.h index ff8e9a340..5668cf059 100644 --- a/src/builtin.h +++ b/src/builtin.h @@ -91,9 +91,11 @@ void builtin_print_help(parser_t &parser, const io_streams_t &streams, const wch wcstring *error_message = nullptr); int builtin_count_args(const wchar_t *const *argv); -void builtin_unknown_option(io_streams_t &streams, const wchar_t *cmd, const wchar_t *opt); +void builtin_unknown_option(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, + const wchar_t *opt, bool print_hints = true); -void builtin_missing_argument(io_streams_t &streams, const wchar_t *cmd, const wchar_t *opt); +void builtin_missing_argument(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, + const wchar_t *opt, bool print_hints = true); void builtin_print_error_trailer(parser_t &parser, output_stream_t &b, const wchar_t *cmd); @@ -103,5 +105,5 @@ struct help_only_cmd_opts_t { bool print_help = false; }; int parse_help_only_cmd_opts(help_only_cmd_opts_t &opts, int *optind, int argc, - const wchar_t **argv, io_streams_t &streams); + const wchar_t **argv, parser_t &parser, io_streams_t &streams); #endif diff --git a/src/builtins/abbr.cpp b/src/builtins/abbr.cpp index 219a5cd28..99e065972 100644 --- a/src/builtins/abbr.cpp +++ b/src/builtins/abbr.cpp @@ -381,7 +381,7 @@ maybe_t builtin_abbr(parser_t &parser, io_streams_t &streams, const wchar_t return STATUS_CMD_OK; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } } diff --git a/src/builtins/argparse.cpp b/src/builtins/argparse.cpp index bf634bbcb..195278551 100644 --- a/src/builtins/argparse.cpp +++ b/src/builtins/argparse.cpp @@ -405,11 +405,13 @@ static int parse_cmd_opts(argparse_cmd_opts_t &opts, int *optind, //!OCLINT(hig break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1], + /* print_hints */ false); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1], + /* print_hints */ false); return STATUS_INVALID_ARGS; } default: { @@ -571,7 +573,8 @@ static int argparse_parse_flags(parser_t &parser, argparse_cmd_opts_t &opts, wgetopter_t w; while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, &long_idx)) != -1) { if (opt == ':') { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1], + false /* print_hints */); return STATUS_INVALID_ARGS; } else if (opt == '?') { // It's not a recognized flag. See if it's an implicit int flag. diff --git a/src/builtins/bg.cpp b/src/builtins/bg.cpp index b23eb0e10..87be5ce60 100644 --- a/src/builtins/bg.cpp +++ b/src/builtins/bg.cpp @@ -48,7 +48,7 @@ maybe_t builtin_bg(parser_t &parser, io_streams_t &streams, const wchar_t * help_only_cmd_opts_t opts; int optind; - int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/bind.cpp b/src/builtins/bind.cpp index f5af776b9..c5b31c47f 100644 --- a/src/builtins/bind.cpp +++ b/src/builtins/bind.cpp @@ -343,7 +343,7 @@ void builtin_bind_t::list_modes(io_streams_t &streams) { } static int parse_cmd_opts(bind_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method) - int argc, const wchar_t **argv, io_streams_t &streams) { + int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; static const wchar_t *const short_options = L":aehkKfM:Lm:s"; static const struct woption long_options[] = {{L"all", no_argument, 'a'}, @@ -424,11 +424,11 @@ static int parse_cmd_opts(bind_cmd_opts_t &opts, int *optind, //!OCLINT(high nc break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case L'?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -452,7 +452,7 @@ maybe_t builtin_bind_t::builtin_bind(parser_t &parser, io_streams_t &stream this->opts = &opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.list_modes) { diff --git a/src/builtins/block.cpp b/src/builtins/block.cpp index 5d541a398..bff86541f 100644 --- a/src/builtins/block.cpp +++ b/src/builtins/block.cpp @@ -23,7 +23,7 @@ struct block_cmd_opts_t { }; static int parse_cmd_opts(block_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method) - int argc, const wchar_t **argv, io_streams_t &streams) { + int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; static const wchar_t *const short_options = L":eghl"; static const struct woption long_options[] = {{L"erase", no_argument, 'e'}, @@ -53,11 +53,11 @@ static int parse_cmd_opts(block_cmd_opts_t &opts, int *optind, //!OCLINT(high n break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -77,7 +77,7 @@ maybe_t builtin_block(parser_t &parser, io_streams_t &streams, const wchar_ block_cmd_opts_t opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/builtin.cpp b/src/builtins/builtin.cpp index 8e3e63ce3..54ff76a47 100644 --- a/src/builtins/builtin.cpp +++ b/src/builtins/builtin.cpp @@ -24,7 +24,7 @@ static const struct woption long_options[] = { {L"help", no_argument, 'h'}, {L"names", no_argument, 'n'}, {L"query", no_argument, 'q'}, {}}; static int parse_cmd_opts(builtin_cmd_opts_t &opts, int *optind, int argc, const wchar_t **argv, - io_streams_t &streams) { + parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; wgetopter_t w; @@ -43,11 +43,11 @@ static int parse_cmd_opts(builtin_cmd_opts_t &opts, int *optind, int argc, const break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -69,7 +69,7 @@ maybe_t builtin_builtin(parser_t &parser, io_streams_t &streams, const wcha builtin_cmd_opts_t opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/cd.cpp b/src/builtins/cd.cpp index fb0dbf85b..8a2023ed9 100644 --- a/src/builtins/cd.cpp +++ b/src/builtins/cd.cpp @@ -31,7 +31,7 @@ maybe_t builtin_cd(parser_t &parser, io_streams_t &streams, const wchar_t * help_only_cmd_opts_t opts; int optind; - int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/command.cpp b/src/builtins/command.cpp index 75d5e5da5..91dd8ce1e 100644 --- a/src/builtins/command.cpp +++ b/src/builtins/command.cpp @@ -28,7 +28,7 @@ static const struct woption long_options[] = { {L"query", no_argument, 'q'}, {L"search", no_argument, 's'}, {}}; static int parse_cmd_opts(command_cmd_opts_t &opts, int *optind, int argc, const wchar_t **argv, - io_streams_t &streams) { + parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; wgetopter_t w; @@ -52,11 +52,11 @@ static int parse_cmd_opts(command_cmd_opts_t &opts, int *optind, int argc, const break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -77,7 +77,7 @@ maybe_t builtin_command(parser_t &parser, io_streams_t &streams, const wcha command_cmd_opts_t opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/commandline.cpp b/src/builtins/commandline.cpp index f140b9834..51bf17f26 100644 --- a/src/builtins/commandline.cpp +++ b/src/builtins/commandline.cpp @@ -268,11 +268,11 @@ maybe_t builtin_commandline(parser_t &parser, io_streams_t &streams, const return STATUS_CMD_OK; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case L'?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -293,7 +293,7 @@ maybe_t builtin_commandline(parser_t &parser, io_streams_t &streams, const } if (argc == w.woptind) { - builtin_missing_argument(streams, cmd, argv[0]); + builtin_missing_argument(parser, streams, cmd, argv[0]); return STATUS_INVALID_ARGS; } diff --git a/src/builtins/complete.cpp b/src/builtins/complete.cpp index d8c05c966..d01e747c4 100644 --- a/src/builtins/complete.cpp +++ b/src/builtins/complete.cpp @@ -294,11 +294,11 @@ maybe_t builtin_complete(parser_t &parser, io_streams_t &streams, const wch return STATUS_CMD_OK; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -369,7 +369,7 @@ maybe_t builtin_complete(parser_t &parser, io_streams_t &streams, const wch if (!state.initialized) { // This corresponds to using 'complete -C' in non-interactive mode. // See #2361 . - builtin_missing_argument(streams, cmd, L"-C"); + builtin_missing_argument(parser, streams, cmd, L"-C"); return STATUS_INVALID_ARGS; } do_complete_param = std::move(state.text); diff --git a/src/builtins/contains.cpp b/src/builtins/contains.cpp index 95eceaef2..1911ad452 100644 --- a/src/builtins/contains.cpp +++ b/src/builtins/contains.cpp @@ -22,7 +22,7 @@ static const struct woption long_options[] = { {L"help", no_argument, 'h'}, {L"index", no_argument, 'i'}, {}}; static int parse_cmd_opts(contains_cmd_opts_t &opts, int *optind, int argc, const wchar_t **argv, - io_streams_t &streams) { + parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; wgetopter_t w; @@ -37,11 +37,11 @@ static int parse_cmd_opts(contains_cmd_opts_t &opts, int *optind, int argc, cons break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -62,7 +62,7 @@ maybe_t builtin_contains(parser_t &parser, io_streams_t &streams, const wch contains_cmd_opts_t opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/disown.cpp b/src/builtins/disown.cpp index 714048b81..8ae8bc0c8 100644 --- a/src/builtins/disown.cpp +++ b/src/builtins/disown.cpp @@ -48,7 +48,7 @@ maybe_t builtin_disown(parser_t &parser, io_streams_t &streams, const wchar help_only_cmd_opts_t opts; int optind; - int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/echo.cpp b/src/builtins/echo.cpp index b4d4a5104..0f15e36b8 100644 --- a/src/builtins/echo.cpp +++ b/src/builtins/echo.cpp @@ -49,7 +49,7 @@ static int parse_cmd_opts(echo_cmd_opts_t &opts, int *optind, int argc, const wc break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { diff --git a/src/builtins/emit.cpp b/src/builtins/emit.cpp index 887ed6f09..b28adb51a 100644 --- a/src/builtins/emit.cpp +++ b/src/builtins/emit.cpp @@ -20,7 +20,7 @@ maybe_t builtin_emit(parser_t &parser, io_streams_t &streams, const wchar_t help_only_cmd_opts_t opts; int optind; - int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/exit.cpp b/src/builtins/exit.cpp index 9b5e69780..47687a644 100644 --- a/src/builtins/exit.cpp +++ b/src/builtins/exit.cpp @@ -34,7 +34,7 @@ static int parse_cmd_opts(exit_cmd_opts_t &opts, int *optind, //!OCLINT(high nc break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { diff --git a/src/builtins/fg.cpp b/src/builtins/fg.cpp index ecd0ec761..f9a51e67d 100644 --- a/src/builtins/fg.cpp +++ b/src/builtins/fg.cpp @@ -35,7 +35,7 @@ maybe_t builtin_fg(parser_t &parser, io_streams_t &streams, const wchar_t * help_only_cmd_opts_t opts; int optind; - int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/function.cpp b/src/builtins/function.cpp index f8b26b0f4..54672da4e 100644 --- a/src/builtins/function.cpp +++ b/src/builtins/function.cpp @@ -178,11 +178,11 @@ static int parse_cmd_opts(function_cmd_opts_t &opts, int *optind, //!OCLINT(hig break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { diff --git a/src/builtins/functions.cpp b/src/builtins/functions.cpp index 51e27df9b..499f036e5 100644 --- a/src/builtins/functions.cpp +++ b/src/builtins/functions.cpp @@ -55,7 +55,7 @@ static const struct woption long_options[] = {{L"erase", no_argument, 'e'}, {}}; static int parse_cmd_opts(functions_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method) - int argc, const wchar_t **argv, io_streams_t &streams) { + int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; wgetopter_t w; @@ -111,11 +111,11 @@ static int parse_cmd_opts(functions_cmd_opts_t &opts, int *optind, //!OCLINT(hi break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -196,7 +196,7 @@ maybe_t builtin_functions(parser_t &parser, io_streams_t &streams, const wc functions_cmd_opts_t opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/history.cpp b/src/builtins/history.cpp index 0caa01ca0..3eb5114ef 100644 --- a/src/builtins/history.cpp +++ b/src/builtins/history.cpp @@ -103,7 +103,7 @@ static bool check_for_unexpected_hist_args(const history_cmd_opts_t &opts, const } static int parse_cmd_opts(history_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method) - int argc, const wchar_t **argv, io_streams_t &streams) { + int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; wgetopter_t w; @@ -184,14 +184,14 @@ static int parse_cmd_opts(history_cmd_opts_t &opts, int *optind, //!OCLINT(high break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { // Try to parse it as a number; e.g., "-123". opts.max_items = fish_wcstol(argv[w.woptind - 1] + 1); if (errno) { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } w.nextchar = nullptr; @@ -214,7 +214,7 @@ maybe_t builtin_history(parser_t &parser, io_streams_t &streams, const wcha history_cmd_opts_t opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/jobs.cpp b/src/builtins/jobs.cpp index 9d1763ec9..994eade9c 100644 --- a/src/builtins/jobs.cpp +++ b/src/builtins/jobs.cpp @@ -160,11 +160,11 @@ maybe_t builtin_jobs(parser_t &parser, io_streams_t &streams, const wchar_t return STATUS_CMD_OK; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { diff --git a/src/builtins/math.cpp b/src/builtins/math.cpp index ea2198d9a..071777884 100644 --- a/src/builtins/math.cpp +++ b/src/builtins/math.cpp @@ -42,7 +42,7 @@ static const struct woption long_options[] = {{L"scale", required_argument, 's'} {}}; static int parse_cmd_opts(math_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method) - int argc, const wchar_t **argv, io_streams_t &streams) { + int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = L"math"; int opt; wgetopter_t w; @@ -83,7 +83,7 @@ static int parse_cmd_opts(math_cmd_opts_t &opts, int *optind, //!OCLINT(high nc break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { @@ -279,7 +279,7 @@ maybe_t builtin_math(parser_t &parser, io_streams_t &streams, const wchar_t // Is this really the right way to handle no expression present? // if (argc == 0) return STATUS_CMD_OK; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/path.cpp b/src/builtins/path.cpp index 79ce5e5d1..9065fa435 100644 --- a/src/builtins/path.cpp +++ b/src/builtins/path.cpp @@ -463,7 +463,8 @@ static int parse_opts(options_t *opts, int *optind, int n_req_args, int argc, co if (retval != STATUS_CMD_OK) return retval; } else if (opt == ':') { streams.err.append(L"path "); - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1], + false /* print_hints */); return STATUS_INVALID_ARGS; } else if (opt == '?') { path_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); diff --git a/src/builtins/pwd.cpp b/src/builtins/pwd.cpp index 82c74d27b..664175276 100644 --- a/src/builtins/pwd.cpp +++ b/src/builtins/pwd.cpp @@ -43,7 +43,7 @@ maybe_t builtin_pwd(parser_t &parser, io_streams_t &streams, const wchar_t builtin_print_help(parser, streams, cmd); return STATUS_CMD_OK; case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { diff --git a/src/builtins/random.cpp b/src/builtins/random.cpp index ef5369663..5f79a2271 100644 --- a/src/builtins/random.cpp +++ b/src/builtins/random.cpp @@ -33,7 +33,7 @@ maybe_t builtin_random(parser_t &parser, io_streams_t &streams, const wchar help_only_cmd_opts_t opts; int optind; - int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/read.cpp b/src/builtins/read.cpp index 38322b38c..0e7574b41 100644 --- a/src/builtins/read.cpp +++ b/src/builtins/read.cpp @@ -177,11 +177,11 @@ static int parse_cmd_opts(read_cmd_opts_t &opts, int *optind, //!OCLINT(high nc break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case L'?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { diff --git a/src/builtins/realpath.cpp b/src/builtins/realpath.cpp index 14143b5a0..32d32e7f4 100644 --- a/src/builtins/realpath.cpp +++ b/src/builtins/realpath.cpp @@ -28,7 +28,7 @@ static const struct woption long_options[] = { {L"no-symlinks", no_argument, 's'}, {L"help", no_argument, 'h'}, {}}; static int parse_cmd_opts(realpath_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method) - int argc, const wchar_t **argv, io_streams_t &streams) { + int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; wgetopter_t w; @@ -43,11 +43,11 @@ static int parse_cmd_opts(realpath_cmd_opts_t &opts, int *optind, //!OCLINT(hig break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -68,7 +68,7 @@ maybe_t builtin_realpath(parser_t &parser, io_streams_t &streams, const wch int argc = builtin_count_args(argv); int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/return.cpp b/src/builtins/return.cpp index 14d99c1ab..2289b72a7 100644 --- a/src/builtins/return.cpp +++ b/src/builtins/return.cpp @@ -37,7 +37,7 @@ static int parse_cmd_opts(return_cmd_opts_t &opts, int *optind, //!OCLINT(high break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { diff --git a/src/builtins/set.cpp b/src/builtins/set.cpp index c9f2b0c4f..9417b884d 100644 --- a/src/builtins/set.cpp +++ b/src/builtins/set.cpp @@ -81,7 +81,7 @@ static const struct woption long_options[] = {{L"export", no_argument, 'x'}, _(L"%ls: successfully set universal '%ls'; but a global by that name shadows it\n") static int parse_cmd_opts(set_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method) - int argc, const wchar_t **argv, io_streams_t &streams) { + int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; @@ -157,7 +157,7 @@ static int parse_cmd_opts(set_cmd_opts_t &opts, int *optind, //!OCLINT(high ncs break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { @@ -175,7 +175,7 @@ static int parse_cmd_opts(set_cmd_opts_t &opts, int *optind, //!OCLINT(high ncs } } } - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -814,7 +814,7 @@ maybe_t builtin_set(parser_t &parser, io_streams_t &streams, const wchar_t set_cmd_opts_t opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; argv += optind; argc -= optind; diff --git a/src/builtins/set_color.cpp b/src/builtins/set_color.cpp index d2a653ba6..67f0f76f8 100644 --- a/src/builtins/set_color.cpp +++ b/src/builtins/set_color.cpp @@ -163,7 +163,7 @@ maybe_t builtin_set_color(parser_t &parser, io_streams_t &streams, const wc return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, L"set_color", argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, L"set_color", argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { diff --git a/src/builtins/source.cpp b/src/builtins/source.cpp index f24da3752..75ef81fb6 100644 --- a/src/builtins/source.cpp +++ b/src/builtins/source.cpp @@ -32,7 +32,7 @@ maybe_t builtin_source(parser_t &parser, io_streams_t &streams, const wchar help_only_cmd_opts_t opts; int optind; - int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_help_only_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/status.cpp b/src/builtins/status.cpp index edbe8824d..dfc0c0639 100644 --- a/src/builtins/status.cpp +++ b/src/builtins/status.cpp @@ -166,7 +166,7 @@ static void print_features(io_streams_t &streams) { } static int parse_cmd_opts(status_cmd_opts_t &opts, int *optind, //!OCLINT(high ncss method) - int argc, const wchar_t **argv, io_streams_t &streams) { + int argc, const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t *cmd = argv[0]; int opt; wgetopter_t w; @@ -266,11 +266,11 @@ static int parse_cmd_opts(status_cmd_opts_t &opts, int *optind, //!OCLINT(high break; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { @@ -290,7 +290,7 @@ maybe_t builtin_status(parser_t &parser, io_streams_t &streams, const wchar status_cmd_opts_t opts; int optind; - int retval = parse_cmd_opts(opts, &optind, argc, argv, streams); + int retval = parse_cmd_opts(opts, &optind, argc, argv, parser, streams); if (retval != STATUS_CMD_OK) return retval; if (opts.print_help) { diff --git a/src/builtins/string.cpp b/src/builtins/string.cpp index 82f152367..0b1cf8df1 100644 --- a/src/builtins/string.cpp +++ b/src/builtins/string.cpp @@ -657,7 +657,8 @@ static int parse_opts(options_t *opts, int *optind, int n_req_args, int argc, co if (retval != STATUS_CMD_OK) return retval; } else if (opt == ':') { streams.err.append(L"string "); // clone of string_error - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1], + false /* print_hints */); return STATUS_INVALID_ARGS; } else if (opt == '?') { string_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); diff --git a/src/builtins/ulimit.cpp b/src/builtins/ulimit.cpp index aacca6022..fd28362a9 100644 --- a/src/builtins/ulimit.cpp +++ b/src/builtins/ulimit.cpp @@ -379,11 +379,11 @@ maybe_t builtin_ulimit(parser_t &parser, io_streams_t &streams, const wchar return STATUS_CMD_OK; } case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { diff --git a/src/builtins/wait.cpp b/src/builtins/wait.cpp index a07d9aec6..4f9ad0898 100644 --- a/src/builtins/wait.cpp +++ b/src/builtins/wait.cpp @@ -150,11 +150,11 @@ maybe_t builtin_wait(parser_t &parser, io_streams_t &streams, const wchar_t print_help = true; break; case ':': { - builtin_missing_argument(streams, cmd, argv[w.woptind - 1]); + builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } case '?': { - builtin_unknown_option(streams, cmd, argv[w.woptind - 1]); + builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; } default: { diff --git a/tests/checks/syntax-error-location.fish b/tests/checks/syntax-error-location.fish index 227765496..eda0a100f 100644 --- a/tests/checks/syntax-error-location.fish +++ b/tests/checks/syntax-error-location.fish @@ -65,3 +65,11 @@ $fish -c 'echo {$,}' # CHECKERR: fish: Expected a variable name after this $. # CHECKERR: echo {$,} # CHECKERR: ^ + +echo "bind -M" | $fish +# CHECKERR: bind: -M: option requires an argument +# CHECKERR: Standard input (line 1): +# CHECKERR: bind -M +# CHECKERR: ^ +# CHECKERR: (Type \'help bind\' for related documentation) +