mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-21 07:35:43 +08:00
Add proper way of storing value for status current-command
There should be no functional changes in this commit. The global variable `$_` set in the parser variables by `reader.cpp` and read by the `status` builtin was deprecated in fish 2.0 but kept around internally because there's no good way to store/share/forward parser variables. A new enum is added that identifies the status variable and they are stored in a private array in the parser. There is no need for synchronization because they are only set during job init and never thereafter. This is currently asserted via ASSERT_IS_MAIN_THREAD() but that assert can be dropped in the interest of making the parser possible to clone and use from worker threads. The old `$_` global variable is still kept for backwards compatibility, though it will be dropped in a future release.
This commit is contained in:
parent
f637fb31b5
commit
e01eb2e615
@ -108,8 +108,12 @@ maybe_t<int> builtin_fg(parser_t &parser, io_streams_t &streams, const wchar_t *
|
||||
}
|
||||
|
||||
wcstring ft = tok_command(job->command());
|
||||
// For compatibility with fish 2.0's $_, now replaced with `status current-command`
|
||||
if (!ft.empty()) parser.set_var_and_fire(L"_", ENV_EXPORT, std::move(ft));
|
||||
if (!ft.empty()) {
|
||||
// Provide value for `status current-command`
|
||||
parser.set_status_var(parser_status_var_t::current_command, ft);
|
||||
// Also provide a value for the deprecated fish 2.0 $_ variable
|
||||
parser.set_var_and_fire(L"_", ENV_EXPORT, std::move(ft));
|
||||
}
|
||||
reader_write_title(job->command(), parser);
|
||||
|
||||
// Note if tty transfer fails, we still try running the job.
|
||||
|
@ -449,10 +449,9 @@ maybe_t<int> builtin_status(parser_t &parser, io_streams_t &streams, const wchar
|
||||
}
|
||||
case STATUS_CURRENT_CMD: {
|
||||
CHECK_FOR_UNEXPECTED_STATUS_ARGS(opts.status_cmd)
|
||||
// HACK: Go via the deprecated variable to get the command.
|
||||
const auto var = parser.vars().get(L"_");
|
||||
if (!var.missing_or_empty()) {
|
||||
streams.out.append(var->as_string());
|
||||
const auto &var = parser.get_status_var(parser_status_var_t::current_command);
|
||||
if (!var.empty()) {
|
||||
streams.out.append(var);
|
||||
streams.out.push_back(L'\n');
|
||||
} else {
|
||||
streams.out.append(program_name);
|
||||
|
19
src/parser.h
19
src/parser.h
@ -244,6 +244,11 @@ struct eval_res_t {
|
||||
: status(status), break_expand(break_expand), was_empty(was_empty), no_status(no_status) {}
|
||||
};
|
||||
|
||||
enum class parser_status_var_t : uint8_t {
|
||||
current_command,
|
||||
count_,
|
||||
};
|
||||
|
||||
class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||
friend class parse_execution_context_t;
|
||||
|
||||
@ -264,6 +269,9 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||
/// top down using range-based for loops.
|
||||
std::deque<block_t> block_list;
|
||||
|
||||
/// Variables set by the single-threaded parser or reader and queryable by any consumer.
|
||||
std::array<wcstring, (int) parser_status_var_t::count_> status_vars_;
|
||||
|
||||
/// The 'depth' of the fish call stack.
|
||||
int eval_level = -1;
|
||||
|
||||
@ -389,6 +397,17 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||
statuses_t get_last_statuses() const { return vars().get_last_statuses(); }
|
||||
void set_last_statuses(statuses_t s) { vars().set_last_statuses(std::move(s)); }
|
||||
|
||||
/// Get a parser status variable
|
||||
const wcstring& get_status_var(parser_status_var_t var) const {
|
||||
return status_vars_.at((int) var);
|
||||
}
|
||||
|
||||
/// Set a parser status variable
|
||||
void set_status_var(parser_status_var_t var, wcstring val) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
status_vars_[(int) var] = std::move(val);
|
||||
}
|
||||
|
||||
/// Cover of vars().set(), which also fires any returned event handlers.
|
||||
/// \return a value like ENV_OK.
|
||||
int set_var_and_fire(const wcstring &key, env_mode_flags_t mode, wcstring val);
|
||||
|
@ -2494,7 +2494,9 @@ static void reader_interactive_init(parser_t &parser) {
|
||||
|
||||
termsize_container_t::shared().invalidate_tty();
|
||||
|
||||
// For compatibility with fish 2.0's $_, now replaced with `status current-command`
|
||||
// Provide value for `status current-command`
|
||||
parser.set_status_var(parser_status_var_t::current_command, L"fish");
|
||||
// Also provide a value for the deprecated fish 2.0 $_ variable
|
||||
parser.vars().set_one(L"_", ENV_GLOBAL, L"fish");
|
||||
}
|
||||
|
||||
@ -2628,8 +2630,12 @@ void reader_data_t::set_buffer_maintaining_pager(const wcstring &b, size_t pos,
|
||||
static eval_res_t reader_run_command(parser_t &parser, const wcstring &cmd) {
|
||||
wcstring ft = tok_command(cmd);
|
||||
|
||||
// For compatibility with fish 2.0's $_, now replaced with `status current-command`
|
||||
if (!ft.empty()) parser.vars().set_one(L"_", ENV_GLOBAL, ft);
|
||||
// Provide values for `status current-command` and `status current-commandline`
|
||||
if (!ft.empty()) {
|
||||
parser.set_status_var(parser_status_var_t::current_command, ft);
|
||||
// Also provide a value for the deprecated fish 2.0 $_ variable
|
||||
parser.vars().set_one(L"_", ENV_GLOBAL, ft);
|
||||
}
|
||||
|
||||
outputter_t &outp = outputter_t::stdoutput();
|
||||
reader_write_title(cmd, parser);
|
||||
@ -2651,7 +2657,9 @@ static eval_res_t reader_run_command(parser_t &parser, const wcstring &cmd) {
|
||||
|
||||
term_steal();
|
||||
|
||||
// For compatibility with fish 2.0's $_, now replaced with `status current-command`
|
||||
// Provide value for `status current-command`
|
||||
parser.set_status_var(parser_status_var_t::current_command, program_name);
|
||||
// Also provide a value for the deprecated fish 2.0 $_ variable
|
||||
parser.vars().set_one(L"_", ENV_GLOBAL, program_name);
|
||||
|
||||
if (have_proc_stat()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user