def subroutine [$variable ...] command-or-block
Define a new XSH2 sub-routine named subroutine. The subroutine may require zero or more parameters. These are declared as a whitespace-separated list of parametric variables. The body of the subroutine is specified as a command-or-block.
A sub-routine can be invoked directly by its name followed by its arguments just as any XSH2 command, or indirectly using the call command followed by an expression evaluating to the routine name and sub-routine arguments. Sub-routine arguments can be arbitrary expressions. These expressions are evaluated prior the sub-routine's code execution and are assigned to the sub-routine's parametric variables in the respective order. The number of parameter variables in a sub-routine definition and the number of arguments in a call to it must match. Calling a sub-routine with less or more arguments than declared is a run-time error.
Parametric variables are lexical variables within the sub-routine body as if they were declared with my.
Note that a subroutine has to be defined before it is first called (in terms of execution -- depending on the structure of the program, the actual definition of the sub-routine must not necessarily precede all references to it).
def l3 $nodes { ls --depth 3 $nodes; # list given nodes upto depth 3 } l3 //chapter; # direct call $subref = 'l3'; call $subref //chapter; # in-direct call
Example 26. Commenting and un-commenting pieces of document
def comment $n # nodes to move to comments $mark # maybe some handy mark to recognize such comments { foreach $n { if ( . = ../@* ) { echo "Warning: attribute nodes are not supported!"; } else { echo "Commenting out:"; ls --depth 0 .; add comment concat($mark,xsh:serialize(.)) replace .; } } } def uncomment $n $mark { foreach $n { if (. = ../comment()) { # is this node a comment node local $string = substring-after(.,"$mark"); add chunk $string replace .; } else { echo "Warning: Ignoring non-comment node:"; ls --depth 0 .; } } } # comment out all chapters with no paragraphs comment //chapter[not(para)] "COMMENT-NOPARA"; # uncomment all comments stamped with COMMENT-NOPARA $mark="COMMENT-NOPARA"; uncomment //comment()[starts-with(.,"$mark")] $mark;