summaryrefslogtreecommitdiff
path: root/dotfiles/system/.zsh/modules/Test/D04parameter.ztst
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles/system/.zsh/modules/Test/D04parameter.ztst')
-rw-r--r--dotfiles/system/.zsh/modules/Test/D04parameter.ztst2058
1 files changed, 2058 insertions, 0 deletions
diff --git a/dotfiles/system/.zsh/modules/Test/D04parameter.ztst b/dotfiles/system/.zsh/modules/Test/D04parameter.ztst
new file mode 100644
index 0000000..9128c3c
--- /dev/null
+++ b/dotfiles/system/.zsh/modules/Test/D04parameter.ztst
@@ -0,0 +1,2058 @@
+# Test parameter expansion. Phew.
+# (By the way, did I say "phew"?)
+
+%prep
+
+ mkdir parameter.tmp
+
+ cd parameter.tmp
+
+ touch boringfile evenmoreboringfile
+
+%test
+
+ foo='the first parameter'
+ bar='the second parameter'
+ print -l $foo ${bar}
+0:Basic scalar parameter substitution
+>the first parameter
+>the second parameter
+
+ array1=(the first array)
+ array2=(the second array)
+ print -l $array1 ${array2}
+0:Basic array parameter substitution
+>the
+>first
+>array
+>the
+>second
+>array
+
+ setopt ksharrays
+ print -l $array1 ${array2}
+ unsetopt ksharrays
+0:Basic ksharray substitution
+>the
+>the
+
+ setopt shwordsplit
+ print -l $foo ${bar}
+ print -l ${==bar}
+ unsetopt shwordsplit
+0:Basic shwordsplit option handling
+>the
+>first
+>parameter
+>the
+>second
+>parameter
+>the second parameter
+
+ print $+foo ${+foo} $+notappearinginthistest ${+notappearinginthistest}
+0:$+...
+>1 1 0 0
+
+ x=()
+ print ${+x} ${+x[1]} ${+x[(r)foo]} ${+x[(r)bar]}
+ x=(foo)
+ print ${+x} ${+x[1]} ${+x[(r)foo]} ${+x[(r)bar]}
+0:$+... with arrays
+>1 0 0 0
+>1 1 1 0
+
+ set1=set1v
+ null1=
+ print ${set1:-set1d} ${set1-set2d} ${null1:-null1d} ${null1-null2d} x
+ print ${unset1:-unset1d} ${unset1-unset2d} x
+0:${...:-...} and ${...-...}
+>set1v set1v null1d x
+>unset1d unset2d x
+
+ set2=irrelevant
+ print ${set1:=set1d} ${set2::=set2d}
+ print $set2
+ wasnull1=
+ wasnull2=
+ print ${wasnull1=wasnull1d} ${wasnull2:=wasnull2d}
+ print $wasnull1 $wasnull2
+0:${...:=...}, ${...::=...}, ${...=...}
+>set1v set2d
+>set2d
+>wasnull2d
+>wasnull2d
+
+ unset array
+ print ${#${(A)=array=word}}
+0:${#${(A)=array=word}} counts array elements
+>1
+
+ (print ${set1:?okhere}; print ${unset1:?exiting1}; print not reached;)
+ (print ${null1?okhere}; print ${null1:?exiting2}; print not reached;)
+1:${...:?...}, ${...?...}
+>set1v
+>
+?(eval):1: unset1: exiting1
+?(eval):2: null1: exiting2
+
+ PROMPT="" $ZTST_testdir/../Src/zsh -fis <<<'
+ unsetopt PROMPT_SP
+ PS1="" PS2="" PS3="" PS4="" RPS1="" RPS2=""
+ exec 2>&1
+ foo() {
+ print ${1:?no arguments given}
+ print not reached
+ }
+ foo
+ print reached
+ ' 2>/dev/null
+0:interactive shell returns to top level on ${...?...} error
+*>*foo:1: 1: no arguments given
+>reached
+
+ print ${set1:+word1} ${set1+word2} ${null1:+word3} ${null1+word4}
+ print ${unset1:+word5} ${unset1+word6}
+0:${...:+...}, ${...+...}
+>word1 word2 word4
+>
+
+ str1='This is very boring indeed.'
+ print ${str1#*s}
+ print ${str1##*s}
+ print $str1##s
+0:${...#...}, ${...##...}
+> is very boring indeed.
+> very boring indeed.
+>This is very boring indeed.##s
+
+ str2='If you'\''re reading this you should go and fix some bugs instead.'
+ print ${str2%d*}
+ print ${str2%%d*}
+0:${...%...}, ${...%%...}
+>If you're reading this you should go and fix some bugs instea
+>If you're rea
+
+ str1='does match'
+ str2='does not match'
+ print ${str1:#does * match}
+ print ${str2:#does * match}
+0:${...:#...}
+>does match
+>
+
+ array1=(arthur boldly claws dogs every fight)
+ print ${array1:#[aeiou]*}
+ print ${(M)array1:#[aeiou]*}
+0:${...:#...}, ${(M)...:#...} with array
+>boldly claws dogs fight
+>arthur every
+
+ str1="$array1"
+ print ${str1/[aeiou]*g/a braw bricht moonlicht nicht the nic}
+ print ${(S)str1/[aeiou]*g/relishe}
+0:scalar ${.../.../...}, ${(S).../.../...}
+>a braw bricht moonlicht nicht the nicht
+>relishes every fight
+
+ print ${array1/[aeiou]*/Y}
+ print ${(S)array1/[aeiou]*/Y}
+0:array ${.../.../...}, ${(S).../.../...}
+>Y bY clY dY Y fY
+>Yrthur bYldly clYws dYgs Yvery fYght
+
+ str1='o this is so, so so very dull'
+ print ${str1//o*/Please no}
+ print ${(S)str1//o*/Please no}
+0:scalar ${...//.../...}, ${(S)...//.../...}
+>Please no
+>Please no this is sPlease no, sPlease no sPlease no very dull
+
+ print ${array1//[aeiou]*/Y}
+ print ${(S)array1//[aeiou]*/Y}
+0:array ${...//.../...}, ${(S)...//.../...}
+>Y bY clY dY Y fY
+>YrthYr bYldly clYws dYgs YvYry fYght
+
+ print ${array1:/[aeiou]*/expletive deleted}
+0:array ${...:/...}
+>expletive deleted boldly claws dogs expletive deleted fight
+
+ str1='a\string\with\backslashes'
+ str2='a/string/with/slashes'
+ print "${str1//\\/-}"
+ print ${str1//\\/-}
+ print "${str2//\//-}"
+ print ${str2//\//-}
+0:use of backslashes in //-substitutions
+>a-string-with-backslashes
+>a-string-with-backslashes
+>a-string-with-slashes
+>a-string-with-slashes
+
+ args=('one' '#foo' '(bar' "'three'" two)
+ mod=('#foo' '(bar' "'three'" sir_not_appearing_in_this_film)
+ print ${args:|mod}
+ print ${args:*mod}
+ print "${(@)args:|mod}"
+ print "${(@)args:*mod}"
+ args=(two words)
+ mod=('one word' 'two words')
+ print "${args:|mod}"
+ print "${args:*mod}"
+ scalar='two words'
+ print ${scalar:|mod}
+ print ${scalar:*mod}
+ print ${args:*nonexistent}
+ empty=
+ print ${args:*empty}
+0:"|" array exclusion and "*" array intersection
+>one two
+>#foo (bar 'three'
+>one two
+>#foo (bar 'three'
+>
+>two words
+>
+>two words
+>
+>
+
+ str1='twocubed'
+ array=(the number of protons in an oxygen nucleus)
+ print $#str1 ${#str1} "$#str1 ${#str1}" $#array ${#array} "$#array ${#array}"
+0:${#...}, $#...
+>8 8 8 8 8 8 8 8
+
+ set 1 2 3 4 5 6 7 8 9
+ print ${##}
+ set 1 2 3 4 5 6 7 8 9 10
+ print ${##}
+ print ${##""}
+ print ${##1}
+ print ${##2}
+ print ${###<->} # oh, for pete's sake...
+0:${##} is length of $#, and other tales of hash horror
+>1
+>2
+>10
+>0
+>10
+>
+
+ array=(once bitten twice shy)
+ print IF${array}THEN
+ print IF${^array}THEN
+0:basic ${^...}
+>IFonce bitten twice shyTHEN
+>IFonceTHEN IFbittenTHEN IFtwiceTHEN IFshyTHEN
+
+ # Quote ${array} here because {...,...} doesn't like unquoted spaces.
+ print IF{"${array}",THEN}ELSE
+ print IF{${^array},THEN}ELSE
+0:combined ${^...} and {...,...}
+>IFonce bitten twice shyELSE IFTHENELSE
+>IFonceELSE IFTHENELSE IFbittenELSE IFTHENELSE IFtwiceELSE IFTHENELSE IFshyELSE IFTHENELSE
+
+ str1='one word'
+ print -l $str1 ${=str1} "split ${=str1}wise"
+0:${=...}
+>one word
+>one
+>word
+>split one
+>wordwise
+
+ str1='*'
+ print $str1 ${~str1} $~str1
+ setopt globsubst
+ print $str1
+ unsetopt globsubst
+0:${~...} and globsubst
+>* boringfile evenmoreboringfile boringfile evenmoreboringfile
+>boringfile evenmoreboringfile
+
+# The following tests a bug where globsubst didn't preserve
+# backslashes when printing out the original string.
+ str1='\\*\\'
+ (
+ setopt globsubst nonomatch
+ [[ \\\\ = $str1 ]] && print -r '\\ matched by' $str1
+ [[ \\foo\\ = $str1 ]] && print -r '\\foo matched by' $str1
+ [[ a\\b\\ = $str1 ]] || print -r 'a\\b not matched by' $str1
+ )
+0:globsubst with backslashes
+>\\ matched by \\*\\
+>\\foo matched by \\*\\
+>a\\b not matched by \\*\\
+
+ (
+ setopt globsubst
+ foo="boring*"
+ print ${foo+$foo}
+ print ${foo+"$foo"}
+ print ${~foo+"$foo"}
+ )
+0:globsubst together with nested quoted expansion
+>boringfile
+>boring*
+>boringfile
+
+ print -l "${$(print one word)}" "${=$(print two words)}"
+0:splitting of $(...) inside ${...}
+>one word
+>two
+>words
+
+ (setopt shwordsplit # ensure this doesn't get set in main shell...
+ test_splitting ()
+ {
+ array="one two three"
+ for e in $array; do
+ echo "'$e'"
+ done
+ }
+ test_split_var=
+ echo _${test_split_var:=$(test_splitting)}_
+ echo "_${test_split_var}_")
+0:SH_WORD_SPLIT inside $(...) inside ${...}
+>_'one' 'two' 'three'_
+>_'one'
+>'two'
+>'three'_
+
+ print -l "${(f)$(print first line\\nsecond line\\nthird line)}"
+0:${(f)$(...)}
+>first line
+>second line
+>third line
+
+ array1=( uno )
+ print -l ${(A)newarray=splitting by numbers}
+ print -l ${(t)newarray}
+ print -l ${(A)=newarray::=splitting by spaces, actually}
+ print -l ${(t)newarray}
+ print -l ${(A)newarray::=$array1}
+ print -l ${(t)newarray}
+ print -l ${newarray::=$array1}
+ print -l ${(t)newarray}
+ print -l ${newarray::=$array2}
+ print -l ${(t)newarray}
+0:${(A)...=...}, ${(A)...::=...}, ${scalar=$array}
+>splitting by numbers
+>array
+>splitting
+>by
+>spaces,
+>actually
+>array
+>uno
+>array
+>uno
+>scalar
+>the second array
+>scalar
+
+ newarray=("split me" "split me" "I\'m yours")
+ print -l "${(@)newarray}"
+0:"${(@)...}"
+>split me
+>split me
+>I'm yours
+
+ foo='$(print Howzat usay)'
+ print -l ${(e)foo}
+0:${(e)...}
+>Howzat
+>usay
+
+ foo='`print Howzat usay`'
+ print -l ${(e)foo}
+0:Regress ${(e)...} with backticks (see zsh-workers/15871)
+>Howzat
+>usay
+
+ foo='\u65\123'
+ print -r ${(g:o:)foo}
+ foo='\u65\0123^X\C-x'
+ print -r ${(g::)foo}
+ foo='^X'
+ bar='\C-\130'
+ [[ ${(g:c:)foo} == ${(g:oe:)bar} ]]
+ echo $?
+0:${(g)...}
+>eS
+>eS^X\C-x
+>0
+
+ foo='I'\''m nearly out of my mind with tedium'
+ bar=foo
+ print ${(P)bar}
+0:${(P)...}
+>I'm nearly out of my mind with tedium
+#' deconfuse emacs
+
+ foo=(I could be watching that programme I recorded)
+ print ${(o)foo}
+ print ${(oi)foo}
+ print ${(O)foo}
+ print ${(Oi)foo}
+0:${(o)...}, ${(O)...}
+>I I be could programme recorded that watching
+>be could I I programme recorded that watching
+>watching that recorded programme could be I I
+>watching that recorded programme I I could be
+
+ foo=(yOU KNOW, THE ONE WITH wILLIAM dALRYMPLE)
+ bar=(doing that tour of India.)
+ print ${(L)foo}
+ print ${(U)bar}
+0:${(L)...}, ${(U)...}
+>you know, the one with william dalrymple
+>DOING THAT TOUR OF INDIA.
+
+ foo='instead here I am stuck by the computer'
+ print ${(C)foo}
+0:${(C)...}
+>Instead Here I Am Stuck By The Computer
+
+ foo=$'\x7f\x00'
+ print -r -- ${(V)foo}
+0:${(V)...}
+>^?^@
+
+ foo='playing '\''stupid'\'' "games" \w\i\t\h $quoting.'
+ print -r ${(q)foo}
+ print -r ${(qq)foo}
+ print -r ${(qqq)foo}
+ print -r ${(qqqq)foo}
+ print -r ${(q-)foo}
+0:${(q...)...}
+>playing\ \'stupid\'\ \"games\"\ \\w\\i\\t\\h\ \$quoting.
+>'playing '\''stupid'\'' "games" \w\i\t\h $quoting.'
+>"playing 'stupid' \"games\" \\w\\i\\t\\h \$quoting."
+>$'playing \'stupid\' "games" \\w\\i\\t\\h $quoting.'
+>'playing '\'stupid\'' "games" \w\i\t\h $quoting.'
+
+ print -r ${(qqqq):-""}
+0:workers/36551: literal empty string in ${(qqqq)...}
+>$''
+
+ x=( a '' '\b' 'c d' '$e' )
+ print -r ${(q)x}
+ print -r ${(q-)x}
+0:Another ${(q...)...} test
+>a '' \\b c\ d \$e
+>a '' '\b' 'c d' '$e'
+
+ print -r -- ${(q-):-foo}
+ print -r -- ${(q-):-foo bar}
+ print -r -- ${(q-):-"*(.)"}
+ print -r -- ${(q-):-"wow 'this is cool' or is it?"}
+ print -r -- ${(q-):-"no-it's-not"}
+0:${(q-)...} minimal single quoting
+>foo
+>'foo bar'
+>'*(.)'
+>'wow '\''this is cool'\'' or is it?'
+>no-it\'s-not
+
+ foo="'and now' \"even the pubs\" \\a\\r\\e shut."
+ print -r ${(Q)foo}
+0:${(Q)...}
+>and now even the pubs are shut.
+
+ foo="X$'\x41'$'\x42'Y"
+ print -r ${(Q)foo}
+0:${(Q)...} with handling of $'...'
+>XABY
+
+ # The following may look a bit random.
+ # For the split we are checking that anything that
+ # would normally be followed by a different word has
+ # an argument break after it and anything that wouldn't doesn't.
+ # For the (Q) we are simply checking that nothing disappears
+ # in the parsing.
+ foo='<five> {six} (seven) >eight< }nine{ |forty-two| $many$ )ten( more'
+ array=(${(z)foo})
+ print -l ${(Q)array}
+0:${(z)...} and ${(Q)...} for some hard to parse cases
+><
+>five
+>>
+>{six}
+>(
+>seven
+>)
+>>
+>eight
+><
+>}nine{
+>|
+>forty-two
+>|
+>$many$
+>)
+>ten( more
+
+ strings=(
+ 'foo=(1 2 3)'
+ '(( 3 + 1 == 8 / 2 ))'
+ 'for (( i = 1 ; i < 10 ; i++ ))'
+ '((0.25542 * 60) - 15)*60'
+ 'repeat 3 (x)'
+ 'repeat 3 (echo foo; echo bar)'
+ 'repeat $(( 2 + 4 )) (x)'
+ 'repeat $( : foo bar; echo 4) (x)'
+ 'repeat "1"'\''2'\''$(( 3 + 0 ))$((echo 4);)\ 5 (x)'
+ )
+ for string in $strings; do
+ array=(${(z)string})
+ for (( i = 1; i <= ${#array}; i++ )); do
+ print -r -- "${i}:${array[i]}:"
+ done
+ done
+0:Some syntactical expressions that are hard to split into words with (z).
+>1:foo=(:
+>2:1:
+>3:2:
+>4:3:
+>5:):
+>1:(( 3 + 1 == 8 / 2 )):
+>1:for:
+>2:((:
+# Leading whitespace is removed, because the word proper hasn't started;
+# trailing whitespace is left because the word is terminated by the
+# semicolon or double parentheses. Bit confusing but sort of consistent.
+>3:i = 1 ;:
+>4:i < 10 ;:
+>5:i++ :
+>6:)):
+# This one needs resolving between a math expression and
+# a command, which causes interesting effects internally.
+>1:(:
+>2:(:
+>3:0.25542:
+>4:*:
+>5:60:
+>6:):
+>7:-:
+>8:15:
+>9:):
+>10:*60:
+>1:repeat:
+>2:3:
+>3:(:
+>4:x:
+>5:):
+>1:repeat:
+>2:3:
+>3:(:
+>4:echo:
+>5:foo:
+>6:;:
+>7:echo:
+>8:bar:
+>9:):
+>1:repeat:
+>2:$(( 2 + 4 )):
+>3:(:
+>4:x:
+>5:):
+>1:repeat:
+>2:$( : foo bar; echo 4):
+>3:(:
+>4:x:
+>5:):
+>1:repeat:
+>2:"1"'2'$(( 3 + 0 ))$((echo 4);)\ 5:
+>3:(:
+>4:x:
+>5:):
+
+
+ line=$'A line with # someone\'s comment\nanother line # (1 more\nanother one'
+ print "*** Normal ***"
+ print -l ${(z)line}
+ print "*** Kept ***"
+ print -l ${(Z+c+)line}
+ print "*** Removed ***"
+ print -l ${(Z+C+)line}
+0:Comments with (z)
+>*** Normal ***
+>A
+>line
+>with
+>#
+>someone's comment
+>another line # (1 more
+>another one
+>*** Kept ***
+>A
+>line
+>with
+># someone's comment
+>;
+>another
+>line
+># (1 more
+>;
+>another
+>one
+>*** Removed ***
+>A
+>line
+>with
+>;
+>another
+>line
+>;
+>another
+>one
+
+ line='with comment # at the end'
+ print -l ${(Z+C+)line}
+0:Test we don't get an additional newline token
+>with
+>comment
+
+ line=$'echo one\necho two # with a comment\necho three'
+ print -l ${(Z+nc+)line}
+0:Treating zplit newlines as ordinary whitespace
+>echo
+>one
+>echo
+>two
+># with a comment
+>echo
+>three
+
+ print -rl - ${(z):-":;(( echo 42 "}
+0:${(z)} with incomplete math expressions
+>:
+>;
+>(( echo 42
+
+ # From parse error on it's not possible to split.
+ # Just check we get the complete string.
+ foo='echo $(|||) bar'
+ print -rl ${(z)foo}
+0:$($(z)} with parse error in command substitution.
+>echo
+>$(|||) bar
+
+ psvar=(dog)
+ setopt promptsubst
+ foo='It shouldn'\''t $(happen) to a %1v.'
+ bar='But `echo what can you do\?`'
+ print -r ${(%)foo}
+ print -r ${(%%)bar}
+0:${(%)...}
+>It shouldn't $(happen) to a dog.
+>But what can you do?
+
+ foo='unmatched "'
+ print ${(QX)foo}
+1:${(QX)...}
+?(eval):2: unmatched "
+# " deconfuse emacs
+
+ array=(characters in an array)
+ print ${(c)#array}
+0:${(c)#...}
+>22
+
+ print ${(w)#array}
+ str='colon::bolon::solon'
+ print ${(ws.:.)#str}
+ print ${(Ws.:.)#str}
+0:${(w)...}, ${(W)...}
+>4
+>3
+>5
+
+ typeset -A assoc
+ assoc=(key1 val1 key2 val2)
+ print ${(o)assoc}
+ print ${(ok)assoc}
+ print ${(ov)assoc}
+ print ${(okv)assoc}
+0:${(k)...}, ${(v)...}
+>val1 val2
+>key1 key2
+>val1 val2
+>key1 key2 val1 val2
+
+ word="obfuscatory"
+ print !${(l.16.)word}! +${(r.16.)word}+
+0:simple padding
+>! obfuscatory! +obfuscatory +
+
+ foo=(resulting words uproariously padded)
+ print ${(pl.10..\x22..X.)foo}
+0:${(pl...)...}
+>Xresulting """"Xwords roariously """Xpadded
+#" deconfuse emacs
+
+ print ${(l.5..X.r.5..Y.)foo}
+ print ${(l.6..X.r.4..Y.)foo}
+ print ${(l.7..X.r.3..Y.)foo}
+ print ${(l.6..X..A.r.6..Y..B.)foo}
+ print ${(l.6..X..AROOGA.r.6..Y..BARSOOM.)foo}
+0:simultaneous left and right padding
+>Xresulting XXXwordsYY proariousl XXpaddedYY
+>XXresultin XXXXwordsY uproarious XXXpaddedY
+>XXXresulti XXXXXwords Xuproariou XXXXpadded
+>XAresultingB XXXAwordsBYY uproariously XXApaddedBYY
+>GAresultingB OOGAwordsBAR uproariously OGApaddedBAR
+
+ foo=(why in goodness name am I doing this)
+ print ${(r.5..!..?.)foo}
+0:${(r...)...}
+>why?! in?!! goodn name? am?!! I?!!! doing this?
+
+ array=(I\'m simply putting a brave face on)
+ print ${(j:--:)array}
+0:${(j)...}
+>I'm--simply--putting--a--brave--face--on
+
+ print ${(F)array}
+0:${(F)...}
+>I'm
+>simply
+>putting
+>a
+>brave
+>face
+>on
+
+ string='zometimez zis getz zplit on a z'
+ print -l ${(s?z?)string}
+0:${(s...)...}
+>ometime
+>
+>is get
+>
+>plit on a
+
+ str=s
+ arr=(a)
+ typeset -A ass
+ ass=(a a)
+ integer i
+ float f
+ print ${(t)str} ${(t)arr} ${(t)ass} ${(t)i} ${(t)f}
+0:${(t)...}
+>scalar array association-local integer-local float-local
+
+ # it's not quite clear that these are actually right unless you know
+ # the algorithm: search along the string for the point at which the
+ # first (last) match occurs, for ## (%%), then take the shortest possible
+ # version of that for # (%). it's as good a definition as anything.
+ string='where is the white windmill, whispered walter wisely'
+ print ${(S)string#h*e}
+ print ${(S)string##h*e}
+ print ${(S)string%h*e}
+ print ${(S)string%%h*e}
+0:${(S)...#...} etc.
+>wre is the white windmill, whispered walter wisely
+>wly
+>where is the white windmill, wred walter wisely
+>where is the white windmill, wly
+
+ setopt extendedglob
+ print ${(SI:1:)string##w[^[:space:]]# }
+ print ${(SI:1+1:)string##w[^[:space:]]# }
+ print ${(SI:1+1+1:)string##w[^[:space:]]# }
+ print ${(SI:1+1+1+1:)string##w[^[:space:]]# }
+0:${(I:...:)...}
+>is the white windmill, whispered walter wisely
+>where is the windmill, whispered walter wisely
+>where is the white whispered walter wisely
+>where is the white windmill, walter wisely
+
+ print ${(MSI:1:)string##w[^[:space:]]# }
+0:${(M...)...}
+>where
+
+ print ${(R)string//w[a-z]# #}
+0:${(R)...}
+>is the ,
+
+ # This (1) doesn't work with // or /
+ # (2) perhaps ought to be 18, to be consistent with normal zsh
+ # substring indexing and with backreferences.
+ print ${(BES)string##white}
+0:${(BE...)...}
+>14 19
+
+ print ${(NS)string##white}
+0:${(N)...}
+>5
+
+ string='abcdefghijklmnopqrstuvwxyz'
+ print ${${string%[aeiou]*}/(#m)?(#e)/${(U)MATCH}}
+0:Rule 1: Nested substitutions
+>abcdefghijklmnopqrsT
+
+ array=(et Swann avec cette muflerie intermittente)
+ string="qui reparaissait chez lui"
+ print ${array[4,5]}
+ print ${array[4,5][1]}
+ print ${array[4,5][1][2,3]}
+ print ${string[4,5]}
+ print ${string[4,5][1]}
+0:Rule 2: Parameter subscripting
+>cette muflerie
+>cette
+>et
+> r
+>
+
+ foo=stringalongamax
+ print ${${(P)foo[1,6]}[1,3]}
+0:Rule 3: Parameter Name Replacement
+>qui
+
+ print "${array[5,6]}"
+ print "${(j.:.)array[1,2]}"
+0:Rule 4: Double-Quoted Joining
+>muflerie intermittente
+>et:Swann
+
+ print "${${array}[5,7]}"
+ print "${${(@)array}[1,2]}"
+0:Rule 5: Nested Subscripting
+>wan
+>et Swann
+
+ print "${${(@)array}[1,2]#?}"
+ print "${(@)${(@)array}[1,2]#?}"
+0:Rule 6: Modifiers
+>t Swann
+>t wann
+
+ array=(she sells z shells by the z shore)
+ (IFS='+'; print ${(s.s.)array})
+0:Rule 7: Forced Joining, and 8: Forced splitting
+>he+ ell +z+ hell +by+the+z+ hore
+
+ setopt shwordsplit
+ string='another poxy boring string'
+ print -l ${${string}/o/ }
+ unsetopt shwordsplit
+0:Rule 9: Shell Word Splitting
+>an
+>ther
+>p
+>xy
+>b
+>ring
+>string
+
+ setopt nonomatch
+ foo='b* e*'
+ print ${(e)~foo}
+ print ${(e)~=foo}
+ setopt nomatch
+0:Rule 10: Re-Evaluation
+>b* e*
+>boringfile evenmoreboringfile
+
+ # ${bar} -> $bar here would yield "bad substitution".
+ bar=confinement
+ print ${(el.20..X.)${bar}}
+0:Rule 11: Padding
+>XXXXXXXXXconfinement
+
+ foo=(bar baz)
+ bar=(ax1 bx1)
+ print "${(@)${foo}[1]}"
+ print "${${(@)foo}[1]}"
+ print -l ${(s/x/)bar}
+ print -l ${(j/x/s/x/)bar}
+ print -l ${(s/x/)bar%%1*}
+0:Examples in manual on parameter expansion
+>b
+>bar
+>a
+>1 b
+>1
+>a
+>1
+>b
+>1
+>a
+> b
+
+ set If "this test fails" "we have broken" the shell again
+ print -l ${1+"$@"}
+0:Regression test of ${1+"$@"} bug
+>If
+>this test fails
+>we have broken
+>the
+>shell
+>again
+
+ set If "this test fails" "we have broken" the shell again
+ print -l "${(A)foo::=$@}"
+ print -l ${(t)foo}
+ print -l $foo
+0:Regression test of "${(A)foo=$@}" bug
+>If this test fails we have broken the shell again
+>array
+>If
+>this test fails
+>we have broken
+>the
+>shell
+>again
+
+ local sure_that='sure that' varieties_of='varieties of' one=1 two=2
+ extra=(5 4 3)
+ unset foo
+ set Make $sure_that "this test keeps" on 'preserving all' "$varieties_of" quoted whitespace
+ print -l ${=1+"$@"}
+ print -l ${(A)=foo=Make $sure_that "this test keeps" on 'preserving all' "$varieties_of" quoted whitespace}
+ print ${(t)foo}
+ print -l ${=1+$one $two}
+ print -l ${1+$extra$two$one}
+0:Regression test of ${=1+"$@"} bug and some related expansions
+>Make
+>sure that
+>this test keeps
+>on
+>preserving all
+>varieties of
+>quoted
+>whitespace
+>Make
+>sure
+>that
+>this test keeps
+>on
+>preserving all
+>varieties of
+>quoted
+>whitespace
+>array
+>1
+>2
+>5
+>4
+>321
+
+ splitfn() {
+ emulate -L sh
+ local HOME="/differs from/bash" foo='1 2' bar='3 4'
+ print -l ${1:-~}
+ touch has\ space
+ print -l ${1:-*[ ]*}
+ print -l ${1:-*[\ ]*}
+ print -l ${1:-*}
+ print -l ${1:-"$foo" $bar}
+ print -l ${==1:-$foo $bar}
+ rm has\ space
+ }
+ splitfn
+0:More bourne-shell-compatible nested word-splitting with wildcards and ~
+>/differs from/bash
+>*[
+>]*
+>has space
+>boringfile
+>evenmoreboringfile
+>has space
+>1 2
+>3
+>4
+>1 2 3 4
+
+ splitfn() {
+ local IFS=.-
+ local foo=1-2.3-4
+ #
+ print "Called with argument '$1'"
+ print "No quotes"
+ print -l ${=1:-1-2.3-4} ${=1:-$foo}
+ print "With quotes on default argument only"
+ print -l ${=1:-"1-2.3-4"} ${=1:-"$foo"}
+ }
+ print 'Using "="'
+ splitfn
+ splitfn 5.6-7.8
+ #
+ splitfn() {
+ emulate -L zsh
+ setopt shwordsplit
+ local IFS=.-
+ local foo=1-2.3-4
+ #
+ print "Called with argument '$1'"
+ print "No quotes"
+ print -l ${1:-1-2.3-4} ${1:-$foo}
+ print "With quotes on default argument only"
+ print -l ${1:-"1-2.3-4"} ${1:-"$foo"}
+ }
+ print Using shwordsplit
+ splitfn
+ splitfn 5.6-7.8
+0:Test of nested word splitting with and without quotes
+>Using "="
+>Called with argument ''
+>No quotes
+>1
+>2
+>3
+>4
+>1
+>2
+>3
+>4
+>With quotes on default argument only
+>1-2.3-4
+>1-2.3-4
+>Called with argument '5.6-7.8'
+>No quotes
+>5
+>6
+>7
+>8
+>5
+>6
+>7
+>8
+>With quotes on default argument only
+>5
+>6
+>7
+>8
+>5
+>6
+>7
+>8
+>Using shwordsplit
+>Called with argument ''
+>No quotes
+>1
+>2
+>3
+>4
+>1
+>2
+>3
+>4
+>With quotes on default argument only
+>1-2.3-4
+>1-2.3-4
+>Called with argument '5.6-7.8'
+>No quotes
+>5
+>6
+>7
+>8
+>5
+>6
+>7
+>8
+>With quotes on default argument only
+>5
+>6
+>7
+>8
+>5
+>6
+>7
+>8
+
+# Tests a long-standing bug with joining on metafied characters in IFS
+ (array=(one two three)
+ IFS=$'\0'
+ foo="$array"
+ for (( i = 1; i <= ${#foo}; i++ )); do
+ char=${foo[i]}
+ print $(( #char ))
+ done)
+0:Joining with NULL character from IFS
+>111
+>110
+>101
+>0
+>116
+>119
+>111
+>0
+>116
+>104
+>114
+>101
+>101
+
+ unset SHLVL
+ (( SHLVL++ ))
+ print $SHLVL
+0:Unsetting and recreation of numerical special parameters
+>1
+
+ unset manpath
+ print $+MANPATH
+ manpath=(/here /there)
+ print $MANPATH
+ unset MANPATH
+ print $+manpath
+ MANPATH=/elsewhere:/somewhere
+ print $manpath
+0:Unsetting and recreation of tied special parameters
+>0
+>/here:/there
+>0
+>/elsewhere /somewhere
+
+ local STRING=a:b
+ typeset -T STRING string
+ print $STRING $string
+ unset STRING
+ set -A string x y z
+ print $STRING $string
+ STRING=a:b
+ typeset -T STRING string
+ print $STRING $string
+ unset STRING
+ set -A string x y z
+ print $STRING $string
+ STRING=a:b
+ typeset -T STRING string
+ print $STRING $string
+ unset string
+ STRING=x:y:z
+ print $STRING $string
+ STRING=a:b
+ typeset -T STRING string
+ print $STRING $string
+ unset string
+ STRING=x:y:z
+ print $STRING $string
+0:Unsetting and recreation of tied normal parameters
+>a:b a b
+>x y z
+>a:b a b
+>x y z
+>a:b a b
+>x:y:z
+>a:b a b
+>x:y:z
+
+ typeset -T tied1 tied2 +
+ typeset -T tied2 tied1 +
+1:Attempts to swap tied variables are safe but futile
+?(eval):typeset:2: already tied as non-scalar: tied2
+
+ string='look for a match in here'
+ if [[ ${string%%(#b)(match)*} = "look for a " ]]; then
+ print $match[1] $mbegin[1] $mend[1] $string[$mbegin[1],$mend[1]]
+ print $#match $#mbegin $#mend
+ else
+ print That didn\'t work.
+ fi
+0:Parameters associated with backreferences
+>match 12 16 match
+>1 1 1
+#' deconfuse emacs
+
+ string='and look for a MATCH in here'
+ if [[ ${(S)string%%(#m)M*H} = "and look for a in here" ]]; then
+ print $MATCH $MBEGIN $MEND $string[$MBEGIN,$MEND]
+ print $#MATCH
+ else
+ print Oh, dear. Back to the drawing board.
+ fi
+0:Parameters associated with (#m) flag
+>MATCH 16 20 MATCH
+>5
+
+ string='this is a string'
+ print ${string//(#m)s/$MATCH $MBEGIN $MEND}
+0:(#m) flag with pure string
+>this 4 4 is 7 7 a s 11 11tring
+
+ print ${${~:-*}//(#m)*/$MATCH=$MATCH}
+0:(#m) flag with tokenized input
+>*=*
+
+ print -l JAMES${(u)${=:-$(echo yes yes)}}JOYCE
+ print -l JAMES${(u)${=:-$(echo yes yes she said yes i will yes)}}JOYCE
+0:Bug with (u) flag reducing arrays to one element
+>JAMESyesJOYCE
+>JAMESyes
+>she
+>said
+>i
+>willJOYCE
+
+ print -l JAMES${(u)${=:-$(echo yes yes she said yes i will yes she said she will and yes she did yes)}}JOYCE
+0:New hash seive unique algorithm for arrays of more than 10 elements
+>JAMESyes
+>she
+>said
+>i
+>will
+>and
+>didJOYCE
+
+ foo=
+ print "${${foo}/?*/replacement}"
+0:Quoted zero-length strings are handled properly
+>
+
+ file=aleftkept
+ print ${file//(#b)(*)left/${match/a/andsome}}
+ print ${file//(#b)(*)left/${match//a/andsome}}
+0:Substitutions where $match is itself substituted in the replacement
+>andsomekept
+>andsomekept
+
+ file=/one/two/three/four
+ print ${file:fh}
+ print ${file:F.1.h}
+ print ${file:F+2+h}
+ print ${file:F(3)h}
+ print ${file:F<4>h}
+ print ${file:F{5}h}
+0:Modifiers with repetition
+>/
+>/one/two/three
+>/one/two
+>/one
+>/
+>/
+
+ baz=foo/bar
+ zab=oof+rab
+ print ${baz:s/\//+/}
+ print "${baz:s/\//+/}"
+ print ${zab:s/+/\//}
+ print "${zab:s/+/\//}"
+0:Quoting of separator in substitution modifier
+>foo+bar
+>foo+bar
+>oof/rab
+>oof/rab
+
+ bsbs='X\\\\Y'
+ print -r -- ${bsbs:s/\\/\\/}
+ print -r -- "${bsbs:s/\\/\\/}"
+ print -r -- ${bsbs:s/\\\\/\\\\/}
+ print -r -- "${bsbs:s/\\\\/\\\\/}"
+ print -r -- ${bsbs:gs/\\/\\/}
+ print -r -- "${bsbs:gs/\\/\\/}"
+ print -r -- ${bsbs:gs/\\\\/\\\\/}
+ print -r -- "${bsbs:gs/\\\\/\\\\/}"
+0:Handling of backslashed backslashes in substitution modifier
+>X\\\\Y
+>X\\\\Y
+>X\\\\Y
+>X\\\\Y
+>X\\\\Y
+>X\\\\Y
+>X\\\\Y
+>X\\\\Y
+
+ print -r ${${:-one/two}:s,/,X&Y,}
+ print -r ${${:-one/two}:s,/,X\&Y,}
+ print -r ${${:-one/two}:s,/,X\\&Y,}
+ print -r "${${:-one/two}:s,/,X&Y,}"
+ print -r "${${:-one/two}:s,/,X\&Y,}"
+ print -r "${${:-one/two}:s,/,X\\&Y,}"
+0:Quoting of ampersand in substitution modifier RHS
+>oneX/Ytwo
+>oneX&Ytwo
+>oneX\/Ytwo
+>oneX/Ytwo
+>oneX&Ytwo
+>oneX\/Ytwo
+
+ nully=($'a\0c' $'a\0b\0b' $'a\0b\0a' $'a\0b\0' $'a\0b' $'a\0' $'a')
+ for string in ${(o)nully}; do
+ for (( i = 1; i <= ${#string}; i++ )); do
+ foo=$string[i]
+ printf "%02x" $(( #foo ))
+ done
+ print
+ done
+0:Sorting arrays with embedded nulls
+>61
+>6100
+>610062
+>61006200
+>6100620061
+>6100620062
+>610063
+
+ array=(X)
+ patterns=("*X*" "spong" "a[b")
+ for pat in $patterns; do
+ print A${array[(r)$pat]}B C${array[(I)$pat]}D
+ done
+0:Bad patterns should never match array elements
+>AXB C1D
+>AB C0D
+>AB C0D
+
+ foo=(a6 a117 a17 b6 b117 b17)
+ print ${(n)foo}
+ print ${(On)foo}
+0:Numeric sorting
+>a6 a17 a117 b6 b17 b117
+>b117 b17 b6 a117 a17 a6
+
+ x=sprodj
+ x[-10]=scrumf
+ print $x
+0:Out of range negative scalar subscripts
+>scrumfsprodj
+
+ a=(some sunny day)
+ a[-10]=(we\'ll meet again)
+ print -l $a
+0:Out of range negative array subscripts
+>we'll
+>meet
+>again
+>some
+>sunny
+>day
+
+# ' emacs likes this close quote
+
+ a=(sping spang spong bumble)
+ print ${a[(i)spong]}
+ print ${a[(i)spung]}
+ print ${a[(ib.1.)spong]}
+ print ${a[(ib.4.)spong]}
+ print ${a[(ib.10.)spong]}
+0:In and out of range reverse matched indices without and with b: arrays
+>3
+>5
+>3
+>5
+>5
+
+ a="thrimblewuddlefrong"
+ print ${a[(i)w]}
+ print ${a[(i)x]}
+ print ${a[(ib.3.)w]}
+ print ${a[(ib.10.)w]}
+ print ${a[(ib.30.)w]}
+0:In and out of range reverse matched indices without and with b: strings
+>9
+>20
+>9
+>20
+>20
+
+ foo="line:with::missing::fields:in:it"
+ print -l ${(s.:.)foo}
+0:Removal of empty fields in unquoted splitting
+>line
+>with
+>missing
+>fields
+>in
+>it
+
+ foo="line:with::missing::fields:in:it"
+ print -l "${(s.:.)foo}"
+0:Hacky removal of empty fields in quoted splitting with no "@"
+>line
+>with
+>missing
+>fields
+>in
+>it
+
+ foo="line:with::missing::fields:in:it:"
+ print -l "${(@s.:.)foo}"
+0:Retention of empty fields in quoted splitting with "@"
+>line
+>with
+>
+>missing
+>
+>fields
+>in
+>it
+>
+
+ str=abcd
+ print -l ${(s..)str}
+ print -l "${(s..)str}"
+0:splitting of strings into characters
+>a
+>b
+>c
+>d
+>a
+>b
+>c
+>d
+
+ array=('%' '$' 'j' '*' '$foo')
+ print ${array[(i)*]} "${array[(i)*]}"
+ print ${array[(ie)*]} "${array[(ie)*]}"
+ key='$foo'
+ print ${array[(ie)$key]} "${array[(ie)$key]}"
+ key='*'
+ print ${array[(ie)$key]} "${array[(ie)$key]}"
+0:Matching array indices with and without quoting
+>1 1
+>4 4
+>5 5
+>4 4
+
+# Ordering of associative arrays is arbitrary, so we need to use
+# patterns that only match one element.
+ typeset -A assoc_r
+ assoc_r=(star '*' of '*this*' and '!that!' or '(the|other)')
+ print ${(kv)assoc_r[(re)*]}
+ print ${(kv)assoc_r[(re)*this*]}
+ print ${(kv)assoc_r[(re)!that!]}
+ print ${(kv)assoc_r[(re)(the|other)]}
+ print ${(kv)assoc_r[(r)*at*]}
+ print ${(kv)assoc_r[(r)*(ywis|bliss|kiss|miss|this)*]}
+ print ${(kv)assoc_r[(r)(this|that|\(the\|other\))]}
+0:Reverse subscripting associative arrays with literal matching
+>star *
+>of *this*
+>and !that!
+>or (the|other)
+>and !that!
+>of *this*
+>or (the|other)
+
+ print $ZSH_SUBSHELL
+ (print $ZSH_SUBSHELL)
+ ( (print $ZSH_SUBSHELL) )
+ ( (print $ZSH_SUBSHELL); print $ZSH_SUBSHELL )
+ print $(print $ZSH_SUBSHELL)
+ cat =(print $ZSH_SUBSHELL)
+0:ZSH_SUBSHELL
+>0
+>1
+>2
+>2
+>1
+>1
+>1
+
+ foo=("|" "?")
+ [[ "|" = ${(j.|.)foo} ]] && print yes || print no
+ [[ "|" = ${(j.|.)~foo} ]] && print yes || print no
+ [[ "|" = ${(~j.|.)foo} ]] && print yes || print no
+ [[ "|" = ${(~~j.|.)foo} ]] && print yes || print no
+ [[ "|" = ${(j.|.~)foo} ]] && print yes || print no
+ [[ "x" = ${(j.|.)foo} ]] && print yes || print no
+ [[ "x" = ${(j.|.)~foo} ]] && print yes || print no
+ [[ "x" = ${(~j.|.)foo} ]] && print yes || print no
+ [[ "x" = ${(~~j.|.)foo} ]] && print yes || print no
+ [[ "x" = ${(j.|.~)foo} ]] && print yes || print no
+0:GLOBSUBST only on parameter substitution arguments
+>no
+>yes
+>yes
+>no
+>no
+>no
+>yes
+>no
+>no
+>no
+
+ rcexbug() {
+ emulate -L zsh
+ setopt rcexpandparam
+ local -A hash
+ local -a full empty
+ full=(X x)
+ hash=(X x)
+ print ORDINARY ARRAYS
+ : The following behaves as documented in zshoptions
+ print FULL expand=$full
+ : Empty arrays remove the adjacent argument
+ print EMPTY expand=$empty
+ print ASSOCIATIVE ARRAY
+ print Subscript flags returning many values
+ print FOUND key=$hash[(I)X] val=$hash[(R)x]
+ : This should behave like $empty, and does
+ print LOST key=$hash[(I)y] val=$hash[(R)Y]
+ print Subscript flags returning single values
+ : Doc says "substitutes ... empty string"
+ : so must not behave like an empty array
+ print STRING key=$hash[(i)y] val=$hash[(r)Y]
+ }
+ rcexbug
+0:Lookup failures on elements of arrays with RC_EXPAND_PARAM
+>ORDINARY ARRAYS
+>FULL expand=X expand=x
+>EMPTY
+>ASSOCIATIVE ARRAY
+>Subscript flags returning many values
+>FOUND key=X val=x
+>LOST
+>Subscript flags returning single values
+>STRING key= val=
+
+ print $zsh_eval_context[1]
+ [[ $ZSH_EVAL_CONTEXT = ${(j.:.)zsh_eval_context} ]] || print Not equal!
+ (( icontext = ${#zsh_eval_context} + 1 ))
+ contextfn() { print $(print $zsh_eval_context[icontext,-1]); }
+ contextfn
+0:$ZSH_EVAL_CONTEXT and $zsh_eval_context
+>toplevel
+>shfunc cmdsubst
+
+ foo="123456789"
+ print ${foo:3}
+ print ${foo: 1 + 3}
+ print ${foo:$(( 2 + 3))}
+ print ${foo:$(echo 3 + 3)}
+ print ${foo:3:1}
+ print ${foo: 1 + 3:(4-2)/2}
+ print ${foo:$(( 2 + 3)):$(( 7 - 6 ))}
+ print ${foo:$(echo 3 + 3):`echo 4 - 3`}
+ print ${foo: -1}
+ print ${foo: -10}
+ print ${foo:5:-2}
+0:Bash-style offsets, scalar
+>456789
+>56789
+>6789
+>789
+>4
+>5
+>6
+>7
+>9
+>123456789
+>67
+
+ foo=(1 2 3 4 5 6 7 8 9)
+ print ${foo:3}
+ print ${foo: 1 + 3}
+ print ${foo:$(( 2 + 3))}
+ print ${foo:$(echo 3 + 3)}
+ print ${foo:3:1}
+ print ${foo: 1 + 3:(4-2)/2}
+ print ${foo:$(( 2 + 3)):$(( 7 - 6 ))}
+ print ${foo:$(echo 3 + 3):`echo 4 - 3`}
+ print ${foo: -1}
+ print ${foo: -10}
+ print ${foo:5:-2}
+0:Bash-style offsets, array
+>4 5 6 7 8 9
+>5 6 7 8 9
+>6 7 8 9
+>7 8 9
+>4
+>5
+>6
+>7
+>9
+>1 2 3 4 5 6 7 8 9
+>6 7
+
+ testfn() {
+ emulate -L sh
+ set -A foo 1 2 3
+ set -- 1 2 3
+ str=abc
+ echo ${foo[*]:0:1}
+ echo ${foo[*]:1:1}
+ echo ${foo[*]: -1:1}
+ :
+ echo ${*:0:1}
+ echo ${*:1:1}
+ echo ${*: -1:1}
+ :
+ echo ${str:0:1}
+ echo ${str:1:1}
+ echo ${str: -1:1}
+ }
+ testfn
+0:Bash-style offsets, Bourne-style indexing
+>1
+>2
+>3
+>testfn
+>1
+>3
+>a
+>b
+>c
+
+ printf "%n" '[0]'
+1:Regression test for identifier test
+?(eval):1: not an identifier: [0]
+
+ str=rts
+ print ${str:0:}
+1:Regression test for missing length after offset
+?(eval):2: unrecognized modifier
+
+ foo="123456789"
+ print ${foo:5:-6}
+1:Regression test for total length < 0 in string
+?(eval):2: substring expression: 3 < 5
+
+ foo=(1 2 3 4 5 6 7 8 9)
+ print ${foo:5:-6}
+1:Regression test for total length < 0 in array
+?(eval):2: substring expression: 3 < 5
+
+ foo=(${(0)"$(print -n)"})
+ print ${#foo}
+0:Nularg removed from split empty string
+>0
+
+ (set -- a b c
+ setopt shwordsplit
+ IFS=
+ print -rl "$*"
+ unset IFS
+ print -rl "$*")
+0:Regression test for shwordsplit with null or unset IFS and quoted array
+>abc
+>a b c
+
+ foo=
+ print ${foo:wq}
+ print ${:wq}
+0:Empty parameter should not cause modifiers to crash the shell
+>
+>
+
+# This used to cause uncontrolled behaviour, but at best
+# you got the wrong output so the check is worth it.
+ args() { print $#; }
+ args ${:*}
+ args ${:|}
+0:Intersection and disjunction with empty parameters
+>0
+>0
+
+ foo=(a b c)
+ bar=(1 2 3)
+ print ${foo:^bar}
+ print ${foo:^^bar}
+ foo=(a b c d)
+ bar=(1 2)
+ print ${foo:^bar}
+ print ${foo:^^bar}
+ foo=('a a' b)
+ bar=(1 '2 2')
+ print -l "${foo:^bar}"
+ print -l "${(@)foo:^bar}"
+0:Zipping arrays, correct output
+>a 1 b 2 c 3
+>a 1 b 2 c 3
+>a 1 b 2
+>a 1 b 2 c 1 d 2
+# maybe this should be changed to output "a a b 1"
+>a a b
+>1
+>a a
+>1
+>b
+>2 2
+
+ foo=(a b c)
+ bar=()
+ print ${foo:^bar}
+ print ${foo:^^bar}
+ print ${bar:^foo}
+ print ${bar:^^foo}
+ print ${bar:^bar}
+ print ${bar:^^bar}
+0:Zipping arrays, one or both inputs empty
+>
+>a b c
+>
+>a b c
+>
+>
+
+ foo=text
+ bar=()
+ print ${foo:^bar}
+ print ${bar:^^foo}
+ bar=other
+ print ${foo:^bar}
+ bar=(array elements)
+ print ${foo:^bar}
+ print ${foo:^^bar}
+ print ${bar:^foo}
+ print ${bar:^^foo}
+0:Zipping arrays, scalar input
+>
+>text
+>text other
+>text array
+>text array text elements
+>array text
+>array text elements text
+
+ foo=(a b c)
+ print ${foo:^^^bar}
+1:Zipping arrays, parsing
+?(eval):2: not an identifier: ^bar
+
+ (setopt nounset
+ print ${foo:^noexist})
+1:Zipping arrays, NO_UNSET part 1
+?(eval):2: noexist: parameter not set
+
+ (setopt nounset
+ print ${noexist:^foo})
+1:Zipping arrays, NO_UNSET part 2
+?(eval):2: noexist: parameter not set
+
+ expr="a@b,c@d:e@f,g@h:i@j,k@l"
+ for sep in : , @; do
+ print -l ${(ps.$sep.)expr}
+ done
+0:Use of variable to get separator when splitting parameter
+>a@b,c@d
+>e@f,g@h
+>i@j,k@l
+>a@b
+>c@d:e@f
+>g@h:i@j
+>k@l
+>a
+>b,c
+>d:e
+>f,g
+>h:i
+>j,k
+>l
+
+ SHLVL=1
+ $ZTST_testdir/../Src/zsh -fc 'echo $SHLVL'
+ $ZTST_testdir/../Src/zsh -fc '(echo $SHLVL)'
+0:SHLVL appears sensible when about to exit shell
+>2
+>2
+
+ # SHLVL is incremented twice and decremented once in between.
+ SHLVL=1
+ $ZTST_testdir/../Src/zsh -fc $ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"'
+ $ZTST_testdir/../Src/zsh -fc '('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL")'
+ $ZTST_testdir/../Src/zsh -fc '( ('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"))'
+0:SHLVL decremented upon implicit exec optimisation
+>2
+>2
+>2
+
+ # SHLVL is incremented twice with no decrement in between.
+ SHLVL=1
+ $ZTST_testdir/../Src/zsh -fc '('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit'
+ $ZTST_testdir/../Src/zsh -fc '(exec '$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit'
+ $ZTST_testdir/../Src/zsh -fc '( ('$ZTST_testdir/../Src/zsh' -fc "echo \$SHLVL"); exit)'
+0:SHLVL not decremented upon exec in subshells
+>3
+>3
+>3
+
+# The following tests the return behaviour of parsestr/parsestrnoerr
+ alias param-test-alias='print $'\''\x45xpanded in substitution'\'
+ param='$(param-test-alias)'
+ print ${(e)param}
+0:Alias expansion in command substitution in parameter evaluation
+>Expanded in substitution
+
+ a=1 b=2 c=3
+ : One;
+ function {
+ : Two
+ echo $_
+ print -l $argv
+ } $_ Three
+ print -l $_ Four;
+0:$_ with anonymous function
+>Two
+>One
+>Three
+>Three
+>Four
+
+ a=1 b=2 c=3
+ : One
+ function {
+ : Two
+ echo $_
+ print -l $argv
+ }
+ print -l "$_" Four
+0:$_ with anonymous function without arguments
+>Two
+>
+>
+>Four
+
+ funnychars='The qu*nk br!wan f@x j/mps o[]r \(e la~# ^"&;'
+ [[ $funnychars = ${~${(b)funnychars}} ]]
+0:${(b)...} quoting protects from GLOB_SUBST
+
+ set -- foo
+ echo $(( $#*3 ))
+ emulate sh -c 'nolenwithoutbrace() { echo $#-1; }'
+ nolenwithoutbrace
+0:Avoid confusion after overloaded characters in braceless substitution in sh
+>13
+>0-1
+
+ a="aaa bab cac"
+ b=d
+ echo $a:gs/a/${b}/
+ a=(aaa bab cac)
+ echo $a:gs/a/${b}/
+0:History modifier works the same for scalar and array substitution
+>ddd bdb cdc
+>ddd bdb cdc
+
+ a=1_2_3_4_5_6
+ print ${a#(*_)(#c2)}
+ print ${a#(*_)(#c5)}
+ print ${a#(*_)(#c7)}
+0:Complicated backtracking with match counts
+>3_4_5_6
+>6
+>1_2_3_4_5_6
+
+ (setopt shwordsplit
+ do_test() {
+ print $#: "$@"
+ }
+ foo=bar
+ foo2="bar bar"
+ do_test ${:- foo }
+ do_test ${:- foo bar }
+ do_test ${:- $foo }
+ do_test ${:- $foo2 }
+ do_test x${:- foo }y
+ do_test x${:- foo bar }y
+ do_test x${:- $foo }y
+ do_test x${:- $foo2 }y
+ do_test x${foo:+ $foo }y
+ )
+0:We Love SH_WORD_SPLIT Day celebrated with space at start of internal subst
+>1: foo
+>2: foo bar
+>1: bar
+>2: bar bar
+>3: x foo y
+>4: x foo bar y
+>3: x bar y
+>4: x bar bar y
+>3: x bar y
+
+ (unsetopt shwordsplit # default, for clarity
+ do_test() {
+ print $#: "$@"
+ }
+ foo=bar
+ foo2="bar bar"
+ do_test ${:- foo }
+ do_test ${:- foo bar }
+ do_test ${:- $foo }
+ do_test ${:- $foo2 }
+ do_test x${:- foo }y
+ do_test x${:- foo bar }y
+ do_test x${:- $foo }y
+ do_test x${:- $foo2 }y
+ do_test x${foo:+ $foo }y
+ )
+0:We Love NO_SH_WORD_SPLIT Even More Day celebrated as sanity check
+>1: foo
+>1: foo bar
+>1: bar
+>1: bar bar
+>1: x foo y
+>1: x foo bar y
+>1: x bar y
+>1: x bar bar y
+>1: x bar y
+
+ testfn() {
+ local scalar=obfuscation
+ local -a array=(alpha bravo charlie delta echo foxtrot)
+ local -A assoc=(one eins two zwei three drei four vier)
+ local name subscript
+ for name subscript in scalar 3 array 5 assoc three; do
+ print ${${(P)name}[$subscript]}
+ done
+ }
+ testfn
+0:${(P)...} with normal subscripting
+>f
+>echo
+>drei
+
+ testfn() {
+ local s1=foo s2=bar
+ local -a val=(s1)
+ print ${${(P)val}[1,3]}
+ val=(s1 s2)
+ print ${${(P)val}[1,3]}
+ }
+ testfn
+1:${(P)...} with array as name
+>foo
+?testfn:5: parameter name reference used with array
+
+ testfn() {
+ local -A assoc=(one buckle two show three knock four door)
+ local name='assoc[two]'
+ print ${${(P)name}[2,3]}
+ }
+ testfn
+0:${(P)...} with internal subscripting
+>ho
+
+ testfn() {
+ local one=two
+ local two=three
+ local three=four
+ local -a four=(all these worlds belong to foo)
+ print ${(P)${(P)${(P)one}}}
+ print ${${(P)${(P)${(P)one}}}[3]}
+ }
+ testfn
+0:nested parameter name references
+>all these worlds belong to foo
+>worlds
+
+ (
+ path=(/random /value)
+ testfn1() {
+ local path=
+ print $#path
+ }
+ testfn1
+ testfn2() {
+ local path=/somewhere
+ print $#path $path
+ }
+ testfn2
+ print $#path $path
+ )
+0:Local special variables with loose typing
+>0
+>1 /somewhere
+>2 /random /value
+
+ print -r -- ${(q+):-}
+ print -r -- ${(q+)IFS}
+ print -r -- ${(q+):-oneword}
+ print -r -- ${(q+):-two words}
+ print -r -- ${(q+):-three so-called \'words\'}
+ (setopt rcquotes; print -r -- ${(q+):-three so-called \'words\'})
+0:${(q+)...}
+>''
+>$' \t\n\C-@'
+>oneword
+>'two words'
+>'three so-called '\''words'\'
+>'three so-called ''words'''
+
+ array=(one two three)
+ array[1]=${nonexistent:-foo}
+ print $array
+0:"-" works after "[" in same expression (Dash problem)
+>foo two three
+
+ (
+ setopt shwordsplit
+ set -- whim:wham:whom
+ IFS=:
+ print -l $@
+ )
+0:Splitting of $@ on IFS: single element
+>whim
+>wham
+>whom
+
+ (
+ setopt shwordsplit
+ set -- one:two bucklemy:shoe
+ IFS=:
+ print -l $@
+ )
+0:Splitting of $@ on IFS: multiple elements
+# No forced joining in this case
+>one
+>two
+>bucklemy
+>shoe
+
+ (
+ set -- one:two bucklemy:shoe
+ print -l ${(s.:.)@}
+ )
+0:Splitting of $@ on (s): multiple elements
+# Forced joining in this case
+>one
+>two bucklemy
+>shoe
+
+ (
+ set -- one:two bucklemy:shoe
+ print -l ${(@s.:.)@}
+ )
+0:Splitting of $@ on (@s): multiple elements
+# Forced non-joining in this case
+>one
+>two
+>bucklemy
+>shoe
+
+ (
+ set -- one:two bucklemy:shoe
+ IFS=
+ setopt shwordsplit
+ print -l ${@} ${(s.:.)*} ${(s.:.j.-.)*}
+ )
+0:Joining of $@ does not happen when IFS is empty, but splitting $* does
+>one:two
+>bucklemy:shoe
+>one
+>twobucklemy
+>shoe
+>one
+>two-bucklemy
+>shoe
+
+ (
+ set -- "one two" "bucklemy shoe"
+ IFS=
+ setopt shwordsplit rcexpandparam
+ print -l "X${(@j.-.)*}"
+ )
+0:Use of @ does not prevent forced join with j
+>Xone two-bucklemy shoe
+
+ () { print -r -- "${(q)1}" "${(b)1}" "${(qq)1}" } '=foo'
+0:(q) and (b) quoting deal with the EQUALS option
+>\=foo =foo '=foo'
+
+ args() { print $#; }
+ a=(foo)
+ args "${a[3,-1]}"
+ args "${(@)a[3,-1]}"
+0:Out-of-range multiple array subscripts with quoting, with and without (@)
+>1
+>0
+
+ a='~-/'; echo $~a
+0:Regression: "-" became Dash in workers/37689, breaking ~- expansion
+*>*
+F:We do not care what $OLDPWD is, as long as it doesn't cause an error