diff --git a/src/builtin_history.cpp b/src/builtin_history.cpp index d86311531..bd0a49fa0 100644 --- a/src/builtin_history.cpp +++ b/src/builtin_history.cpp @@ -15,6 +15,7 @@ #include "fallback.h" // IWYU pragma: keep #include "history.h" #include "io.h" +#include "parser.h" #include "reader.h" #include "wgetopt.h" #include "wutil.h" // IWYU pragma: keep @@ -218,7 +219,7 @@ int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv) { // Use the default history if we have none (which happens if invoked non-interactively, e.g. // from webconfig.py. history_t *history = reader_get_history(); - if (!history) history = &history_t::history_with_name(history_session_id()); + if (!history) history = &history_t::history_with_name(history_session_id(parser.vars())); // If a history command hasn't already been specified via a flag check the first word. // Note that this can be simplified after we eliminate allowing subcommands as flags. diff --git a/src/builtin_read.cpp b/src/builtin_read.cpp index 1bab82707..0ea09bd94 100644 --- a/src/builtin_read.cpp +++ b/src/builtin_read.cpp @@ -204,7 +204,8 @@ static int read_interactive(wcstring &buff, int nchars, bool shell, bool silent, int exit_res = STATUS_CMD_OK; const wchar_t *line; - wcstring read_history_ID = history_session_id(); + auto &vars = env_stack_t::principal(); + wcstring read_history_ID = history_session_id(vars); if (!read_history_ID.empty()) read_history_ID += L"_read"; reader_push(read_history_ID); diff --git a/src/env.cpp b/src/env.cpp index 5e1d4b6e9..07c8e3a41 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -811,7 +811,7 @@ static void handle_fish_history_change(const wcstring &op, const wcstring &var_n env_stack_t &vars) { UNUSED(op); UNUSED(var_name); - reader_change_history(history_session_id().c_str()); + reader_change_history(history_session_id(vars).c_str()); } static void handle_function_path_change(const wcstring &op, const wcstring &var_name, @@ -1391,7 +1391,7 @@ maybe_t env_stack_t::get(const wcstring &key, env_mode_flags_t mode) history_t *history = reader_get_history(); if (!history) { - history = &history_t::history_with_name(history_session_id()); + history = &history_t::history_with_name(history_session_id(*this)); } wcstring_list_t result; if (history) history->get_history(result); diff --git a/src/expand.cpp b/src/expand.cpp index 4b546839e..c9bba8fcd 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -353,7 +353,7 @@ static bool expand_variables(wcstring instr, std::vector *out, siz // Note reader_get_history may return null, if we are running non-interactively (e.g. from // web_config). if (is_main_thread()) { - history = &history_t::history_with_name(history_session_id()); + history = &history_t::history_with_name(history_session_id(env_stack_t::principal())); } } else if (var_name != wcstring{VARIABLE_EXPAND_EMPTY}) { var = env_get(var_name); diff --git a/src/history.cpp b/src/history.cpp index 685e61916..920b4c46d 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -1694,6 +1694,8 @@ void history_t::clear() { this->clear_file_state(); } +bool history_t::is_default() const { return name == DFLT_FISH_HISTORY_SESSION_ID; } + bool history_t::is_empty() { scoped_lock locker(lock); @@ -1804,9 +1806,6 @@ static bool should_import_bash_history_line(const std::string &line) { /// commands. We can't actually parse bash syntax and the bash history file does not unambiguously /// encode multiline commands. void history_t::populate_from_bash(FILE *stream) { - // We do not import bash history if an alternative fish history file is being used. - if (history_session_id() != DFLT_FISH_HISTORY_SESSION_ID) return; - // Process the entire history file until EOF is observed. bool eof = false; while (!eof) { @@ -1867,10 +1866,10 @@ void history_collection_t::save() { void history_save_all() { histories.save(); } /// Return the prefix for the files to be used for command and read history. -wcstring history_session_id() { +wcstring history_session_id(const environment_t &vars) { wcstring result = DFLT_FISH_HISTORY_SESSION_ID; - const auto var = env_get(L"fish_history"); + const auto var = vars.get(L"fish_history"); if (var) { wcstring session_id = var->as_string(); if (session_id.empty()) { diff --git a/src/history.h b/src/history.h index 4b50554b6..033766060 100644 --- a/src/history.h +++ b/src/history.h @@ -22,6 +22,7 @@ #include "wutil.h" // IWYU pragma: keep struct io_streams_t; +class environment_t; // Fish supports multiple shells writing to history at once. Here is its strategy: // @@ -214,6 +215,9 @@ class history_t { // Returns history with the given name, creating it if necessary. static history_t &history_with_name(const wcstring &name); + /// Returns whether this is using the default name. + bool is_default() const; + // Determines whether the history is empty. Unfortunately this cannot be const, since it may // require populating the history. bool is_empty(); @@ -357,7 +361,7 @@ class history_search_t { void history_save_all(); /// Return the prefix for the files to be used for command and read history. -wcstring history_session_id(); +wcstring history_session_id(const environment_t &vars); /// Given a list of paths and a working directory, return the paths that are valid /// This does disk I/O and may only be called in a background thread diff --git a/src/reader.cpp b/src/reader.cpp index 6784c4138..26c2cab80 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -2150,8 +2150,9 @@ void reader_import_history_if_necessary() { data->history->populate_from_config_path(); } - // Import history from bash, etc. if our current history is still empty. - if (data->history && data->history->is_empty()) { + // Import history from bash, etc. if our current history is still empty and is the default + // history. + if (data->history && data->history->is_empty() && data->history->is_default()) { // 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. @@ -2346,7 +2347,8 @@ uint32_t reader_run_count() { return run_count; } /// Read interactively. Read input from stdin while providing editing facilities. static int read_i() { - reader_push(history_session_id()); + parser_t &parser = parser_t::principal_parser(); + reader_push(history_session_id(parser.vars())); reader_set_complete_function(&complete); reader_set_highlight_function(&highlight_shell); reader_set_test_function(&reader_shell_test); @@ -2354,7 +2356,6 @@ static int read_i() { reader_set_expand_abbreviations(true); reader_import_history_if_necessary(); - parser_t &parser = parser_t::principal_parser(); reader_data_t *data = current_data(); data->prev_end_loop = 0;