mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-24 12:35:44 +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 "env.h"
|
||||
#include "exec.h"
|
||||
#include "parser.h"
|
||||
#include "wutil.h" // IWYU pragma: keep
|
||||
|
||||
/// 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 (really_load && !script_source.empty()) {
|
||||
// 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) {
|
||||
|
|
|
@ -169,7 +169,7 @@ wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t
|
|||
wcstring out;
|
||||
const wcstring name_esc = escape_string(name, 1);
|
||||
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++) {
|
||||
out.append(lst.at(i));
|
||||
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);
|
||||
|
||||
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) {
|
||||
streams.err.append(output);
|
||||
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);
|
||||
if (cached_entry == condition_cache.end()) {
|
||||
// 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;
|
||||
} else {
|
||||
// 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
|
||||
// systems with a large set of manuals, but it should be ok since apropos is only called once.
|
||||
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;
|
||||
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.
|
||||
if (!setup_child_process(0, all_ios)) {
|
||||
// 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";
|
||||
if (shlvl_var) {
|
||||
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;
|
||||
}
|
||||
|
||||
static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst, bool apply_exit_status,
|
||||
bool is_subcmd) {
|
||||
static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, wcstring_list_t *lst,
|
||||
bool apply_exit_status, bool is_subcmd) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
bool prev_subshell = is_subshell;
|
||||
const int prev_status = proc_get_last_status();
|
||||
bool split_output = false;
|
||||
|
||||
const auto ifs = env_get(L"IFS");
|
||||
const auto ifs = parser.vars().get(L"IFS");
|
||||
if (!ifs.missing_or_empty()) {
|
||||
split_output = true;
|
||||
}
|
||||
|
@ -1163,13 +1163,13 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst, boo
|
|||
return subcommand_status;
|
||||
}
|
||||
|
||||
int exec_subshell(const wcstring &cmd, std::vector<wcstring> &outputs, bool apply_exit_status,
|
||||
bool is_subcmd) {
|
||||
int exec_subshell(const wcstring &cmd, parser_t &parser, std::vector<wcstring> &outputs,
|
||||
bool apply_exit_status, bool is_subcmd) {
|
||||
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();
|
||||
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.
|
||||
///
|
||||
/// \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);
|
||||
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.
|
||||
void exec_close(int fd);
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "iothread.h"
|
||||
#include "parse_constants.h"
|
||||
#include "parse_util.h"
|
||||
#include "parser.h"
|
||||
#include "path.h"
|
||||
#include "proc.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()
|
||||
/// as last_idx instead of string.size()-1.
|
||||
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();
|
||||
|
||||
// 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()));
|
||||
}
|
||||
} else if (var_name != wcstring{VARIABLE_EXPAND_EMPTY}) {
|
||||
var = env_get(var_name);
|
||||
var = vars.get(var_name);
|
||||
}
|
||||
|
||||
// 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.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.
|
||||
res.append(join_strings(var_item_list, delimit));
|
||||
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 {
|
||||
// Normal cartesian-product expansion.
|
||||
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(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;
|
||||
}
|
||||
}
|
||||
|
@ -637,7 +638,10 @@ static bool expand_cmdsubst(const wcstring &input, std::vector<completion_t> *ou
|
|||
|
||||
wcstring_list_t sub_res;
|
||||
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,
|
||||
L"Unknown error while evaulating command substitution");
|
||||
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.
|
||||
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) {
|
||||
size_t 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;
|
||||
if (username.empty()) {
|
||||
// Current users home directory.
|
||||
auto home_var = env_get(L"HOME");
|
||||
auto home_var = vars.get(L"HOME");
|
||||
if (home_var.missing_or_empty()) {
|
||||
input.clear();
|
||||
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.
|
||||
const wcstring &tmp = input;
|
||||
if (!tmp.empty() && tmp.at(0) == L'~') {
|
||||
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
|
||||
// with the tilde. If it does not, there's nothing to do.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
// 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.
|
||||
wcstring result = str;
|
||||
if (string_prefixes_string(L"/", result)) {
|
||||
wcstring home_directory = L"~";
|
||||
expand_tilde(home_directory);
|
||||
expand_tilde(home_directory, vars);
|
||||
if (!string_suffixes_string(L"/", home_directory)) {
|
||||
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));
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -946,7 +951,7 @@ static expand_error_t expand_stage_home_and_self(wcstring input, std::vector<com
|
|||
parse_error_list_t *errors) {
|
||||
(void)errors;
|
||||
if (!(EXPAND_SKIP_HOME_DIRECTORIES & flags)) {
|
||||
expand_home_directory(input);
|
||||
expand_home_directory(input, vars);
|
||||
}
|
||||
expand_percent_self(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) {
|
||||
// Hack to un-expand tildes (see #647).
|
||||
if (!(flags & EXPAND_SKIP_HOME_DIRECTORIES)) {
|
||||
unexpand_tildes(input, &completions);
|
||||
unexpand_tildes(input, vars, &completions);
|
||||
}
|
||||
out_completions->insert(out_completions->end(),
|
||||
std::make_move_iterator(completions.begin()),
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "maybe.h"
|
||||
#include "parse_constants.h"
|
||||
|
||||
class environment_t;
|
||||
class env_var_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.
|
||||
///
|
||||
/// \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.
|
||||
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,
|
||||
/// none() if not.
|
||||
|
|
|
@ -1502,11 +1502,17 @@ static void test_lru() {
|
|||
|
||||
/// A crappy environment_t that only knows about PWD.
|
||||
struct pwd_environment_t : public environment_t {
|
||||
std::map<wcstring, wcstring> extras;
|
||||
|
||||
virtual maybe_t<env_var_t> get(const wcstring &key,
|
||||
env_mode_flags_t mode = ENV_DEFAULT) const override {
|
||||
if (key == L"PWD") {
|
||||
return env_var_t{wgetcwd(), 0};
|
||||
}
|
||||
auto extra = extras.find(key);
|
||||
if (extra != extras.end()) {
|
||||
return env_var_t(extra->second, ENV_DEFAULT);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -2620,9 +2626,9 @@ static void test_completion_insertions() {
|
|||
}
|
||||
|
||||
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;
|
||||
complete(command, &comps, COMPLETION_REQUEST_AUTOSUGGESTION, pwd_environment_t{});
|
||||
complete(command, &comps, COMPLETION_REQUEST_AUTOSUGGESTION, vars);
|
||||
|
||||
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
|
||||
// backslashes.
|
||||
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/1foo 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";
|
||||
|
||||
perform_one_autosuggestion_cd_test(L"cd test/autosuggest_test/0", L"foobar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd \"test/autosuggest_test/0", L"foobar/", __LINE__);
|
||||
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__);
|
||||
pwd_environment_t vars{};
|
||||
vars.extras[L"HOME"] = parser_t::principal_parser().vars().get(L"HOME")->as_string();
|
||||
|
||||
vars.set_one(L"AUTOSUGGEST_TEST_LOC", ENV_LOCAL, wd);
|
||||
perform_one_autosuggestion_cd_test(L"cd $AUTOSUGGEST_TEST_LOC/0", L"foobar/", __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/start/", L"unique2/unique3/",
|
||||
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/0", L"foobar/", vars, __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/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__);
|
||||
|
||||
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;
|
||||
perform_one_autosuggestion_cd_test(L"cd 0", L"foobar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd \"0", L"foobar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd '0", L"foobar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd 1", L"foo bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd \"1", L"foo bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd '1", L"foo bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd 2", L"foo bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd \"2", L"foo bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd '2", L"foo bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd 3", L"foo\\bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd \"3", L"foo\\bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd '3", L"foo\\bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd 4", L"foo'bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd \"4", L"foo'bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd '4", L"foo'bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd 5", L"foo\"bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd \"5", L"foo\"bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd '5", L"foo\"bar/", __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd 0", L"foobar/", vars, __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd \"0", L"foobar/", vars, __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd '0", L"foobar/", vars, __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/", vars, __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/", vars, __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/", vars, __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/", vars, __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/", vars, __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/", vars, __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/", vars, __LINE__);
|
||||
perform_one_autosuggestion_cd_test(L"cd '5", L"foo\"bar/", vars, __LINE__);
|
||||
|
||||
// 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__);
|
||||
|
||||
// Don't crash on ~ (issue #2696). Note this is cwd dependent.
|
||||
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 ~hahaha/", L"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/", vars, __LINE__);
|
||||
perform_one_completion_cd_test(L"cd ~haha", L"ha/", __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;
|
||||
|
||||
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 );
|
||||
|
||||
|
|
|
@ -96,8 +96,8 @@ static const struct block_lookup_entry block_lookup[] = {
|
|||
{(block_type_t)0, 0, 0}};
|
||||
|
||||
// Given a file path, return something nicer. Currently we just "unexpand" tildes.
|
||||
static wcstring user_presentable_path(const wcstring &path) {
|
||||
return replace_home_directory_with_tilde(path);
|
||||
wcstring parser_t::user_presentable_path(const wcstring &path) const {
|
||||
return replace_home_directory_with_tilde(path, vars());
|
||||
}
|
||||
|
||||
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.
|
||||
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().
|
||||
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.
|
||||
next_path = wd;
|
||||
}
|
||||
expand_tilde(next_path);
|
||||
expand_tilde(next_path, env_vars);
|
||||
if (next_path.empty()) continue;
|
||||
|
||||
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,
|
||||
const environment_t &vars) {
|
||||
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) ||
|
||||
string_prefixes_string(L"../", exp_path) || string_suffixes_string(L"/", exp_path) ||
|
||||
exp_path == L"..") {
|
||||
|
|
|
@ -400,6 +400,9 @@ class reader_data_t {
|
|||
/// Return the variable set used for e.g. command duration.
|
||||
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(); }
|
||||
|
||||
/// Constructor
|
||||
|
@ -829,7 +832,8 @@ void reader_write_title(const wcstring &cmd, bool reset_cursor_position) {
|
|||
|
||||
wcstring_list_t lst;
|
||||
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()) {
|
||||
fputws(L"\x1B]0;", stdout);
|
||||
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).
|
||||
if (function_exists(MODE_PROMPT_FUNCTION_NAME)) {
|
||||
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
|
||||
// them.
|
||||
for (size_t i = 0; i < mode_indicator_list.size(); i++) {
|
||||
|
@ -878,7 +883,7 @@ static void exec_prompt() {
|
|||
if (!data->left_prompt.empty()) {
|
||||
wcstring_list_t prompt_list;
|
||||
// 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++) {
|
||||
if (i > 0) data->left_prompt_buff += L'\n';
|
||||
data->left_prompt_buff += prompt_list.at(i);
|
||||
|
@ -888,7 +893,7 @@ static void exec_prompt() {
|
|||
if (!data->right_prompt.empty()) {
|
||||
wcstring_list_t prompt_list;
|
||||
// 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++) {
|
||||
// Right prompt does not support multiple lines, so just concatenate all of them.
|
||||
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
|
||||
// (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 auto var = env_get(L"HISTFILE");
|
||||
const auto var = data->vars().get(L"HISTFILE");
|
||||
wcstring path = (var ? var->as_string() : L"~/.bash_history");
|
||||
expand_tilde(path);
|
||||
expand_tilde(path, data->vars());
|
||||
FILE *f = wfopen(path, "r");
|
||||
if (f) {
|
||||
data->history->populate_from_bash(f);
|
||||
|
|
Loading…
Reference in New Issue
Block a user