fish-shell/tests/checks/expansion.fish
Fabian Homborg 29e9f4838a Run parse_util_detect_errors on -c commands
This didn't do all the syntax checks, so something like

    fish -c 'echo foo; and $status'

complained of a missing command `0` (i.e. $status), and

    fish -c 'echo foo | exec grep'

hit an assert!

So we do what read_ni does, parse each command into an ast, run
parse_util_detect_errors on it if it worked and then eval the ast.

It is possible to do this neater by modifying parser::eval, but I
can't find where.
2021-07-27 18:37:20 +02:00

318 lines
6.8 KiB
Fish

# RUN: %fish -C 'set -g fish %fish' %s
# caret position (#5812)
printf '<%s>\n' ($fish -c ' $f[a]' 2>&1)
# CHECK: <fish: Invalid index value>
# CHECK: < $f[a]>
# CHECK: < ^>
printf '<%s>\n' ($fish -c 'if $f[a]; end' 2>&1)
# CHECK: <fish: Invalid index value>
# CHECK: <if $f[a]; end>
# CHECK: < ^>
set a A
set aa AA
set aaa AAA
echo {$aa}a{1,2,3}(for a in 1 2 3; echo $a; end)
#CHECK: AAa11 AAa21 AAa31 AAa12 AAa22 AAa32 AAa13 AAa23 AAa33
# basic expansion test
echo {}
echo {apple}
echo {apple,orange}
#CHECK: {}
#CHECK: {apple}
#CHECK: apple orange
# expansion tests with spaces
echo {apple, orange}
echo { apple, orange, banana }
#CHECK: apple orange
#CHECK: apple orange banana
# expansion with spaces and cartesian products
echo \'{ hello , world }\'
#CHECK: 'hello' 'world'
# expansion with escapes
for phrase in {good\,, beautiful ,morning}
echo -n "$phrase "
end | string trim
for phrase in {goodbye\,,\ cruel\ ,world\n}
echo -n $phrase
end
#CHECK: good, beautiful morning
#CHECK: goodbye, cruel world
# dual expansion cartesian product
echo { alpha, beta }\ {lambda, gamma }, | string replace -r ',$' ''
#CHECK: alpha lambda, beta lambda, alpha gamma, beta gamma
# expansion with subshells
for name in { (echo Meg), (echo Jo) }
echo $name
end
#CHECK: Meg
#CHECK: Jo
# subshells with expansion
for name in (for name in {Beth, Amy}; printf "$name\n"; end)
printf "$name\n"
end
#CHECK: Beth
#CHECK: Amy
echo {{a,b}}
#CHECK: {a} {b}
# Test expansion of variables
# We don't use the test utility function of the same name because we want
# different behavior. Specifically, that the expansion of any variables or
# other strings before we are invoked produce the expected expansion.
function expansion --description 'Prints argument count followed by arguments'
echo (count $argv) $argv
end
set -l foo
expansion "$foo"
expansion $foo
expansion "prefix$foo"
expansion prefix$foo
#CHECK: 1
#CHECK: 0
#CHECK: 1 prefix
#CHECK: 0
expansion "$$foo"
expansion $$foo
expansion "prefix$$foo"
expansion prefix$$foo
#CHECK: 1
#CHECK: 0
#CHECK: 1 prefix
#CHECK: 0
set -l foo ''
expansion "$foo"
expansion $foo
expansion "prefix$foo"
expansion prefix$foo
#CHECK: 1
#CHECK: 1
#CHECK: 1 prefix
#CHECK: 1 prefix
expansion "$$foo"
expansion $$foo
expansion "prefix$$foo"
expansion prefix$$foo
#CHECK: 1
#CHECK: 0
#CHECK: 1 prefix
#CHECK: 0
set -l foo bar
set -l bar
expansion "$$foo"
expansion $$foo
expansion "prefix$$foo"
expansion prefix$$foo
#CHECK: 1
#CHECK: 0
#CHECK: 1 prefix
#CHECK: 0
set -l bar baz
expansion "$$foo"
expansion $$foo
expansion "prefix$$foo"
expansion prefix$$foo
#CHECK: 1 baz
#CHECK: 1 baz
#CHECK: 1 prefixbaz
#CHECK: 1 prefixbaz
set -l bar baz quux
expansion "$$foo"
expansion $$foo
expansion "prefix$$foo"
expansion prefix$$foo
#CHECK: 1 baz quux
#CHECK: 2 baz quux
#CHECK: 1 prefixbaz quux
#CHECK: 2 prefixbaz prefixquux
set -l foo bar fooer fooest
set -l fooer
set -l fooest
expansion "$$foo"
expansion $$foo
expansion "prefix$$foo"
expansion prefix$$foo
#CHECK: 1 baz quux fooer fooest
#CHECK: 2 baz quux
#CHECK: 1 prefixbaz quux fooer fooest
#CHECK: 2 prefixbaz prefixquux
set -l fooer ''
expansion $$foo
expansion prefix$$foo
#CHECK: 3 baz quux
#CHECK: 3 prefixbaz prefixquux prefix
# Slices
set -l foo bar '' fooest
expansion "$$foo"
expansion $$foo
expansion "prefix$$foo"
expansion prefix$$foo
expansion $foo[-5..2] # No result, because the starting index is invalid and we force-reverse.
expansion $foo[-2..-1]
expansion $foo[-10..-5]
expansion (printf '%s\n' $foo)[-5..2]
expansion (printf '%s\n' $foo)[-2..-1]
expansion (printf '%s\n' $foo)[-10..-5]
expansion (echo one)[2..-1]
#CHECK: 1 baz quux fooest
#CHECK: 2 baz quux
#CHECK: 1 prefixbaz quux fooest
#CHECK: 2 prefixbaz prefixquux
#CHECK: 0
#CHECK: 2 fooest
#CHECK: 0
#CHECK: 0
#CHECK: 2 fooest
#CHECK: 0
#CHECK: 0
set -l foo
expansion "$foo[1]"
expansion $foo[1]
expansion "$foo[-1]"
expansion $foo[-1]
expansion "$foo[2]"
expansion $foo[2]
expansion "$foo[1 2]"
expansion $foo[1 2]
expansion "$foo[2 1]"
expansion $foo[2 1]
#CHECK: 1
#CHECK: 0
#CHECK: 1
#CHECK: 0
#CHECK: 1
#CHECK: 0
#CHECK: 1
#CHECK: 0
#CHECK: 1
#CHECK: 0
set -l foo a b c
expansion $foo[17]
expansion $foo[-17]
expansion $foo[17..18]
expansion $foo[4..-2]
#CHECK: 0
#CHECK: 0
#CHECK: 0
#CHECK: 0
set -l foo a
expansion $foo[2..-1]
#CHECK: 0
echo "$foo[d]"
#CHECKERR: {{.*}}expansion.fish (line {{\d+}}): Invalid index value
#CHECKERR: echo "$foo[d]"
#CHECKERR: ^
echo $foo[d]
#CHECKERR: {{.*}}expansion.fish (line {{\d+}}): Invalid index value
#CHECKERR: echo $foo[d]
#CHECKERR: ^
echo ()[1]
# No output
echo ()[d]
#CHECKERR: {{.*}}expansion.fish (line {{\d+}}): Invalid index value
#CHECKERR: echo ()[d]
#CHECKERR: ^
set -l outer out1 out2
set -l inner 1 2
echo $outer[$inner[2]]
#CHECK: out2
echo $outer[$inner[2..1]]
#CHECK: out2 out1
# Percent self
echo %selfNOT NOT%self \%self "%self" '%self'
echo %self | string match -qr '^\\d+$'
#CHECK: %selfNOT NOT%self %self %self %self
echo "All digits: $status"
#CHECK: All digits: 0
set paren ')'
echo $$paren
#CHECKERR: {{.*}}expansion.fish (line {{\d+}}): $) is not a valid variable in fish.
#CHECKERR: echo $$paren
#CHECKERR: ^
# Test tilde expansion
# On OS X, /tmp is symlinked to /private/tmp
# $PWD is our best bet for resolving it
set -l saved $PWD
cd (mktemp -d)
set tmpdir $PWD
cd $saved
mkdir $tmpdir/realhome
ln -s $tmpdir/realhome $tmpdir/linkhome
set expandedtilde (env HOME=$tmpdir/linkhome $fish -c 'echo ~')
if test $expandedtilde != $tmpdir/linkhome
echo '~ expands to' $expandedtilde ' - expected ' $tmpdir/linkhome
end
rm $tmpdir/linkhome
rmdir $tmpdir/realhome
rmdir $tmpdir
# Test path variables
set TEST_DELIMITER one two three
set TEST_DELIMITER_PATH one two three
echo TEST_DELIMITER: $TEST_DELIMITER "$TEST_DELIMITER"
echo TEST_DELIMITER_PATH: $TEST_DELIMITER_PATH "$TEST_DELIMITER_PATH"
#CHECK: TEST_DELIMITER: one two three one two three
#CHECK: TEST_DELIMITER_PATH: one two three one:two:three
set testvar ONE:TWO:THREE
echo "Not a path: $testvar" (count $testvar)
#CHECK: Not a path: ONE:TWO:THREE 1
set --path testvar $testvar
echo "As a path: $testvar" (count $testvar)
#CHECK: As a path: ONE:TWO:THREE 3
set testvar "$testvar:FOUR"
echo "Appended path: $testvar" (count $testvar)
#CHECK: Appended path: ONE:TWO:THREE:FOUR 4
set --unpath testvar $testvar
echo "Back to normal variable: $testvar" (count $testvar)
#CHECK: Back to normal variable: ONE TWO THREE FOUR 4
# Test fatal syntax errors
$fish -c 'echo $,foo'
#CHECKERR: fish: $, is not a valid variable in fish.
#CHECKERR: echo $,foo
#CHECKERR: ^
$fish -c 'echo {'
#CHECKERR: fish: Unexpected end of string, incomplete parameter expansion
#CHECKERR: echo {
#CHECKERR: ^
$fish -c 'echo {}}'
#CHECKERR: fish: Unexpected '}' for unopened brace expansion
#CHECKERR: echo {}}
#CHECKERR: ^
$fish -c 'command (asd)'
#CHECKERR: fish: Command substitutions not allowed
#CHECKERR: command (asd)
#CHECKERR: ^
true