Promote completion_mode_t to a real type

Eliminate big #defines like NO_COMMON.
This commit is contained in:
ridiculousfish 2019-04-25 14:21:06 -07:00
parent d962668aa0
commit 96bc8a14ca
4 changed files with 46 additions and 43 deletions

View file

@ -29,8 +29,8 @@
/// Silly function.
static void builtin_complete_add2(const wchar_t *cmd, bool cmd_is_path, const wchar_t *short_opt,
const wcstring_list_t &gnu_opts, const wcstring_list_t &old_opts,
int result_mode, const wchar_t *condition, const wchar_t *comp,
const wchar_t *desc, int flags) {
completion_mode_t result_mode, const wchar_t *condition,
const wchar_t *comp, const wchar_t *desc, int flags) {
for (const wchar_t *s = short_opt; *s; s++) {
complete_add(cmd, cmd_is_path, wcstring{*s}, option_type_short, result_mode, condition,
comp, desc, flags);
@ -55,7 +55,7 @@ static void builtin_complete_add2(const wchar_t *cmd, bool cmd_is_path, const wc
/// Silly function.
static void builtin_complete_add(const wcstring_list_t &cmds, const wcstring_list_t &paths,
const wchar_t *short_opt, wcstring_list_t &gnu_opt,
wcstring_list_t &old_opt, int result_mode,
wcstring_list_t &old_opt, completion_mode_t result_mode,
const wchar_t *condition, const wchar_t *comp, const wchar_t *desc,
int flags) {
for (const wcstring &cmd : cmds) {
@ -114,7 +114,7 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
wchar_t *cmd = argv[0];
int argc = builtin_count_args(argv);
int result_mode = SHARED;
completion_mode_t result_mode{};
int remove = 0;
wcstring short_opt;
wcstring_list_t gnu_opt, old_opt;
@ -152,15 +152,16 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
switch (opt) {
case 'x': {
result_mode |= EXCLUSIVE;
result_mode.no_files = true;
result_mode.requires_param = true;
break;
}
case 'f': {
result_mode |= NO_FILES;
result_mode.no_files = true;
break;
}
case 'r': {
result_mode |= NO_COMMON;
result_mode.requires_param = true;
break;
}
case 'k': {

View file

@ -97,9 +97,8 @@ typedef struct complete_entry_opt {
wcstring desc;
// Condition under which to use the option.
wcstring condition;
// Must be one of the values SHARED, NO_FILES, NO_COMMON, EXCLUSIVE, and determines how
// completions should be performed on the argument after the switch.
int result_mode;
// Determines how completions should be performed on the argument after the switch.
completion_mode_t result_mode;
// Completion flags.
complete_flags_t flags;
@ -440,8 +439,9 @@ static completion_entry_t &complete_get_exact_entry(completion_entry_set_t &comp
}
void complete_add(const wchar_t *cmd, bool cmd_is_path, const wcstring &option,
complete_option_type_t option_type, int result_mode, const wchar_t *condition,
const wchar_t *comp, const wchar_t *desc, complete_flags_t flags) {
complete_option_type_t option_type, completion_mode_t result_mode,
const wchar_t *condition, const wchar_t *comp, const wchar_t *desc,
complete_flags_t flags) {
CHECK(cmd, );
// option should be empty iff the option type is arguments only.
assert(option.empty() == (option_type == option_type_args_only));
@ -852,7 +852,7 @@ static bool short_ok(const wcstring &arg, const complete_entry_opt_t *entry,
break;
}
}
if (match == NULL || (match->result_mode & NO_COMMON)) {
if (match == NULL || (match->result_mode.requires_param)) {
result = false;
break;
}
@ -946,8 +946,8 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
for (const complete_entry_opt_t &o : options) {
const wchar_t *arg = param_match2(&o, str.c_str());
if (arg != NULL && this->condition_test(o.condition)) {
if (o.result_mode & NO_COMMON) use_common = false;
if (o.result_mode & NO_FILES) use_files = false;
if (o.result_mode.requires_param) use_common = false;
if (o.result_mode.no_files) use_files = false;
complete_from_args(arg, o.comp, o.localized_desc(), o.flags);
}
}
@ -962,8 +962,8 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
if (o.type == option_type_single_long && param_match(&o, popt.c_str()) &&
this->condition_test(o.condition)) {
old_style_match = true;
if (o.result_mode & NO_COMMON) use_common = false;
if (o.result_mode & NO_FILES) use_files = false;
if (o.result_mode.requires_param) use_common = false;
if (o.result_mode.no_files) use_files = false;
complete_from_args(str, o.comp, o.localized_desc(), o.flags);
}
}
@ -976,12 +976,12 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
// token, so that it can be differed from a regular argument.
// Here we are testing the previous argument for a GNU-style match,
// to see how we should complete the current argument
if (o.type == option_type_double_long && !(o.result_mode & NO_COMMON))
if (o.type == option_type_double_long && !o.result_mode.requires_param)
continue;
if (param_match(&o, popt.c_str()) && this->condition_test(o.condition)) {
if (o.result_mode & NO_COMMON) use_common = false;
if (o.result_mode & NO_FILES) use_files = false;
if (o.result_mode.requires_param) use_common = false;
if (o.result_mode.no_files) use_files = false;
complete_from_args(str, o.comp, o.localized_desc(), o.flags);
}
}
@ -998,7 +998,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) == 0);
complete_from_args(str, o.comp, o.localized_desc(), o.flags);
}
@ -1043,7 +1043,7 @@ bool completer_t::complete_param(const wcstring &cmd_orig, const wcstring &popt,
}
has_arg = !o.comp.empty();
req_arg = (o.result_mode & NO_COMMON);
req_arg = o.result_mode.requires_param;
if (o.type == option_type_double_long && (has_arg && !req_arg)) {
// Optional arguments to a switch can only be handled using the '=', so we add it as
@ -1616,10 +1616,15 @@ wcstring complete_print() {
for (const completion_entry_t &e : all_completions) {
const option_list_t &options = e.get_options();
for (const complete_entry_opt_t &o : options) {
const wchar_t *modestr[] = {L"", L" --no-files", L" --require-parameter",
L" --exclusive"};
append_format(out, L"complete%ls", modestr[o.result_mode]);
const wchar_t *modestr = L"";
if (o.result_mode.no_files && o.result_mode.requires_param) {
modestr = L" --exclusive";
} else if (o.result_mode.no_files) {
modestr = L" --no-files";
} else if (o.result_mode.requires_param) {
modestr = L" --require-parameter";
}
append_format(out, L"complete%ls", modestr);
append_switch(out, e.cmd_is_path ? L"path" : L"command",
escape_string(e.cmd, ESCAPE_ALL));

View file

@ -12,15 +12,13 @@
#include "common.h"
/// Use all completions.
#define SHARED 0
/// Do not use file completion.
#define NO_FILES 1
/// Require a parameter after completion.
#define NO_COMMON 2
/// Only use the argument list specifies with completion after option. This is the same as (NO_FILES
/// | NO_COMMON).
#define EXCLUSIVE 3
struct completion_mode_t {
/// If set, skip file completions.
bool no_files{false};
/// If set, require a parameter after completion.
bool requires_param{false};
};
/// Separator between completion and description.
#define COMPLETE_SEP L'\004'
@ -148,19 +146,16 @@ void completions_sort_and_prioritize(std::vector<completion_t> *comps,
/// \param option The name of an option.
/// \param option_type The type of option: can be option_type_short (-x),
/// option_type_single_long (-foo), option_type_double_long (--bar).
/// \param result_mode Whether to search further completions when this completion has been
/// succesfully matched. If result_mode is SHARED, any other completions may also be used. If
/// result_mode is NO_FILES, file completion should not be used, but other completions may be used.
/// If result_mode is NO_COMMON, on option may follow it - only a parameter. If result_mode is
/// EXCLUSIVE, no option may follow it, and file completion is not performed.
/// \param result_mode Controls how to search further completions when this completion has been
/// succesfully matched.
/// \param comp A space separated list of completions which may contain subshells.
/// \param desc A description of the completion.
/// \param condition a command to be run to check it this completion should be used. If \c condition
/// is empty, the completion is always used.
/// \param flags A set of completion flags
void complete_add(const wchar_t *cmd, bool cmd_is_path, const wcstring &option,
complete_option_type_t option_type, int result_mode, const wchar_t *condition,
const wchar_t *comp, const wchar_t *desc, int flags);
complete_option_type_t option_type, completion_mode_t result_mode,
const wchar_t *condition, const wchar_t *comp, const wchar_t *desc, int flags);
/// Remove a previously defined completion.
void complete_remove(const wcstring &cmd, bool cmd_is_path, const wcstring &option,

View file

@ -2579,7 +2579,9 @@ static void test_complete() {
do_test(completions.size() == 0);
// Trailing spaces (#1261).
complete_add(L"foobarbaz", false, wcstring(), option_type_args_only, NO_FILES, NULL, L"qux",
completion_mode_t no_files{};
no_files.no_files = true;
complete_add(L"foobarbaz", false, wcstring(), option_type_args_only, no_files, NULL, L"qux",
NULL, COMPLETE_AUTO_SPACE);
completions.clear();
complete(L"foobarbaz ", &completions, COMPLETION_REQUEST_DEFAULT, vars);