From 391af6af0ccd229d3a050ccdf13ba4260dc71990 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 9 Sep 2018 02:25:51 -0700 Subject: [PATCH] Introduce class environment_t This will be used as a base class for variable snapshots and variable stacks. --- src/autoload.cpp | 2 +- src/autoload.h | 4 ++-- src/env.cpp | 11 +++++++---- src/env.h | 17 +++++++++++++++-- src/function.cpp | 2 +- src/function.h | 2 +- src/highlight.cpp | 14 +++++++------- src/highlight.h | 8 ++++---- src/path.cpp | 6 +++--- src/path.h | 6 +++--- src/proc.cpp | 2 +- src/reader.h | 4 ++-- 12 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/autoload.cpp b/src/autoload.cpp index 6d577fc46..8614731e3 100644 --- a/src/autoload.cpp +++ b/src/autoload.cpp @@ -96,7 +96,7 @@ int autoload_t::load(const wcstring &cmd, bool reload) { return res; } -bool autoload_t::can_load(const wcstring &cmd, const env_vars_snapshot_t &vars) { +bool autoload_t::can_load(const wcstring &cmd, const environment_t &vars) { auto path_var = vars.get(env_var_name); if (path_var.missing_or_empty()) return false; diff --git a/src/autoload.h b/src/autoload.h index ceb703c53..249b49c34 100644 --- a/src/autoload.h +++ b/src/autoload.h @@ -40,7 +40,7 @@ struct autoload_function_t { bool is_placeholder; }; -class env_vars_snapshot_t; +class environment_t; /// Class representing a path from which we can autoload and the autoloaded contents. class autoload_t : public lru_cache_t { @@ -88,7 +88,7 @@ class autoload_t : public lru_cache_t { int unload(const wcstring &cmd); /// Check whether the given command could be loaded, but do not load it. - bool can_load(const wcstring &cmd, const env_vars_snapshot_t &vars); + bool can_load(const wcstring &cmd, const environment_t &vars); /// Invalidates all entries. Uesd when the underlying path variable changes. void invalidate(); diff --git a/src/env.cpp b/src/env.cpp index 148e0eb71..7a9b18e80 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -1589,6 +1589,8 @@ void env_set_argv(const wchar_t *const *argv) { } } +environment_t::~environment_t() = default; + env_vars_snapshot_t::env_vars_snapshot_t(const wchar_t *const *keys) { ASSERT_IS_MAIN_THREAD(); wcstring key; @@ -1596,12 +1598,13 @@ env_vars_snapshot_t::env_vars_snapshot_t(const wchar_t *const *keys) { key.assign(keys[i]); const auto var = env_get(key); if (var) { - vars[key] = *var; + vars[key] = std::move(*var); } } } -env_vars_snapshot_t::env_vars_snapshot_t() {} +env_vars_snapshot_t::env_vars_snapshot_t() = default; +env_vars_snapshot_t::~env_vars_snapshot_t() = default; // 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. @@ -1610,10 +1613,10 @@ const env_vars_snapshot_t &env_vars_snapshot_t::current() { return sCurrentSnaps bool env_vars_snapshot_t::is_current() const { return this == &sCurrentSnapshot; } -maybe_t env_vars_snapshot_t::get(const wcstring &key) const { +maybe_t env_vars_snapshot_t::get(const wcstring &key, env_mode_flags_t mode) const { // If we represent the current state, bounce to env_get. if (this->is_current()) { - return env_get(key); + return env_get(key, mode); } auto iter = vars.find(key); if (iter == vars.end()) return none(); diff --git a/src/env.h b/src/env.h index 30fb4ab0d..26b186c1f 100644 --- a/src/env.h +++ b/src/env.h @@ -131,6 +131,17 @@ class env_var_t { bool operator!=(const env_var_t &rhs) const { return ! (*this == rhs); } }; +/// An environment is read-only access to variable values. +class environment_t { + protected: + environment_t() = default; + + public: + virtual maybe_t get(const wcstring &key, + env_mode_flags_t mode = ENV_DEFAULT) const = 0; + virtual ~environment_t(); +}; + /// 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); @@ -180,7 +191,7 @@ wcstring env_get_pwd_slash(); /// Update the read_byte_limit variable. void env_set_read_limit(); -class env_vars_snapshot_t { +class env_vars_snapshot_t : public environment_t { std::map vars; bool is_current() const; @@ -191,7 +202,9 @@ class env_vars_snapshot_t { env_vars_snapshot_t(const wchar_t *const *keys); env_vars_snapshot_t(); - maybe_t get(const wcstring &key) const; + ~env_vars_snapshot_t(); + + maybe_t get(const wcstring &key, env_mode_flags_t mode = ENV_DEFAULT) const override; // Returns the fake snapshot representing the live variables array. static const env_vars_snapshot_t ¤t(); diff --git a/src/function.cpp b/src/function.cpp index 30593812a..f709b08f0 100644 --- a/src/function.cpp +++ b/src/function.cpp @@ -198,7 +198,7 @@ void function_load(const wcstring &cmd) { } } -int function_exists_no_autoload(const wcstring &cmd, const env_vars_snapshot_t &vars) { +int function_exists_no_autoload(const wcstring &cmd, const environment_t &vars) { if (parser_keywords_is_reserved(cmd)) return 0; scoped_rlock locker(functions_lock); return loaded_functions.find(cmd) != loaded_functions.end() || diff --git a/src/function.h b/src/function.h index 7520e19c7..d823bdeeb 100644 --- a/src/function.h +++ b/src/function.h @@ -77,7 +77,7 @@ int function_exists(const wcstring &name); void function_load(const wcstring &name); /// Returns true if the function with the name name exists, without triggering autoload. -int function_exists_no_autoload(const wcstring &name, const env_vars_snapshot_t &vars); +int function_exists_no_autoload(const wcstring &name, const environment_t &vars); /// Returns all function names. /// diff --git a/src/highlight.cpp b/src/highlight.cpp index a6612b68f..211d7c0d7 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -333,7 +333,7 @@ static bool autosuggest_parse_command(const wcstring &buff, wcstring *out_expand bool autosuggest_validate_from_history(const history_item_t &item, const wcstring &working_directory, - const env_vars_snapshot_t &vars) { + const environment_t &vars) { ASSERT_IS_BACKGROUND_THREAD(); bool handled = false, suggestionOK = false; @@ -667,7 +667,7 @@ class highlighter_t { // Cursor position. const size_t cursor_pos; // Environment variables. Again, a reference member variable! - const env_vars_snapshot_t &vars; + const environment_t &vars; // Whether it's OK to do I/O. const bool io_ok; // Working directory. @@ -698,7 +698,7 @@ class highlighter_t { public: // Constructor - highlighter_t(const wcstring &str, size_t pos, const env_vars_snapshot_t &ev, wcstring wd, + highlighter_t(const wcstring &str, size_t pos, const environment_t &ev, wcstring wd, bool can_do_io) : buff(str), cursor_pos(pos), @@ -985,7 +985,7 @@ void highlighter_t::color_children(const parse_node_t &parent, parse_token_type_ /// Determine if a command is valid. static bool command_is_valid(const wcstring &cmd, enum parse_statement_decoration_t decoration, - const wcstring &working_directory, const env_vars_snapshot_t &vars) { + const wcstring &working_directory, const environment_t &vars) { // Determine which types we check, based on the decoration. bool builtin_ok = true, function_ok = true, abbreviation_ok = true, command_ok = true, implicit_cd_ok = true; @@ -1196,7 +1196,7 @@ const highlighter_t::color_array_t &highlighter_t::highlight() { } void highlight_shell(const wcstring &buff, std::vector &color, size_t pos, - wcstring_list_t *error, const env_vars_snapshot_t &vars) { + wcstring_list_t *error, const environment_t &vars) { UNUSED(error); // Do something sucky and get the current working directory on this background thread. This // should really be passed in. @@ -1208,7 +1208,7 @@ void highlight_shell(const wcstring &buff, std::vector &color, } void highlight_shell_no_io(const wcstring &buff, std::vector &color, size_t pos, - wcstring_list_t *error, const env_vars_snapshot_t &vars) { + wcstring_list_t *error, const environment_t &vars) { UNUSED(error); // Do something sucky and get the current working directory on this background thread. This // should really be passed in. @@ -1306,7 +1306,7 @@ static void highlight_universal_internal(const wcstring &buffstr, } void highlight_universal(const wcstring &buff, std::vector &color, size_t pos, - wcstring_list_t *error, const env_vars_snapshot_t &vars) { + wcstring_list_t *error, const environment_t &vars) { UNUSED(error); UNUSED(vars); assert(buff.size() == color.size()); diff --git a/src/highlight.h b/src/highlight.h index e4e255f27..bfac1d3f2 100644 --- a/src/highlight.h +++ b/src/highlight.h @@ -75,12 +75,12 @@ class history_item_t; /// \param error a list in which a description of each error will be inserted. May be 0, in whcich /// case no error descriptions will be generated. void highlight_shell(const wcstring &buffstr, std::vector &color, size_t pos, - wcstring_list_t *error, const env_vars_snapshot_t &vars); + wcstring_list_t *error, const environment_t &vars); /// Perform a non-blocking shell highlighting. The function will not do any I/O that may block. As a /// result, invalid commands may not be detected, etc. void highlight_shell_no_io(const wcstring &buffstr, std::vector &color, - size_t pos, wcstring_list_t *error, const env_vars_snapshot_t &vars); + size_t pos, wcstring_list_t *error, const environment_t &vars); /// Perform syntax highlighting for the text in buff. Matching quotes and paranthesis are /// highlighted. The result is stored in the color array as a color_code from the HIGHLIGHT_ enum @@ -93,7 +93,7 @@ void highlight_shell_no_io(const wcstring &buffstr, std::vector &color, size_t pos, - wcstring_list_t *error, const env_vars_snapshot_t &vars); + wcstring_list_t *error, const environment_t &vars); /// Translate from HIGHLIGHT_* to FISH_COLOR_* according to environment variables. Defaults to /// FISH_COLOR_NORMAL. @@ -109,7 +109,7 @@ rgb_color_t highlight_get_color(highlight_spec_t highlight, bool is_background); /// reference whether the suggestion is valid or not. bool autosuggest_validate_from_history(const history_item_t &item, const wcstring &working_directory, - const env_vars_snapshot_t &vars); + const environment_t &vars); // Tests whether the specified string cpath is the prefix of anything we could cd to. directories is // a list of possible parent directories (typically either the working directory, or the cdpath). diff --git a/src/path.cpp b/src/path.cpp index 2b1b027dc..a4a8e1c3f 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -115,7 +115,7 @@ static bool path_get_path_core(const wcstring &cmd, wcstring *out_path, return false; } -bool path_get_path(const wcstring &cmd, wcstring *out_path, const env_vars_snapshot_t &vars) { +bool path_get_path(const wcstring &cmd, wcstring *out_path, const environment_t &vars) { return path_get_path_core(cmd, out_path, vars.get(L"PATH")); } @@ -158,7 +158,7 @@ wcstring_list_t path_get_paths(const wcstring &cmd) { } bool path_get_cdpath(const wcstring &dir, wcstring *out, const wcstring &wd, - const env_vars_snapshot_t &env_vars) { + const environment_t &env_vars) { int err = ENOENT; if (dir.empty()) return false; @@ -216,7 +216,7 @@ bool path_get_cdpath(const wcstring &dir, wcstring *out, const wcstring &wd, } bool path_can_be_implicit_cd(const wcstring &path, const wcstring &wd, wcstring *out_path, - const env_vars_snapshot_t &vars) { + const environment_t &vars) { wcstring exp_path = path; expand_tilde(exp_path); diff --git a/src/path.h b/src/path.h index bb166c812..e6c2174aa 100644 --- a/src/path.h +++ b/src/path.h @@ -40,7 +40,7 @@ bool path_get_data(wcstring &path); /// false if the command can not be found else true. The result /// should be freed with free(). bool path_get_path(const wcstring &cmd, wcstring *output_or_NULL, - const env_vars_snapshot_t &vars = env_vars_snapshot_t::current()); + const environment_t &vars = env_vars_snapshot_t::current()); /// Return all the paths that match the given command. wcstring_list_t path_get_paths(const wcstring &cmd); @@ -61,13 +61,13 @@ wcstring_list_t path_get_paths(const wcstring &cmd); /// \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 wcstring &wd, - const env_vars_snapshot_t &vars = env_vars_snapshot_t::current()); + const environment_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 /// reference (if desired). This requires it to start with one of the allowed prefixes (., .., ~) /// and resolve to a directory. bool path_can_be_implicit_cd(const wcstring &path, const wcstring &wd, wcstring *out_path = NULL, - const env_vars_snapshot_t &vars = env_vars_snapshot_t::current()); + const environment_t &vars = env_vars_snapshot_t::current()); /// Remove double slashes and trailing slashes from a path, e.g. transform foo//bar/ into foo/bar. /// The string is modified in-place. diff --git a/src/proc.cpp b/src/proc.cpp index 6f692fb50..f8794b82e 100644 --- a/src/proc.cpp +++ b/src/proc.cpp @@ -6,6 +6,7 @@ // IWYU pragma: no_include <__bit_reference> #include "config.h" +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include #if HAVE_TERM_H #include diff --git a/src/reader.h b/src/reader.h index 2d4338b76..1ecca836c 100644 --- a/src/reader.h +++ b/src/reader.h @@ -14,8 +14,8 @@ #include "highlight.h" #include "parse_constants.h" +class environment_t; class history_t; -class env_vars_snapshot_t; class io_chain_t; /// Helper class for storing a command line. @@ -160,7 +160,7 @@ void reader_set_complete_function(complete_function_t); /// The type of a highlight function. typedef void (*highlight_function_t)(const wcstring &, std::vector &, size_t, - wcstring_list_t *, const env_vars_snapshot_t &vars); + wcstring_list_t *, const environment_t &vars); /// Function type for testing if a string is valid for the reader to return. using test_function_t = parser_test_error_bits_t (*)(const wcstring &);