Remove the abbreviation cache

Read abbreviations directly from the environment.
This commit is contained in:
ridiculousfish 2018-09-24 01:47:38 -04:00
parent 9f62a53077
commit 038f3cca6d
6 changed files with 41 additions and 45 deletions

View File

@ -625,8 +625,6 @@ static void react_to_variable_change(const wchar_t *op, const wcstring &key, env
auto dispatch = var_dispatch_table.find(key);
if (dispatch != var_dispatch_table.end()) {
(*dispatch->second)(op, key, vars);
} else if (string_prefixes_string(L"_fish_abbr_", key)) {
update_abbr_cache(op, key);
} else if (string_prefixes_string(L"fish_color_", key)) {
reader_react_to_color_change();
}

View File

@ -1188,34 +1188,33 @@ bool fish_xdm_login_hack_hack_hack_hack(std::vector<std::string> *cmds, int argc
return result;
}
static owning_lock<std::map<wcstring, wcstring>> s_abbreviations;
void update_abbr_cache(const wchar_t *op, const wcstring &varname) {
wcstring abbr;
if (!unescape_string(varname.substr(wcslen(L"_fish_abbr_")), &abbr, 0, STRING_STYLE_VAR)) {
debug(1, L"Abbreviation var '%ls' is not correctly encoded, ignoring it.", varname.c_str());
return;
}
auto abbreviations = s_abbreviations.acquire();
abbreviations->erase(abbr);
if (wcscmp(op, L"ERASE") != 0) {
const auto expansion = env_get(varname);
if (!expansion.missing_or_empty()) {
abbreviations->emplace(abbr, expansion->as_string());
}
}
}
maybe_t<wcstring> expand_abbreviation(const wcstring &src) {
if (src.empty()) return none();
bool expand_abbreviation(const wcstring &src, wcstring *output) {
if (src.empty()) return false;
auto abbreviations = s_abbreviations.acquire();
auto abbr = abbreviations->find(src);
if (abbr == abbreviations->end()) return false;
if (output != NULL) output->assign(abbr->second);
return true;
const auto &vars = env_stack_t::principal();
wcstring unesc_src;
if (!unescape_string(src, &unesc_src, STRING_STYLE_VAR)) {
return none();
}
wcstring var_name = L"_fish_abbr_" + unesc_src;
auto var_value = vars.get(var_name);
if (var_value) {
return var_value->as_string();
}
return none();
}
std::map<wcstring, wcstring> get_abbreviations() {
auto abbreviations = s_abbreviations.acquire();
return *abbreviations;
// TODO: try to make this cheaper
const auto &vars = env_stack_t::principal();
const size_t fish_abbr_len = wcslen(L"_fish_abbr_");
auto names = vars.get_names(0);
std::map<wcstring, wcstring> result;
for (const wcstring &name : names) {
if (string_prefixes_string(L"_fish_abbr_", name)) {
result[name.substr(fish_abbr_len)] = vars.get(name)->as_string();
}
}
return result;
}

View File

@ -14,6 +14,7 @@
#include <vector>
#include "common.h"
#include "maybe.h"
#include "parse_constants.h"
class env_var_t;
@ -156,10 +157,9 @@ void expand_tilde(wcstring &input);
/// Perform the opposite of tilde expansion on the string, which is modified in place.
wcstring replace_home_directory_with_tilde(const wcstring &str);
/// Abbreviation support. Expand src as an abbreviation, returning true if one was found, false if
/// not. If result is not-null, returns the abbreviation by reference.
void update_abbr_cache(const wchar_t *op, const wcstring &varname);
bool expand_abbreviation(const wcstring &src, wcstring *output);
/// Abbreviation support. Expand src as an abbreviation, returning the expanded form if found,
/// none() if not.
maybe_t<wcstring> expand_abbreviation(const wcstring &src);
/// \return a snapshot of all abbreviations as a map abbreviation->expansion.
std::map<wcstring, wcstring> get_abbreviations();

View File

@ -1781,19 +1781,19 @@ static void test_abbreviations() {
if (ret != 0) err(L"Unable to set abbreviation variable");
}
wcstring result;
if (expand_abbreviation(L"", &result)) err(L"Unexpected success with empty abbreviation");
if (expand_abbreviation(L"nothing", &result))
err(L"Unexpected success with missing abbreviation");
if (expand_abbreviation(L"")) err(L"Unexpected success with empty abbreviation");
if (expand_abbreviation(L"nothing")) err(L"Unexpected success with missing abbreviation");
if (!expand_abbreviation(L"gc", &result)) err(L"Unexpected failure with gc abbreviation");
if (result != L"git checkout") err(L"Wrong abbreviation result for gc");
result.clear();
auto mresult = expand_abbreviation(L"gc");
if (!mresult) err(L"Unexpected failure with gc abbreviation");
if (*mresult != L"git checkout") err(L"Wrong abbreviation result for gc");
if (!expand_abbreviation(L"foo", &result)) err(L"Unexpected failure with foo abbreviation");
if (result != L"bar") err(L"Wrong abbreviation result for foo");
mresult = expand_abbreviation(L"foo");
if (!mresult) err(L"Unexpected failure with foo abbreviation");
if (*mresult != L"bar") err(L"Wrong abbreviation result for foo");
bool expanded;
wcstring result;
expanded = reader_expand_abbreviation_in_command(L"just a command", 3, &result);
if (expanded) err(L"Command wrongly expanded on line %ld", (long)__LINE__);
expanded = reader_expand_abbreviation_in_command(L"gc somebranch", 0, &result);

View File

@ -1015,7 +1015,7 @@ static bool command_is_valid(const wcstring &cmd, enum parse_statement_decoratio
if (!is_valid && function_ok) is_valid = function_exists_no_autoload(cmd, vars);
// Abbreviations
if (!is_valid && abbreviation_ok) is_valid = expand_abbreviation(cmd, NULL);
if (!is_valid && abbreviation_ok) is_valid = expand_abbreviation(cmd).has_value();
// Regular commands
if (!is_valid && command_ok) is_valid = path_get_path(cmd, NULL, vars);

View File

@ -747,14 +747,13 @@ bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t curso
bool result = false;
if (matching_cmd_node) {
const wcstring token = matching_cmd_node.get_source(subcmd);
wcstring abbreviation;
if (expand_abbreviation(token, &abbreviation)) {
if (auto abbreviation = expand_abbreviation(token)) {
// There was an abbreviation! Replace the token in the full command. Maintain the
// relative position of the cursor.
if (output != NULL) {
output->assign(cmdline);
source_range_t r = *matching_cmd_node.source_range();
output->replace(subcmd_offset + r.start, r.length, abbreviation);
output->replace(subcmd_offset + r.start, r.length, *abbreviation);
}
result = true;
}