From c36ad2761892a8f7dbb9cffc1ab2c2a470b93bf5 Mon Sep 17 00:00:00 2001 From: Kurtis Rader Date: Sat, 5 Aug 2017 18:22:49 -0700 Subject: [PATCH] stop subclassing env_var_t from wcstring This is the first step to implementing issue #4200 is to stop subclassing env_var_t from wcstring. Not too surprisingly doing this identified several places that were incorrectly treating env_var_t and wcstring as interchangeable types. I'm not talking about those places that passed an env_var_t instance to a function that takes a wcstring. I'm talking about doing things like assigning the former to the latter type, relying on the implicit conversion, and thus losing information. We also rename `env_get_string()` to `env_get()` for symmetry with `env_set()` and to make it clear the function does not return a string. --- src/autoload.cpp | 6 +- src/autoload.h | 3 +- src/builtin_cd.cpp | 2 +- src/builtin_functions.cpp | 2 +- src/builtin_read.cpp | 4 +- src/builtin_set.cpp | 44 +++++------ src/common.cpp | 8 +- src/complete.cpp | 9 ++- src/env.cpp | 162 +++++++++++++++++++++----------------- src/env.h | 60 +++++++------- src/exec.cpp | 4 +- src/expand.cpp | 24 +++--- src/function.cpp | 4 +- src/highlight.cpp | 12 +-- src/history.cpp | 5 +- src/input.cpp | 4 +- src/input_common.cpp | 2 +- src/output.cpp | 2 +- src/path.cpp | 24 +++--- src/path.h | 2 +- src/reader.cpp | 4 +- src/screen.cpp | 4 +- 22 files changed, 205 insertions(+), 186 deletions(-) diff --git a/src/autoload.cpp b/src/autoload.cpp index ae3a7aafc..a9f944aed 100644 --- a/src/autoload.cpp +++ b/src/autoload.cpp @@ -69,7 +69,7 @@ int autoload_t::load(const wcstring &cmd, bool reload) { CHECK_BLOCK(0); ASSERT_IS_MAIN_THREAD(); - env_var_t path_var = env_get_string(env_var_name); + env_var_t path_var = env_get(env_var_name); // Do we know where to look? if (path_var.empty()) return 0; @@ -79,7 +79,7 @@ int autoload_t::load(const wcstring &cmd, bool reload) { if (path_var != this->last_path) { this->last_path = path_var; this->last_path_tokenized.clear(); - tokenize_variable_array(this->last_path, this->last_path_tokenized); + this->last_path.to_list(this->last_path_tokenized); scoped_lock locker(lock); this->evict_all_nodes(); @@ -115,7 +115,7 @@ bool autoload_t::can_load(const wcstring &cmd, const env_vars_snapshot_t &vars) if (path_var.missing_or_empty()) return false; std::vector path_list; - tokenize_variable_array(path_var, path_list); + path_var.to_list(path_list); return this->locate_file_and_maybe_load_it(cmd, false, false, path_list); } diff --git a/src/autoload.h b/src/autoload.h index 63886390e..d04003c25 100644 --- a/src/autoload.h +++ b/src/autoload.h @@ -8,6 +8,7 @@ #include #include "common.h" +#include "env.h" #include "lru.h" /// Record of an attempt to access a file. @@ -50,7 +51,7 @@ class autoload_t : public lru_cache_t { /// The environment variable name. const wcstring env_var_name; /// The path from which we most recently autoloaded. - wcstring last_path; + env_var_t last_path; /// the most reecently autoloaded path, tokenized (split on separators). wcstring_list_t last_path_tokenized; /// A table containing all the files that are currently being loaded. diff --git a/src/builtin_cd.cpp b/src/builtin_cd.cpp index e73808fab..8513f4a50 100644 --- a/src/builtin_cd.cpp +++ b/src/builtin_cd.cpp @@ -39,7 +39,7 @@ int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv) { if (argv[optind]) { dir_in = env_var_t(argv[optind]); } else { - dir_in = env_get_string(L"HOME"); + dir_in = env_get(L"HOME"); if (dir_in.missing_or_empty()) { streams.err.append_format(_(L"%ls: Could not find home directory\n"), cmd); return STATUS_CMD_ERROR; diff --git a/src/builtin_functions.cpp b/src/builtin_functions.cpp index 5e6b42433..6a3a3ef49 100644 --- a/src/builtin_functions.cpp +++ b/src/builtin_functions.cpp @@ -193,7 +193,7 @@ static wcstring functions_def(const wcstring &name) { it != end; ++it) { wcstring_list_t lst; if (!it->second.missing()) { - tokenize_variable_array(it->second, lst); + it->second.to_list(lst); } // This forced tab is crummy, but we don't know what indentation style the function uses. diff --git a/src/builtin_read.cpp b/src/builtin_read.cpp index 0291a084a..cfd32ace2 100644 --- a/src/builtin_read.cpp +++ b/src/builtin_read.cpp @@ -427,9 +427,9 @@ int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv) { } if (!opts.have_delimiter) { - env_var_t ifs = env_get_string(L"IFS"); + env_var_t ifs = env_get(L"IFS"); if (!ifs.missing_or_empty()) { - opts.delimiter = ifs; + opts.delimiter = ifs.as_string(); } } if (opts.delimiter.empty()) { diff --git a/src/builtin_set.cpp b/src/builtin_set.cpp index 264e2339d..533f36ff3 100644 --- a/src/builtin_set.cpp +++ b/src/builtin_set.cpp @@ -212,7 +212,7 @@ static int validate_cmd_opts(const wchar_t *cmd, set_cmd_opts_t &opts, //!OCLIN static int check_global_scope_exists(const wchar_t *cmd, set_cmd_opts_t &opts, const wchar_t *dest, io_streams_t &streams) { if (opts.universal) { - env_var_t global_dest = env_get_string(dest, ENV_GLOBAL); + env_var_t global_dest = env_get(dest, ENV_GLOBAL); if (!global_dest.missing()) { streams.err.append_format( _(L"%ls: Warning: universal scope selected, but a global variable '%ls' exists.\n"), @@ -239,9 +239,8 @@ static int my_env_path_setup(const wchar_t *cmd, const wchar_t *key, //!OCLINT( // not the (missing) local value. Also don't bother to complain about relative paths, which // don't start with /. wcstring_list_t existing_values; - const env_var_t existing_variable = env_get_string(key, ENV_DEFAULT); - if (!existing_variable.missing_or_empty()) - tokenize_variable_array(existing_variable, existing_values); + const env_var_t existing_variable = env_get(key, ENV_DEFAULT); + if (!existing_variable.missing_or_empty()) existing_variable.to_list(existing_values); for (size_t i = 0; i < list.size(); i++) { const wcstring &dir = list.at(i); @@ -346,9 +345,9 @@ static int parse_index(std::vector &indexes, wchar_t *src, int scope, io_s *p = L'\0'; // split the var name from the indexes/slices p++; - env_var_t var_str = env_get_string(src, scope); + env_var_t var_str = env_get(src, scope); wcstring_list_t var; - if (!var_str.missing()) tokenize_variable_array(var_str, var); + if (!var_str.missing()) var_str.to_list(var); int count = 0; @@ -457,15 +456,16 @@ static int builtin_set_list(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, streams.out.append(e_key); if (!names_only) { - env_var_t value = env_get_string(key, compute_scope(opts)); - if (!value.missing()) { + env_var_t var = env_get(key, compute_scope(opts)); + if (!var.missing()) { bool shorten = false; - if (opts.shorten_ok && value.length() > 64) { + wcstring val = var.as_string(); + if (opts.shorten_ok && val.length() > 64) { shorten = true; - value.resize(60); + val.resize(60); } - wcstring e_value = expand_escape_variable(value); + wcstring e_value = expand_escape_variable(val); streams.out.append(L" "); streams.out.append(e_value); @@ -500,8 +500,8 @@ static int builtin_set_query(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, if (idx_count) { wcstring_list_t result; - env_var_t dest_str = env_get_string(dest, scope); - if (!dest_str.missing()) tokenize_variable_array(dest_str, result); + env_var_t dest_str = env_get(dest, scope); + if (!dest_str.missing()) dest_str.to_list(result); for (auto idx : indexes) { if (idx < 1 || (size_t)idx > result.size()) retval++; @@ -538,12 +538,12 @@ static void show_scope(const wchar_t *var_name, int scope, io_streams_t &streams } if (env_exist(var_name, scope)) { - const env_var_t evar = env_get_string(var_name, scope | ENV_EXPORT | ENV_USER); + const env_var_t evar = env_get(var_name, scope | ENV_EXPORT | ENV_USER); const wchar_t *exportv = evar.missing() ? _(L"unexported") : _(L"exported"); - const env_var_t var = env_get_string(var_name, scope | ENV_USER); + const env_var_t var = env_get(var_name, scope | ENV_USER); wcstring_list_t result; - if (!var.empty()) tokenize_variable_array(var, result); + if (!var.empty()) var.to_list(result); streams.out.append_format(_(L"$%ls: set in %ls scope, %ls, with %d elements\n"), var_name, scope_name, exportv, result.size()); @@ -632,10 +632,10 @@ static int builtin_set_erase(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, if (idx_count == 0) { // unset the var retval = env_remove(dest, scope); } else { // remove just the specified indexes of the var - const env_var_t dest_var = env_get_string(dest, scope); + const env_var_t dest_var = env_get(dest, scope); if (dest_var.missing()) return STATUS_CMD_ERROR; wcstring_list_t result; - tokenize_variable_array(dest_var, result); + dest_var.to_list(result); erase_values(result, indexes); retval = my_env_set(cmd, dest, result, scope, streams); } @@ -658,9 +658,9 @@ static int set_var_array(const wchar_t *cmd, set_cmd_opts_t &opts, const wchar_t for (int i = 0; i < argc; i++) new_values.push_back(argv[i]); } - env_var_t var_str = env_get_string(varname, scope); + env_var_t var_str = env_get(varname, scope); wcstring_list_t var_array; - if (!var_str.missing()) tokenize_variable_array(var_str, var_array); + if (!var_str.missing()) var_str.to_list(var_array); new_values.insert(new_values.end(), var_array.begin(), var_array.end()); if (opts.append) { @@ -691,8 +691,8 @@ static int set_var_slices(const wchar_t *cmd, set_cmd_opts_t &opts, const wchar_ } int scope = compute_scope(opts); // calculate the variable scope based on the provided options - const env_var_t var_str = env_get_string(varname, scope); - if (!var_str.missing()) tokenize_variable_array(var_str, new_values); + const env_var_t var_str = env_get(varname, scope); + if (!var_str.missing()) var_str.to_list(new_values); // Slice indexes have been calculated, do the actual work. wcstring_list_t result; diff --git a/src/common.cpp b/src/common.cpp index b52dbf076..e568043f6 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -1554,8 +1554,8 @@ static void validate_new_termsize(struct winsize *new_termsize) { } #endif // Fallback to the environment vars. - env_var_t col_var = env_get_string(L"COLUMNS"); - env_var_t row_var = env_get_string(L"LINES"); + env_var_t col_var = env_get(L"COLUMNS"); + env_var_t row_var = env_get(L"LINES"); if (!col_var.missing_or_empty() && !row_var.missing_or_empty()) { // Both vars have to have valid values. int col = fish_wcstoi(col_var.c_str()); @@ -1582,11 +1582,11 @@ static void validate_new_termsize(struct winsize *new_termsize) { /// Export the new terminal size as env vars and to the kernel if possible. static void export_new_termsize(struct winsize *new_termsize) { wchar_t buf[64]; - env_var_t cols = env_get_string(L"COLUMNS", ENV_EXPORT); + env_var_t cols = env_get(L"COLUMNS", ENV_EXPORT); swprintf(buf, 64, L"%d", (int)new_termsize->ws_col); env_set(L"COLUMNS", buf, ENV_GLOBAL | (cols.missing_or_empty() ? 0 : ENV_EXPORT)); - env_var_t lines = env_get_string(L"LINES", ENV_EXPORT); + env_var_t lines = env_get(L"LINES", ENV_EXPORT); swprintf(buf, 64, L"%d", (int)new_termsize->ws_row); env_set(L"LINES", buf, ENV_GLOBAL | (lines.missing_or_empty() ? 0 : ENV_EXPORT)); diff --git a/src/complete.cpp b/src/complete.cpp index 51b6acd91..2df3cb501 100644 --- a/src/complete.cpp +++ b/src/complete.cpp @@ -1106,12 +1106,13 @@ bool completer_t::complete_variable(const wcstring &str, size_t start_offset) { wcstring desc; if (this->wants_descriptions()) { // Can't use this->vars here, it could be any variable. - env_var_t value_unescaped = env_get_string(env_name); - if (value_unescaped.missing()) continue; + env_var_t var = env_get(env_name); + if (var.missing()) continue; - wcstring value = expand_escape_variable(value_unescaped); - if (this->type() != COMPLETE_AUTOSUGGEST) + wcstring value = expand_escape_variable(var.as_string()); + if (this->type() != COMPLETE_AUTOSUGGEST) { desc = format_string(COMPLETE_VAR_DESC_VAL, value.c_str()); + } } append_completion(&this->completions, comp, desc, flags, match); diff --git a/src/env.cpp b/src/env.cpp index 0fd675539..7a6ef56d5 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -331,13 +331,13 @@ static bool var_is_timezone(const wcstring &key) { return key == L"TZ"; } /// Properly sets all timezone information. static void handle_timezone(const wchar_t *env_var_name) { debug(2, L"handle_timezone() called in response to '%ls' changing", env_var_name); - const env_var_t val = env_get_string(env_var_name, ENV_EXPORT); - const std::string &value = wcs2string(val); + const env_var_t var = env_get(env_var_name, ENV_EXPORT); const std::string &name = wcs2string(env_var_name); - debug(2, L"timezone var %s='%s'", name.c_str(), value.c_str()); - if (val.empty()) { + debug(2, L"timezone var %s='%s'", name.c_str(), var.c_str()); + if (var.missing_or_empty()) { unsetenv(name.c_str()); } else { + const std::string &value = wcs2string(var.as_string()); setenv(name.c_str(), value.c_str(), 1); } tzset(); @@ -350,13 +350,13 @@ static void fix_colon_delimited_var(const wcstring &var_name) { // While we auto split/join MANPATH we do not want to replace empty elements with "." (#4158). if (var_name == L"MANPATH") return; - const env_var_t paths = env_get_string(var_name); + const env_var_t paths = env_get(var_name); if (paths.missing_or_empty()) return; bool modified = false; wcstring_list_t pathsv; wcstring_list_t new_pathsv; - tokenize_variable_array(paths, pathsv); + paths.to_list(pathsv); for (auto next_path : pathsv) { if (next_path.empty()) { next_path = L"."; @@ -400,13 +400,14 @@ static void init_locale() { char *old_msg_locale = strdup(setlocale(LC_MESSAGES, NULL)); for (auto var_name : locale_variables) { - const env_var_t val = env_get_string(var_name, ENV_EXPORT); + const env_var_t var = env_get(var_name, ENV_EXPORT); const std::string &name = wcs2string(var_name); - const std::string &value = wcs2string(val); - debug(2, L"locale var %s='%s'", name.c_str(), value.c_str()); - if (val.empty()) { + if (var.missing_or_empty()) { + debug(2, L"locale var %s missing or empty", name.c_str()); unsetenv(name.c_str()); } else { + const std::string &value = wcs2string(var.as_string()); + debug(2, L"locale var %s='%s'", name.c_str(), value.c_str()); setenv(name.c_str(), value.c_str(), 1); } } @@ -455,17 +456,17 @@ bool term_supports_setting_title() { return can_set_term_title; } /// don't. Since we can't see the underlying terminal below screen there is no way to fix this. static const wcstring_list_t title_terms({L"xterm", L"screen", L"tmux", L"nxterm", L"rxvt"}); static bool does_term_support_setting_title() { - const env_var_t term_str = env_get_string(L"TERM"); - if (term_str.missing()) return false; + const env_var_t term_var = env_get(L"TERM"); + if (term_var.missing_or_empty()) return false; - const wchar_t *term = term_str.c_str(); - bool recognized = contains(title_terms, term_str); + const wchar_t *term = term_var.c_str(); + bool recognized = contains(title_terms, term_var.as_string()); if (!recognized) recognized = !wcsncmp(term, L"xterm-", wcslen(L"xterm-")); if (!recognized) recognized = !wcsncmp(term, L"screen-", wcslen(L"screen-")); if (!recognized) recognized = !wcsncmp(term, L"tmux-", wcslen(L"tmux-")); if (!recognized) { - if (term_str == L"linux") return false; - if (term_str == L"dumb") return false; + if (wcscmp(term, L"linux") == 0) return false; + if (wcscmp(term, L"dumb") == 0) return false; char buf[PATH_MAX]; int retval = ttyname_r(STDIN_FILENO, buf, PATH_MAX); @@ -479,11 +480,12 @@ static bool does_term_support_setting_title() { static void update_fish_color_support() { // Detect or infer term256 support. If fish_term256 is set, we respect it; // otherwise infer it from the TERM variable or use terminfo. - env_var_t fish_term256 = env_get_string(L"fish_term256"); - env_var_t term = env_get_string(L"TERM"); + env_var_t fish_term256 = env_get(L"fish_term256"); + env_var_t term_var = env_get(L"TERM"); + wcstring term = term_var.missing_or_empty() ? L"" : term_var.as_string(); bool support_term256 = false; // default to no support if (!fish_term256.missing_or_empty()) { - support_term256 = from_string(fish_term256); + support_term256 = from_string(fish_term256.as_string()); debug(2, L"256 color support determined by 'fish_term256'"); } else if (term.find(L"256color") != wcstring::npos) { // TERM=*256color*: Explicitly supported. @@ -491,11 +493,12 @@ static void update_fish_color_support() { debug(2, L"256 color support enabled for '256color' in TERM"); } else if (term.find(L"xterm") != wcstring::npos) { // Assume that all xterms are 256, except for OS X SnowLeopard - const env_var_t prog = env_get_string(L"TERM_PROGRAM"); - const env_var_t progver = env_get_string(L"TERM_PROGRAM_VERSION"); - if (prog == L"Apple_Terminal" && !progver.missing_or_empty()) { + const env_var_t prog_var = env_get(L"TERM_PROGRAM"); + const env_var_t progver_var = env_get(L"TERM_PROGRAM_VERSION"); + wcstring term_program = prog_var.missing_or_empty() ? L"" : prog_var.as_string(); + if (term_program == L"Apple_Terminal" && !progver_var.missing_or_empty()) { // OS X Lion is version 300+, it has 256 color support - if (strtod(wcs2str(progver), NULL) > 300) { + if (strtod(wcs2str(progver_var.as_string()), NULL) > 300) { support_term256 = true; debug(2, L"256 color support enabled for TERM=xterm + modern Terminal.app"); } @@ -511,10 +514,10 @@ static void update_fish_color_support() { debug(2, L"256 color support not enabled (yet)"); } - env_var_t fish_term24bit = env_get_string(L"fish_term24bit"); + env_var_t fish_term24bit = env_get(L"fish_term24bit"); bool support_term24bit; if (!fish_term24bit.missing_or_empty()) { - support_term24bit = from_string(fish_term24bit); + support_term24bit = from_string(fish_term24bit.as_string()); debug(2, L"'fish_term24bit' preference: 24-bit color %s", support_term24bit ? L"enabled" : L"disabled"); } else { @@ -534,12 +537,14 @@ static void update_fish_color_support() { static bool initialize_curses_using_fallback(const char *term) { // If $TERM is already set to the fallback name we're about to use there isn't any point in // seeing if the fallback name can be used. - const char *term_env = wcs2str(env_get_string(L"TERM")); + env_var_t term_var = env_get(L"TERM"); + if (term_var.missing_or_empty()) return false; + + const char *term_env = wcs2str(term_var.as_string()); if (!strcmp(term_env, DEFAULT_TERM1) || !strcmp(term_env, DEFAULT_TERM2)) return false; - if (is_interactive_session) { - debug(1, _(L"Using fallback terminal type '%s'."), term); - } + if (is_interactive_session) debug(1, _(L"Using fallback terminal type '%s'."), term); + int err_ret; if (setupterm((char *)term, STDOUT_FILENO, &err_ret) == OK) return true; if (is_interactive_session) { @@ -559,20 +564,21 @@ static void init_path_vars() { /// Initialize the curses subsystem. static void init_curses() { for (auto var_name : curses_variables) { - const env_var_t val = env_get_string(var_name, ENV_EXPORT); + const env_var_t var = env_get(var_name, ENV_EXPORT); const std::string &name = wcs2string(var_name); - const std::string &value = wcs2string(val); - debug(2, L"curses var %s='%s'", name.c_str(), value.c_str()); - if (val.empty()) { + if (var.missing_or_empty()) { + debug(2, L"curses var %s missing or empty", name.c_str()); unsetenv(name.c_str()); } else { + const std::string &value = wcs2string(var.as_string()); + debug(2, L"curses var %s='%s'", name.c_str(), value.c_str()); setenv(name.c_str(), value.c_str(), 1); } } int err_ret; if (setupterm(NULL, STDOUT_FILENO, &err_ret) == ERR) { - env_var_t term = env_get_string(L"TERM"); + env_var_t term = env_get(L"TERM"); if (is_interactive_session) { debug(1, _(L"Could not set up terminal.")); if (term.missing_or_empty()) { @@ -666,7 +672,7 @@ static void universal_callback(fish_message_type_t type, const wchar_t *name) { /// Make sure the PATH variable contains something. static void setup_path() { - const env_var_t path = env_get_string(L"PATH"); + const env_var_t path = env_get(L"PATH"); if (path.missing_or_empty()) { const wchar_t *value = L"/usr/bin" ARRAY_SEP_STR L"/bin"; env_set(L"PATH", value, ENV_GLOBAL | ENV_EXPORT); @@ -677,10 +683,10 @@ static void setup_path() { /// defaults. They will be updated later by the `get_current_winsize()` function if they need to be /// adjusted. static void env_set_termsize() { - env_var_t cols = env_get_string(L"COLUMNS"); + env_var_t cols = env_get(L"COLUMNS"); if (cols.missing_or_empty()) env_set(L"COLUMNS", DFLT_TERM_COL_STR, ENV_GLOBAL); - env_var_t rows = env_get_string(L"LINES"); + env_var_t rows = env_get(L"LINES"); if (rows.missing_or_empty()) env_set(L"LINES", DFLT_TERM_ROW_STR, ENV_GLOBAL); } @@ -698,7 +704,7 @@ bool env_set_pwd() { /// Allow the user to override the limit on how much data the `read` command will process. /// This is primarily for testing but could be used by users in special situations. void env_set_read_limit() { - env_var_t read_byte_limit_var = env_get_string(L"FISH_READ_BYTE_LIMIT"); + env_var_t read_byte_limit_var = env_get(L"FISH_READ_BYTE_LIMIT"); if (!read_byte_limit_var.missing_or_empty()) { size_t limit = fish_wcstoull(read_byte_limit_var.c_str()); if (errno) { @@ -710,10 +716,11 @@ void env_set_read_limit() { } wcstring env_get_pwd_slash(void) { - env_var_t pwd = env_get_string(L"PWD"); - if (pwd.missing_or_empty()) { + env_var_t pwd_var = env_get(L"PWD"); + if (pwd_var.missing_or_empty()) { return L""; } + wcstring pwd = pwd_var.as_string(); if (!string_suffixes_string(L"/", pwd)) { pwd.push_back(L'/'); } @@ -722,7 +729,7 @@ wcstring env_get_pwd_slash(void) { /// Set up the USER variable. static void setup_user(bool force) { - if (env_get_string(L"USER").missing_or_empty() || force) { + if (env_get(L"USER").missing_or_empty() || force) { struct passwd userinfo; struct passwd *result; char buf[8192]; @@ -863,12 +870,12 @@ void env_init(const struct config_paths_t *paths /* or NULL */) { env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL); // Set up SHLVL variable. - const env_var_t shlvl_str = env_get_string(L"SHLVL"); + const env_var_t shlvl_var = env_get(L"SHLVL"); wcstring nshlvl_str = L"1"; - if (!shlvl_str.missing()) { + if (!shlvl_var.missing_or_empty()) { const wchar_t *end; // TODO: Figure out how to handle invalid numbers better. Shouldn't we issue a diagnostic? - long shlvl_i = fish_wcstol(shlvl_str.c_str(), &end); + long shlvl_i = fish_wcstol(shlvl_var.c_str(), &end); if (!errno && shlvl_i >= 0) { nshlvl_str = to_string(shlvl_i + 1); } @@ -881,10 +888,10 @@ void env_init(const struct config_paths_t *paths /* or NULL */) { // if the target user is root, unless "--preserve-environment" is used. // Since that is an explicit choice, we should allow it to enable e.g. // env HOME=(mktemp -d) su --preserve-environment fish - if (env_get_string(L"HOME").missing_or_empty()) { - const env_var_t unam = env_get_string(L"USER"); - if (!unam.missing_or_empty()) { - char *unam_narrow = wcs2str(unam.c_str()); + if (env_get(L"HOME").missing_or_empty()) { + env_var_t user_var = env_get(L"USER"); + if (!user_var.missing_or_empty()) { + char *unam_narrow = wcs2str(user_var.c_str()); struct passwd userinfo; struct passwd *result; char buf[8192]; @@ -892,9 +899,11 @@ void env_init(const struct config_paths_t *paths /* or NULL */) { if (retval || !result) { // Maybe USER is set but it's bogus. Reset USER from the db and try again. setup_user(true); - const env_var_t unam = env_get_string(L"USER"); - unam_narrow = wcs2str(unam.c_str()); - retval = getpwnam_r(unam_narrow, &userinfo, buf, sizeof(buf), &result); + user_var = env_get(L"USER"); + if (!user_var.missing_or_empty()) { + unam_narrow = wcs2str(user_var.c_str()); + retval = getpwnam_r(unam_narrow, &userinfo, buf, sizeof(buf), &result); + } } if (!retval && result && userinfo.pw_dir) { const wcstring dir = str2wcstring(userinfo.pw_dir); @@ -918,9 +927,8 @@ void env_init(const struct config_paths_t *paths /* or NULL */) { env_set_read_limit(); // initialize the read_byte_limit // Set g_use_posix_spawn. Default to true. - env_var_t use_posix_spawn = env_get_string(L"fish_use_posix_spawn"); - g_use_posix_spawn = - (use_posix_spawn.missing_or_empty() ? true : from_string(use_posix_spawn)); + env_var_t use_posix_spawn = env_get(L"fish_use_posix_spawn"); + g_use_posix_spawn = use_posix_spawn.missing_or_empty() ? true : from_string(use_posix_spawn.as_string()); // Set fish_bind_mode to "default". env_set(FISH_BIND_MODE_VAR, DEFAULT_BIND_MODE, ENV_GLOBAL); @@ -1208,12 +1216,22 @@ int env_remove(const wcstring &key, int var_mode) { return !erased; } -const wchar_t *env_var_t::c_str(void) const { - assert(!is_missing); //!OCLINT(multiple unary operator) - return wcstring::c_str(); +wcstring env_var_t::as_string(void) const { + assert(!is_missing); + return val; } -env_var_t env_get_string(const wcstring &key, env_mode_flags_t mode) { +const wchar_t *env_var_t::c_str(void) const { + assert(!is_missing); + return val.c_str(); +} + +void env_var_t::to_list(wcstring_list_t &out) const { + assert(!is_missing); + tokenize_variable_array(val, out); +} + +env_var_t env_get(const wcstring &key, env_mode_flags_t mode) { const bool has_scope = mode & (ENV_LOCAL | ENV_GLOBAL | ENV_UNIVERSAL); const bool search_local = !has_scope || (mode & ENV_LOCAL); const bool search_global = !has_scope || (mode & ENV_GLOBAL); @@ -1232,18 +1250,18 @@ env_var_t env_get_string(const wcstring &key, env_mode_flags_t mode) { if (!is_main_thread()) { return env_var_t::missing_var(); } - env_var_t result; history_t *history = reader_get_history(); if (!history) { history = &history_t::history_with_name(history_session_id()); } + wcstring result; if (history) history->get_string_representation(&result, ARRAY_SEP_STR); - return result; + return env_var_t(result); } else if (key == L"status") { - return to_string(proc_get_last_status()); + return env_var_t(to_string(proc_get_last_status())); } else if (key == L"umask") { - return format_string(L"0%0.3o", get_umask()); + return env_var_t(format_string(L"0%0.3o", get_umask())); } // We should never get here unless the electric var list is out of sync with the above code. DIE("unerecognized electric var name"); @@ -1276,7 +1294,7 @@ env_var_t env_get_string(const wcstring &key, env_mode_flags_t mode) { if (!search_universal) return env_var_t::missing_var(); // 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_string. + // values). Make sure we do this outside the env_lock because it may itself call `env_get()`. if (is_main_thread() && !get_proc_had_barrier()) { set_proc_had_barrier(true); env_universal_barrier(); @@ -1487,12 +1505,12 @@ void var_stack_t::update_export_array_if_necessary() { const wcstring_list_t uni = uvars()->get_names(true, false); for (size_t i = 0; i < uni.size(); i++) { const wcstring &key = uni.at(i); - const env_var_t val = uvars()->get(key); + const env_var_t var = uvars()->get(key); - if (!val.missing() && val != ENV_NULL) { + if (!var.missing() && var.as_string() != ENV_NULL) { // Note that std::map::insert does NOT overwrite a value already in the map, // which we depend on here. - vals.insert(std::pair(key, val)); + vals.insert(std::pair(key, var.as_string())); } } } @@ -1533,16 +1551,16 @@ env_vars_snapshot_t::env_vars_snapshot_t(const wchar_t *const *keys) { wcstring key; for (size_t i = 0; keys[i]; i++) { key.assign(keys[i]); - const env_var_t val = env_get_string(key); - if (!val.missing()) { - vars[key] = val; + const env_var_t var = env_get(key); + if (!var.missing()) { + vars[key] = var.as_string(); } } } env_vars_snapshot_t::env_vars_snapshot_t() {} -// The "current" variables are not a snapshot at all, but instead trampoline to env_get_string, etc. +// The "current" variables are not a snapshot at all, but instead trampoline to env_get, etc. // We identify the current snapshot based on pointer values. static const env_vars_snapshot_t sCurrentSnapshot; const env_vars_snapshot_t &env_vars_snapshot_t::current() { return sCurrentSnapshot; } @@ -1550,9 +1568,9 @@ const env_vars_snapshot_t &env_vars_snapshot_t::current() { return sCurrentSnaps bool env_vars_snapshot_t::is_current() const { return this == &sCurrentSnapshot; } env_var_t env_vars_snapshot_t::get(const wcstring &key) const { - // If we represent the current state, bounce to env_get_string. + // If we represent the current state, bounce to env_get. if (this->is_current()) { - return env_get_string(key); + return env_get(key); } std::map::const_iterator iter = vars.find(key); return iter == vars.end() ? env_var_t::missing_var() : env_var_t(iter->second); diff --git a/src/env.h b/src/env.h index 7160e893d..64a2327df 100644 --- a/src/env.h +++ b/src/env.h @@ -24,7 +24,7 @@ extern bool curses_initialized; /// Value denoting a null string. #define ENV_NULL L"\x1d" -// Flags that may be passed as the 'mode' in env_set / env_get_string. +// Flags that may be passed as the 'mode' in env_set / env_get. enum { /// Default mode. ENV_DEFAULT = 0, @@ -69,11 +69,16 @@ void env_init(const struct config_paths_t *paths = NULL); /// routines. void misc_init(); -int env_set(const wcstring &key, const wchar_t *val, env_mode_flags_t mode); +/// Tokenize the specified string into the specified wcstring_list_t. +/// +/// \param val the input string. The contents of this string is not changed. +/// \param out the list in which to place the elements. +void tokenize_variable_array(const wcstring &val, wcstring_list_t &out); -class env_var_t : public wcstring { +class env_var_t { private: bool is_missing; + wcstring val; public: static env_var_t missing_var() { @@ -82,41 +87,36 @@ class env_var_t : public wcstring { return result; } - env_var_t(const env_var_t &x) : wcstring(x), is_missing(x.is_missing) {} - env_var_t(const wcstring &x) : wcstring(x), is_missing(false) {} - env_var_t(const wchar_t *x) : wcstring(x), is_missing(false) {} - env_var_t() : wcstring(L""), is_missing(false) {} + env_var_t(const env_var_t &x) : val(x.val), is_missing(x.is_missing) {} + env_var_t(const wcstring &x) : val(x), is_missing(false) {} + env_var_t(const wchar_t *x) : val(x), is_missing(false) {} + env_var_t() : val(L""), is_missing(false) {} + bool empty(void) const { return val.empty(); }; bool missing(void) const { return is_missing; } - - bool missing_or_empty(void) const { return missing() || empty(); } + bool missing_or_empty(void) const { return missing() || val.empty(); } const wchar_t *c_str(void) const; + void to_list(wcstring_list_t &out) const; + wcstring as_string() const; - env_var_t &operator=(const env_var_t &s) { - is_missing = s.is_missing; - wcstring::operator=(s); + env_var_t &operator=(const env_var_t &v) { + is_missing = v.is_missing; + val = v.val; return *this; } - bool operator==(const env_var_t &s) const { - return is_missing == s.is_missing && - static_cast(*this) == static_cast(s); - } + bool operator==(const env_var_t &s) const { return is_missing == s.is_missing && val == s.val; } - bool operator==(const wcstring &s) const { - return !is_missing && static_cast(*this) == s; - } + bool operator==(const wcstring &s) const { return !is_missing && val == s; } - bool operator!=(const env_var_t &s) const { return !(*this == s); } + bool operator!=(const env_var_t &v) const { return val != v.val; } - bool operator!=(const wcstring &s) const { return !(*this == s); } + bool operator!=(const wcstring &s) const { return val != s; } - bool operator==(const wchar_t *s) const { - return !is_missing && static_cast(*this) == s; - } + bool operator!=(const wchar_t *s) const { return val != s; } - bool operator!=(const wchar_t *s) const { return !(*this == s); } + bool operator==(const wchar_t *s) const { return !is_missing && val == s; } }; /// Gets the variable with the specified name, or env_var_t::missing_var if it does not exist or is @@ -124,7 +124,9 @@ class env_var_t : public wcstring { /// /// \param key The name of the variable to get /// \param mode An optional scope to search in. All scopes are searched if unset -env_var_t env_get_string(const wcstring &key, env_mode_flags_t mode = ENV_DEFAULT); +env_var_t env_get(const wcstring &key, env_mode_flags_t mode = ENV_DEFAULT); + +int env_set(const wcstring &key, const wchar_t *val, env_mode_flags_t mode); /// Returns true if the specified key exists. This can't be reliably done using env_get, since /// env_get returns null for 0-element arrays. @@ -214,10 +216,4 @@ bool term_supports_setting_title(); /// Returns the fish internal representation for an array of strings. std::unique_ptr list_to_array_val(const wcstring_list_t &list); std::unique_ptr list_to_array_val(const wchar_t **list); - -/// Tokenize the specified string into the specified wcstring_list_t. -/// -/// \param val the input string. The contents of this string is not changed. -/// \param out the list in which to place the elements. -void tokenize_variable_array(const wcstring &val, wcstring_list_t &out); #endif diff --git a/src/exec.cpp b/src/exec.cpp index 44f41255c..5af251572 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -405,7 +405,7 @@ void exec_job(parser_t &parser, job_t *j) { // really make sense, so I'm not trying to fix it here. if (!setup_child_process(j, 0, all_ios)) { // Decrement SHLVL as we're removing ourselves from the shell "stack". - const env_var_t shlvl_str = env_get_string(L"SHLVL", ENV_GLOBAL | ENV_EXPORT); + const env_var_t shlvl_str = env_get(L"SHLVL", ENV_GLOBAL | ENV_EXPORT); wcstring nshlvl_str = L"0"; if (!shlvl_str.missing()) { long shlvl_i = fish_wcstol(shlvl_str.c_str()); @@ -1111,7 +1111,7 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst, boo const int prev_status = proc_get_last_status(); bool split_output = false; - const env_var_t ifs = env_get_string(L"IFS"); + const env_var_t ifs = env_get(L"IFS"); if (!ifs.missing_or_empty()) { split_output = true; } diff --git a/src/expand.cpp b/src/expand.cpp index 79f4cec7d..aa972a458 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -144,7 +144,7 @@ static void append_cmdsub_error(parse_error_list_t *errors, size_t source_start, /// Return the environment variable value for the string starting at \c in. static env_var_t expand_var(const wchar_t *in) { if (!in) return env_var_t::missing_var(); - return env_get_string(in); + return env_get(in); } /// Test if the specified string does not contain character which can not be used inside a quoted @@ -777,19 +777,19 @@ static int expand_variables(const wcstring &instr, std::vector *ou } var_tmp.append(instr, start_pos, var_len); - env_var_t var_val; + env_var_t var; if (var_len == 1 && var_tmp[0] == VARIABLE_EXPAND_EMPTY) { - var_val = env_var_t::missing_var(); + var = env_var_t::missing_var(); } else { - var_val = expand_var(var_tmp.c_str()); + var = expand_var(var_tmp.c_str()); } - if (!var_val.missing()) { + if (!var.missing()) { int all_vars = 1; wcstring_list_t var_item_list; if (is_ok) { - tokenize_variable_array(var_val, var_item_list); + var.to_list(var_item_list); const size_t slice_start = stop_pos; if (slice_start < insize && instr.at(slice_start) == L'[') { @@ -1173,7 +1173,7 @@ static void expand_home_directory(wcstring &input) { env_var_t home; if (username.empty()) { // Current users home directory. - home = env_get_string(L"HOME"); + home = env_get(L"HOME"); // If home is either missing or empty, // treat it like an empty list. // $HOME is defined to be a _path_, @@ -1201,7 +1201,7 @@ static void expand_home_directory(wcstring &input) { } } - wchar_t *realhome = wrealpath(home, NULL); + wchar_t *realhome = wrealpath(home.as_string(), NULL); if (!tilde_error && realhome) { input.replace(input.begin(), input.begin() + tail_idx, realhome); @@ -1433,12 +1433,12 @@ static expand_error_t expand_stage_wildcards(const wcstring &input, std::vector< } else { // 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. - env_var_t paths = env_get_string(for_cd ? L"CDPATH" : L"PATH"); + env_var_t paths = env_get(for_cd ? L"CDPATH" : L"PATH"); if (paths.missing_or_empty()) paths = for_cd ? L"." : L""; // Tokenize it into path names. std::vector pathsv; - tokenize_variable_array(paths, pathsv); + paths.to_list(pathsv); for (auto next_path : pathsv) { effective_working_dirs.push_back( path_apply_working_directory(next_path, working_dir)); @@ -1592,9 +1592,9 @@ void update_abbr_cache(const wchar_t *op, const wcstring varname) { } abbreviations.erase(abbr); if (wcscmp(op, L"ERASE") != 0) { - const env_var_t expansion = env_get_string(varname); + const env_var_t expansion = env_get(varname); if (!expansion.missing_or_empty()) { - abbreviations.emplace(std::make_pair(abbr, expansion)); + abbreviations.emplace(std::make_pair(abbr, expansion.as_string())); } } } diff --git a/src/function.cpp b/src/function.cpp index c61f8bb47..ac529d62d 100644 --- a/src/function.cpp +++ b/src/function.cpp @@ -78,7 +78,7 @@ static int load(const wcstring &name) { static void autoload_names(std::set &names, int get_hidden) { size_t i; - const env_var_t path_var_wstr = env_get_string(L"fish_function_path"); + const env_var_t path_var_wstr = env_get(L"fish_function_path"); if (path_var_wstr.missing()) return; const wchar_t *path_var = path_var_wstr.c_str(); @@ -121,7 +121,7 @@ void function_init() { static std::map snapshot_vars(const wcstring_list_t &vars) { std::map result; for (wcstring_list_t::const_iterator it = vars.begin(), end = vars.end(); it != end; ++it) { - result.insert(std::make_pair(*it, env_get_string(*it))); + result.insert(std::make_pair(*it, env_get(*it))); } return result; } diff --git a/src/highlight.cpp b/src/highlight.cpp index 8722bf7ad..69c9d0a45 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -221,12 +221,12 @@ static bool is_potential_cd_path(const wcstring &path, const wcstring &working_d directories.push_back(working_directory); } else { // Get the CDPATH. - env_var_t cdpath = env_get_string(L"CDPATH"); + env_var_t cdpath = env_get(L"CDPATH"); if (cdpath.missing_or_empty()) cdpath = L"."; // Tokenize it into directories. std::vector pathsv; - tokenize_variable_array(cdpath, pathsv); + cdpath.to_list(pathsv); for (auto next_path : pathsv) { if (next_path.empty()) next_path = L"."; // Ensure that we use the working directory for relative cdpaths like ".". @@ -268,17 +268,17 @@ rgb_color_t highlight_get_color(highlight_spec_t highlight, bool is_background) return rgb_color_t::normal(); } - env_var_t val_wstr = env_get_string(highlight_var[idx]); + env_var_t var = env_get(highlight_var[idx]); // debug( 1, L"%d -> %d -> %ls", highlight, idx, val ); - if (val_wstr.missing()) val_wstr = env_get_string(highlight_var[0]); + if (var.missing()) var = env_get(highlight_var[0]); - if (!val_wstr.missing()) result = parse_color(val_wstr, treat_as_background); + if (!var.missing()) result = parse_color(var.as_string(), treat_as_background); // Handle modifiers. if (highlight & highlight_modifier_valid_path) { - env_var_t val2_wstr = env_get_string(L"fish_color_valid_path"); + env_var_t val2_wstr = env_get(L"fish_color_valid_path"); const wcstring val2 = val2_wstr.missing() ? L"" : val2_wstr.c_str(); rgb_color_t result2 = parse_color(val2, is_background); diff --git a/src/history.cpp b/src/history.cpp index 915e0b726..a293933b9 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -1796,8 +1796,9 @@ void history_sanity_check() { wcstring history_session_id() { wcstring result = DFLT_FISH_HISTORY_SESSION_ID; - const env_var_t session_id = env_get_string(L"FISH_HISTORY"); - if (!session_id.missing()) { + const env_var_t var = env_get(L"FISH_HISTORY"); + if (!var.missing()) { + wcstring session_id = var.as_string(); if (session_id.empty()) { result = L""; } else if (session_id == L"default") { diff --git a/src/input.cpp b/src/input.cpp index d4dc16698..94d4a4469 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -201,8 +201,8 @@ static int input_function_args_index = 0; /// Return the current bind mode. wcstring input_get_bind_mode() { - env_var_t mode = env_get_string(FISH_BIND_MODE_VAR); - return mode.missing() ? DEFAULT_BIND_MODE : mode; + env_var_t mode = env_get(FISH_BIND_MODE_VAR); + return mode.missing() ? DEFAULT_BIND_MODE : mode.as_string(); } /// Set the current bind mode. diff --git a/src/input_common.cpp b/src/input_common.cpp index 3ccb2324b..22c402a7d 100644 --- a/src/input_common.cpp +++ b/src/input_common.cpp @@ -160,7 +160,7 @@ static wint_t readb() { // Update the wait_on_escape_ms value in response to the fish_escape_delay_ms user variable being // set. void update_wait_on_escape_ms() { - env_var_t escape_time_ms = env_get_string(L"fish_escape_delay_ms"); + env_var_t escape_time_ms = env_get(L"fish_escape_delay_ms"); if (escape_time_ms.missing_or_empty()) { wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT; return; diff --git a/src/output.cpp b/src/output.cpp index 41422b52b..94252223b 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -554,7 +554,7 @@ void writembs_check(char *mbs, const char *mbs_name, const char *file, long line if (mbs != NULL) { tputs(mbs, 1, &writeb); } else { - env_var_t term = env_get_string(L"TERM"); + env_var_t term = env_get(L"TERM"); const wchar_t *fmt = _(L"Tried to use terminfo string %s on line %ld of %s, which is " L"undefined in terminal of type \"%ls\". Please report this error to %s"); diff --git a/src/path.cpp b/src/path.cpp index 7af742974..adba7451d 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -50,7 +50,7 @@ static bool path_get_path_core(const wcstring &cmd, wcstring *out_path, int err = ENOENT; wcstring bin_path; if (!bin_path_var.missing()) { - bin_path = bin_path_var; + bin_path = bin_path_var.as_string(); } else { // Note that PREFIX is defined in the `Makefile` and is thus defined when this module is // compiled. This ensures we always default to "/bin", "/usr/bin" and the bin dir defined @@ -104,7 +104,7 @@ bool path_get_path(const wcstring &cmd, wcstring *out_path, const env_vars_snaps } bool path_get_path(const wcstring &cmd, wcstring *out_path) { - return path_get_path_core(cmd, out_path, env_get_string(L"PATH")); + return path_get_path_core(cmd, out_path, env_get(L"PATH")); } wcstring_list_t path_get_paths(const wcstring &cmd) { @@ -122,9 +122,9 @@ wcstring_list_t path_get_paths(const wcstring &cmd) { return paths; } - wcstring env_path = env_get_string(L"PATH"); + env_var_t path_var = env_get(L"PATH"); std::vector pathsv; - tokenize_variable_array(env_path, pathsv); + path_var.to_list(pathsv); for (auto path : pathsv) { if (path.empty()) continue; append_path_component(path, cmd); @@ -141,10 +141,11 @@ wcstring_list_t path_get_paths(const wcstring &cmd) { return paths; } -bool path_get_cdpath(const wcstring &dir, wcstring *out, const wchar_t *wd, +bool path_get_cdpath(const env_var_t &dir_var, wcstring *out, const wchar_t *wd, const env_vars_snapshot_t &env_vars) { int err = ENOENT; - if (dir.empty()) return false; + if (dir_var.missing_or_empty()) return false; + wcstring dir = dir_var.as_string(); if (wd) { size_t len = wcslen(wd); @@ -168,7 +169,7 @@ bool path_get_cdpath(const wcstring &dir, wcstring *out, const wchar_t *wd, if (cdpaths.missing_or_empty()) cdpaths = L"."; std::vector cdpathsv; - tokenize_variable_array(cdpaths, cdpathsv); + cdpaths.to_list(cdpathsv); for (auto next_path : cdpathsv) { if (next_path.empty()) next_path = L"."; if (next_path == L"." && wd != NULL) { @@ -287,19 +288,20 @@ static void path_create(wcstring &path, const wcstring &xdg_var, const wcstring // The vars we fetch must be exported. Allowing them to be universal doesn't make sense and // allowing that creates a lock inversion that deadlocks the shell since we're called before // uvars are available. - const env_var_t xdg_dir = env_get_string(xdg_var, ENV_GLOBAL | ENV_EXPORT); + const env_var_t xdg_dir = env_get(xdg_var, ENV_GLOBAL | ENV_EXPORT); if (!xdg_dir.missing_or_empty()) { using_xdg = true; - path = xdg_dir + L"/fish"; + path = xdg_dir.as_string() + L"/fish"; if (create_directory(path) != -1) { path_done = true; } else { saved_errno = errno; } } else { - const env_var_t home = env_get_string(L"HOME", ENV_GLOBAL | ENV_EXPORT); + const env_var_t home = env_get(L"HOME", ENV_GLOBAL | ENV_EXPORT); if (!home.missing_or_empty()) { - path = home + (which_dir == L"config" ? L"/.config/fish" : L"/.local/share/fish"); + path = home.as_string() + + (which_dir == L"config" ? L"/.config/fish" : L"/.local/share/fish"); if (create_directory(path) != -1) { path_done = true; } else { diff --git a/src/path.h b/src/path.h index 371d0ef86..2b62dfa03 100644 --- a/src/path.h +++ b/src/path.h @@ -61,7 +61,7 @@ wcstring_list_t path_get_paths(const wcstring &cmd); /// \param vars The environment variable snapshot to use (for the CDPATH variable) /// \return 0 if the command can not be found, the path of the command otherwise. The path should be /// free'd with free(). -bool path_get_cdpath(const wcstring &dir, wcstring *out_or_NULL, const wchar_t *wd = NULL, +bool path_get_cdpath(const env_var_t &dir, wcstring *out_or_NULL, const wchar_t *wd = NULL, const env_vars_snapshot_t &vars = env_vars_snapshot_t::current()); /// Returns whether the path can be used for an implicit cd command; if so, also returns the path by diff --git a/src/reader.cpp b/src/reader.cpp index 72271f858..89a0d767d 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -2063,8 +2063,8 @@ void reader_import_history_if_necessary(void) { // Try opening a bash file. We make an effort to respect $HISTFILE; this isn't very complete // (AFAIK it doesn't have to be exported), and to really get this right we ought to ask bash // itself. But this is better than nothing. - const env_var_t var = env_get_string(L"HISTFILE"); - wcstring path = (var.missing() ? L"~/.bash_history" : var); + const env_var_t var = env_get(L"HISTFILE"); + wcstring path = (var.missing() ? L"~/.bash_history" : var.as_string()); expand_tilde(path); FILE *f = wfopen(path, "r"); if (f) { diff --git a/src/screen.cpp b/src/screen.cpp index 0d0d3cc1d..9b0988276 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -120,8 +120,8 @@ static bool is_screen_name_escape_seq(const wchar_t *code, size_t *resulting_len #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_string(L"TERM"); - if (term_name.missing() || !string_prefixes_string(L"screen", term_name)) { + 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