mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-03-15 23:22:53 +08:00
Join variables by their delimiter in quoted expansion
This switches quoted expansion like "$foo" to use foo's delimiter instead of space. The delimiter is space for normal variables and colonf or path variables. Expansions like "$PATH" will now expand using ':'.
This commit is contained in:
parent
3f3b3a7006
commit
5947aa0171
@ -1898,7 +1898,18 @@ wcstring_list_t split_string(const wcstring &val, wchar_t sep) {
|
||||
}
|
||||
|
||||
wcstring join_strings(const wcstring_list_t &vals, wchar_t sep) {
|
||||
if (vals.empty()) return wcstring{};
|
||||
|
||||
// Reserve the size we will need.
|
||||
// count-1 separators, plus the length of all strings.
|
||||
size_t size = vals.size() - 1;
|
||||
for (const wcstring &s : vals) {
|
||||
size += s.size();
|
||||
}
|
||||
|
||||
// Construct the string.
|
||||
wcstring result;
|
||||
result.reserve(size);
|
||||
bool first = true;
|
||||
for (const wcstring &s : vals) {
|
||||
if (!first) {
|
||||
|
@ -1302,10 +1302,13 @@ int env_remove(const wcstring &key, int var_mode) {
|
||||
|
||||
const wcstring_list_t &env_var_t::as_list() const { return vals; }
|
||||
|
||||
wchar_t env_var_t::get_delimiter() const {
|
||||
return is_pathvar() ? PATH_ARRAY_SEP : NONPATH_ARRAY_SEP;
|
||||
}
|
||||
|
||||
/// Return a string representation of the var.
|
||||
wcstring env_var_t::as_string() const {
|
||||
wchar_t sep = is_pathvar() ? PATH_ARRAY_SEP : NONPATH_ARRAY_SEP;
|
||||
return join_strings(vals, sep);
|
||||
return join_strings(vals, get_delimiter());
|
||||
}
|
||||
|
||||
void env_var_t::to_list(wcstring_list_t &out) const {
|
||||
|
@ -101,6 +101,9 @@ class env_var_t {
|
||||
void to_list(wcstring_list_t &out) const;
|
||||
const wcstring_list_t &as_list() const;
|
||||
|
||||
/// \return the character used when delimiting quoted expansion.
|
||||
wchar_t get_delimiter() const;
|
||||
|
||||
void set_vals(wcstring_list_t v) { vals = std::move(v); }
|
||||
|
||||
void set_exports(bool exportv) {
|
||||
|
@ -447,6 +447,9 @@ static bool expand_variables(wcstring instr, std::vector<completion_t> *out, siz
|
||||
}
|
||||
|
||||
if (is_single) {
|
||||
// Quoted expansion. Here we expect the variable's delimiter.
|
||||
// Note history always has a space delimiter.
|
||||
wchar_t delimit = history ? L' ' : var->get_delimiter();
|
||||
wcstring res(instr, 0, varexp_char_idx);
|
||||
if (!res.empty()) {
|
||||
if (res.back() != VARIABLE_EXPAND_SINGLE) {
|
||||
@ -457,15 +460,8 @@ static bool expand_variables(wcstring instr, std::vector<completion_t> *out, siz
|
||||
}
|
||||
}
|
||||
|
||||
// Append all entries in var_item_list, separated by spaces.
|
||||
// Remove the last space.
|
||||
if (!var_item_list.empty()) {
|
||||
for (const wcstring &item : var_item_list) {
|
||||
res.append(item);
|
||||
res.push_back(L' ');
|
||||
}
|
||||
res.pop_back();
|
||||
}
|
||||
// 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);
|
||||
} else {
|
||||
|
@ -19,3 +19,6 @@ echo $$paren
|
||||
|
||||
####################
|
||||
# Test tilde expansion
|
||||
|
||||
####################
|
||||
# Test delimiters
|
||||
|
@ -126,3 +126,8 @@ end
|
||||
unlink $tmpdir/linkhome
|
||||
rmdir $tmpdir/realhome
|
||||
rmdir $tmpdir
|
||||
|
||||
logmsg Test delimiters
|
||||
set TEST_DELIMITER one two three
|
||||
set TEST_DELIMITER_PATH one two three
|
||||
echo "$TEST_DELIMITER" "$TEST_DELIMITER_PATH"
|
||||
|
@ -73,3 +73,7 @@ All digits: 0
|
||||
|
||||
####################
|
||||
# Test tilde expansion
|
||||
|
||||
####################
|
||||
# Test delimiters
|
||||
one two three one:two:three
|
||||
|
@ -306,8 +306,9 @@ set -gx FOOPATH one two three four
|
||||
../test/root/bin/fish -c 'echo Elements in FOO and FOOPATH: (count $FOO) (count $FOOPATH)'
|
||||
# some must use colon separators!
|
||||
set -lx MANPATH man1 man2 man3 ; env | grep '^MANPATH='
|
||||
# ensure we don't escape colon values
|
||||
# ensure we don't escape space and colon values
|
||||
set -x DONT_ESCAPE_COLONS 1: 2: :3: ; env | grep '^DONT_ESCAPE_COLONS='
|
||||
|
||||
set -x DONT_ESCAPE_SPACES '1 ' '2 ' ' 3 ' 4 ; env | grep '^DONT_ESCAPE_SPACES='
|
||||
set -x DONT_ESCAPE_COLONS_PATH 1: 2: :3: ; env | grep '^DONT_ESCAPE_COLONS_PATH='
|
||||
|
||||
true
|
||||
|
@ -44,3 +44,5 @@ Elements in DISPLAY: 1
|
||||
Elements in FOO and FOOPATH: 1 4
|
||||
MANPATH=man1:man2:man3
|
||||
DONT_ESCAPE_COLONS=1: 2: :3:
|
||||
DONT_ESCAPE_SPACES=1 2 3 4
|
||||
DONT_ESCAPE_COLONS_PATH=1::2:::3:
|
||||
|
Loading…
x
Reference in New Issue
Block a user