diff --git a/builtin.cpp b/builtin.cpp index 0bff83d38..61f7ed8b8 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -4460,7 +4460,7 @@ void builtin_get_names(std::vector &list) { for (size_t i=0; i < BUILTIN_COUNT; i++) { - list.push_back(completion_t(builtin_datas[i].name)); + append_completion(list, builtin_datas[i].name); } } diff --git a/complete.cpp b/complete.cpp index 49f3df3ef..5676d5bb3 100644 --- a/complete.cpp +++ b/complete.cpp @@ -466,7 +466,13 @@ void completion_autoload_t::command_removed(const wcstring &cmd) /** Create a new completion entry */ void append_completion(std::vector &completions, const wcstring &comp, const wcstring &desc, complete_flags_t flags, string_fuzzy_match_t match) { - completions.push_back(completion_t(comp, desc, match, flags)); + /* 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. */ + completions.push_back(completion_t(wcstring())); + completion_t *last = &completions.back(); + last->completion = comp; + last->description = desc; + last->match = match; + last->flags = flags; } /** @@ -1191,7 +1197,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++) { - possible_comp.push_back(completion_t(names.at(i))); + append_completion(possible_comp, names.at(i)); } this->complete_strings(str_cmd, 0, &complete_function_desc, possible_comp, 0); diff --git a/complete.h b/complete.h index cd4f22a16..fa00c3e5b 100644 --- a/complete.h +++ b/complete.h @@ -124,7 +124,7 @@ public: int flags; /* Construction. Note: defining these so that they are not inlined reduces the executable size. */ - completion_t(const wcstring &comp, const wcstring &desc = L"", string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_match_exact), int flags_val = 0); + completion_t(const wcstring &comp, const wcstring &desc = wcstring(), string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_match_exact), int flags_val = 0); completion_t(const completion_t &); completion_t &operator=(const completion_t &); @@ -268,7 +268,7 @@ void complete_load(const wcstring &cmd, bool reload); \param flags completion flags */ -void append_completion(std::vector &completions, const wcstring &comp, const wcstring &desc = L"", int flags = 0, string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_match_exact)); +void append_completion(std::vector &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); diff --git a/env.cpp b/env.cpp index 13f87b6cc..acf132c8a 100644 --- a/env.cpp +++ b/env.cpp @@ -892,6 +892,7 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode) if (!is_universal) { event_t ev = event_t::variable_event(key); + ev.arguments.reserve(3); ev.arguments.push_back(L"VARIABLE"); ev.arguments.push_back(L"SET"); ev.arguments.push_back(key); diff --git a/expand.cpp b/expand.cpp index a73118b89..6216da222 100644 --- a/expand.cpp +++ b/expand.cpp @@ -785,7 +785,15 @@ static int expand_pid(const wcstring &instr_with_sep, expand_flags_t flags, std::vector &out) { - + /* 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'}; + if (instr_with_sep.find_first_of(some_chars) == wcstring::npos) + { + /* Nothing to do */ + append_completion(out, instr_with_sep); + return 1; + } + /* expand_string calls us with internal separators in instr...sigh */ wcstring instr = instr_with_sep; remove_internal_separator(instr, false); @@ -1372,7 +1380,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 &outList) +static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector &out_list) { wchar_t *paran_begin=0, *paran_end=0; std::vector sub_res; @@ -1390,7 +1398,7 @@ static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector< L"Mismatched parenthesis"); return 0; case 0: - outList.push_back(completion_t(input)); + append_completion(out_list, input); return 1; case 1: @@ -1455,15 +1463,15 @@ static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector< */ for (i=0; i &output, expa if ((!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean(input.c_str())) { - output.push_back(completion_t(input)); + append_completion(output, input); return EXPAND_OK; } @@ -1681,7 +1689,7 @@ int expand_string(const wcstring &input, std::vector &output, expa parser.error(CMDSUBST_ERROR, -1, L"Command substitutions not allowed"); return EXPAND_ERROR; } - in->push_back(completion_t(input)); + append_completion(*in, input); } else { @@ -1709,7 +1717,7 @@ int expand_string(const wcstring &input, std::vector &output, expa next[i] = L'$'; } } - out->push_back(completion_t(next)); + append_completion(*out, next); } else { @@ -1725,7 +1733,7 @@ int expand_string(const wcstring &input, std::vector &output, expa for (i=0; i < in->size(); i++) { - wcstring next = in->at(i).completion; + const wcstring &next = in->at(i).completion; if (!expand_brackets(parser, next, flags, *out)) { @@ -1745,7 +1753,7 @@ int expand_string(const wcstring &input, std::vector &output, expa if (flags & ACCEPT_INCOMPLETE) { - if (next[0] == PROCESS_EXPAND) + if (! next.empty() && next.at(0) == PROCESS_EXPAND) { /* If process expansion matches, we are not @@ -1758,7 +1766,7 @@ int expand_string(const wcstring &input, std::vector &output, expa } else { - out->push_back(completion_t(next)); + append_completion(*out, next); } } else @@ -1840,7 +1848,7 @@ int expand_string(const wcstring &input, std::vector &output, expa { if (!(flags & ACCEPT_INCOMPLETE)) { - out->push_back(completion_t(next_str)); + append_completion(*out, next_str); } } } @@ -1970,19 +1978,19 @@ bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector *args) val.resize(last_good + 1); args->clear(); - args->push_back(completion_t(L"set")); + append_completion(*args, L"set"); if (key == L"DBUS_SESSION_BUS_ADDRESS") - args->push_back(completion_t(L"-x")); - args->push_back(completion_t(key)); - args->push_back(completion_t(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(); - args->push_back(completion_t(L"echo")); - args->push_back(completion_t(L"-n")); + append_completion(*args, L"echo"); + append_completion(*args, L"-n"); result = true; } } diff --git a/parse_execution.cpp b/parse_execution.cpp index aeca11a72..c628b1d63 100644 --- a/parse_execution.cpp +++ b/parse_execution.cpp @@ -805,11 +805,11 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process(job_t return parse_execution_errored; } - wcstring actual_cmd; + wcstring path_to_external_command; if (process_type == EXTERNAL) { /* Determine the actual command. This may be an implicit cd. */ - bool has_command = path_get_path(cmd, &actual_cmd); + bool has_command = path_get_path(cmd, &path_to_external_command); /* If there was no command, then we care about the value of errno after checking for it, to distinguish between e.g. no file vs permissions problem */ const int no_cmd_err_code = errno; @@ -843,7 +843,7 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process(job_t /* Implicit cd is simple */ argument_list.push_back(L"cd"); argument_list.push_back(cmd); - actual_cmd.clear(); + path_to_external_command.clear(); /* If we have defined a wrapper around cd, use it, otherwise use the cd builtin */ process_type = function_exists(L"cd") ? INTERNAL_FUNCTION : INTERNAL_BUILTIN; @@ -878,7 +878,7 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process(job_t proc->type = process_type; proc->set_argv(argument_list); proc->set_io_chain(process_io_chain); - proc->actual_cmd = actual_cmd; + proc->actual_cmd = path_to_external_command; return parse_execution_success; } diff --git a/parser.cpp b/parser.cpp index a96f72b1c..c2ef76814 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1939,7 +1939,7 @@ int parser_t::parse_job(process_t *p, job_t *j, tokenizer_t *tok) } } } - args.push_back(completion_t(nxt)); + append_completion(args, nxt); } if (error_code == 0) @@ -1982,8 +1982,8 @@ int parser_t::parse_job(process_t *p, job_t *j, tokenizer_t *tok) if (use_implicit_cd) { args.clear(); - args.push_back(completion_t(L"cd")); - args.push_back(completion_t(implicit_cd_path)); + append_completion(args, L"cd"); + append_completion(args, implicit_cd_path); /* If we have defined a wrapper around cd, use it, otherwise use the cd builtin */ if (use_function && function_exists(L"cd"))