complete: Add "--force-files"

This allows a completion to specify that *it* takes files.

Useful for things like `sudo -e`, because sudo usually doesn't take
any files.
This commit is contained in:
Fabian Homborg 2019-05-30 19:12:49 +02:00
parent d28e8fb7de
commit 4ebb6cf39e
6 changed files with 30 additions and 6 deletions

View File

@ -16,6 +16,7 @@ Synopsis
[( -a | --arguments ) OPTION_ARGUMENTS]
[( -k | --keep-order )]
[( -f | --no-files )]
[( -F | --force-files )]
[( -r | --require-parameter )]
[( -x | --exclusive )]
[( -w | --wraps ) WRAPPED_COMMAND]...
@ -56,9 +57,11 @@ the fish manual.
- ``-k`` or ``--keep-order`` preserves the order of the ``OPTION_ARGUMENTS`` specified via ``-a`` or ``--arguments`` instead of sorting alphabetically. Multiple ``complete`` calls with ``-k`` result in arguments of the later ones displayed first.
- ``-f`` or ``--no-files`` specifies that the options specified by this completion may not be followed by a filename.
- ``-f`` or ``--no-files`` says that the options specified by this completion may not be followed by a filename.
- ``-r`` or ``--require-parameter`` specifies that the options specified by this completion always must have an option argument, i.e. may not be followed by another option.
- ``-F`` or ``--force-files`` says that the options specified by this completion may be followed by a filename, even if another applicable ``complete`` specified ``--no-files``.
- ``-r`` or ``--require-parameter`` says that the options specified by this completion must have an option argument, i.e. may not be followed by another option.
- ``-x`` or ``--exclusive`` implies both ``-r`` and ``-f``.

View File

@ -126,9 +126,10 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
wcstring_list_t wrap_targets;
bool preserve_order = false;
static const wchar_t *const short_options = L":a:c:p:s:l:o:d:frxeuAn:C::w:hk";
static const wchar_t *const short_options = L":a:c:p:s:l:o:d:fFrxeuAn:C::w:hk";
static const struct woption long_options[] = {{L"exclusive", no_argument, NULL, 'x'},
{L"no-files", no_argument, NULL, 'f'},
{L"force-files", no_argument, NULL, 'F'},
{L"require-parameter", no_argument, NULL, 'r'},
{L"path", required_argument, NULL, 'p'},
{L"command", required_argument, NULL, 'c'},
@ -160,6 +161,9 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
result_mode.no_files = true;
break;
}
case 'F': {
result_mode.force_files = true;
}
case 'r': {
result_mode.requires_param = true;
break;
@ -259,6 +263,11 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
}
}
if (result_mode.no_files && result_mode.force_files) {
streams.err.append_format(BUILTIN_ERR_COMBO2, L"complete", L"'--no-files' and '--force-files'");
return STATUS_INVALID_ARGS;
}
if (w.woptind != argc) {
// Use one left-over arg as the do-complete argument
// to enable `complete -C "git check"`.

View File

@ -886,7 +886,7 @@ static void complete_load(const wcstring &name) {
/// Insert results into comp_out. Return true to perform file completion, false to disable it.
bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
const wcstring &str, bool use_switches) {
bool use_common = 1, use_files = 1;
bool use_common = true, use_files = true, has_force = false;
wcstring cmd, path;
parse_cmd_string(cmd_orig, &path, &cmd, vars);
@ -955,6 +955,7 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
if (arg != NULL && this->condition_test(o.condition)) {
if (o.result_mode.requires_param) use_common = false;
if (o.result_mode.no_files) use_files = false;
if (o.result_mode.force_files) has_force = true;
complete_from_args(arg, o.comp, o.localized_desc(), o.flags);
}
}
@ -971,6 +972,7 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
old_style_match = true;
if (o.result_mode.requires_param) use_common = false;
if (o.result_mode.no_files) use_files = false;
if (o.result_mode.force_files) has_force = true;
complete_from_args(str, o.comp, o.localized_desc(), o.flags);
}
}
@ -989,6 +991,7 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
if (param_match(&o, popt.c_str()) && this->condition_test(o.condition)) {
if (o.result_mode.requires_param) use_common = false;
if (o.result_mode.no_files) use_files = false;
if (o.result_mode.force_files) has_force = true;
complete_from_args(str, o.comp, o.localized_desc(), o.flags);
}
}
@ -1005,7 +1008,7 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
// If this entry is for the base command, check if any of the arguments match.
if (!this->condition_test(o.condition)) continue;
if (o.option.empty()) {
use_files = use_files && ((o.result_mode.no_files) == 0);
use_files = use_files && (!(o.result_mode.no_files));
complete_from_args(str, o.comp, o.localized_desc(), o.flags);
}
@ -1067,7 +1070,7 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
}
}
return use_files;
return has_force || use_files;
}
/// Perform generic (not command-specific) expansions on the specified string.
@ -1628,6 +1631,8 @@ wcstring complete_print() {
modestr = L" --exclusive";
} else if (o.result_mode.no_files) {
modestr = L" --no-files";
} else if (o.result_mode.force_files) {
modestr = L" --force-files";
} else if (o.result_mode.requires_param) {
modestr = L" --require-parameter";
}

View File

@ -17,6 +17,7 @@
struct completion_mode_t {
/// If set, skip file completions.
bool no_files{false};
bool force_files{false};
/// If set, require a parameter after completion.
bool requires_param{false};

View File

@ -27,3 +27,8 @@ complete -C'myalias2 call3 '
function t --wraps t; echo t; end
complete -c t -fa '(t)'
complete -C't '
# Ensure file completion happens even though it was disabled above.
complete -c t -l fileoption -rF
# Only match this file because I don't want to touch this any time we add a test file.
complete -C't --fileoption ' | string match complete.in

View File

@ -13,3 +13,4 @@ arg2 call2
complete_test_alpha1 arg1 call3
complete_test_alpha1 arg2 call3
t
complete.in