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

View file

@ -97,9 +97,8 @@ typedef struct complete_entry_opt {
wcstring desc; wcstring desc;
// Condition under which to use the option. // Condition under which to use the option.
wcstring condition; wcstring condition;
// Must be one of the values SHARED, NO_FILES, NO_COMMON, EXCLUSIVE, and determines how // Determines how completions should be performed on the argument after the switch.
// completions should be performed on the argument after the switch. completion_mode_t result_mode;
int result_mode;
// Completion flags. // Completion flags.
complete_flags_t 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, 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, complete_option_type_t option_type, completion_mode_t result_mode,
const wchar_t *comp, const wchar_t *desc, complete_flags_t flags) { const wchar_t *condition, const wchar_t *comp, const wchar_t *desc,
complete_flags_t flags) {
CHECK(cmd, ); CHECK(cmd, );
// option should be empty iff the option type is arguments only. // option should be empty iff the option type is arguments only.
assert(option.empty() == (option_type == option_type_args_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; break;
} }
} }
if (match == NULL || (match->result_mode & NO_COMMON)) { if (match == NULL || (match->result_mode.requires_param)) {
result = false; result = false;
break; 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) { for (const complete_entry_opt_t &o : options) {
const wchar_t *arg = param_match2(&o, str.c_str()); const wchar_t *arg = param_match2(&o, str.c_str());
if (arg != NULL && this->condition_test(o.condition)) { if (arg != NULL && this->condition_test(o.condition)) {
if (o.result_mode & NO_COMMON) use_common = false; if (o.result_mode.requires_param) use_common = false;
if (o.result_mode & NO_FILES) use_files = false; if (o.result_mode.no_files) use_files = false;
complete_from_args(arg, o.comp, o.localized_desc(), o.flags); 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()) && if (o.type == option_type_single_long && param_match(&o, popt.c_str()) &&
this->condition_test(o.condition)) { this->condition_test(o.condition)) {
old_style_match = true; old_style_match = true;
if (o.result_mode & NO_COMMON) use_common = false; if (o.result_mode.requires_param) use_common = false;
if (o.result_mode & NO_FILES) use_files = false; if (o.result_mode.no_files) use_files = false;
complete_from_args(str, o.comp, o.localized_desc(), o.flags); 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. // token, so that it can be differed from a regular argument.
// Here we are testing the previous argument for a GNU-style match, // Here we are testing the previous argument for a GNU-style match,
// to see how we should complete the current argument // 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; continue;
if (param_match(&o, popt.c_str()) && this->condition_test(o.condition)) { 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.requires_param) use_common = false;
if (o.result_mode & NO_FILES) use_files = false; if (o.result_mode.no_files) use_files = false;
complete_from_args(str, o.comp, o.localized_desc(), o.flags); 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 entry is for the base command, check if any of the arguments match.
if (!this->condition_test(o.condition)) continue; if (!this->condition_test(o.condition)) continue;
if (o.option.empty()) { 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); 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(); 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)) { 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 // 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) { for (const completion_entry_t &e : all_completions) {
const option_list_t &options = e.get_options(); const option_list_t &options = e.get_options();
for (const complete_entry_opt_t &o : options) { for (const complete_entry_opt_t &o : options) {
const wchar_t *modestr[] = {L"", L" --no-files", L" --require-parameter", const wchar_t *modestr = L"";
L" --exclusive"}; if (o.result_mode.no_files && o.result_mode.requires_param) {
modestr = L" --exclusive";
append_format(out, L"complete%ls", modestr[o.result_mode]); } 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", append_switch(out, e.cmd_is_path ? L"path" : L"command",
escape_string(e.cmd, ESCAPE_ALL)); escape_string(e.cmd, ESCAPE_ALL));

View file

@ -12,15 +12,13 @@
#include "common.h" #include "common.h"
/// Use all completions. struct completion_mode_t {
#define SHARED 0 /// If set, skip file completions.
/// Do not use file completion. bool no_files{false};
#define NO_FILES 1
/// Require a parameter after completion. /// If set, require a parameter after completion.
#define NO_COMMON 2 bool requires_param{false};
/// Only use the argument list specifies with completion after option. This is the same as (NO_FILES };
/// | NO_COMMON).
#define EXCLUSIVE 3
/// Separator between completion and description. /// Separator between completion and description.
#define COMPLETE_SEP L'\004' #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 The name of an option.
/// \param option_type The type of option: can be option_type_short (-x), /// \param option_type The type of option: can be option_type_short (-x),
/// option_type_single_long (-foo), option_type_double_long (--bar). /// option_type_single_long (-foo), option_type_double_long (--bar).
/// \param result_mode Whether to search further completions when this completion has been /// \param result_mode Controls how to search further completions when this completion has been
/// succesfully matched. If result_mode is SHARED, any other completions may also be used. If /// succesfully matched.
/// 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 comp A space separated list of completions which may contain subshells. /// \param comp A space separated list of completions which may contain subshells.
/// \param desc A description of the completion. /// \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 /// \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. /// is empty, the completion is always used.
/// \param flags A set of completion flags /// \param flags A set of completion flags
void complete_add(const wchar_t *cmd, bool cmd_is_path, const wcstring &option, 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, complete_option_type_t option_type, completion_mode_t result_mode,
const wchar_t *comp, const wchar_t *desc, int flags); const wchar_t *condition, const wchar_t *comp, const wchar_t *desc, int flags);
/// Remove a previously defined completion. /// Remove a previously defined completion.
void complete_remove(const wcstring &cmd, bool cmd_is_path, const wcstring &option, 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); do_test(completions.size() == 0);
// Trailing spaces (#1261). // 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); NULL, COMPLETE_AUTO_SPACE);
completions.clear(); completions.clear();
complete(L"foobarbaz ", &completions, COMPLETION_REQUEST_DEFAULT, vars); complete(L"foobarbaz ", &completions, COMPLETION_REQUEST_DEFAULT, vars);