mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-22 10:57:30 +08:00
Add set --no-event
This allows running `set` without triggering any event handlers. That is useful, for example, if you want to set a variable in an event handler for that variable - we could do it, for example, in the fish_user_path or fish_key_bindings handlers. This is something the `block` builtin was supposed to be for, but it never really worked because it only allows suppressing the event for the duration, they would fire later. See #9030. Because it is possible to abuse this, we only have a long-option so that people see what is up.
This commit is contained in:
parent
403920e9d6
commit
f1e19884fb
|
@ -9,7 +9,7 @@ Synopsis
|
|||
.. synopsis::
|
||||
|
||||
set
|
||||
set (-f | --function) (-l | --local) (-g | --global) (-U | --universal)
|
||||
set (-f | --function) (-l | --local) (-g | --global) (-U | --universal) [--no-event]
|
||||
set [-Uflg] NAME [VALUE ...]
|
||||
set [-Uflg] NAME[[INDEX ...]] [VALUE ...]
|
||||
set (-a | --append) [-flgU] NAME VALUE ...
|
||||
|
@ -102,6 +102,11 @@ Further options:
|
|||
It shows the scopes the given variables are set in, along with the values in each and whether or not it is exported.
|
||||
No other flags can be used with this option.
|
||||
|
||||
**--no-event**
|
||||
Don't generate a variable change event when setting or erasing a variable.
|
||||
We recommend using this carefully because the event handlers are usually set up for a reason.
|
||||
Possible uses include modifying the variable inside a variable handler.
|
||||
|
||||
**-L** or **--long**
|
||||
Do not abbreviate long values when printing set variables.
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ struct Options {
|
|||
append: bool,
|
||||
prepend: bool,
|
||||
preserve_failure_exit_status: bool,
|
||||
no_event: bool,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
|
@ -65,6 +66,7 @@ impl Default for Options {
|
|||
append: false,
|
||||
prepend: false,
|
||||
preserve_failure_exit_status: true,
|
||||
no_event: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +100,7 @@ impl Options {
|
|||
/// Values used for long-only options.
|
||||
const PATH_ARG: char = 1 as char;
|
||||
const UNPATH_ARG: char = 2 as char;
|
||||
const NO_EVENT_ARG: char = 3 as char;
|
||||
// Variables used for parsing the argument list. This command is atypical in using the "+"
|
||||
// (REQUIRE_ORDER) option for flag parsing. This is not typical of most fish commands. It means
|
||||
// we stop scanning for flags when the first non-flag argument is seen.
|
||||
|
@ -118,6 +121,7 @@ impl Options {
|
|||
wopt(L!("prepend"), NoArgument, 'p'),
|
||||
wopt(L!("path"), NoArgument, PATH_ARG),
|
||||
wopt(L!("unpath"), NoArgument, UNPATH_ARG),
|
||||
wopt(L!("no-event"), NoArgument, NO_EVENT_ARG),
|
||||
wopt(L!("help"), NoArgument, 'h'),
|
||||
];
|
||||
|
||||
|
@ -148,6 +152,7 @@ impl Options {
|
|||
'u' => opts.unexport = true,
|
||||
PATH_ARG => opts.pathvar = true,
|
||||
UNPATH_ARG => opts.unpathvar = true,
|
||||
NO_EVENT_ARG => opts.no_event = true,
|
||||
'U' => opts.universal = true,
|
||||
'L' => opts.shorten_ok = false,
|
||||
'S' => {
|
||||
|
@ -341,13 +346,18 @@ fn handle_env_return(retval: EnvStackSetResult, cmd: &wstr, key: &wstr, streams:
|
|||
/// description of the problem to stderr.
|
||||
fn env_set_reporting_errors(
|
||||
cmd: &wstr,
|
||||
opts: &Options,
|
||||
key: &wstr,
|
||||
scope: EnvMode,
|
||||
list: Vec<WString>,
|
||||
streams: &mut IoStreams,
|
||||
parser: &Parser,
|
||||
) -> EnvStackSetResult {
|
||||
let retval = parser.set_var_and_fire(key, scope | EnvMode::USER, list);
|
||||
let retval = if opts.no_event {
|
||||
parser.set_var(key, scope | EnvMode::USER, list)
|
||||
} else {
|
||||
parser.set_var_and_fire(key, scope | EnvMode::USER, list)
|
||||
};
|
||||
// If this returned OK, the parser already fired the event.
|
||||
handle_env_return(retval, cmd, key, streams);
|
||||
retval
|
||||
|
@ -776,7 +786,7 @@ fn erase(
|
|||
if retval != EnvStackSetResult::ENV_NOT_FOUND {
|
||||
handle_env_return(retval, cmd, split.varname, streams);
|
||||
}
|
||||
if retval == EnvStackSetResult::ENV_OK {
|
||||
if retval == EnvStackSetResult::ENV_OK && !opts.no_event {
|
||||
event::fire(parser, Event::variable_erase(split.varname.to_owned()));
|
||||
}
|
||||
} else {
|
||||
|
@ -785,8 +795,15 @@ fn erase(
|
|||
return STATUS_CMD_ERROR;
|
||||
};
|
||||
let result = erased_at_indexes(var.as_list().to_owned(), split.indexes);
|
||||
retval =
|
||||
env_set_reporting_errors(cmd, split.varname, scope, result, streams, parser);
|
||||
retval = env_set_reporting_errors(
|
||||
cmd,
|
||||
opts,
|
||||
split.varname,
|
||||
scope,
|
||||
result,
|
||||
streams,
|
||||
parser,
|
||||
);
|
||||
}
|
||||
|
||||
// Set $status to the last error value.
|
||||
|
@ -951,7 +968,8 @@ fn set_internal(
|
|||
};
|
||||
|
||||
// Set the value back in the variable stack and fire any events.
|
||||
let retval = env_set_reporting_errors(cmd, split.varname, scope, new_values, streams, parser);
|
||||
let retval =
|
||||
env_set_reporting_errors(cmd, opts, split.varname, scope, new_values, streams, parser);
|
||||
|
||||
if retval == EnvStackSetResult::ENV_OK {
|
||||
warn_if_uvar_shadows_global(cmd, opts, split.varname, streams, parser);
|
||||
|
|
|
@ -805,6 +805,11 @@ impl Parser {
|
|||
res
|
||||
}
|
||||
|
||||
/// Cover of vars().set(), without firing events
|
||||
pub fn set_var(&self, key: &wstr, mode: EnvMode, vals: Vec<WString>) -> EnvStackSetResult {
|
||||
self.vars().set(key, mode, vals)
|
||||
}
|
||||
|
||||
/// Update any universal variables and send event handlers.
|
||||
/// If `always` is set, then do it even if we have no pending changes (that is, look for
|
||||
/// changes from other fish instances); otherwise only sync if this instance has changed uvars.
|
||||
|
|
|
@ -965,4 +965,33 @@ set -e undefined[..1]
|
|||
set -l negative_oob 1 2 3
|
||||
set -q negative_oob[-10..1]
|
||||
|
||||
# --no-event
|
||||
|
||||
function onevent --on-variable nonevent
|
||||
echo ONEVENT $argv $nonevent
|
||||
end
|
||||
|
||||
set -g nonevent bar
|
||||
set -e nonevent
|
||||
|
||||
# CHECK: ONEVENT VARIABLE SET nonevent bar
|
||||
# CHECK: ONEVENT VARIABLE ERASE nonevent
|
||||
|
||||
set -g --no-event nonevent 2
|
||||
set -e --no-event nonevent
|
||||
set -S nonevent
|
||||
|
||||
set -g --no-event nonevent 3
|
||||
set -e nonevent
|
||||
# CHECK: ONEVENT VARIABLE ERASE nonevent
|
||||
|
||||
set -g nonevent 4
|
||||
# CHECK: ONEVENT VARIABLE SET nonevent 4
|
||||
set -e --no-event nonevent
|
||||
|
||||
set -l nonevent 4
|
||||
set -e nonevent
|
||||
# CHECK: ONEVENT VARIABLE SET nonevent
|
||||
# CHECK: ONEVENT VARIABLE ERASE nonevent
|
||||
|
||||
exit 0
|
||||
|
|
Loading…
Reference in New Issue
Block a user