Instantize env_set in env.h and env.cpp

This commit is contained in:
ridiculousfish 2018-09-17 21:26:21 -07:00
parent abcd24f716
commit 3eb15109cf
4 changed files with 48 additions and 43 deletions

View File

@ -112,8 +112,8 @@ static const wcstring_list_t locale_variables({L"LANG", L"LANGUAGE", L"LC_ALL",
static const wcstring_list_t curses_variables({L"TERM", L"TERMINFO", L"TERMINFO_DIRS"}); static const wcstring_list_t curses_variables({L"TERM", L"TERMINFO", L"TERMINFO_DIRS"});
// Some forward declarations to make it easy to logically group the code. // Some forward declarations to make it easy to logically group the code.
static void init_locale(); static void init_locale(const environment_t &vars);
static void init_curses(); static void init_curses(const environment_t &vars);
// Struct representing one level in the function variable stack. // Struct representing one level in the function variable stack.
// Only our variable stack should create and destroy these // Only our variable stack should create and destroy these
@ -264,8 +264,10 @@ void var_stack_t::pop() {
} }
} }
if (locale_changed) init_locale(); // TODO: instantize this locale and curses
if (curses_changed) init_curses(); const auto &vars = env_stack_t::principal();
if (locale_changed) init_locale(vars);
if (curses_changed) init_curses(vars);
} }
env_node_ref_t var_stack_t::next_scope_to_search(const env_node_ref_t &node) const { env_node_ref_t var_stack_t::next_scope_to_search(const env_node_ref_t &node) const {
@ -346,9 +348,9 @@ static mode_t get_umask() {
} }
/// Properly sets all timezone information. /// Properly sets all timezone information.
static void handle_timezone(const wchar_t *env_var_name) { 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 env_var_t var = env_get(env_var_name, ENV_EXPORT);
const auto var = env_get(env_var_name, ENV_DEFAULT); const auto var = vars.get(env_var_name, ENV_DEFAULT);
debug(2, L"handle_timezone() current timezone var: |%ls| => |%ls|", env_var_name, debug(2, L"handle_timezone() current timezone var: |%ls| => |%ls|", env_var_name,
!var ? L"MISSING" : var->as_string().c_str()); !var ? L"MISSING" : var->as_string().c_str());
const std::string &name = wcs2string(env_var_name); const std::string &name = wcs2string(env_var_name);
@ -383,13 +385,13 @@ static void fix_colon_delimited_var(const wcstring &var_name, env_stack_t &vars)
} }
/// Initialize the locale subsystem. /// Initialize the locale subsystem.
static void init_locale() { static void init_locale(const environment_t &vars) {
// We have to make a copy because the subsequent setlocale() call to change the locale will // We have to make a copy because the subsequent setlocale() call to change the locale will
// invalidate the pointer from the this setlocale() call. // invalidate the pointer from the this setlocale() call.
char *old_msg_locale = strdup(setlocale(LC_MESSAGES, NULL)); char *old_msg_locale = strdup(setlocale(LC_MESSAGES, NULL));
for (const auto &var_name : locale_variables) { for (const auto &var_name : locale_variables) {
const auto var = env_get(var_name, ENV_EXPORT); const auto var = vars.get(var_name, ENV_EXPORT);
const std::string &name = wcs2string(var_name); const std::string &name = wcs2string(var_name);
if (var.missing_or_empty()) { if (var.missing_or_empty()) {
debug(5, L"locale var %s missing or empty", name.c_str()); debug(5, L"locale var %s missing or empty", name.c_str());
@ -434,8 +436,8 @@ bool term_supports_setting_title() { return can_set_term_title; }
/// terminal title if the underlying terminal does so, but will print garbage on terminals that /// terminal title if the underlying terminal does so, but will print garbage on terminals that
/// don't. Since we can't see the underlying terminal below screen there is no way to fix this. /// don't. Since we can't see the underlying terminal below screen there is no way to fix this.
static const wchar_t *const title_terms[] = {L"xterm", L"screen", L"tmux", L"nxterm", L"rxvt"}; static const wchar_t *const title_terms[] = {L"xterm", L"screen", L"tmux", L"nxterm", L"rxvt"};
static bool does_term_support_setting_title() { static bool does_term_support_setting_title(const environment_t &vars) {
const auto term_var = env_get(L"TERM"); const auto term_var = vars.get(L"TERM");
if (term_var.missing_or_empty()) return false; if (term_var.missing_or_empty()) return false;
const wcstring term_str = term_var->as_string(); const wcstring term_str = term_var->as_string();
@ -460,11 +462,11 @@ static bool does_term_support_setting_title() {
} }
/// Updates our idea of whether we support term256 and term24bit (see issue #10222). /// Updates our idea of whether we support term256 and term24bit (see issue #10222).
static void update_fish_color_support() { static void update_fish_color_support(const environment_t &vars) {
// Detect or infer term256 support. If fish_term256 is set, we respect it; // Detect or infer term256 support. If fish_term256 is set, we respect it;
// otherwise infer it from the TERM variable or use terminfo. // otherwise infer it from the TERM variable or use terminfo.
auto fish_term256 = env_get(L"fish_term256"); auto fish_term256 = vars.get(L"fish_term256");
auto term_var = env_get(L"TERM"); auto term_var = vars.get(L"TERM");
wcstring term = term_var.missing_or_empty() ? L"" : term_var->as_string(); wcstring term = term_var.missing_or_empty() ? L"" : term_var->as_string();
bool support_term256 = false; // default to no support bool support_term256 = false; // default to no support
if (!fish_term256.missing_or_empty()) { if (!fish_term256.missing_or_empty()) {
@ -476,8 +478,8 @@ static void update_fish_color_support() {
debug(2, L"256 color support enabled for '256color' in TERM"); debug(2, L"256 color support enabled for '256color' in TERM");
} else if (term.find(L"xterm") != wcstring::npos) { } else if (term.find(L"xterm") != wcstring::npos) {
// Assume that all xterms are 256, except for OS X SnowLeopard // Assume that all xterms are 256, except for OS X SnowLeopard
const auto prog_var = env_get(L"TERM_PROGRAM"); const auto prog_var = vars.get(L"TERM_PROGRAM");
const auto progver_var = env_get(L"TERM_PROGRAM_VERSION"); const auto progver_var = vars.get(L"TERM_PROGRAM_VERSION");
wcstring term_program = prog_var.missing_or_empty() ? L"" : prog_var->as_string(); wcstring term_program = prog_var.missing_or_empty() ? L"" : prog_var->as_string();
if (term_program == L"Apple_Terminal" && !progver_var.missing_or_empty()) { if (term_program == L"Apple_Terminal" && !progver_var.missing_or_empty()) {
// OS X Lion is version 300+, it has 256 color support // OS X Lion is version 300+, it has 256 color support
@ -497,7 +499,7 @@ static void update_fish_color_support() {
debug(2, L"256 color support not enabled (yet)"); debug(2, L"256 color support not enabled (yet)");
} }
auto fish_term24bit = env_get(L"fish_term24bit"); auto fish_term24bit = vars.get(L"fish_term24bit");
bool support_term24bit; bool support_term24bit;
if (!fish_term24bit.missing_or_empty()) { if (!fish_term24bit.missing_or_empty()) {
support_term24bit = from_string<bool>(fish_term24bit->as_string()); support_term24bit = from_string<bool>(fish_term24bit->as_string());
@ -520,7 +522,8 @@ static void update_fish_color_support() {
static bool initialize_curses_using_fallback(const char *term) { 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 // 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. // seeing if the fallback name can be used.
auto term_var = env_get(L"TERM"); auto &vars = env_stack_t::globals();
auto term_var = vars.get(L"TERM");
if (term_var.missing_or_empty()) return false; if (term_var.missing_or_empty()) return false;
auto term_env = wcs2string(term_var->as_string()); auto term_env = wcs2string(term_var->as_string());
@ -547,12 +550,13 @@ static void init_path_vars() {
/// Update the value of g_guessed_fish_emoji_width /// Update the value of g_guessed_fish_emoji_width
static void guess_emoji_width() { static void guess_emoji_width() {
wcstring term; wcstring term;
if (auto term_var = env_get(L"TERM_PROGRAM")) { auto &vars = env_stack_t::globals();
if (auto term_var = vars.get(L"TERM_PROGRAM")) {
term = term_var->as_string(); term = term_var->as_string();
} }
double version = 0; double version = 0;
if (auto version_var = env_get(L"TERM_PROGRAM_VERSION")) { if (auto version_var = vars.get(L"TERM_PROGRAM_VERSION")) {
std::string narrow_version = wcs2string(version_var->as_string()); std::string narrow_version = wcs2string(version_var->as_string());
version = strtod(narrow_version.c_str(), NULL); version = strtod(narrow_version.c_str(), NULL);
} }
@ -569,10 +573,10 @@ static void guess_emoji_width() {
} }
/// Initialize the curses subsystem. /// Initialize the curses subsystem.
static void init_curses() { static void init_curses(const environment_t &vars) {
for (const auto &var_name : curses_variables) { for (const auto &var_name : curses_variables) {
std::string name = wcs2string(var_name); std::string name = wcs2string(var_name);
const auto var = env_get(var_name, ENV_EXPORT); const auto var = vars.get(var_name, ENV_EXPORT);
if (var.missing_or_empty()) { if (var.missing_or_empty()) {
debug(2, L"curses var %s missing or empty", name.c_str()); debug(2, L"curses var %s missing or empty", name.c_str());
unsetenv(name.c_str()); unsetenv(name.c_str());
@ -585,7 +589,7 @@ static void init_curses() {
int err_ret; int err_ret;
if (setupterm(NULL, STDOUT_FILENO, &err_ret) == ERR) { if (setupterm(NULL, STDOUT_FILENO, &err_ret) == ERR) {
auto term = env_get(L"TERM"); auto term = vars.get(L"TERM");
if (is_interactive_session) { if (is_interactive_session) {
debug(1, _(L"Could not set up terminal.")); debug(1, _(L"Could not set up terminal."));
if (term.missing_or_empty()) { if (term.missing_or_empty()) {
@ -601,9 +605,9 @@ static void init_curses() {
} }
} }
can_set_term_title = does_term_support_setting_title(); can_set_term_title = does_term_support_setting_title(vars);
term_has_xn = tigetflag((char *)"xenl") == 1; // does terminal have the eat_newline_glitch term_has_xn = tigetflag((char *)"xenl") == 1; // does terminal have the eat_newline_glitch
update_fish_color_support(); update_fish_color_support(vars);
// Invalidate the cached escape sequences since they may no longer be valid. // Invalidate the cached escape sequences since they may no longer be valid.
cached_layouts.clear(); cached_layouts.clear();
curses_initialized = true; curses_initialized = true;
@ -679,7 +683,7 @@ void env_stack_t::set_pwd_from_getcwd() {
/// Allow the user to override the limit on how much data the `read` command will process. /// 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. /// This is primarily for testing but could be used by users in special situations.
void env_stack_t::set_read_limit() { void env_stack_t::set_read_limit() {
auto read_byte_limit_var = env_get(L"fish_read_limit"); auto read_byte_limit_var = this->get(L"fish_read_limit");
if (!read_byte_limit_var.missing_or_empty()) { if (!read_byte_limit_var.missing_or_empty()) {
size_t limit = fish_wcstoull(read_byte_limit_var->as_string().c_str()); size_t limit = fish_wcstoull(read_byte_limit_var->as_string().c_str());
if (errno) { if (errno) {
@ -708,14 +712,15 @@ wcstring environment_t::get_pwd_slash() const {
/// Set up the USER variable. /// Set up the USER variable.
static void setup_user(bool force) { static void setup_user(bool force) {
if (force || env_get(L"USER").missing_or_empty()) { auto &vars = env_stack_t::globals();
if (force || vars.get(L"USER").missing_or_empty()) {
struct passwd userinfo; struct passwd userinfo;
struct passwd *result; struct passwd *result;
char buf[8192]; char buf[8192];
int retval = getpwuid_r(getuid(), &userinfo, buf, sizeof(buf), &result); int retval = getpwuid_r(getuid(), &userinfo, buf, sizeof(buf), &result);
if (!retval && result) { if (!retval && result) {
const wcstring uname = str2wcstring(userinfo.pw_name); const wcstring uname = str2wcstring(userinfo.pw_name);
env_stack_t::globals().set_one(L"USER", ENV_GLOBAL | ENV_EXPORT, uname); vars.set_one(L"USER", ENV_GLOBAL | ENV_EXPORT, uname);
} }
} }
} }
@ -755,7 +760,7 @@ static void handle_fish_term_change(const wcstring &op, const wcstring &var_name
env_stack_t &vars) { env_stack_t &vars) {
UNUSED(op); UNUSED(op);
UNUSED(var_name); UNUSED(var_name);
update_fish_color_support(); update_fish_color_support(vars);
reader_react_to_color_change(); reader_react_to_color_change();
} }
@ -763,7 +768,7 @@ static void handle_escape_delay_change(const wcstring &op, const wcstring &var_n
env_stack_t &vars) { env_stack_t &vars) {
UNUSED(op); UNUSED(op);
UNUSED(var_name); UNUSED(var_name);
update_wait_on_escape_ms(); update_wait_on_escape_ms(vars);
} }
static void handle_change_emoji_width(const wcstring &op, const wcstring &var_name, static void handle_change_emoji_width(const wcstring &op, const wcstring &var_name,
@ -771,7 +776,7 @@ static void handle_change_emoji_width(const wcstring &op, const wcstring &var_na
(void)op; (void)op;
(void)var_name; (void)var_name;
int new_width = 0; int new_width = 0;
if (auto width_str = env_get(L"fish_emoji_width")) { if (auto width_str = vars.get(L"fish_emoji_width")) {
new_width = fish_wcstol(width_str->as_string().c_str()); new_width = fish_wcstol(width_str->as_string().c_str());
} }
g_fish_emoji_width = std::max(0, new_width); g_fish_emoji_width = std::max(0, new_width);
@ -782,7 +787,7 @@ static void handle_change_ambiguous_width(const wcstring &op, const wcstring &va
(void)op; (void)op;
(void)var_name; (void)var_name;
int new_width = 1; int new_width = 1;
if (auto width_str = env_get(L"fish_ambiguous_width")) { if (auto width_str = vars.get(L"fish_ambiguous_width")) {
new_width = fish_wcstol(width_str->as_string().c_str()); new_width = fish_wcstol(width_str->as_string().c_str());
} }
g_fish_ambiguous_width = std::max(0, new_width); g_fish_ambiguous_width = std::max(0, new_width);
@ -825,7 +830,7 @@ static void handle_complete_path_change(const wcstring &op, const wcstring &var_
static void handle_tz_change(const wcstring &op, const wcstring &var_name, env_stack_t &vars) { static void handle_tz_change(const wcstring &op, const wcstring &var_name, env_stack_t &vars) {
UNUSED(op); UNUSED(op);
handle_timezone(var_name.c_str()); handle_timezone(var_name.c_str(), vars);
} }
static void handle_magic_colon_var_change(const wcstring &op, const wcstring &var_name, static void handle_magic_colon_var_change(const wcstring &op, const wcstring &var_name,
@ -837,14 +842,14 @@ static void handle_magic_colon_var_change(const wcstring &op, const wcstring &va
static void handle_locale_change(const wcstring &op, const wcstring &var_name, env_stack_t &vars) { static void handle_locale_change(const wcstring &op, const wcstring &var_name, env_stack_t &vars) {
UNUSED(op); UNUSED(op);
UNUSED(var_name); UNUSED(var_name);
init_locale(); init_locale(vars);
} }
static void handle_curses_change(const wcstring &op, const wcstring &var_name, env_stack_t &vars) { static void handle_curses_change(const wcstring &op, const wcstring &var_name, env_stack_t &vars) {
UNUSED(op); UNUSED(op);
UNUSED(var_name); UNUSED(var_name);
guess_emoji_width(); guess_emoji_width();
init_curses(); init_curses(vars);
} }
/// Populate the dispatch table used by `react_to_variable_change()` to efficiently call the /// Populate the dispatch table used by `react_to_variable_change()` to efficiently call the
@ -915,8 +920,8 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
path_get_data(user_data_dir); path_get_data(user_data_dir);
vars.set_one(FISH_USER_DATA_DIR, ENV_GLOBAL, user_data_dir); vars.set_one(FISH_USER_DATA_DIR, ENV_GLOBAL, user_data_dir);
init_locale(); init_locale(vars);
init_curses(); init_curses(vars);
init_input(); init_input();
init_path_vars(); init_path_vars();
guess_emoji_width(); guess_emoji_width();
@ -966,8 +971,8 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
// if the target user is root, unless "--preserve-environment" is used. // 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. // Since that is an explicit choice, we should allow it to enable e.g.
// env HOME=(mktemp -d) su --preserve-environment fish // env HOME=(mktemp -d) su --preserve-environment fish
if (env_get(L"HOME").missing_or_empty()) { if (vars.get(L"HOME").missing_or_empty()) {
auto user_var = env_get(L"USER"); auto user_var = vars.get(L"USER");
if (!user_var.missing_or_empty()) { if (!user_var.missing_or_empty()) {
char *unam_narrow = wcs2str(user_var->as_string()); char *unam_narrow = wcs2str(user_var->as_string());
struct passwd userinfo; struct passwd userinfo;
@ -977,7 +982,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */) {
if (retval || !result) { if (retval || !result) {
// Maybe USER is set but it's bogus. Reset USER from the db and try again. // Maybe USER is set but it's bogus. Reset USER from the db and try again.
setup_user(true); setup_user(true);
user_var = env_get(L"USER"); user_var = vars.get(L"USER");
if (!user_var.missing_or_empty()) { if (!user_var.missing_or_empty()) {
unam_narrow = wcs2str(user_var->as_string()); unam_narrow = wcs2str(user_var->as_string());
retval = getpwnam_r(unam_narrow, &userinfo, buf, sizeof(buf), &result); retval = getpwnam_r(unam_narrow, &userinfo, buf, sizeof(buf), &result);

View File

@ -168,7 +168,7 @@ void env_set_read_limit();
/// A environment stack of scopes. This is the main class that tracks fish variables. /// A environment stack of scopes. This is the main class that tracks fish variables.
struct var_stack_t; struct var_stack_t;
class env_node_t; class env_node_t;
class env_stack_t : public environment_t { class env_stack_t final : public environment_t {
friend class parser_t; friend class parser_t;
std::unique_ptr<var_stack_t> vars_; std::unique_ptr<var_stack_t> vars_;

View File

@ -158,8 +158,8 @@ static wint_t readb() {
// Update the wait_on_escape_ms value in response to the fish_escape_delay_ms user variable being // Update the wait_on_escape_ms value in response to the fish_escape_delay_ms user variable being
// set. // set.
void update_wait_on_escape_ms() { void update_wait_on_escape_ms(const environment_t &vars) {
auto escape_time_ms = env_get(L"fish_escape_delay_ms"); auto escape_time_ms = vars.get(L"fish_escape_delay_ms");
if (escape_time_ms.missing_or_empty()) { if (escape_time_ms.missing_or_empty()) {
wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT; wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT;
return; return;

View File

@ -89,7 +89,7 @@ void input_common_init(int (*ih)());
void input_common_destroy(); void input_common_destroy();
/// Adjust the escape timeout. /// Adjust the escape timeout.
void update_wait_on_escape_ms(); void update_wait_on_escape_ms(const environment_t &vars);
/// Function used by input_readch to read bytes from stdin until enough bytes have been read to /// Function used by input_readch to read bytes from stdin until enough bytes have been read to
/// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously been /// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously been