diff --git a/doc_src/builtin.txt b/doc_src/builtin.txt index 4c465ef18..20664823e 100644 --- a/doc_src/builtin.txt +++ b/doc_src/builtin.txt @@ -2,7 +2,8 @@ \subsection builtin-synopsis Synopsis \fish{synopsis} -builtin BUILTINNAME [OPTIONS...] +builtin [OPTIONS...] BUILTINNAME +builtin --query BUILTINNAMES... \endfish \subsection builtin-description Description @@ -12,6 +13,7 @@ builtin BUILTINNAME [OPTIONS...] The following parameters are available: - `-n` or `--names` List the names of all defined builtins +- `-q` or `--query` tests if any of the specified builtins exists. \subsection builtin-example Example diff --git a/src/builtin_builtin.cpp b/src/builtin_builtin.cpp index bc59f1369..4ac852b60 100644 --- a/src/builtin_builtin.cpp +++ b/src/builtin_builtin.cpp @@ -17,10 +17,13 @@ struct builtin_cmd_opts_t { bool print_help = false; bool list_names = false; + bool query = false; }; -static const wchar_t *const short_options = L":hn"; +static const wchar_t *const short_options = L":hnq"; static const struct woption long_options[] = { - {L"help", no_argument, NULL, 'h'}, {L"names", no_argument, NULL, 'n'}, {NULL, 0, NULL, 0}}; + {L"help", no_argument, NULL, 'h'}, {L"names", no_argument, NULL, 'n'}, + {L"query", no_argument, NULL, 'q'}, + {NULL, 0, NULL, 0}}; static int parse_cmd_opts(builtin_cmd_opts_t &opts, int *optind, int argc, wchar_t **argv, parser_t &parser, io_streams_t &streams) { @@ -37,6 +40,10 @@ static int parse_cmd_opts(builtin_cmd_opts_t &opts, int *optind, int argc, wchar opts.list_names = true; break; } + case 'q': { + opts.query = true; + break; + } case ':': { builtin_missing_argument(parser, streams, cmd, argv[w.woptind - 1]); return STATUS_INVALID_ARGS; @@ -73,6 +80,24 @@ int builtin_builtin(parser_t &parser, io_streams_t &streams, wchar_t **argv) { return STATUS_CMD_OK; } + if (opts.query && opts.list_names) { + streams.err.append_format(BUILTIN_ERR_COMBO2, cmd, + _(L"--query and --names are mutually exclusive")); + return STATUS_INVALID_ARGS; + } + + if (opts.query) { + wcstring_list_t names = builtin_get_names(); + retval = STATUS_CMD_ERROR; + for (int i = optind; i < argc; i++) { + if (contains(names, argv[i])) { + retval = STATUS_CMD_OK; + break; + } + } + return retval; + } + if (opts.list_names) { wcstring_list_t names = builtin_get_names(); std::sort(names.begin(), names.end()); diff --git a/tests/test_builtinbuiltin.err b/tests/test_builtinbuiltin.err new file mode 100644 index 000000000..ff818897a --- /dev/null +++ b/tests/test_builtinbuiltin.err @@ -0,0 +1,2 @@ +builtin: Invalid combination of options, +--query and --names are mutually exclusive diff --git a/tests/test_builtinbuiltin.in b/tests/test_builtinbuiltin.in new file mode 100644 index 000000000..4293a96e1 --- /dev/null +++ b/tests/test_builtinbuiltin.in @@ -0,0 +1,7 @@ +# Tests for the "builtin" builtin/keyword. +builtin -q string; and echo String exists +builtin -q; and echo None exists +builtin -q string echo banana; and echo Some of these exist +builtin -nq string +echo $status +exit 0 diff --git a/tests/test_builtinbuiltin.out b/tests/test_builtinbuiltin.out new file mode 100644 index 000000000..11c0882b4 --- /dev/null +++ b/tests/test_builtinbuiltin.out @@ -0,0 +1,3 @@ +String exists +Some of these exist +2