fish-shell/tests/checks/cmdsub.fish
Johannes Altmanninger e40eba3585 Treat text following quoted command substitution as quoted
Commit ec3d3a481 (Support "$(cmd)" command substitution without line
splitting, 2021-07-02) started treating an input string like
"a$()b" as if it were "a"$()"b". Yet, we do not actually insert the
virtual quotes. Instead we just adapted the definition of when quotes
are closed - hence the changes to quote_end().

parse_util_locate_cmdsubst_range() is aware
of the changes to quote_end() but some of its
callers like parse_util_detect_errors_in_argument() and
highlighter_t::color_as_argument() are not.  They split strings at
command substitution boundaries without handling the special quoting
rules. (Only the expansion logic did it right.)

Fix this by handling the special quoting rules inside
parse_util_locate_cmdsubst_range(). This is a bit hacky since it
makes it harder for callers to process some substrings in between
command substitutions, but that's okay because current callers only
care about what's inside the command substitutions.

Fixes #8394
2021-10-30 18:02:10 +02:00

60 lines
1.1 KiB
Fish

#RUN: %fish %s
echo $(echo 1\n2)
# CHECK: 1 2
# Command substitution inside double quotes strips trailing newline.
echo "a$(echo b)c"
# CHECK: abc
# Nesting
echo "$(echo "$(echo a)")"
# CHECK: a
echo "$(echo $(echo b))"
# CHECK: b
echo "$(echo multiple).$(echo command).$(echo substitutions)"
# CHECK: multiple.command.substitutions
test -n "$()" || echo "empty list is interpolated to empty string"
# CHECK: empty list is interpolated to empty string
# Variables in command substitution output are not expanded.
echo "$(echo \~ \$HOME)"
# CHECK: ~ $HOME
echo "$(printf %s 'quoted command substitution multiline output
line 2
line 3
')"
# CHECK: quoted command substitution multiline output
# CHECK: line 2
# CHECK: line 3
echo trim any newlines "$(echo \n\n\n)" after cmdsub
#CHECK: trim any newlines after cmdsub
echo i{1, (echo 2), "$(echo 3)"}
# CHECK: i1 i2 i3
echo "$(echo index\nrange\nexpansion)[2]"
#CHECK: range
echo "$(echo '"')"
#CHECK: "
echo "$(echo $(echo 1) ())"
#CHECK: 1
echo "$(echo 1))"
# CHECK: 1)
echo "($(echo 1))"
# CHECK: (1)
echo "$(echo 1) ( $(echo 2)"
# CHECK: 1 ( 2
echo "$(echo A)B$(echo C)D"(echo E)
# CHECK: ABCDE