17.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. See 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.)