%prep mkdir funcdef.tmp cd funcdef.tmp %test fn1() { return 1; } fn2() { fn1 print $? return 2 } fn2 2:Basic status returns from functions >1 fnz() { } false fnz 0:Empty function body resets status fn3() { return 3; } fnstat() { print $?; } fn3 fnstat 0:Status is not reset on non-empty function body >3 function f$$ () { print regress expansion of function names } f$$ 0:Regression test: 'function f$$ () { ... }' >regress expansion of function names function foo () print bar foo 0:Function definition without braces >bar functions -M m1 m1() { (( $# )) } print $(( m1() )) print $(( m1(1) )) print $(( m1(1,2) )) 0:User-defined math functions, argument handling >0 >1 >2 functions -M m2 m2() { integer sum local val for val in $*; do (( sum += $val )) done } print $(( m2(1) )) print $(( m2(1,3+3,4**2) )) 0:User-defined math functions, complex argument handling >1 >23 functions -M m3 1 2 m3() { (( 1 )) } print zero (print $(( m3() ))) print one print $(( m3(1) )) print two print $(( m3(1,2) )) print three (print $(( m3(1,2,3) ))) 1:User-defined math functions, argument checking >zero >one >1 >two >1 >three ?(eval):4: wrong number of arguments: m3() ?(eval):10: wrong number of arguments: m3(1,2,3) functions -M m4 0 0 testmathfunc functions -M m5 0 0 testmathfunc testmathfunc() { if [[ $0 = m4 ]]; then (( 4 )) else (( 5 )) fi } print $(( m4() )) print $(( m5() )) 0:User-defined math functions, multiple interfaces >4 >5 command_not_found_handler() { print "Great News! I've handled the command:" print "$1" print "with arguments:" print -l ${argv[2,-1]} } ACommandWhichHadBetterNotExistOnTheSystem and some "really useful" args 0:Command not found handler, success >Great News! I've handled the command: >ACommandWhichHadBetterNotExistOnTheSystem >with arguments: >and >some >really useful >args # ' deconfuse emacs command_not_found_handler() { print "Your command:" >&2 print "$1" >&2 print "has gone down the tubes. Sorry." >&2 return 1 } ThisCommandDoesNotExistEither 127:Command not found handler, failure ?Your command: ?ThisCommandDoesNotExistEither ?has gone down the tubes. Sorry. ?(eval):7: command not found: ThisCommandDoesNotExistEither local variable=outside print "I am $variable" function { local variable=inside print "I am $variable" } print "I am $variable" () { local variable="inside again" print "I am $variable" } print "I am $variable" 0:Anonymous function scope >I am outside >I am inside >I am outside >I am inside again >I am outside integer i for (( i = 0; i < 10; i++ )); do function { case $i in ([13579]) print $i is odd ;| ([2468]) print $i is even ;| ([2357]) print $i is prime ;; esac }; done 0:Anonymous function with patterns in loop >1 is odd >2 is even >2 is prime >3 is odd >3 is prime >4 is even >5 is odd >5 is prime >6 is even >7 is odd >7 is prime >8 is even >9 is odd echo stuff in file >file.in function { sed 's/stuff/rubbish/' } file.out cat file.out 0:Anonymous function redirection >rubbish in file variable="Do be do" print $variable function { print $variable local variable="Da de da" print $variable function { print $variable local variable="Dum da dum" print $variable } print $variable } print $variable 0:Nested anonymous functions >Do be do >Do be do >Da de da >Da de da >Dum da dum >Da de da >Do be do () (cat $1 $2) <(print process expanded) =(print expanded to file) 0:Process substitution with anonymous functions >process expanded >expanded to file () { print This has arguments $*; } of all sorts; print After the function function { print More stuff $*; } and why not; print Yet more 0:Anonymous function with arguments >This has arguments of all sorts >After the function >More stuff and why not >Yet more fn() { (){ print Anonymous function 1 $*; } with args function { print Anonymous function 2 $*; } with more args print Following bit } functions fn 0:Text representation of anonymous function with arguments >fn () { > () { > print Anonymous function 1 $* > } with args > () { > print Anonymous function 2 $* > } with more args > print Following bit >} touch yes no () { echo $1 } (y|z)* (echo here) () { echo $* } some (y|z)* () { echo empty };(echo here) 0:Anonymous function arguments and command arguments >yes >here >some yes >empty >here if true; then f() { echo foo1; } else f() { echo bar1; } fi; f if false; then f() { echo foo2; } else f() { echo bar2; } fi; f 0:Compatibility with other shells when not anonymous functions >foo1 >bar2 ( setopt ignorebraces fpath=(.) print "{ echo OK }\n[[ -o ignorebraces ]] || print 'ignorebraces is off'" \ >emufunctest (autoload -z emufunctest; emufunctest) 2>&1 emulate zsh -c 'autoload -Uz emufunctest' emufunctest [[ -o ignorebraces ]] && print 'ignorebraces is still on here' ) 0:sticky emulation applies to autoloads and autoloaded function execution >emufunctest:3: parse error near `\n' >OK >ignorebraces is off >ignorebraces is still on here #` (matching error message for editors parsing the file) # lsfoo should not be expanded as an anonymous function argument alias lsfoo='This is not ls.' () (echo anon func; echo "$@") lsfoo 0:Anonmous function with arguments in a form nobody sane would ever use but unfortunately we have to support anyway >anon func >lsfoo print foo | () cat 0:Simple anonymous function should not simplify enclosing pipeline >foo alias fooalias=barexpansion funcwithalias() { echo $(fooalias); } functions funcwithalias barexpansion() { print This is the correct output.; } funcwithalias 0:Alias expanded in command substitution does not appear expanded in text >funcwithalias () { > echo $(fooalias) >} >This is the correct output. %clean rm -f file.in file.out