From 77884bc21a991ead6713f61e2e34c6a8eaf2eb80 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 25 Sep 2018 00:17:05 -0400 Subject: [PATCH] Instantize env_get This removes env_get(). All fish variable accesses must go through an environment_t. --- src/builtin_pwd.cpp | 3 ++- src/builtin_status.cpp | 2 +- src/env.cpp | 16 +++++----------- src/env.h | 7 ++----- src/expand.cpp | 8 +++----- src/expand.h | 2 +- src/fish_tests.cpp | 37 ++++++++++++++++++++----------------- src/highlight.cpp | 2 +- src/reader.cpp | 13 +++++++------ src/reader.h | 2 +- src/screen.cpp | 12 +----------- 11 files changed, 44 insertions(+), 60 deletions(-) diff --git a/src/builtin_pwd.cpp b/src/builtin_pwd.cpp index f32a783c7..f9d7fda9c 100644 --- a/src/builtin_pwd.cpp +++ b/src/builtin_pwd.cpp @@ -6,6 +6,7 @@ #include "common.h" #include "fallback.h" // IWYU pragma: keep #include "io.h" +#include "parser.h" #include "wgetopt.h" #include "wutil.h" // IWYU pragma: keep @@ -48,7 +49,7 @@ int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv) { } wcstring pwd; - if (auto tmp = env_get(L"PWD")) { + if (auto tmp = parser.vars().get(L"PWD")) { pwd = tmp->as_string(); } if (resolve_symlinks) { diff --git a/src/builtin_status.cpp b/src/builtin_status.cpp index 4862a8897..9a6b66c26 100644 --- a/src/builtin_status.cpp +++ b/src/builtin_status.cpp @@ -424,7 +424,7 @@ int builtin_status(parser_t &parser, io_streams_t &streams, wchar_t **argv) { case STATUS_CURRENT_CMD: { CHECK_FOR_UNEXPECTED_STATUS_ARGS(opts.status_cmd) // HACK: Go via the deprecated variable to get the command. - const auto var = env_get(L"_"); + const auto var = parser.vars().get(L"_"); if (!var.missing_or_empty()) { streams.out.append(var->as_string()); streams.out.push_back(L'\n'); diff --git a/src/env.cpp b/src/env.cpp index f150accc0..f48cfde2b 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -349,7 +349,6 @@ static mode_t get_umask() { /// Properly sets all timezone information. static void handle_timezone(const wchar_t *env_var_name, const environment_t &vars) { - // const env_var_t var = env_get(env_var_name, ENV_EXPORT); const auto var = vars.get(env_var_name, ENV_DEFAULT); debug(2, L"handle_timezone() current timezone var: |%ls| => |%ls|", env_var_name, !var ? L"MISSING" : var->as_string().c_str()); @@ -697,7 +696,7 @@ void env_stack_t::mark_changed_exported() { vars_stack().mark_changed_exported() wcstring environment_t::get_pwd_slash() const { // Return "/" if PWD is missing. // See https://github.com/fish-shell/fish-shell/issues/5080 - auto pwd_var = env_get(L"PWD"); + auto pwd_var = get(L"PWD"); wcstring pwd; if (!pwd_var.missing_or_empty()) { pwd = pwd_var->as_string(); @@ -951,8 +950,8 @@ void env_init(const struct config_paths_t *paths /* or NULL */) { get_hostname_identifier(hostname); vars.set_one(L"hostname", ENV_GLOBAL, hostname); - // Set up SHLVL variable. Not we can't use env_get because SHLVL is read-only, and therefore was - // not inherited from the environment. + // Set up SHLVL variable. Not we can't use vars.get() because SHLVL is read-only, and therefore + // was not inherited from the environment. wcstring nshlvl_str = L"1"; if (const char *shlvl_var = getenv("SHLVL")) { const wchar_t *end; @@ -1049,7 +1048,7 @@ static int set_umask(const wcstring_list_t &list_val) { } if (errno || mask > 0777 || mask < 0) return ENV_INVALID; - // Do not actually create a umask variable. On env_get() it will be calculated. + // Do not actually create a umask variable. On env_stack_t::get() it will be calculated. umask(mask); return ENV_OK; } @@ -1422,7 +1421,7 @@ maybe_t env_stack_t::get(const wcstring &key, env_mode_flags_t mode) if (!search_universal) return none(); // Another hack. Only do a universal barrier on the main thread (since it can change variable - // values). Make sure we do this outside the env_lock because it may itself call `env_get()`. + // values). Make sure we do this outside the env_lock because it may itself call `get()`. if (is_main_thread() && !get_proc_had_barrier()) { set_proc_had_barrier(true); env_universal_barrier(); @@ -1440,11 +1439,6 @@ maybe_t env_stack_t::get(const wcstring &key, env_mode_flags_t mode) return none(); } -/// Legacy versions. -maybe_t env_get(const wcstring &key, env_mode_flags_t mode) { - return env_stack_t::principal().get(key, mode); -} - void env_universal_barrier() { env_stack_t::principal().universal_barrier(); } /// Returns true if the specified scope or any non-shadowed non-global subscopes contain an exported diff --git a/src/env.h b/src/env.h index 8b82cc2ad..970d05cad 100644 --- a/src/env.h +++ b/src/env.h @@ -22,8 +22,8 @@ extern bool curses_initialized; // Flags that may be passed as the 'mode' in env_stack_t::set() / environment_t::get(). enum { - /// Default mode. Used with `env_get()` to indicate the caller doesn't care what scope the var - /// is in or whether it is exported or unexported. + /// Default mode. Used with `env_stack_t::get()` to indicate the caller doesn't care what scope + /// the var is in or whether it is exported or unexported. ENV_DEFAULT = 0, /// Flag for local (to the current block) variable. ENV_LOCAL = 1 << 0, @@ -160,9 +160,6 @@ class null_environment_t : public environment_t { wcstring_list_t get_names(int flags) const override; }; -/// Gets the variable with the specified name, or none() if it does not exist. -maybe_t env_get(const wcstring &key, env_mode_flags_t mode = ENV_DEFAULT); - /// Synchronizes all universal variable changes: writes everything out, reads stuff in. void env_universal_barrier(); diff --git a/src/expand.cpp b/src/expand.cpp index 4beb86782..1d0b1601c 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -1010,7 +1010,7 @@ static expand_error_t expand_stage_wildcards(wcstring path_to_expand, std::vecto // Get the PATH/CDPATH and CWD. Perhaps these should be passed in. An empty CDPATH // implies just the current directory, while an empty PATH is left empty. wcstring_list_t paths; - if (auto paths_var = env_get(for_cd ? L"CDPATH" : L"PATH")) { + if (auto paths_var = vars.get(for_cd ? L"CDPATH" : L"PATH")) { paths = paths_var->as_list(); } if (paths.empty()) { @@ -1193,17 +1193,15 @@ bool fish_xdm_login_hack_hack_hack_hack(std::vector *cmds, int argc return result; } -maybe_t expand_abbreviation(const wcstring &src) { +maybe_t expand_abbreviation(const wcstring &src, const environment_t &vars) { if (src.empty()) return none(); - 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) { + if (auto var_value = vars.get(var_name)) { return var_value->as_string(); } return none(); diff --git a/src/expand.h b/src/expand.h index 4cf67e71c..180ed9d2f 100644 --- a/src/expand.h +++ b/src/expand.h @@ -160,7 +160,7 @@ wcstring replace_home_directory_with_tilde(const wcstring &str, const environmen /// Abbreviation support. Expand src as an abbreviation, returning the expanded form if found, /// none() if not. -maybe_t expand_abbreviation(const wcstring &src); +maybe_t expand_abbreviation(const wcstring &src, const environment_t &vars); /// \return a snapshot of all abbreviations as a map abbreviation->expansion. std::map get_abbreviations(); diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 9efe2c2e7..cd030583b 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -1787,59 +1787,62 @@ static void test_abbreviations() { if (ret != 0) err(L"Unable to set abbreviation variable"); } - 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"", vars)) err(L"Unexpected success with empty abbreviation"); + if (expand_abbreviation(L"nothing", vars)) err(L"Unexpected success with missing abbreviation"); - auto mresult = expand_abbreviation(L"gc"); + auto mresult = expand_abbreviation(L"gc", vars); if (!mresult) err(L"Unexpected failure with gc abbreviation"); if (*mresult != L"git checkout") err(L"Wrong abbreviation result for gc"); - mresult = expand_abbreviation(L"foo"); + mresult = expand_abbreviation(L"foo", vars); 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); + expanded = reader_expand_abbreviation_in_command(L"just a command", 3, vars, &result); if (expanded) err(L"Command wrongly expanded on line %ld", (long)__LINE__); - expanded = reader_expand_abbreviation_in_command(L"gc somebranch", 0, &result); + expanded = reader_expand_abbreviation_in_command(L"gc somebranch", 0, vars, &result); if (!expanded) err(L"Command not expanded on line %ld", (long)__LINE__); - expanded = reader_expand_abbreviation_in_command(L"gc somebranch", wcslen(L"gc"), &result); + expanded = + reader_expand_abbreviation_in_command(L"gc somebranch", wcslen(L"gc"), vars, &result); if (!expanded) err(L"gc not expanded"); if (result != L"git checkout somebranch") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str()); // Space separation. - expanded = reader_expand_abbreviation_in_command(L"gx somebranch", wcslen(L"gc"), &result); + expanded = + reader_expand_abbreviation_in_command(L"gx somebranch", wcslen(L"gc"), vars, &result); if (!expanded) err(L"gx not expanded"); if (result != L"git checkout somebranch") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str()); expanded = reader_expand_abbreviation_in_command(L"echo hi ; gc somebranch", - wcslen(L"echo hi ; g"), &result); + wcslen(L"echo hi ; g"), vars, &result); if (!expanded) err(L"gc not expanded on line %ld", (long)__LINE__); if (result != L"echo hi ; git checkout somebranch") err(L"gc incorrectly expanded on line %ld", (long)__LINE__); expanded = reader_expand_abbreviation_in_command( - L"echo (echo (echo (echo (gc ", wcslen(L"echo (echo (echo (echo (gc"), &result); + L"echo (echo (echo (echo (gc ", wcslen(L"echo (echo (echo (echo (gc"), vars, &result); if (!expanded) err(L"gc not expanded on line %ld", (long)__LINE__); if (result != L"echo (echo (echo (echo (git checkout ") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str()); // If commands should be expanded. - expanded = reader_expand_abbreviation_in_command(L"if gc", wcslen(L"if gc"), &result); + expanded = reader_expand_abbreviation_in_command(L"if gc", wcslen(L"if gc"), vars, &result); if (!expanded) err(L"gc not expanded on line %ld", (long)__LINE__); if (result != L"if git checkout") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str()); // Others should not be. - expanded = reader_expand_abbreviation_in_command(L"of gc", wcslen(L"of gc"), &result); + expanded = reader_expand_abbreviation_in_command(L"of gc", wcslen(L"of gc"), vars, &result); if (expanded) err(L"gc incorrectly expanded on line %ld", (long)__LINE__); // Others should not be. - expanded = reader_expand_abbreviation_in_command(L"command gc", wcslen(L"command gc"), &result); + expanded = + reader_expand_abbreviation_in_command(L"command gc", wcslen(L"command gc"), vars, &result); if (expanded) err(L"gc incorrectly expanded on line %ld", (long)__LINE__); vars.pop(); @@ -2662,9 +2665,9 @@ static void perform_one_autosuggestion_cd_test(const wcstring &command, const wc } static void perform_one_completion_cd_test(const wcstring &command, const wcstring &expected, - long line) { + const environment_t &vars, long line) { std::vector comps; - complete(command, &comps, COMPLETION_REQUEST_DEFAULT, env_vars_snapshot_t{}); + complete(command, &comps, COMPLETION_REQUEST_DEFAULT, vars); bool expects_error = (expected == L""); @@ -2795,8 +2798,8 @@ static void test_autosuggest_suggest_special() { if (system("mkdir -p '~hahaha/path1/path2/'")) err(L"mkdir failed"); perform_one_autosuggestion_cd_test(L"cd ~haha", L"ha/path1/path2/", vars, __LINE__); perform_one_autosuggestion_cd_test(L"cd ~hahaha/", L"path1/path2/", vars, __LINE__); - perform_one_completion_cd_test(L"cd ~haha", L"ha/", __LINE__); - perform_one_completion_cd_test(L"cd ~hahaha/", L"path1/", __LINE__); + perform_one_completion_cd_test(L"cd ~haha", L"ha/", vars, __LINE__); + perform_one_completion_cd_test(L"cd ~hahaha/", L"path1/", vars, __LINE__); parser_t::principal_parser().vars().remove(L"HOME", ENV_LOCAL | ENV_EXPORT); popd(); diff --git a/src/highlight.cpp b/src/highlight.cpp index 9b844f89f..cda55083b 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -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).has_value(); + if (!is_valid && abbreviation_ok) is_valid = expand_abbreviation(cmd, vars).has_value(); // Regular commands if (!is_valid && command_ok) is_valid = path_get_path(cmd, NULL, vars); diff --git a/src/reader.cpp b/src/reader.cpp index 339e9d360..69a1d2d41 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -395,7 +395,7 @@ class reader_data_t { void pager_selection_changed(); /// Expand abbreviations at the current cursor position, minus backtrack_amt. - bool expand_abbreviation_as_necessary(size_t cursor_backtrack) const; + static bool expand_abbreviation_as_necessary(size_t cursor_backtrack); /// Return the variable set used for e.g. command duration. env_stack_t &vars() { return parser_t::principal_parser().vars(); } @@ -699,7 +699,7 @@ void reader_data_t::pager_selection_changed() { /// Expand abbreviations at the given cursor position. Does NOT inspect 'data'. bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t cursor_pos, - wcstring *output) { + const environment_t &vars, wcstring *output) { // See if we are at "command position". Get the surrounding command substitution, and get the // extent of the first token. const wchar_t *const buff = cmdline.c_str(); @@ -750,7 +750,7 @@ 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); - if (auto abbreviation = expand_abbreviation(token)) { + if (auto abbreviation = expand_abbreviation(token, vars)) { // There was an abbreviation! Replace the token in the full command. Maintain the // relative position of the cursor. if (output != NULL) { @@ -767,15 +767,16 @@ bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t curso /// Expand abbreviations at the current cursor position, minus the given cursor backtrack. This may /// change the command line but does NOT repaint it. This is to allow the caller to coalesce /// repaints. -bool reader_data_t::expand_abbreviation_as_necessary(size_t cursor_backtrack) const { +bool reader_data_t::expand_abbreviation_as_necessary(size_t cursor_backtrack) { reader_data_t *data = current_data(); bool result = false; editable_line_t *el = data->active_edit_line(); - if (this->expand_abbreviations && el == &data->command_line) { + if (data->expand_abbreviations && el == &data->command_line) { // Try expanding abbreviations. wcstring new_cmdline; size_t cursor_pos = el->position - mini(el->position, cursor_backtrack); - if (reader_expand_abbreviation_in_command(el->text, cursor_pos, &new_cmdline)) { + if (reader_expand_abbreviation_in_command(el->text, cursor_pos, data->vars(), + &new_cmdline)) { // We expanded an abbreviation! The cursor moves by the difference in the command line // lengths. size_t new_buff_pos = el->position + new_cmdline.size() - el->text.size(); diff --git a/src/reader.h b/src/reader.h index 3854ae4f7..873b8341d 100644 --- a/src/reader.h +++ b/src/reader.h @@ -216,7 +216,7 @@ wcstring combine_command_and_autosuggestion(const wcstring &cmdline, /// Expand abbreviations at the given cursor position. Exposed for testing purposes only. bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t cursor_pos, - wcstring *output); + const environment_t &vars, wcstring *output); /// Apply a completion string. Exposed for testing only. wcstring completion_apply_to_command_line(const wcstring &val_str, complete_flags_t flags, diff --git a/src/screen.cpp b/src/screen.cpp index 63e0906e7..1f4058405 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -110,21 +110,11 @@ static bool allow_soft_wrap() { return auto_right_margin; } -/// Does this look like the escape sequence for setting a screen name. +/// Does this look like the escape sequence for setting a screen name? static bool is_screen_name_escape_seq(const wchar_t *code, size_t *resulting_length) { if (code[1] != L'k') { return false; } - -#if 0 - // TODO: Decide if this should be removed or modified to also test for TERM values that begin - // with "tmux". See issue #3512. - const env_var_t term_name = env_get(L"TERM"); - if (term_name.missing_or_empty() || !string_prefixes_string(L"screen", term_name)) { - return false; - } -#endif - const wchar_t *const screen_name_end_sentinel = L"\x1B\\"; const wchar_t *screen_name_end = wcsstr(&code[2], screen_name_end_sentinel); if (screen_name_end == NULL) {