calc: Conditionals in Macros
18.2.2 Conditionals in Keyboard Macros
--------------------------------------
The ‘Z [’ (‘calc-kbd-if’) and ‘Z ]’ (‘calc-kbd-end-if’) commands allow
you to put simple tests in a keyboard macro. When Calc sees the ‘Z [’,
it pops an object from the stack and, if the object is a non-zero value,
continues executing keystrokes. But if the object is zero, or if it is
not provably nonzero, Calc skips ahead to the matching ‘Z ]’ keystroke.
Logical Operations, for a set of commands for performing tests
which conveniently produce 1 for true and 0 for false.
For example, ‘<RET> 0 a < Z [ n Z ]’ implements an absolute-value
function in the form of a keyboard macro. This macro duplicates the
number on the top of the stack, pushes zero and compares using ‘a <’
(‘calc-less-than’), then, if the number was less than zero, executes ‘n’
(‘calc-change-sign’). Otherwise, the change-sign command is skipped.
To program this macro, type ‘C-x (’, type the above sequence of
keystrokes, then type ‘C-x )’. Note that the keystrokes will be
executed while you are making the definition as well as when you later
re-execute the macro by typing ‘X’. Thus you should make sure a
suitable number is on the stack before defining the macro so that you
don’t get a stack-underflow error during the definition process.
Conditionals can be nested arbitrarily. However, there should be
exactly one ‘Z ]’ for each ‘Z [’ in a keyboard macro.
The ‘Z :’ (‘calc-kbd-else’) command allows you to choose between two
keystroke sequences. The general format is ‘COND Z [ THEN-PART Z :
ELSE-PART Z ]’. If COND is true (i.e., if the top of stack contains a
non-zero number after COND has been executed), the THEN-PART will be
executed and the ELSE-PART will be skipped. Otherwise, the THEN-PART
will be skipped and the ELSE-PART will be executed.
The ‘Z |’ (‘calc-kbd-else-if’) command allows you to choose between
any number of alternatives. For example, ‘COND1 Z [ PART1 Z : COND2 Z |
PART2 Z : PART3 Z ]’ will execute PART1 if COND1 is true, otherwise it
will execute PART2 if COND2 is true, otherwise it will execute PART3.
More precisely, ‘Z [’ pops a number and conditionally skips to the
next matching ‘Z :’ or ‘Z ]’ key. ‘Z ]’ has no effect when actually
executed. ‘Z :’ skips to the next matching ‘Z ]’. ‘Z |’ pops a number
and conditionally skips to the next matching ‘Z :’ or ‘Z ]’; thus, ‘Z [’
and ‘Z |’ are functionally equivalent except that ‘Z [’ participates in
nesting but ‘Z |’ does not.
Calc’s conditional and looping constructs work by scanning the
keyboard macro for occurrences of character sequences like ‘Z:’ and
‘Z]’. One side-effect of this is that if you use these constructs you
must be careful that these character pairs do not occur by accident in
other parts of the macros. Since Calc rarely uses shift-‘Z’ for any
purpose except as a prefix character, this is not likely to be a
problem. Another side-effect is that it will not work to define your
own custom key bindings for these commands. Only the standard shift-‘Z’
bindings will work correctly.
If Calc gets stuck while skipping characters during the definition of
a macro, type ‘Z C-g’ to cancel the definition. (Typing plain ‘C-g’
actually adds a ‘C-g’ keystroke to the macro.)