mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-24 14:23:52 +08:00
Instantize contents of exec.cpp and others
This commit is contained in:
parent
038f3cca6d
commit
6f52e6bb1c
|
@ -19,6 +19,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "env.h"
|
#include "env.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
|
#include "parser.h"
|
||||||
#include "wutil.h" // IWYU pragma: keep
|
#include "wutil.h" // IWYU pragma: keep
|
||||||
|
|
||||||
/// The time before we'll recheck an autoloaded file.
|
/// The time before we'll recheck an autoloaded file.
|
||||||
|
@ -256,7 +257,8 @@ bool autoload_t::locate_file_and_maybe_load_it(const wcstring &cmd, bool really_
|
||||||
// If we have a script, either built-in or a file source, then run it.
|
// If we have a script, either built-in or a file source, then run it.
|
||||||
if (really_load && !script_source.empty()) {
|
if (really_load && !script_source.empty()) {
|
||||||
// Do nothing on failure.
|
// Do nothing on failure.
|
||||||
exec_subshell(script_source, false /* do not apply exit status */);
|
exec_subshell(script_source, parser_t::principal_parser(),
|
||||||
|
false /* do not apply exit status */);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (really_load) {
|
if (really_load) {
|
||||||
|
|
|
@ -169,7 +169,7 @@ wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t
|
||||||
wcstring out;
|
wcstring out;
|
||||||
const wcstring name_esc = escape_string(name, 1);
|
const wcstring name_esc = escape_string(name, 1);
|
||||||
wcstring cmd = format_string(L"__fish_print_help %ls", name_esc.c_str());
|
wcstring cmd = format_string(L"__fish_print_help %ls", name_esc.c_str());
|
||||||
if (exec_subshell(cmd, lst, false /* don't apply exit status */) >= 0) {
|
if (exec_subshell(cmd, parser, lst, false /* don't apply exit status */) >= 0) {
|
||||||
for (size_t i = 0; i < lst.size(); i++) {
|
for (size_t i = 0; i < lst.size(); i++) {
|
||||||
out.append(lst.at(i));
|
out.append(lst.at(i));
|
||||||
out.push_back(L'\n');
|
out.push_back(L'\n');
|
||||||
|
|
|
@ -453,7 +453,7 @@ static int validate_arg(parser_t &parser, const argparse_cmd_opts_t &opts, optio
|
||||||
}
|
}
|
||||||
vars.set_one(var_name_prefix + L"value", ENV_LOCAL, woptarg);
|
vars.set_one(var_name_prefix + L"value", ENV_LOCAL, woptarg);
|
||||||
|
|
||||||
int retval = exec_subshell(opt_spec->validation_command, cmd_output, false);
|
int retval = exec_subshell(opt_spec->validation_command, parser, cmd_output, false);
|
||||||
for (const auto &output : cmd_output) {
|
for (const auto &output : cmd_output) {
|
||||||
streams.err.append(output);
|
streams.err.append(output);
|
||||||
streams.err.push_back(L'\n');
|
streams.err.push_back(L'\n');
|
||||||
|
|
|
@ -410,7 +410,9 @@ bool completer_t::condition_test(const wcstring &condition) {
|
||||||
condition_cache_t::iterator cached_entry = condition_cache.find(condition);
|
condition_cache_t::iterator cached_entry = condition_cache.find(condition);
|
||||||
if (cached_entry == condition_cache.end()) {
|
if (cached_entry == condition_cache.end()) {
|
||||||
// Compute new value and reinsert it.
|
// Compute new value and reinsert it.
|
||||||
test_res = (0 == exec_subshell(condition, false /* don't apply exit status */));
|
// TODO: rationalize this parser_t usage.
|
||||||
|
test_res = (0 == exec_subshell(condition, parser_t::principal_parser(),
|
||||||
|
false /* don't apply exit status */));
|
||||||
condition_cache[condition] = test_res;
|
condition_cache[condition] = test_res;
|
||||||
} else {
|
} else {
|
||||||
// Use the old value.
|
// Use the old value.
|
||||||
|
@ -591,7 +593,9 @@ void completer_t::complete_cmd_desc(const wcstring &str) {
|
||||||
// search if we know the location of the whatis database. This can take some time on slower
|
// search if we know the location of the whatis database. This can take some time on slower
|
||||||
// systems with a large set of manuals, but it should be ok since apropos is only called once.
|
// systems with a large set of manuals, but it should be ok since apropos is only called once.
|
||||||
wcstring_list_t list;
|
wcstring_list_t list;
|
||||||
if (exec_subshell(lookup_cmd, list, false /* don't apply exit status */) != -1) {
|
// TODO: rationalize this use of principal_parser.
|
||||||
|
if (exec_subshell(lookup_cmd, parser_t::principal_parser(), list,
|
||||||
|
false /* don't apply exit status */) != -1) {
|
||||||
std::unordered_map<wcstring, wcstring> lookup;
|
std::unordered_map<wcstring, wcstring> lookup;
|
||||||
lookup.reserve(list.size());
|
lookup.reserve(list.size());
|
||||||
|
|
||||||
|
|
18
src/exec.cpp
18
src/exec.cpp
|
@ -369,7 +369,7 @@ void internal_exec(env_stack_t &vars, job_t *j, const io_chain_t &all_ios) {
|
||||||
// really make sense, so I'm not trying to fix it here.
|
// really make sense, so I'm not trying to fix it here.
|
||||||
if (!setup_child_process(0, all_ios)) {
|
if (!setup_child_process(0, all_ios)) {
|
||||||
// Decrement SHLVL as we're removing ourselves from the shell "stack".
|
// Decrement SHLVL as we're removing ourselves from the shell "stack".
|
||||||
auto shlvl_var = env_get(L"SHLVL", ENV_GLOBAL | ENV_EXPORT);
|
auto shlvl_var = vars.get(L"SHLVL", ENV_GLOBAL | ENV_EXPORT);
|
||||||
wcstring shlvl_str = L"0";
|
wcstring shlvl_str = L"0";
|
||||||
if (shlvl_var) {
|
if (shlvl_var) {
|
||||||
long shlvl = fish_wcstol(shlvl_var->as_string().c_str());
|
long shlvl = fish_wcstol(shlvl_var->as_string().c_str());
|
||||||
|
@ -1085,14 +1085,14 @@ bool exec_job(parser_t &parser, shared_ptr<job_t> j) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst, bool apply_exit_status,
|
static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, wcstring_list_t *lst,
|
||||||
bool is_subcmd) {
|
bool apply_exit_status, bool is_subcmd) {
|
||||||
ASSERT_IS_MAIN_THREAD();
|
ASSERT_IS_MAIN_THREAD();
|
||||||
bool prev_subshell = is_subshell;
|
bool prev_subshell = is_subshell;
|
||||||
const int prev_status = proc_get_last_status();
|
const int prev_status = proc_get_last_status();
|
||||||
bool split_output = false;
|
bool split_output = false;
|
||||||
|
|
||||||
const auto ifs = env_get(L"IFS");
|
const auto ifs = parser.vars().get(L"IFS");
|
||||||
if (!ifs.missing_or_empty()) {
|
if (!ifs.missing_or_empty()) {
|
||||||
split_output = true;
|
split_output = true;
|
||||||
}
|
}
|
||||||
|
@ -1163,13 +1163,13 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst, boo
|
||||||
return subcommand_status;
|
return subcommand_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exec_subshell(const wcstring &cmd, std::vector<wcstring> &outputs, bool apply_exit_status,
|
int exec_subshell(const wcstring &cmd, parser_t &parser, std::vector<wcstring> &outputs,
|
||||||
bool is_subcmd) {
|
bool apply_exit_status, bool is_subcmd) {
|
||||||
ASSERT_IS_MAIN_THREAD();
|
ASSERT_IS_MAIN_THREAD();
|
||||||
return exec_subshell_internal(cmd, &outputs, apply_exit_status, is_subcmd);
|
return exec_subshell_internal(cmd, parser, &outputs, apply_exit_status, is_subcmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int exec_subshell(const wcstring &cmd, bool apply_exit_status, bool is_subcmd) {
|
int exec_subshell(const wcstring &cmd, parser_t &parser, bool apply_exit_status, bool is_subcmd) {
|
||||||
ASSERT_IS_MAIN_THREAD();
|
ASSERT_IS_MAIN_THREAD();
|
||||||
return exec_subshell_internal(cmd, NULL, apply_exit_status, is_subcmd);
|
return exec_subshell_internal(cmd, parser, NULL, apply_exit_status, is_subcmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,10 @@ bool exec_job(parser_t &parser, std::shared_ptr<job_t> j);
|
||||||
/// \param outputs The list to insert output into.
|
/// \param outputs The list to insert output into.
|
||||||
///
|
///
|
||||||
/// \return the status of the last job to exit, or -1 if en error was encountered.
|
/// \return the status of the last job to exit, or -1 if en error was encountered.
|
||||||
int exec_subshell(const wcstring &cmd, std::vector<wcstring> &outputs, bool preserve_exit_status,
|
int exec_subshell(const wcstring &cmd, parser_t &parser, std::vector<wcstring> &outputs,
|
||||||
|
bool preserve_exit_status, bool is_subcmd = false);
|
||||||
|
int exec_subshell(const wcstring &cmd, parser_t &parser, bool preserve_exit_status,
|
||||||
bool is_subcmd = false);
|
bool is_subcmd = false);
|
||||||
int exec_subshell(const wcstring &cmd, bool preserve_exit_status, bool is_subcmd = false);
|
|
||||||
|
|
||||||
/// Loops over close until the syscall was run without being interrupted.
|
/// Loops over close until the syscall was run without being interrupted.
|
||||||
void exec_close(int fd);
|
void exec_close(int fd);
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "iothread.h"
|
#include "iothread.h"
|
||||||
#include "parse_constants.h"
|
#include "parse_constants.h"
|
||||||
#include "parse_util.h"
|
#include "parse_util.h"
|
||||||
|
#include "parser.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
|
@ -292,7 +293,7 @@ static size_t parse_slice(const wchar_t *in, wchar_t **end_ptr, std::vector<long
|
||||||
/// actually starts operating on last_idx-1. As such, to process a string fully, pass string.size()
|
/// actually starts operating on last_idx-1. As such, to process a string fully, pass string.size()
|
||||||
/// as last_idx instead of string.size()-1.
|
/// as last_idx instead of string.size()-1.
|
||||||
static bool expand_variables(wcstring instr, std::vector<completion_t> *out, size_t last_idx,
|
static bool expand_variables(wcstring instr, std::vector<completion_t> *out, size_t last_idx,
|
||||||
parse_error_list_t *errors) {
|
const environment_t &vars, parse_error_list_t *errors) {
|
||||||
const size_t insize = instr.size();
|
const size_t insize = instr.size();
|
||||||
|
|
||||||
// last_idx may be 1 past the end of the string, but no further.
|
// last_idx may be 1 past the end of the string, but no further.
|
||||||
|
@ -356,7 +357,7 @@ static bool expand_variables(wcstring instr, std::vector<completion_t> *out, siz
|
||||||
history = &history_t::history_with_name(history_session_id(env_stack_t::principal()));
|
history = &history_t::history_with_name(history_session_id(env_stack_t::principal()));
|
||||||
}
|
}
|
||||||
} else if (var_name != wcstring{VARIABLE_EXPAND_EMPTY}) {
|
} else if (var_name != wcstring{VARIABLE_EXPAND_EMPTY}) {
|
||||||
var = env_get(var_name);
|
var = vars.get(var_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse out any following slice.
|
// Parse out any following slice.
|
||||||
|
@ -406,7 +407,7 @@ static bool expand_variables(wcstring instr, std::vector<completion_t> *out, siz
|
||||||
res.push_back(VARIABLE_EXPAND_EMPTY);
|
res.push_back(VARIABLE_EXPAND_EMPTY);
|
||||||
}
|
}
|
||||||
res.append(instr, var_name_and_slice_stop, wcstring::npos);
|
res.append(instr, var_name_and_slice_stop, wcstring::npos);
|
||||||
return expand_variables(std::move(res), out, varexp_char_idx, errors);
|
return expand_variables(std::move(res), out, varexp_char_idx, vars, errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +464,7 @@ static bool expand_variables(wcstring instr, std::vector<completion_t> *out, siz
|
||||||
// Append all entries in var_item_list, separated by the delimiter.
|
// Append all entries in var_item_list, separated by the delimiter.
|
||||||
res.append(join_strings(var_item_list, delimit));
|
res.append(join_strings(var_item_list, delimit));
|
||||||
res.append(instr, var_name_and_slice_stop, wcstring::npos);
|
res.append(instr, var_name_and_slice_stop, wcstring::npos);
|
||||||
return expand_variables(std::move(res), out, varexp_char_idx, errors);
|
return expand_variables(std::move(res), out, varexp_char_idx, vars, errors);
|
||||||
} else {
|
} else {
|
||||||
// Normal cartesian-product expansion.
|
// Normal cartesian-product expansion.
|
||||||
for (const wcstring &item : var_item_list) {
|
for (const wcstring &item : var_item_list) {
|
||||||
|
@ -480,7 +481,7 @@ static bool expand_variables(wcstring instr, std::vector<completion_t> *out, siz
|
||||||
}
|
}
|
||||||
new_in.append(item);
|
new_in.append(item);
|
||||||
new_in.append(instr, var_name_and_slice_stop, wcstring::npos);
|
new_in.append(instr, var_name_and_slice_stop, wcstring::npos);
|
||||||
if (!expand_variables(std::move(new_in), out, varexp_char_idx, errors)) {
|
if (!expand_variables(std::move(new_in), out, varexp_char_idx, vars, errors)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -637,7 +638,10 @@ static bool expand_cmdsubst(const wcstring &input, std::vector<completion_t> *ou
|
||||||
|
|
||||||
wcstring_list_t sub_res;
|
wcstring_list_t sub_res;
|
||||||
const wcstring subcmd(paren_begin + 1, paren_end - paren_begin - 1);
|
const wcstring subcmd(paren_begin + 1, paren_end - paren_begin - 1);
|
||||||
if (exec_subshell(subcmd, sub_res, true /* apply_exit_status */, true /* is_subcmd */) == -1) {
|
// TODO: justify this parser_t::principal_parser
|
||||||
|
auto &parser = parser_t::principal_parser();
|
||||||
|
if (exec_subshell(subcmd, parser, sub_res, true /* apply_exit_status */,
|
||||||
|
true /* is_subcmd */) == -1) {
|
||||||
append_cmdsub_error(errors, SOURCE_LOCATION_UNKNOWN,
|
append_cmdsub_error(errors, SOURCE_LOCATION_UNKNOWN,
|
||||||
L"Unknown error while evaulating command substitution");
|
L"Unknown error while evaulating command substitution");
|
||||||
return false;
|
return false;
|
||||||
|
@ -742,7 +746,7 @@ static wcstring get_home_directory_name(const wcstring &input, size_t *out_tail_
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts tilde expansion of the string specified, modifying it in place.
|
/// Attempts tilde expansion of the string specified, modifying it in place.
|
||||||
static void expand_home_directory(wcstring &input) {
|
static void expand_home_directory(wcstring &input, const environment_t &vars) {
|
||||||
if (!input.empty() && input.at(0) == HOME_DIRECTORY) {
|
if (!input.empty() && input.at(0) == HOME_DIRECTORY) {
|
||||||
size_t tail_idx;
|
size_t tail_idx;
|
||||||
wcstring username = get_home_directory_name(input, &tail_idx);
|
wcstring username = get_home_directory_name(input, &tail_idx);
|
||||||
|
@ -750,7 +754,7 @@ static void expand_home_directory(wcstring &input) {
|
||||||
maybe_t<wcstring> home;
|
maybe_t<wcstring> home;
|
||||||
if (username.empty()) {
|
if (username.empty()) {
|
||||||
// Current users home directory.
|
// Current users home directory.
|
||||||
auto home_var = env_get(L"HOME");
|
auto home_var = vars.get(L"HOME");
|
||||||
if (home_var.missing_or_empty()) {
|
if (home_var.missing_or_empty()) {
|
||||||
input.clear();
|
input.clear();
|
||||||
return;
|
return;
|
||||||
|
@ -787,16 +791,17 @@ static void expand_percent_self(wcstring &input) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void expand_tilde(wcstring &input) {
|
void expand_tilde(wcstring &input, const environment_t &vars) {
|
||||||
// Avoid needless COW behavior by ensuring we use const at.
|
// Avoid needless COW behavior by ensuring we use const at.
|
||||||
const wcstring &tmp = input;
|
const wcstring &tmp = input;
|
||||||
if (!tmp.empty() && tmp.at(0) == L'~') {
|
if (!tmp.empty() && tmp.at(0) == L'~') {
|
||||||
input.at(0) = HOME_DIRECTORY;
|
input.at(0) = HOME_DIRECTORY;
|
||||||
expand_home_directory(input);
|
expand_home_directory(input, vars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unexpand_tildes(const wcstring &input, std::vector<completion_t> *completions) {
|
static void unexpand_tildes(const wcstring &input, const environment_t &vars,
|
||||||
|
std::vector<completion_t> *completions) {
|
||||||
// If input begins with tilde, then try to replace the corresponding string in each completion
|
// If input begins with tilde, then try to replace the corresponding string in each completion
|
||||||
// with the tilde. If it does not, there's nothing to do.
|
// with the tilde. If it does not, there's nothing to do.
|
||||||
if (input.empty() || input.at(0) != L'~') return;
|
if (input.empty() || input.at(0) != L'~') return;
|
||||||
|
@ -818,7 +823,7 @@ static void unexpand_tildes(const wcstring &input, std::vector<completion_t> *co
|
||||||
|
|
||||||
// Expand username_with_tilde.
|
// Expand username_with_tilde.
|
||||||
wcstring home = username_with_tilde;
|
wcstring home = username_with_tilde;
|
||||||
expand_tilde(home);
|
expand_tilde(home, vars);
|
||||||
|
|
||||||
// Now for each completion that starts with home, replace it with the username_with_tilde.
|
// Now for each completion that starts with home, replace it with the username_with_tilde.
|
||||||
for (size_t i = 0; i < completions->size(); i++) {
|
for (size_t i = 0; i < completions->size(); i++) {
|
||||||
|
@ -835,12 +840,12 @@ static void unexpand_tildes(const wcstring &input, std::vector<completion_t> *co
|
||||||
|
|
||||||
// If the given path contains the user's home directory, replace that with a tilde. We don't try to
|
// If the given path contains the user's home directory, replace that with a tilde. We don't try to
|
||||||
// be smart about case insensitivity, etc.
|
// be smart about case insensitivity, etc.
|
||||||
wcstring replace_home_directory_with_tilde(const wcstring &str) {
|
wcstring replace_home_directory_with_tilde(const wcstring &str, const environment_t &vars) {
|
||||||
// Only absolute paths get this treatment.
|
// Only absolute paths get this treatment.
|
||||||
wcstring result = str;
|
wcstring result = str;
|
||||||
if (string_prefixes_string(L"/", result)) {
|
if (string_prefixes_string(L"/", result)) {
|
||||||
wcstring home_directory = L"~";
|
wcstring home_directory = L"~";
|
||||||
expand_tilde(home_directory);
|
expand_tilde(home_directory, vars);
|
||||||
if (!string_suffixes_string(L"/", home_directory)) {
|
if (!string_suffixes_string(L"/", home_directory)) {
|
||||||
home_directory.push_back(L'/');
|
home_directory.push_back(L'/');
|
||||||
}
|
}
|
||||||
|
@ -928,7 +933,7 @@ static expand_error_t expand_stage_variables(wcstring input, std::vector<complet
|
||||||
append_completion(out, std::move(next));
|
append_completion(out, std::move(next));
|
||||||
} else {
|
} else {
|
||||||
size_t size = next.size();
|
size_t size = next.size();
|
||||||
if (!expand_variables(std::move(next), out, size, errors)) {
|
if (!expand_variables(std::move(next), out, size, vars, errors)) {
|
||||||
return EXPAND_ERROR;
|
return EXPAND_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -946,7 +951,7 @@ static expand_error_t expand_stage_home_and_self(wcstring input, std::vector<com
|
||||||
parse_error_list_t *errors) {
|
parse_error_list_t *errors) {
|
||||||
(void)errors;
|
(void)errors;
|
||||||
if (!(EXPAND_SKIP_HOME_DIRECTORIES & flags)) {
|
if (!(EXPAND_SKIP_HOME_DIRECTORIES & flags)) {
|
||||||
expand_home_directory(input);
|
expand_home_directory(input, vars);
|
||||||
}
|
}
|
||||||
expand_percent_self(input);
|
expand_percent_self(input);
|
||||||
append_completion(out, std::move(input));
|
append_completion(out, std::move(input));
|
||||||
|
@ -1087,7 +1092,7 @@ expand_error_t expand_string(wcstring input, std::vector<completion_t> *out_comp
|
||||||
if (total_result != EXPAND_ERROR) {
|
if (total_result != EXPAND_ERROR) {
|
||||||
// Hack to un-expand tildes (see #647).
|
// Hack to un-expand tildes (see #647).
|
||||||
if (!(flags & EXPAND_SKIP_HOME_DIRECTORIES)) {
|
if (!(flags & EXPAND_SKIP_HOME_DIRECTORIES)) {
|
||||||
unexpand_tildes(input, &completions);
|
unexpand_tildes(input, vars, &completions);
|
||||||
}
|
}
|
||||||
out_completions->insert(out_completions->end(),
|
out_completions->insert(out_completions->end(),
|
||||||
std::make_move_iterator(completions.begin()),
|
std::make_move_iterator(completions.begin()),
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "maybe.h"
|
#include "maybe.h"
|
||||||
#include "parse_constants.h"
|
#include "parse_constants.h"
|
||||||
|
|
||||||
|
class environment_t;
|
||||||
class env_var_t;
|
class env_var_t;
|
||||||
class environment_t;
|
class environment_t;
|
||||||
|
|
||||||
|
@ -152,10 +153,10 @@ wcstring expand_escape_variable(const env_var_t &var);
|
||||||
/// Perform tilde expansion and nothing else on the specified string, which is modified in place.
|
/// Perform tilde expansion and nothing else on the specified string, which is modified in place.
|
||||||
///
|
///
|
||||||
/// \param input the string to tilde expand
|
/// \param input the string to tilde expand
|
||||||
void expand_tilde(wcstring &input);
|
void expand_tilde(wcstring &input, const environment_t &vars);
|
||||||
|
|
||||||
/// Perform the opposite of tilde expansion on the string, which is modified in place.
|
/// Perform the opposite of tilde expansion on the string, which is modified in place.
|
||||||
wcstring replace_home_directory_with_tilde(const wcstring &str);
|
wcstring replace_home_directory_with_tilde(const wcstring &str, const environment_t &vars);
|
||||||
|
|
||||||
/// Abbreviation support. Expand src as an abbreviation, returning the expanded form if found,
|
/// Abbreviation support. Expand src as an abbreviation, returning the expanded form if found,
|
||||||
/// none() if not.
|
/// none() if not.
|
||||||
|
|
|
@ -1502,11 +1502,17 @@ static void test_lru() {
|
||||||
|
|
||||||
/// A crappy environment_t that only knows about PWD.
|
/// A crappy environment_t that only knows about PWD.
|
||||||
struct pwd_environment_t : public environment_t {
|
struct pwd_environment_t : public environment_t {
|
||||||
|
std::map<wcstring, wcstring> extras;
|
||||||
|
|
||||||
virtual maybe_t<env_var_t> get(const wcstring &key,
|
virtual maybe_t<env_var_t> get(const wcstring &key,
|
||||||
env_mode_flags_t mode = ENV_DEFAULT) const override {
|
env_mode_flags_t mode = ENV_DEFAULT) const override {
|
||||||
if (key == L"PWD") {
|
if (key == L"PWD") {
|
||||||
return env_var_t{wgetcwd(), 0};
|
return env_var_t{wgetcwd(), 0};
|
||||||
}
|
}
|
||||||
|
auto extra = extras.find(key);
|
||||||
|
if (extra != extras.end()) {
|
||||||
|
return env_var_t(extra->second, ENV_DEFAULT);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2620,9 +2626,9 @@ static void test_completion_insertions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void perform_one_autosuggestion_cd_test(const wcstring &command, const wcstring &expected,
|
static void perform_one_autosuggestion_cd_test(const wcstring &command, const wcstring &expected,
|
||||||
long line) {
|
const environment_t &vars, long line) {
|
||||||
std::vector<completion_t> comps;
|
std::vector<completion_t> comps;
|
||||||
complete(command, &comps, COMPLETION_REQUEST_AUTOSUGGESTION, pwd_environment_t{});
|
complete(command, &comps, COMPLETION_REQUEST_AUTOSUGGESTION, vars);
|
||||||
|
|
||||||
bool expects_error = (expected == L"<error>");
|
bool expects_error = (expected == L"<error>");
|
||||||
|
|
||||||
|
@ -2694,7 +2700,6 @@ static void perform_one_completion_cd_test(const wcstring &command, const wcstri
|
||||||
// Testing test_autosuggest_suggest_special, in particular for properly handling quotes and
|
// Testing test_autosuggest_suggest_special, in particular for properly handling quotes and
|
||||||
// backslashes.
|
// backslashes.
|
||||||
static void test_autosuggest_suggest_special() {
|
static void test_autosuggest_suggest_special() {
|
||||||
auto &vars = parser_t::principal_parser().vars();
|
|
||||||
if (system("mkdir -p 'test/autosuggest_test/0foobar'")) err(L"mkdir failed");
|
if (system("mkdir -p 'test/autosuggest_test/0foobar'")) err(L"mkdir failed");
|
||||||
if (system("mkdir -p 'test/autosuggest_test/1foo bar'")) err(L"mkdir failed");
|
if (system("mkdir -p 'test/autosuggest_test/1foo bar'")) err(L"mkdir failed");
|
||||||
if (system("mkdir -p 'test/autosuggest_test/2foo bar'")) err(L"mkdir failed");
|
if (system("mkdir -p 'test/autosuggest_test/2foo bar'")) err(L"mkdir failed");
|
||||||
|
@ -2724,60 +2729,72 @@ static void test_autosuggest_suggest_special() {
|
||||||
|
|
||||||
const wcstring wd = L"test/autosuggest_test";
|
const wcstring wd = L"test/autosuggest_test";
|
||||||
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/0", L"foobar/", __LINE__);
|
pwd_environment_t vars{};
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/0", L"foobar/", __LINE__);
|
vars.extras[L"HOME"] = parser_t::principal_parser().vars().get(L"HOME")->as_string();
|
||||||
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/0", L"foobar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/1", L"foo bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/1", L"foo bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/1", L"foo bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/2", L"foo bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/2", L"foo bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/2", L"foo bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/3", L"foo\\bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/3", L"foo\\bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/3", L"foo\\bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/4", L"foo'bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/4", L"foo'bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/4", L"foo'bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/5", L"foo\"bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/5", L"foo\"bar/", __LINE__);
|
|
||||||
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/5", L"foo\"bar/", __LINE__);
|
|
||||||
|
|
||||||
vars.set_one(L"AUTOSUGGEST_TEST_LOC", ENV_LOCAL, wd);
|
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/0", L"foobar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd $AUTOSUGGEST_TEST_LOC/0", L"foobar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/0", L"foobar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd ~/test_autosuggest_suggest_specia", L"l/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/0", L"foobar/", vars, __LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/1", L"foo bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/start/", L"unique2/unique3/",
|
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/1", L"foo bar/", vars,
|
||||||
|
__LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/1", L"foo bar/", vars, __LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/2", L"foo bar/", vars, __LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/2", L"foo bar/", vars,
|
||||||
|
__LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/2", L"foo bar/", vars,
|
||||||
|
__LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/3", L"foo\\bar/", vars, __LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/3", L"foo\\bar/", vars,
|
||||||
|
__LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/3", L"foo\\bar/", vars,
|
||||||
|
__LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/4", L"foo'bar/", vars, __LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/4", L"foo'bar/", vars,
|
||||||
|
__LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/4", L"foo'bar/", vars, __LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/5", L"foo\"bar/", vars, __LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/5", L"foo\"bar/", vars,
|
||||||
|
__LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd 'test/autosuggest_test/5", L"foo\"bar/", vars,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
|
|
||||||
|
vars.extras[L"AUTOSUGGEST_TEST_LOC"] = wd;
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd $AUTOSUGGEST_TEST_LOC/0", L"foobar/", vars, __LINE__);
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd ~/test_autosuggest_suggest_specia", L"l/", vars,
|
||||||
|
__LINE__);
|
||||||
|
|
||||||
|
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/start/", L"unique2/unique3/",
|
||||||
|
vars, __LINE__);
|
||||||
|
|
||||||
if (!pushd(wcs2string(wd).c_str())) return;
|
if (!pushd(wcs2string(wd).c_str())) return;
|
||||||
perform_one_autosuggestion_cd_test(L"cd 0", L"foobar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd 0", L"foobar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"0", L"foobar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd \"0", L"foobar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd '0", L"foobar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd '0", L"foobar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd 1", L"foo bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd 1", L"foo bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"1", L"foo bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd \"1", L"foo bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd '1", L"foo bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd '1", L"foo bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd 2", L"foo bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd 2", L"foo bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"2", L"foo bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd \"2", L"foo bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd '2", L"foo bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd '2", L"foo bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd 3", L"foo\\bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd 3", L"foo\\bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"3", L"foo\\bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd \"3", L"foo\\bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd '3", L"foo\\bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd '3", L"foo\\bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd 4", L"foo'bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd 4", L"foo'bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"4", L"foo'bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd \"4", L"foo'bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd '4", L"foo'bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd '4", L"foo'bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd 5", L"foo\"bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd 5", L"foo\"bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd \"5", L"foo\"bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd \"5", L"foo\"bar/", vars, __LINE__);
|
||||||
perform_one_autosuggestion_cd_test(L"cd '5", L"foo\"bar/", __LINE__);
|
perform_one_autosuggestion_cd_test(L"cd '5", L"foo\"bar/", vars, __LINE__);
|
||||||
|
|
||||||
// A single quote should defeat tilde expansion.
|
// A single quote should defeat tilde expansion.
|
||||||
perform_one_autosuggestion_cd_test(L"cd '~/test_autosuggest_suggest_specia'", L"<error>",
|
perform_one_autosuggestion_cd_test(L"cd '~/test_autosuggest_suggest_specia'", L"<error>", vars,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
|
|
||||||
// Don't crash on ~ (issue #2696). Note this is cwd dependent.
|
// Don't crash on ~ (issue #2696). Note this is cwd dependent.
|
||||||
if (system("mkdir -p '~hahaha/path1/path2/'")) err(L"mkdir failed");
|
if (system("mkdir -p '~hahaha/path1/path2/'")) err(L"mkdir failed");
|
||||||
perform_one_autosuggestion_cd_test(L"cd ~haha", L"ha/path1/path2/", __LINE__);
|
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/", __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 ~haha", L"ha/", __LINE__);
|
||||||
perform_one_completion_cd_test(L"cd ~hahaha/", L"path1/", __LINE__);
|
perform_one_completion_cd_test(L"cd ~hahaha/", L"path1/", __LINE__);
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ bool is_potential_path(const wcstring &potential_path_fragment, const wcstring_l
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
wcstring path_with_magic(potential_path_fragment);
|
wcstring path_with_magic(potential_path_fragment);
|
||||||
if (flags & PATH_EXPAND_TILDE) expand_tilde(path_with_magic);
|
if (flags & PATH_EXPAND_TILDE) expand_tilde(path_with_magic, vars);
|
||||||
|
|
||||||
// debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
|
// debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,8 @@ static const struct block_lookup_entry block_lookup[] = {
|
||||||
{(block_type_t)0, 0, 0}};
|
{(block_type_t)0, 0, 0}};
|
||||||
|
|
||||||
// Given a file path, return something nicer. Currently we just "unexpand" tildes.
|
// Given a file path, return something nicer. Currently we just "unexpand" tildes.
|
||||||
static wcstring user_presentable_path(const wcstring &path) {
|
wcstring parser_t::user_presentable_path(const wcstring &path) const {
|
||||||
return replace_home_directory_with_tilde(path);
|
return replace_home_directory_with_tilde(path, vars());
|
||||||
}
|
}
|
||||||
|
|
||||||
parser_t::parser_t() : variables(env_stack_t::principal()) {}
|
parser_t::parser_t() : variables(env_stack_t::principal()) {}
|
||||||
|
|
|
@ -199,6 +199,9 @@ class parser_t {
|
||||||
/// every block if it is of type FUNCTION_CALL.
|
/// every block if it is of type FUNCTION_CALL.
|
||||||
const wchar_t *is_function(size_t idx = 0) const;
|
const wchar_t *is_function(size_t idx = 0) const;
|
||||||
|
|
||||||
|
// Given a file path, return something nicer. Currently we just "unexpand" tildes.
|
||||||
|
wcstring user_presentable_path(const wcstring &path) const;
|
||||||
|
|
||||||
/// Helper for stack_trace().
|
/// Helper for stack_trace().
|
||||||
void stack_trace_internal(size_t block_idx, wcstring *out) const;
|
void stack_trace_internal(size_t block_idx, wcstring *out) const;
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,7 @@ maybe_t<wcstring> path_get_cdpath(const wcstring &dir, const wcstring &wd,
|
||||||
// TODO: if next_path starts with ./ we need to replace the . with the wd.
|
// TODO: if next_path starts with ./ we need to replace the . with the wd.
|
||||||
next_path = wd;
|
next_path = wd;
|
||||||
}
|
}
|
||||||
expand_tilde(next_path);
|
expand_tilde(next_path, env_vars);
|
||||||
if (next_path.empty()) continue;
|
if (next_path.empty()) continue;
|
||||||
|
|
||||||
wcstring whole_path = next_path;
|
wcstring whole_path = next_path;
|
||||||
|
@ -213,7 +213,7 @@ maybe_t<wcstring> path_get_cdpath(const wcstring &dir, const wcstring &wd,
|
||||||
maybe_t<wcstring> path_as_implicit_cd(const wcstring &path, const wcstring &wd,
|
maybe_t<wcstring> path_as_implicit_cd(const wcstring &path, const wcstring &wd,
|
||||||
const environment_t &vars) {
|
const environment_t &vars) {
|
||||||
wcstring exp_path = path;
|
wcstring exp_path = path;
|
||||||
expand_tilde(exp_path);
|
expand_tilde(exp_path, vars);
|
||||||
if (string_prefixes_string(L"/", exp_path) || string_prefixes_string(L"./", exp_path) ||
|
if (string_prefixes_string(L"/", exp_path) || string_prefixes_string(L"./", exp_path) ||
|
||||||
string_prefixes_string(L"../", exp_path) || string_suffixes_string(L"/", exp_path) ||
|
string_prefixes_string(L"../", exp_path) || string_suffixes_string(L"/", exp_path) ||
|
||||||
exp_path == L"..") {
|
exp_path == L"..") {
|
||||||
|
|
|
@ -400,6 +400,9 @@ class reader_data_t {
|
||||||
/// Return the variable set used for e.g. command duration.
|
/// Return the variable set used for e.g. command duration.
|
||||||
env_stack_t &vars() { return parser_t::principal_parser().vars(); }
|
env_stack_t &vars() { return parser_t::principal_parser().vars(); }
|
||||||
|
|
||||||
|
/// Hackish access to the parser. TODO: rationalize this.
|
||||||
|
parser_t &parser() { return parser_t::principal_parser(); }
|
||||||
|
|
||||||
const env_stack_t &vars() const { return parser_t::principal_parser().vars(); }
|
const env_stack_t &vars() const { return parser_t::principal_parser().vars(); }
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
@ -829,7 +832,8 @@ void reader_write_title(const wcstring &cmd, bool reset_cursor_position) {
|
||||||
|
|
||||||
wcstring_list_t lst;
|
wcstring_list_t lst;
|
||||||
proc_push_interactive(0);
|
proc_push_interactive(0);
|
||||||
if (exec_subshell(fish_title_command, lst, false /* ignore exit status */) != -1 &&
|
if (exec_subshell(fish_title_command, current_data()->parser(), lst,
|
||||||
|
false /* ignore exit status */) != -1 &&
|
||||||
!lst.empty()) {
|
!lst.empty()) {
|
||||||
fputws(L"\x1B]0;", stdout);
|
fputws(L"\x1B]0;", stdout);
|
||||||
for (size_t i = 0; i < lst.size(); i++) {
|
for (size_t i = 0; i < lst.size(); i++) {
|
||||||
|
@ -867,7 +871,8 @@ static void exec_prompt() {
|
||||||
// Prepend any mode indicator to the left prompt (issue #1988).
|
// Prepend any mode indicator to the left prompt (issue #1988).
|
||||||
if (function_exists(MODE_PROMPT_FUNCTION_NAME)) {
|
if (function_exists(MODE_PROMPT_FUNCTION_NAME)) {
|
||||||
wcstring_list_t mode_indicator_list;
|
wcstring_list_t mode_indicator_list;
|
||||||
exec_subshell(MODE_PROMPT_FUNCTION_NAME, mode_indicator_list, apply_exit_status);
|
exec_subshell(MODE_PROMPT_FUNCTION_NAME, data->parser(), mode_indicator_list,
|
||||||
|
apply_exit_status);
|
||||||
// We do not support multiple lines in the mode indicator, so just concatenate all of
|
// We do not support multiple lines in the mode indicator, so just concatenate all of
|
||||||
// them.
|
// them.
|
||||||
for (size_t i = 0; i < mode_indicator_list.size(); i++) {
|
for (size_t i = 0; i < mode_indicator_list.size(); i++) {
|
||||||
|
@ -878,7 +883,7 @@ static void exec_prompt() {
|
||||||
if (!data->left_prompt.empty()) {
|
if (!data->left_prompt.empty()) {
|
||||||
wcstring_list_t prompt_list;
|
wcstring_list_t prompt_list;
|
||||||
// Ignore return status.
|
// Ignore return status.
|
||||||
exec_subshell(data->left_prompt, prompt_list, apply_exit_status);
|
exec_subshell(data->left_prompt, data->parser(), prompt_list, apply_exit_status);
|
||||||
for (size_t i = 0; i < prompt_list.size(); i++) {
|
for (size_t i = 0; i < prompt_list.size(); i++) {
|
||||||
if (i > 0) data->left_prompt_buff += L'\n';
|
if (i > 0) data->left_prompt_buff += L'\n';
|
||||||
data->left_prompt_buff += prompt_list.at(i);
|
data->left_prompt_buff += prompt_list.at(i);
|
||||||
|
@ -888,7 +893,7 @@ static void exec_prompt() {
|
||||||
if (!data->right_prompt.empty()) {
|
if (!data->right_prompt.empty()) {
|
||||||
wcstring_list_t prompt_list;
|
wcstring_list_t prompt_list;
|
||||||
// Status is ignored.
|
// Status is ignored.
|
||||||
exec_subshell(data->right_prompt, prompt_list, apply_exit_status);
|
exec_subshell(data->right_prompt, data->parser(), prompt_list, apply_exit_status);
|
||||||
for (size_t i = 0; i < prompt_list.size(); i++) {
|
for (size_t i = 0; i < prompt_list.size(); i++) {
|
||||||
// Right prompt does not support multiple lines, so just concatenate all of them.
|
// Right prompt does not support multiple lines, so just concatenate all of them.
|
||||||
data->right_prompt_buff += prompt_list.at(i);
|
data->right_prompt_buff += prompt_list.at(i);
|
||||||
|
@ -2155,9 +2160,9 @@ void reader_import_history_if_necessary() {
|
||||||
// Try opening a bash file. We make an effort to respect $HISTFILE; this isn't very complete
|
// 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
|
// (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.
|
// itself. But this is better than nothing.
|
||||||
const auto var = env_get(L"HISTFILE");
|
const auto var = data->vars().get(L"HISTFILE");
|
||||||
wcstring path = (var ? var->as_string() : L"~/.bash_history");
|
wcstring path = (var ? var->as_string() : L"~/.bash_history");
|
||||||
expand_tilde(path);
|
expand_tilde(path, data->vars());
|
||||||
FILE *f = wfopen(path, "r");
|
FILE *f = wfopen(path, "r");
|
||||||
if (f) {
|
if (f) {
|
||||||
data->history->populate_from_bash(f);
|
data->history->populate_from_bash(f);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user