Stop passing mutable references to completions around

Replace uses of vector<completion_t>& with vector<completion_t>*
This makes it clear at the call site that the object may be mutated.
This commit is contained in:
ridiculousfish 2015-07-27 18:45:47 -07:00
parent 85dad6913e
commit 6e3231a9d7
12 changed files with 101 additions and 99 deletions

View File

@ -4226,8 +4226,10 @@ wcstring_list_t builtin_get_names(void)
return result;
}
void builtin_get_names(std::vector<completion_t> &list)
void builtin_get_names(std::vector<completion_t> *list)
{
assert(list != NULL);
list->reserve(list->size() + BUILTIN_COUNT);
for (size_t i=0; i < BUILTIN_COUNT; i++)
{
append_completion(list, builtin_datas[i].name);

View File

@ -142,10 +142,10 @@ int builtin_exists(const wcstring &cmd);
int builtin_run(parser_t &parser, const wchar_t * const *argv, const io_chain_t &io);
/** Returns a list of all builtin names */
wcstring_list_t builtin_get_names(void);
wcstring_list_t builtin_get_names();
/** Insert all builtin names into list. */
void builtin_get_names(std::vector<completion_t> &list);
void builtin_get_names(std::vector<completion_t> *list);
/**
Pushes a new set of input/output to the stack. The new stdin is supplied, a new set of output strings is created.

View File

@ -461,15 +461,16 @@ void completion_autoload_t::command_removed(const wcstring &cmd)
/** Create a new completion entry. */
void append_completion(std::vector<completion_t> &completions, const wcstring &comp, const wcstring &desc, complete_flags_t flags, string_fuzzy_match_t match)
void append_completion(std::vector<completion_t> *completions, const wcstring &comp, const wcstring &desc, complete_flags_t flags, string_fuzzy_match_t match)
{
/* If we just constructed the completion and used push_back, we would get two string copies. Try to avoid that by making a stubby completion in the vector first, and then copying our string in. Note that completion_t's constructor will munge 'flags' so it's important that we pass those to the constructor.
Nasty hack for #1241 - since the constructor needs the completion string to resolve AUTO_SPACE, and we aren't providing it with the completion, we have to do the resolution ourselves. We should get this resolving out of the constructor.
*/
assert(completions != NULL);
const wcstring empty;
completions.push_back(completion_t(empty, empty, match, resolve_auto_space(comp, flags)));
completion_t *last = &completions.back();
completions->push_back(completion_t(empty, empty, match, resolve_auto_space(comp, flags)));
completion_t *last = &completions->back();
last->completion = comp;
last->description = desc;
}
@ -973,7 +974,7 @@ void completer_t::complete_strings(const wcstring &wc_escaped,
if (next_str)
{
wildcard_complete(next_str, wc, desc, desc_func, this->completions, this->expand_flags(), flags);
wildcard_complete(next_str, wc, desc, desc_func, &this->completions, this->expand_flags(), flags);
}
}
@ -1140,7 +1141,7 @@ void completer_t::complete_cmd(const wcstring &str_cmd, bool use_function, bool
if (use_command)
{
if (expand_string(str_cmd, this->completions, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags(), NULL) != EXPAND_ERROR)
if (expand_string(str_cmd, &this->completions, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags(), NULL) != EXPAND_ERROR)
{
if (this->wants_descriptions())
{
@ -1150,7 +1151,7 @@ void completer_t::complete_cmd(const wcstring &str_cmd, bool use_function, bool
}
if (use_implicit_cd)
{
if (!expand_string(str_cmd, this->completions, ACCEPT_INCOMPLETE | DIRECTORIES_ONLY | this->expand_flags(), NULL))
if (!expand_string(str_cmd, &this->completions, ACCEPT_INCOMPLETE | DIRECTORIES_ONLY | this->expand_flags(), NULL))
{
// Not valid as implicit cd.
}
@ -1179,7 +1180,7 @@ void completer_t::complete_cmd(const wcstring &str_cmd, bool use_function, bool
size_t prev_count = this->completions.size();
if (expand_string(nxt_completion,
this->completions,
&this->completions,
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags(), NULL) != EXPAND_ERROR)
{
/* For all new completions, if COMPLETE_NO_CASE is set, then use only the last path component */
@ -1205,7 +1206,7 @@ void completer_t::complete_cmd(const wcstring &str_cmd, bool use_function, bool
wcstring_list_t names = function_get_names(str_cmd.at(0) == L'_');
for (size_t i=0; i < names.size(); i++)
{
append_completion(possible_comp, names.at(i));
append_completion(&possible_comp, names.at(i));
}
this->complete_strings(str_cmd, 0, &complete_function_desc, possible_comp, 0);
@ -1215,7 +1216,7 @@ void completer_t::complete_cmd(const wcstring &str_cmd, bool use_function, bool
if (use_builtin)
{
builtin_get_names(possible_comp);
builtin_get_names(&possible_comp);
this->complete_strings(str_cmd, 0, &builtin_get_desc, possible_comp, 0);
}
@ -1240,9 +1241,6 @@ void completer_t::complete_from_args(const wcstring &str,
const wcstring &desc,
complete_flags_t flags)
{
std::vector<completion_t> possible_comp;
bool is_autosuggest = (this->type() == COMPLETE_AUTOSUGGEST);
parser_t parser(is_autosuggest ? PARSER_TYPE_COMPLETIONS_ONLY : PARSER_TYPE_GENERAL, false /* don't show errors */);
@ -1250,7 +1248,8 @@ void completer_t::complete_from_args(const wcstring &str,
if (! is_autosuggest)
proc_push_interactive(0);
parser.expand_argument_list(args, possible_comp);
std::vector<completion_t> possible_comp;
parser.expand_argument_list(args, &possible_comp);
if (! is_autosuggest)
proc_pop_interactive();
@ -1538,7 +1537,7 @@ bool completer_t::complete_param(const wcstring &scmd_orig, const wcstring &spop
completion[0] = o->short_opt;
completion[1] = 0;
append_completion(this->completions, completion, desc, 0);
append_completion(&this->completions, completion, desc, 0);
}
@ -1593,14 +1592,14 @@ bool completer_t::complete_param(const wcstring &scmd_orig, const wcstring &spop
homebrew getopt-like functions.
*/
wcstring completion = format_string(L"%ls=", whole_opt.c_str()+offset);
append_completion(this->completions,
append_completion(&this->completions,
completion,
C_(o->desc),
flags);
}
append_completion(this->completions,
append_completion(&this->completions,
whole_opt.c_str() + offset,
C_(o->desc),
flags);
@ -1649,7 +1648,7 @@ void completer_t::complete_param_expand(const wcstring &str, bool do_file, bool
const wcstring sep_string = wcstring(str, sep_index + 1);
std::vector<completion_t> local_completions;
if (expand_string(sep_string,
local_completions,
&local_completions,
flags,
NULL) == EXPAND_ERROR)
{
@ -1678,7 +1677,7 @@ void completer_t::complete_param_expand(const wcstring &str, bool do_file, bool
flags &= ~EXPAND_FUZZY_MATCH;
if (expand_string(str,
this->completions,
&this->completions,
flags, NULL) == EXPAND_ERROR)
{
debug(3, L"Error while expanding string '%ls'", str.c_str());
@ -1735,7 +1734,7 @@ bool completer_t::complete_variable(const wcstring &str, size_t start_offset)
desc = format_string(COMPLETE_VAR_DESC_VAL, value.c_str());
}
append_completion(this->completions, comp, desc, flags, match);
append_completion(&this->completions, comp, desc, flags, match);
res = true;
}
@ -1846,7 +1845,7 @@ bool completer_t::try_complete_user(const wcstring &str)
if (wcsncmp(user_name, pw_name, name_len)==0)
{
wcstring desc = format_string(COMPLETE_USER_DESC, pw_name);
append_completion(this->completions,
append_completion(&this->completions,
&pw_name[name_len],
desc,
COMPLETE_NO_SPACE);
@ -1858,7 +1857,7 @@ bool completer_t::try_complete_user(const wcstring &str)
wcstring name = format_string(L"~%ls", pw_name);
wcstring desc = format_string(COMPLETE_USER_DESC, pw_name);
append_completion(this->completions,
append_completion(&this->completions,
name,
desc,
COMPLETE_REPLACES_TOKEN | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE);

View File

@ -262,7 +262,7 @@ void complete_load(const wcstring &cmd, bool reload);
\param flags completion flags
*/
void append_completion(std::vector<completion_t> &completions, const wcstring &comp, const wcstring &desc = wcstring(), int flags = 0, string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_match_exact));
void append_completion(std::vector<completion_t> *completions, const wcstring &comp, const wcstring &desc = wcstring(), int flags = 0, string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_match_exact));
/* Function used for testing */
void complete_set_variable_names(const wcstring_list_t *names);

View File

@ -607,7 +607,7 @@ static int find_job(const struct find_job_data_t *info)
{
if (!j->command_is_empty())
{
append_completion(completions, to_string<long>(j->pgid));
append_completion(&completions, to_string<long>(j->pgid));
break;
}
}
@ -638,7 +638,7 @@ static int find_job(const struct find_job_data_t *info)
if (wcsncmp(proc, jid, wcslen(proc))==0)
{
wcstring desc_buff = format_string(COMPLETE_JOB_DESC_VAL, j->command_wcstr());
append_completion(completions,
append_completion(&completions,
jid+wcslen(proc),
desc_buff,
0);
@ -657,7 +657,7 @@ static int find_job(const struct find_job_data_t *info)
j = job_get(jid);
if ((j != 0) && (j->command_wcstr() != 0) && (!j->command_is_empty()))
{
append_completion(completions, to_string<long>(j->pgid));
append_completion(&completions, to_string<long>(j->pgid));
}
}
}
@ -682,14 +682,14 @@ static int find_job(const struct find_job_data_t *info)
{
if (flags & ACCEPT_INCOMPLETE)
{
append_completion(completions,
append_completion(&completions,
j->command_wcstr() + offset + wcslen(proc),
COMPLETE_JOB_DESC,
0);
}
else
{
append_completion(completions, to_string<long>(j->pgid));
append_completion(&completions, to_string<long>(j->pgid));
found = 1;
}
}
@ -713,14 +713,14 @@ static int find_job(const struct find_job_data_t *info)
{
if (flags & ACCEPT_INCOMPLETE)
{
append_completion(completions,
append_completion(&completions,
wcstring(p->actual_cmd, offset + wcslen(proc)),
COMPLETE_CHILD_PROCESS_DESC,
0);
}
else
{
append_completion(completions,
append_completion(&completions,
to_string<long>(p->pid),
L"",
0);
@ -750,11 +750,11 @@ static int find_job(const struct find_job_data_t *info)
understand the contents of the /proc filesystem, all the users
processes are searched for matches.
*/
static void find_process(const wchar_t *proc, expand_flags_t flags, std::vector<completion_t> &out)
static void find_process(const wchar_t *proc, expand_flags_t flags, std::vector<completion_t> *out)
{
if (!(flags & EXPAND_SKIP_JOBS))
{
const struct find_job_data_t data = {proc, flags, &out};
const struct find_job_data_t data = {proc, flags, out};
int found = iothread_perform_on_main(find_job, &data);
if (found)
{
@ -789,7 +789,7 @@ static void find_process(const wchar_t *proc, expand_flags_t flags, std::vector<
/**
Process id expansion
*/
static bool expand_pid(const wcstring &instr_with_sep, expand_flags_t flags, std::vector<completion_t> &out, parse_error_list_t *errors)
static bool expand_pid(const wcstring &instr_with_sep, expand_flags_t flags, std::vector<completion_t> *out, parse_error_list_t *errors)
{
/* Hack. If there's no INTERNAL_SEP and no PROCESS_EXPAND, then there's nothing to do. Check out this "null terminated string." */
const wchar_t some_chars[] = {INTERNAL_SEPARATOR, PROCESS_EXPAND, L'\0'};
@ -852,10 +852,10 @@ static bool expand_pid(const wcstring &instr_with_sep, expand_flags_t flags, std
}
/* This is sort of crummy - find_process doesn't return any indication of success, so instead we check to see if it inserted any completions */
const size_t prev_count = out.size();
const size_t prev_count = out->size();
find_process(in+1, flags, out);
if (prev_count == out.size())
if (prev_count == out->size())
{
if (!(flags & ACCEPT_INCOMPLETE))
{
@ -974,7 +974,7 @@ static size_t parse_slice(const wchar_t *in, wchar_t **end_ptr, std::vector<long
As such, to process a string fully, pass string.size() as last_idx
instead of string.size()-1.
*/
static int expand_variables(parser_t &parser, const wcstring &instr, std::vector<completion_t> &out, long last_idx, parse_error_list_t *errors)
static int expand_variables(parser_t &parser, const wcstring &instr, std::vector<completion_t> *out, long last_idx, parse_error_list_t *errors)
{
const size_t insize = instr.size();
@ -1258,7 +1258,7 @@ static int expand_variables(parser_t &parser, const wcstring &instr, std::vector
/**
Perform bracket expansion
*/
static int expand_brackets(parser_t &parser, const wcstring &instr, int flags, std::vector<completion_t> &out, parse_error_list_t *errors)
static int expand_brackets(parser_t &parser, const wcstring &instr, int flags, std::vector<completion_t> *out, parse_error_list_t *errors)
{
bool syntax_error = false;
int bracket_count=0;
@ -1388,7 +1388,7 @@ static int expand_brackets(parser_t &parser, const wcstring &instr, int flags, s
/**
Perform cmdsubst expansion
*/
static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector<completion_t> &out_list, parse_error_list_t *errors)
static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector<completion_t> *out_list, parse_error_list_t *errors)
{
wchar_t *paran_begin=0, *paran_end=0;
std::vector<wcstring> sub_res;
@ -1468,7 +1468,7 @@ static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector<
of the string is inserted into the tail_expand array list
*/
std::vector<completion_t> tail_expand;
expand_cmdsubst(parser, tail_begin, tail_expand, errors /* TODO: offset error locations */);
expand_cmdsubst(parser, tail_begin, &tail_expand, errors /* TODO: offset error locations */);
/*
Combine the result of the current command substitution with the
@ -1683,7 +1683,7 @@ static void remove_internal_separator(wcstring &str, bool conv)
}
int expand_string(const wcstring &input, std::vector<completion_t> &output, expand_flags_t flags, parse_error_list_t *errors)
int expand_string(const wcstring &input, std::vector<completion_t> *output, expand_flags_t flags, parse_error_list_t *errors)
{
parser_t parser(PARSER_TYPE_ERRORS_ONLY, true /* show errors */);
@ -1708,11 +1708,11 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
append_cmdsub_error(errors, SOURCE_LOCATION_UNKNOWN, L"Command substitutions not allowed");
return EXPAND_ERROR;
}
append_completion(*in, input);
append_completion(in, input);
}
else
{
int cmdsubst_ok = expand_cmdsubst(parser, input, *in, errors);
int cmdsubst_ok = expand_cmdsubst(parser, input, in, errors);
if (! cmdsubst_ok)
return EXPAND_ERROR;
}
@ -1736,11 +1736,11 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
next[i] = L'$';
}
}
append_completion(*out, next);
append_completion(out, next);
}
else
{
if (!expand_variables(parser, next, *out, next.size(), errors))
if (!expand_variables(parser, next, out, next.size(), errors))
{
return EXPAND_ERROR;
}
@ -1754,7 +1754,7 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
{
const wcstring &next = in->at(i).completion;
if (!expand_brackets(parser, next, flags, *out, errors))
if (!expand_brackets(parser, next, flags, out, errors))
{
return EXPAND_ERROR;
}
@ -1783,10 +1783,10 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
}
else
{
append_completion(*out, next);
append_completion(out, next);
}
}
else if (! expand_pid(next, flags, *out, errors))
else if (! expand_pid(next, flags, out, errors))
{
return EXPAND_ERROR;
}
@ -1824,7 +1824,7 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
}
std::vector<completion_t> expanded;
wc_res = wildcard_expand_string(rest, start, flags, expanded);
wc_res = wildcard_expand_string(rest, start, flags, &expanded);
if (flags & ACCEPT_INCOMPLETE)
{
out->insert(out->end(), expanded.begin(), expanded.end());
@ -1860,7 +1860,7 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
{
if (!(flags & ACCEPT_INCOMPLETE))
{
append_completion(*out, next);
append_completion(out, next);
}
}
}
@ -1872,7 +1872,7 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
}
// Return our output
output.insert(output.end(), out->begin(), out->end());
output->insert(output->end(), out->begin(), out->end());
return res;
}
@ -1887,7 +1887,7 @@ bool expand_one(wcstring &string, expand_flags_t flags, parse_error_list_t *erro
return true;
}
if (expand_string(string, completions, flags | EXPAND_NO_DESCRIPTIONS, errors))
if (expand_string(string, &completions, flags | EXPAND_NO_DESCRIPTIONS, errors))
{
if (completions.size() == 1)
{
@ -1990,19 +1990,19 @@ bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector<completion_t> *args)
val.resize(last_good + 1);
args->clear();
append_completion(*args, L"set");
append_completion(args, L"set");
if (key == L"DBUS_SESSION_BUS_ADDRESS")
append_completion(*args, L"-x");
append_completion(*args, key);
append_completion(*args, val);
append_completion(args, L"-x");
append_completion(args, key);
append_completion(args, val);
result = true;
}
else if (string_prefixes_string(L"export DBUS_SESSION_BUS_ADDRESS;", cmd))
{
/* Nothing, we already exported it */
args->clear();
append_completion(*args, L"echo");
append_completion(*args, L"-n");
append_completion(args, L"echo");
append_completion(args, L"-n");
result = true;
}
}

View File

@ -152,7 +152,7 @@ class parser_t;
\param errors Resulting errors, or NULL to ignore
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH. EXPAND_WILDCARD_NO_MATCH and EXPAND_WILDCARD_MATCH are normal exit conditions used only on strings containing wildcards to tell if the wildcard produced any matches.
*/
__warn_unused int expand_string(const wcstring &input, std::vector<completion_t> &output, expand_flags_t flags, parse_error_list_t *errors);
__warn_unused int expand_string(const wcstring &input, std::vector<completion_t> *output, expand_flags_t flags, parse_error_list_t *errors);
/**

View File

@ -739,7 +739,7 @@ static void test_parser()
say(L"Testing eval_args");
completion_list_t comps;
parser_t::principal_parser().expand_argument_list(L"alpha 'beta gamma' delta", comps);
parser_t::principal_parser().expand_argument_list(L"alpha 'beta gamma' delta", &comps);
do_test(comps.size() == 3);
do_test(comps.at(0).completion == L"alpha");
do_test(comps.at(1).completion == L"beta gamma");
@ -1344,7 +1344,7 @@ static bool expand_test(const wchar_t *in, expand_flags_t flags, ...)
wchar_t *arg;
parse_error_list_t errors;
if (expand_string(in, output, flags, &errors) == EXPAND_ERROR)
if (expand_string(in, &output, flags, &errors) == EXPAND_ERROR)
{
if (errors.empty())
{
@ -1583,7 +1583,7 @@ static void test_pager_navigation()
completion_list_t completions;
for (size_t i=0; i < 19; i++)
{
append_completion(completions, L"abcdefghij");
append_completion(&completions, L"abcdefghij");
}
pager_t pager;

View File

@ -525,7 +525,7 @@ parse_execution_result_t parse_execution_context_t::run_switch_statement(const p
/* Expand it. We need to offset any errors by the position of the string */
std::vector<completion_t> switch_values_expanded;
parse_error_list_t errors;
int expand_ret = expand_string(switch_value, switch_values_expanded, EXPAND_NO_DESCRIPTIONS, &errors);
int expand_ret = expand_string(switch_value, &switch_values_expanded, EXPAND_NO_DESCRIPTIONS, &errors);
parse_error_offset_source_start(&errors, switch_value_node.source_start);
switch (expand_ret)
@ -985,7 +985,7 @@ parse_execution_result_t parse_execution_context_t::determine_arguments(const pa
/* Expand this string */
std::vector<completion_t> arg_expanded;
parse_error_list_t errors;
int expand_ret = expand_string(arg_str, arg_expanded, EXPAND_NO_DESCRIPTIONS, &errors);
int expand_ret = expand_string(arg_str, &arg_expanded, EXPAND_NO_DESCRIPTIONS, &errors);
parse_error_offset_source_start(&errors, arg_node.source_start);
switch (expand_ret)
{

View File

@ -494,8 +494,9 @@ void parser_t::emit_profiling(const char *path) const
}
}
void parser_t::expand_argument_list(const wcstring &arg_list_src, std::vector<completion_t> &output_arg_list)
void parser_t::expand_argument_list(const wcstring &arg_list_src, std::vector<completion_t> *output_arg_list)
{
assert(output_arg_list != NULL);
expand_flags_t eflags = 0;
if (! show_errors)
eflags |= EXPAND_NO_DESCRIPTIONS;

View File

@ -314,7 +314,7 @@ public:
\param arg_src String to evaluate as an argument list
\param output List to insert output into
*/
void expand_argument_list(const wcstring &arg_src, std::vector<completion_t> &output);
void expand_argument_list(const wcstring &arg_src, std::vector<completion_t> *output);
/**
Returns a string describing the current parser pisition in the format 'FILENAME (line LINE_NUMBER): LINE'.

View File

@ -211,7 +211,7 @@ static bool wildcard_complete_internal(const wcstring &orig,
bool is_first,
const wchar_t *desc,
wcstring(*desc_func)(const wcstring &),
std::vector<completion_t> &out,
std::vector<completion_t> *out,
expand_flags_t expand_flags,
complete_flags_t flags)
{
@ -316,17 +316,17 @@ static bool wildcard_complete_internal(const wcstring &orig,
/* Try all submatches */
for (size_t i=0; str[i] != L'\0'; i++)
{
const size_t before_count = out.size();
const size_t before_count = out->size();
if (wildcard_complete_internal(orig, str + i, wc+1, false, desc, desc_func, out, expand_flags, flags))
{
res = true;
/* #929: if the recursive call gives us a prefix match, just stop. This is sloppy - what we really want to do is say, once we've seen a match of a particular type, ignore all matches of that type further down the string, such that the wildcard produces the "minimal match." */
bool has_prefix_match = false;
const size_t after_count = out.size();
const size_t after_count = out->size();
for (size_t j = before_count; j < after_count; j++)
{
if (out[j].match.type <= fuzzy_match_prefix)
if (out->at(j).match.type <= fuzzy_match_prefix)
{
has_prefix_match = true;
break;
@ -354,13 +354,12 @@ bool wildcard_complete(const wcstring &str,
const wchar_t *wc,
const wchar_t *desc,
wcstring(*desc_func)(const wcstring &),
std::vector<completion_t> &out,
std::vector<completion_t> *out,
expand_flags_t expand_flags,
complete_flags_t flags)
{
bool res;
res = wildcard_complete_internal(str, str.c_str(), wc, true, desc, desc_func, out, expand_flags, flags);
return res;
assert(out != NULL);
return wildcard_complete_internal(str, str.c_str(), wc, true, desc, desc_func, out, expand_flags, flags);
}
@ -515,12 +514,13 @@ static wcstring file_get_desc(const wcstring &filename,
\param wc the wildcard to match against
\param is_cmd whether we are performing command completion
*/
static void wildcard_completion_allocate(std::vector<completion_t> &list,
static void wildcard_completion_allocate(std::vector<completion_t> *list,
const wcstring &fullname,
const wcstring &completion,
const wchar_t *wc,
expand_flags_t expand_flags)
{
assert(list != NULL);
struct stat buf, lbuf;
wcstring sb;
wcstring munged_completion;
@ -644,9 +644,9 @@ static bool test_flags(const wchar_t *filename, expand_flags_t flags)
}
/** Appends a completion to the completion list, if the string is missing from the set. */
static void insert_completion_if_missing(const wcstring &str, std::vector<completion_t> &out, std::set<wcstring> &completion_set)
static void insert_completion_if_missing(const wcstring &str, std::vector<completion_t> *out, std::set<wcstring> *completion_set)
{
if (completion_set.insert(str).second)
if (completion_set->insert(str).second)
append_completion(out, str);
}
@ -665,7 +665,7 @@ static void insert_completion_if_missing(const wcstring &str, std::vector<comple
static int wildcard_expand_internal(const wchar_t *wc,
const wchar_t * const base_dir,
expand_flags_t flags,
std::vector<completion_t> &out,
std::vector<completion_t> *out,
std::set<wcstring> &completion_set,
std::set<file_id_t> &visited_files)
{
@ -776,7 +776,7 @@ static int wildcard_expand_internal(const wchar_t *wc,
else
{
res = 1;
insert_completion_if_missing(base_dir, out, completion_set);
insert_completion_if_missing(base_dir, out, &completion_set);
}
}
else
@ -792,7 +792,7 @@ static int wildcard_expand_internal(const wchar_t *wc,
/* Test for matches before stating file, so as to minimize the number of calls to the much slower stat function. The only expand flag we care about is EXPAND_FUZZY_MATCH; we have no complete flags. */
std::vector<completion_t> test;
if (wildcard_complete(name_str, wc, L"", NULL, test, flags & EXPAND_FUZZY_MATCH, 0))
if (wildcard_complete(name_str, wc, L"", NULL, &test, flags & EXPAND_FUZZY_MATCH, 0))
{
if (test_flags(long_name.c_str(), flags))
{
@ -823,7 +823,7 @@ static int wildcard_expand_internal(const wchar_t *wc,
}
if (! skip)
{
insert_completion_if_missing(long_name, out, completion_set);
insert_completion_if_missing(long_name, out, &completion_set);
}
res = 1;
}
@ -959,17 +959,18 @@ static int wildcard_expand_internal(const wchar_t *wc,
}
int wildcard_expand(const wchar_t *wc,
const wchar_t *base_dir,
expand_flags_t flags,
std::vector<completion_t> &out)
static int wildcard_expand(const wchar_t *wc,
const wchar_t *base_dir,
expand_flags_t flags,
std::vector<completion_t> *out)
{
size_t c = out.size();
assert(out != NULL);
size_t c = out->size();
/* Make a set of used completion strings so we can do fast membership tests inside wildcard_expand_internal. Otherwise wildcards like '**' are very slow, because we end up with an N^2 membership test.
*/
std::set<wcstring> completion_set;
for (std::vector<completion_t>::const_iterator iter = out.begin(); iter != out.end(); ++iter)
for (std::vector<completion_t>::const_iterator iter = out->begin(); iter != out->end(); ++iter)
{
completion_set.insert(iter->completion);
}
@ -986,29 +987,28 @@ int wildcard_expand(const wchar_t *wc,
wc_base = wcstring(wc, (wc_base_ptr-wc)+1);
}
for (size_t i=c; i<out.size(); i++)
for (size_t i=c; i<out->size(); i++)
{
completion_t &c = out.at(i);
completion_t &c = out->at(i);
if (c.flags & COMPLETE_REPLACES_TOKEN)
{
c.completion = format_string(L"%ls%ls%ls", base_dir, wc_base.c_str(), c.completion.c_str());
// completion = base_dir + wc_base + completion
c.completion.insert(0, wc_base);
c.completion.insert(0, base_dir);
}
}
}
return res;
}
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_flags_t flags, std::vector<completion_t> &outputs)
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_flags_t flags, std::vector<completion_t> *output)
{
assert(output != NULL);
/* Hackish fix for 1631. We are about to call c_str(), which will produce a string truncated at any embedded nulls. We could fix this by passing around the size, etc. However embedded nulls are never allowed in a filename, so we just check for them and return 0 (no matches) if there is an embedded null. This isn't quite right, e.g. it will fail for \0?, but that is an edge case. */
if (wc.find(L'\0') != wcstring::npos)
{
return 0;
}
// PCA: not convinced this temporary variable is really necessary
std::vector<completion_t> lst;
int res = wildcard_expand(wc.c_str(), base_dir.c_str(), flags, lst);
outputs.insert(outputs.end(), lst.begin(), lst.end());
return res;
return wildcard_expand(wc.c_str(), base_dir.c_str(), flags, output);
}

View File

@ -68,7 +68,7 @@ enum
\return 1 if matches where found, 0 otherwise. Return -1 on abort (I.e. ^C was pressed).
*/
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_flags_t flags, std::vector<completion_t> &out);
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_flags_t flags, std::vector<completion_t> *out);
/**
Test whether the given wildcard matches the string. Does not perform any I/O.
@ -90,7 +90,7 @@ bool wildcard_complete(const wcstring &str,
const wchar_t *wc,
const wchar_t *desc,
wcstring(*desc_func)(const wcstring &),
std::vector<completion_t> &out,
std::vector<completion_t> *out,
expand_flags_t expand_flags,
complete_flags_t flags);