Allow erasing in multiple scopes in one go

This commit is contained in:
Mahmoud Al-Qudsi 2022-10-15 16:05:36 -05:00
parent fa932533f2
commit fed64999bc

View File

@ -204,12 +204,15 @@ static int validate_cmd_opts(const wchar_t *cmd, const set_cmd_opts_t &opts, int
return STATUS_INVALID_ARGS; return STATUS_INVALID_ARGS;
} }
// Variables can only have one scope. // Variables can only have one scope...
if (opts.local + opts.function + opts.global + opts.universal > 1) { if (opts.local + opts.function + opts.global + opts.universal > 1) {
// ..unless we are erasing a variable, in which case we can erase from several in one go.
if (!opts.erase) {
streams.err.append_format(BUILTIN_ERR_GLOCAL, cmd); streams.err.append_format(BUILTIN_ERR_GLOCAL, cmd);
builtin_print_error_trailer(parser, streams.err, cmd); builtin_print_error_trailer(parser, streams.err, cmd);
return STATUS_INVALID_ARGS; return STATUS_INVALID_ARGS;
} }
}
// Variables can only have one export status. // Variables can only have one export status.
if (opts.exportv && opts.unexport) { if (opts.exportv && opts.unexport) {
@ -391,7 +394,7 @@ static maybe_t<split_var_t> split_var_and_indexes(const wchar_t *arg, env_mode_f
return res; return res;
} }
/// Given a list of values and 1-based indexes, return a new list, with those elements removed. /// Given a list of values and 1-based indexes, return a new list with those elements removed.
/// Note this deliberately accepts both args by value, as it modifies them both. /// Note this deliberately accepts both args by value, as it modifies them both.
static wcstring_list_t erased_at_indexes(wcstring_list_t input, std::vector<long> indexes) { static wcstring_list_t erased_at_indexes(wcstring_list_t input, std::vector<long> indexes) {
// Sort our indexes into *descending* order. // Sort our indexes into *descending* order.
@ -620,7 +623,11 @@ static int builtin_set_show(const wchar_t *cmd, const set_cmd_opts_t &opts, int
static int builtin_set_erase(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, static int builtin_set_erase(const wchar_t *cmd, set_cmd_opts_t &opts, int argc,
const wchar_t **argv, parser_t &parser, io_streams_t &streams) { const wchar_t **argv, parser_t &parser, io_streams_t &streams) {
int ret = STATUS_CMD_OK; int ret = STATUS_CMD_OK;
env_mode_flags_t scope = compute_scope(opts); env_mode_flags_t scopes = compute_scope(opts);
// `set -e` is allowed to be called with multiple scopes.
for (int bit = 0; 1<<bit <= ENV_USER; ++bit) {
int scope = scopes & 1<<bit;
if (scope == 0 || (scope == ENV_USER && scopes != ENV_USER)) continue;
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
auto split = split_var_and_indexes(argv[i], scope, parser.vars(), streams); auto split = split_var_and_indexes(argv[i], scope, parser.vars(), streams);
if (!split) { if (!split) {
@ -661,6 +668,7 @@ static int builtin_set_erase(const wchar_t *cmd, set_cmd_opts_t &opts, int argc,
warn_if_uvar_shadows_global(cmd, opts, split->varname, streams, parser); warn_if_uvar_shadows_global(cmd, opts, split->varname, streams, parser);
} }
} }
}
return ret; return ret;
} }