mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-29 06:13:20 +00:00
builtin set: make slice index range optional, like in slice expansion
Expansion parses slices like "$PATH[1..2]", but so does "set" when assigning
"set PATH[1..2] . .". Commit be06f842a
("Allow to omit indices in index
range expansions") forgot the latter.
This commit is contained in:
parent
ca3d226659
commit
062f24d91b
3 changed files with 42 additions and 18 deletions
|
@ -269,7 +269,8 @@ static bool validate_path_warning_on_colons(const wchar_t *cmd,
|
||||||
// not the (missing) local value. Also don't bother to complain about relative paths, which
|
// not the (missing) local value. Also don't bother to complain about relative paths, which
|
||||||
// don't start with /.
|
// don't start with /.
|
||||||
const auto existing_variable = vars.get(key, ENV_DEFAULT);
|
const auto existing_variable = vars.get(key, ENV_DEFAULT);
|
||||||
const wcstring_list_t &existing_values = existing_variable ? existing_variable->as_list() : wcstring_list_t{};
|
const wcstring_list_t &existing_values =
|
||||||
|
existing_variable ? existing_variable->as_list() : wcstring_list_t{};
|
||||||
|
|
||||||
for (const wcstring &dir : list) {
|
for (const wcstring &dir : list) {
|
||||||
if (!string_prefixes_string(L"/", dir) || contains(existing_values, dir)) {
|
if (!string_prefixes_string(L"/", dir) || contains(existing_values, dir)) {
|
||||||
|
@ -341,8 +342,8 @@ static void handle_env_return(int retval, const wchar_t *cmd, const wchar_t *key
|
||||||
/// Call vars.set. If this is a path variable, e.g. PATH, validate the elements. On error, print a
|
/// Call vars.set. If this is a path variable, e.g. PATH, validate the elements. On error, print a
|
||||||
/// description of the problem to stderr.
|
/// description of the problem to stderr.
|
||||||
static int env_set_reporting_errors(const wchar_t *cmd, const wchar_t *key, int scope,
|
static int env_set_reporting_errors(const wchar_t *cmd, const wchar_t *key, int scope,
|
||||||
wcstring_list_t list, io_streams_t &streams,
|
wcstring_list_t list, io_streams_t &streams, env_stack_t &vars,
|
||||||
env_stack_t &vars, std::vector<event_t> *evts) {
|
std::vector<event_t> *evts) {
|
||||||
if (is_path_variable(key) && !validate_path_warning_on_colons(cmd, key, list, streams, vars)) {
|
if (is_path_variable(key) && !validate_path_warning_on_colons(cmd, key, list, streams, vars)) {
|
||||||
return STATUS_CMD_ERROR;
|
return STATUS_CMD_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -377,23 +378,38 @@ static int parse_index(std::vector<long> &indexes, wchar_t *src, int scope, io_s
|
||||||
|
|
||||||
while (*p != L']') {
|
while (*p != L']') {
|
||||||
const wchar_t *end;
|
const wchar_t *end;
|
||||||
long l_ind = fish_wcstol(p, &end);
|
long l_ind;
|
||||||
if (errno > 0) { // ignore errno == -1 meaning the int did not end with a '\0'
|
if (indexes.empty() && *p == L'.' && p[1] == L'.') {
|
||||||
streams.err.append_format(_(L"%ls: Invalid index starting at '%ls'\n"), L"set", src);
|
// If we are at the first index expression, a missing start-index means the range starts
|
||||||
return -1;
|
// at the first item.
|
||||||
|
l_ind = 1; // first index
|
||||||
|
} else {
|
||||||
|
l_ind = fish_wcstol(p, &end);
|
||||||
|
if (errno > 0) { // ignore errno == -1 meaning the int did not end with a '\0'
|
||||||
|
streams.err.append_format(_(L"%ls: Invalid index starting at '%ls'\n"), L"set",
|
||||||
|
src);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p = const_cast<wchar_t *>(end);
|
||||||
}
|
}
|
||||||
p = const_cast<wchar_t *>(end);
|
|
||||||
|
|
||||||
// Convert negative index to a positive index.
|
// Convert negative index to a positive index.
|
||||||
if (l_ind < 0) l_ind = varsize + l_ind + 1;
|
if (l_ind < 0) l_ind = varsize + l_ind + 1;
|
||||||
|
|
||||||
if (*p == L'.' && *(p + 1) == L'.') {
|
if (*p == L'.' && *(p + 1) == L'.') {
|
||||||
p += 2;
|
p += 2;
|
||||||
long l_ind2 = fish_wcstol(p, &end);
|
long l_ind2;
|
||||||
if (errno > 0) { // ignore errno == -1 meaning the int did not end with a '\0'
|
// If we are at the last index range expression, a missing end-index means the range
|
||||||
return -1;
|
// spans until the last item.
|
||||||
|
if (indexes.empty() && *p == L']') {
|
||||||
|
l_ind2 = -1;
|
||||||
|
} else {
|
||||||
|
l_ind2 = fish_wcstol(p, &end);
|
||||||
|
if (errno > 0) { // ignore errno == -1 meaning the int did not end with a '\0'
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p = const_cast<wchar_t *>(end);
|
||||||
}
|
}
|
||||||
p = const_cast<wchar_t *>(end);
|
|
||||||
|
|
||||||
// Convert negative index to a positive index.
|
// Convert negative index to a positive index.
|
||||||
if (l_ind2 < 0) l_ind2 = varsize + l_ind2 + 1;
|
if (l_ind2 < 0) l_ind2 = varsize + l_ind2 + 1;
|
||||||
|
@ -676,8 +692,8 @@ static int builtin_set_erase(const wchar_t *cmd, set_cmd_opts_t &opts, int argc,
|
||||||
wcstring_list_t result;
|
wcstring_list_t result;
|
||||||
dest_var->to_list(result);
|
dest_var->to_list(result);
|
||||||
erase_values(result, indexes);
|
erase_values(result, indexes);
|
||||||
retval =
|
retval = env_set_reporting_errors(cmd, dest, scope, std::move(result), streams,
|
||||||
env_set_reporting_errors(cmd, dest, scope, std::move(result), streams, parser.vars(), &evts);
|
parser.vars(), &evts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire any events.
|
// Fire any events.
|
||||||
|
@ -800,8 +816,8 @@ static int builtin_set_set(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, w
|
||||||
if (retval != STATUS_CMD_OK) return retval;
|
if (retval != STATUS_CMD_OK) return retval;
|
||||||
|
|
||||||
std::vector<event_t> evts;
|
std::vector<event_t> evts;
|
||||||
retval =
|
retval = env_set_reporting_errors(cmd, varname, scope, std::move(new_values), streams,
|
||||||
env_set_reporting_errors(cmd, varname, scope, std::move(new_values), streams, parser.vars(), &evts);
|
parser.vars(), &evts);
|
||||||
// Fire any events.
|
// Fire any events.
|
||||||
for (const auto &evt : evts) {
|
for (const auto &evt : evts) {
|
||||||
event_fire(parser, evt);
|
event_fire(parser, evt);
|
||||||
|
|
|
@ -206,7 +206,7 @@ static size_t parse_slice(const wchar_t *in, wchar_t **end_ptr, std::vector<long
|
||||||
const wchar_t *end;
|
const wchar_t *end;
|
||||||
long tmp;
|
long tmp;
|
||||||
if (idx.empty() && in[pos] == L'.' && in[pos + 1] == L'.') {
|
if (idx.empty() && in[pos] == L'.' && in[pos + 1] == L'.') {
|
||||||
// If we are at the first index expression, a missing start index means the range starts
|
// If we are at the first index expression, a missing start-index means the range starts
|
||||||
// at the first item.
|
// at the first item.
|
||||||
tmp = 1; // first index
|
tmp = 1; // first index
|
||||||
end = &in[pos];
|
end = &in[pos];
|
||||||
|
@ -229,7 +229,7 @@ static size_t parse_slice(const wchar_t *in, wchar_t **end_ptr, std::vector<long
|
||||||
while (iswspace(in[pos])) pos++; // Allow the space in "[.. ]".
|
while (iswspace(in[pos])) pos++; // Allow the space in "[.. ]".
|
||||||
|
|
||||||
long tmp1;
|
long tmp1;
|
||||||
// Check if we are at the last index range expression, a missing end index means the
|
// If we are at the last index range expression then a missing end-index means the
|
||||||
// range spans until the last item.
|
// range spans until the last item.
|
||||||
if (in[pos] == L']') {
|
if (in[pos] == L']') {
|
||||||
tmp1 = -1; // last index
|
tmp1 = -1; // last index
|
||||||
|
|
|
@ -70,3 +70,11 @@ echo $test[ (true)..3]
|
||||||
#CHECK:
|
#CHECK:
|
||||||
echo $test[ (string join \n 1 2 3)..3 ]
|
echo $test[ (string join \n 1 2 3)..3 ]
|
||||||
#CHECK: 1 2 3 2 3 3
|
#CHECK: 1 2 3 2 3 3
|
||||||
|
|
||||||
|
set -l list 1 2 3
|
||||||
|
set list[..2] $list[2..1]
|
||||||
|
echo $list # CHECK: 2 1 3
|
||||||
|
|
||||||
|
set -l list 1 2 3
|
||||||
|
set list[2..] $list[-1..2]
|
||||||
|
echo $list # CHECK: 1 3 2
|
||||||
|
|
Loading…
Reference in a new issue