<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=US-ASCII">
<meta name="author" content="mailto:webmaster@zap.tartarus.org">
<meta name="description" content="Zap is a configurable programmers' editor for Acorn RISC OS">
<title>Commands: Zap's command language</title>
</head>
<body background='/img/background.png' text="#000000" bgcolor="#DCDCDC" link="#20209F" vlink="#008000" alink="#FF2020">
<p align='center'><a href="Chapter10">Previous</a> | <a href="Contents">Contents</a> | <a href="IndexPage">Index</a> | <a href="Chapter12">Next</a></p>

<ul>
<li><a href="#C11">Chapter 11: Commands: Zap's command language</a>
<ul>
<li><a href="#S11.1">11.1 Types of command</a></li>
<li><a href="#S11.2">11.2 Parameter evaluation</a>
<ul>
<li><a href="#S11.2.1">11.2.1 Allowed syntax</a></li>
<li><a href="#S11.2.2">11.2.2 Accessing system variables</a></li>
<li><a href="#S11.2.3">11.2.3 Dynamic versus static evaluation</a></li>
</ul></li>
<li><a href="#S11.3">11.3 Functions</a></li>
<li><a href="#S11.4">11.4 Variables</a>
<ul>
<li><a href="#S11.4.1">11.4.1 Local variables</a></li>
<li><a href="#S11.4.2">11.4.2 Configuration variables</a></li>
</ul></li>
<li><a href="#S11.5">11.5 Conditional constructs</a>
<ul>
<li><a href="#S11.5.1">11.5.1 <code>IF</code></a></li>
<li><a href="#S11.5.2">11.5.2 <code>CASE</code></a></li>
</ul></li>
<li><a href="#S11.6">11.6 Looping constructs</a>
<ul>
<li><a href="#S11.6.1">11.6.1 <code>WHILE</code></a></li>
<li><a href="#S11.6.2">11.6.2 <code>REPEAT</code></a></li>
</ul></li>
<li><a href="#S11.7">11.7 Examples</a>
<ul>
<li><a href="#S11.7.1">11.7.1 Simple conditional</a></li>
<li><a href="#S11.7.2">11.7.2 Simple loop</a></li>
<li><a href="#S11.7.3">11.7.3 'For'-style loop and static evaluation</a></li>
<li><a href="#S11.7.4">11.7.4 Loop and conditional</a></li>
</ul></li>
</ul></li>
</ul>
<h1><a name="C11"></a>Chapter 11: Commands: Zap's command language</h1>
<p>
Here we explore fully Zap's internal command language. Be warned that this gets fairly sophisticated - with this, you can effectively write your own commands to do a wide variety of things. This section is certainly unnecessary for the basic user of Zap (some might argue that it is only really useful to those seeking to bend a recalcitrant Zap to their every whim; but clearly this is not the truth :-).
</p>
<p>
You might like to look at <a href="Chapter9#S9.4">section 9.4</a> first, which introduces the basic system. However we'll go over that again here in more depth, so it's not essential.
</p>
<p>
You can enter commands into Zap in a number of ways. Firstly, and most immediately, you can press <code>cEscape</code> and type them directly into the <a name="i0"></a>minibuffer; pressing <code>Return</code> will execute them at once. Secondly, you can bind them to a key, by entering them into the <code>Keys</code> file. Thirdly, you can attach them to a menu by entering them into the <code>Menus</code> file. See <a href="Chapter12#C12">chapter 12</a>, and in particular <a href="Chapter12#S12.3.3">section 12.3.3</a> and <a href="Chapter12#S12.3.5">section 12.3.5</a> for information on the last two. You can also bind commands to be automatically executed when you load a particular file or type of file - see <a href="Chapter12#S12.3.2">section 12.3.2</a> for more information.
</p>
<p>
Throughout the rest of this section, where it matters, we will assume that you are entering commands into the minibuffer. The main difference is that errors are reported immediately (and you can't stop Zap from starting up by getting a command wrong in the minibuffer - you can sometimes in the configuration files).
</p>
<p>
If you <em>do</em> get something wrong, Zap will try to tell you roughly what's happened. Unfortunately, parts of Zap's command language are dealt with by the operating system, and the error messages from these bits can be a little obtuse at times. One irritating message is <code>Expression buffer overflow</code>, which simply means that whatever you're trying to evaluate is too long; expressions cannot be longer than 255 characters (this is set by the OS, so unfortunately we have no way of increasing it).
</p>
<p>
Remember that commands may be chained together using <code>:</code> (as in BASIC), and that comments may be placed after commands using <code>;</code> - these run until the next <code>:</code>, or the end of the command string.
</p>
<h2><a name="S11.1"></a>11.1 Types of command</h2>
<p>
Commands can take a parameter; there are four different types. These are:
</p>
<ul><li>
none - command takes no parameters at all.
</li>
<li>
byte - command takes a byte; specifying a number that won't fit into a byte will be reduced to just the least significant byte.
</li>
<li>
word - command takes a word.
</li>
<li>
string - command takes a string.
</li>
</ul>
<p>
You must always get the parameter type right.
</p>
<p>
Numbers may optionally be given enclosed in parentheses or quotes: <code>WRAPWIDTH 76</code>, <code>WRAPWIDTH (76)</code> and <code>WRAPWIDTH "76"</code> are all valid.
</p>
<p>
Strings may be given either in double quotes <code>"</code>, in which case additional quotes must be doubled up (so <code>"He said ""Hi!"", then left"</code> would be a valid string); or in parentheses, in which case quotes within the parameter must be matched. So <code>("Go on", said Michael)</code> is valid, but <code>("Hey!)</code> isn't. Note that <code>("I thought (and it was a sensible thought) that you were dead.")</code> is also valid.
</p>
<h2><a name="S11.2"></a>11.2 Parameter evaluation</h2>
<p>
Clearly, in some cases, you might want to do a quick calculation, and insert the result into Zap (or use it as the parameter to any command, in fact). You can do this: remember that the <code>INSERT</code> command takes a string parameter, and inserts that at the cursor. All we need to do is to evaluate an expression, and convert it to a string. This can be done using <code>INSERT $(50 + 70)</code>.
</p>
<p>
This inserts the string <code>120</code> into your file.
</p>
<p>
If you need to feed the result of an evaluation to a command that takes a numeric argument, you need to make the result be a number so it's the right type for the command. The <code>WRAPWIDTH</code> command is just such: <code>WRAPWIDTH #(50 + 70)</code>.
</p>
<p>
This sets the wrap width to 120 for the current file.
</p>
<p>
The bit inside the brackets is known as an <em>expression</em>; it is <em>evaluated</em> to get a result, which is then converted to the right type (string or number) to become the parameter.
</p>
<p>
(For historical reasons, you can also use <code>@(...)</code> instead of <code>$(...)</code>; this is strongly deprecated, and if you start using it will almost certainly cease to be supported at the most inconvenient moment!)
</p>
<h3><a name="S11.2.1"></a>11.2.1 Allowed syntax</h3>
<p>
Parameter evaluation actually uses the operating system call <code>OS_EvaluateExpression</code> (which is also used by <code>*EVAL</code>). Hence anything that can be fed to <code>OS_EvaluateExpression</code> is valid syntax for parameter evaluation. (In addition, Zap first substitutes the results from Zap function calls and Zap variables; we shall meet these later.)
</p>
<p>
You can either build up a string using the evaluation system, or a number. (You then convert to whatever you need using either <code>$(...)</code> or <code>#(...)</code> as described above.) Operations you can perform on numbers include:
</p>
<ul><li>
<code>+, -, *, /, MOD</code> - integer operations.
</li>
<li>
<code>=, &lt;, &gt;, &lt;=, &gt;=, &lt;&gt;</code> - integer comparison (the result is either false=0, or true=-1 - however if you try to just do <code>INSERT $(0 &lt; 1)</code> Zap will actually insert <code>4294967295</code>, which is the unsigned value of -1. To insert <code>-1</code>, use <code>INSERT $(STR(0 &lt; 1))</code>).
</li>
<li>
<code>&gt;&gt;, &lt;&lt;</code> - arithmetic shift right and left.
</li>
<li>
<code>&gt;&gt;&gt;</code> - logical shift right.
</li>
<li>
<code>STR</code> - convert to a string.
</li>
<li>
<code>AND, OR, EOR, NOT</code> - (bitwise) logical operators.
</li>
</ul>
<p>
String operations you can perform include:
</p>
<ul><li>
<code>+</code> - string concatenation.
</li>
<li>
<code>=, &lt;, &gt;, &lt;=, &gt;=, &lt;&gt;</code> - string comparison (the result is either false=0, or true=-1, as above).
</li>
<li>
<code>VAL</code> - convert to an integer.
</li>
<li>
<code>RIGHT, LEFT</code> - substring extraction.
</li>
<li>
<code>LEN</code> - length of a string (result is an integer).
</li>
</ul>
<p>
Brackets can be used to force expansion and evaluation in a certain order. For instance the example <code>INSERT $(STR(0 &lt; 1))</code> above evaluates (0 &lt; 1), which yields an integer -1 (true), and then converts to a string <code>-1</code>. The parameter is then converted to a string (ie: nothing is done to it) before being passed to the INSERT command to insert it at the cursor position. This sounds like a lot of work just to insert the string <code>-1</code>, but a few examples should help here. Only the parameter itself is given - it's assumed that you'll be using it as <code>INSERT $(&lt;parameter&gt;)</code>.
</p>
<ul><li>
<code>STR ("Jimmy" &lt; "Fish")</code> - Evaluates to <code>1</code> if <code>Jimmy</code> is before <code>Fish</code> in the alphabet. It isn't, so it actually evaluates to <code>0</code>.
</li>
<li>
<code>STR ((10 + 16) / 2) RIGHT 1</code> - Evaluates to the last digit (as a string) of the result of the integer expression (10 + 16) / 2 (ie: 3).
</li>
<li>
<code>"The " + "cat " + "sat " + "on " + "the " + "mat (slowly)."</code> - Evaluates to the string <code>The cat sat on the mat (slowly).</code>.
</li>
</ul>
<p>
These examples seem quite trivial. In the next section, we show how to use system variables (eg: <code>&lt;Wimp$Scrap&gt;</code>) within expressions.
</p>
<p>
You should beware of bugs in the operating system evaluation. For instance, <code>INSERT $(1&lt;2 AND 3&gt;4)</code> will insert <code>14</code>, instead of the expected <code>0</code>. In this case, you can avoid the problem by doing <code>INSERT $(3&gt;4 AND 1&lt;2)</code> - similar workarounds are almost always possible.
</p>
<h3><a name="S11.2.2"></a>11.2.2 Accessing system variables</h3>
<p>
Since parameter evaluation uses the operating system routines, you can access system variables. This is done in the following way: <code>INSERT $(sys$date)</code>.
</p>
<p>
We've given the entire command here because otherwise it might not have been obvious what was going on: anywhere that you would normally put a string (delimited by quotes) in an expression, you can put the name of a system variable and that will be inserted. Bear in mind that while most system variables are strings, some are numbers - so you can use a numeric system variable anywhere you might use a number in an expression. For instance, if you had a system variable myvar whose value was the number six (say created by <code>*seteval myvar 6</code>), you could do <code>INSERT $(myvar / 2)</code> to insert the string <code>3</code>.
</p>
<h3><a name="S11.2.3"></a>11.2.3 Dynamic versus static evaluation</h3>
<p>
The above examples are known as <em>dynamic evaluation</em> - because the expression is evaluated every single time the parameter is required. While this is generally fine when you type things into the minibuffer, it clearly might not be so helpful if you want to use it in the <code>Keys</code> or <code>Menus</code> files, where it might be being executed regularly as part of a keystroke or menu item. Evaluating the expression takes time that you'd probably rather not spend; what we need is <em>static evaluation</em>, that only gets evaluated once, the first time the parameter is used (in the case of the <code>Keys</code> or <code>Menus</code> files, the parameter is actually evaluated when the file is loaded).
</p>
<p>
We can do static evaluation as follows:
</p>
<pre><code>     WRAPWIDTH #=(50+70)
     INSERT $=(Sys$Time)
     INSERT $EVAL (Sys$Time LEFT 5)
</code></pre>
<p>
This works exactly the same way as for dynamic evaluation - the only difference is that the different brackets force static evaluation rather than dynamic. The last example is a static function call; the first two are static evaluations to number and string respectively.
</p>
<p>
From the above examples, it may not be clear why dynamic evaluation - every single time the parameter is needed - is ever different from static. However consider that the value of system variables may change over time - and in the next two sections we will introduce functions and variables, which can be used inside evaluated parameters, and which can and will change as you use Zap. Using them, it should become clear that dynamic and static would have very different effects if the parameter say included a function call to find out where the cursor was.
</p>
<p>
Further, when we consider looping constructs, which allow a group of commands to be executed an arbitrary number of times, the difference between dynamic and static evaluation for commands typed into the minibuffer will become important as well.
</p>
<h2><a name="S11.3"></a>11.3 <a name="i1"></a>Functions</h2>
<p>
Functions are a special type of Zap command; instead of performing an action, they return a value which can be used in an expression. As such, they can take any of the parameter types of normal commands. In particular, they can take evaluated expressions as parameters (although it starts to get rather difficult to find concrete and useful examples of this!).
</p>
<p>
Functions are introduced with an <code>@</code> character. For instance: <code>INSERT $(@MODEN)</code>.
</p>
<p>
This inserts the name of the current mode (in lower case).
</p>
<p>
Many functions are supplied by Zap itself, and several more by the command extensions, particularly <a name="i2"></a><em>ZapText</em> and <a name="i3"></a><em>ZapUtil</em>. You should see the documentation with each of these for more information, and several examples on how to use them.
</p>
<p>
For completeness, here's the best example we could find which uses only core commands and functions, and demonstrates use of a function which in turn takes an evaluated expression as a parameter: <code>INSERT $(@CHAROFF #(my_charoff))</code>.
</p>
<p>
This inserts the value (ie a number from 0 to 255) of the character at an offset given by the system variable my_charoff from the current cursor position. 255 is inserted if the character is outside the file (this is a feature of the <code>@CHAR</code> function).
</p>
<h2><a name="S11.4"></a>11.4 Variables</h2>
<p>
Clearly if we can evaluate things, we might like to store them in variables somehow. You can do this using the <code>SET</code> command: <code>SET (variable=expression)</code>.
</p>
<p>
For instance, <code>SET (foo="string")</code> sets the Zap variable called <code>foo</code> to the string value <code>string</code>. <code>SET (bar=12)</code> sets the Zap variable <code>bar</code> to the numeric value 12. Since we use an expression to set the value of a variable, we can perform calculations, use functions - and even use other variables (once we've shown you how to use them :-).
</p>
<p>
Variable names may contain letters, digits, and the characters <code>`</code>, <code>_</code> and <code>$</code>, and must not start with a digit or <code>$</code>.
</p>
<p>
To unset a variable, use the <code>UNSET</code> command. This takes a <em>wildcarded</em> variable name. For instance, <code>UNSET (*)</code> unsets all the Zap variables; <code>UNSET (q*x)</code> unsets all Zap variables beginning <code>q</code> and ending <code>x</code>; <code>UNSET (b#r)</code> unsets all Zap variables with three characters in their names, the first being <code>b</code> and the last <code>r</code>.
</p>
<p>
In order to use a variable in an expression, prefix it with <code>@$</code> or <code>@#.</code> Use <code>@$</code> with strings, and <code>@#</code> with numbers. For instance: <code>INSERT $(@$foo)</code>.
</p>
<p>
To evaluate a variable as an expression, use <code>@=</code>: <code>INSERT $(@=bar)</code>.
</p>
<p>
If you need to include a literal <code>@</code>, you'll have to quote it <em>unless</em> it's in a string, eg: <code>$(Alias$@@RunType_FFF+" this @ doesn't need to be quoted")</code>.
</p>
<h3><a name="S11.4.1"></a>11.4.1 Local variables</h3>
<p>
To declare variables <em>local</em>, use the command <code>LOCAL</code>, which takes a comma-separated list of variable names: <code>LOCAL (foo,bar)</code>.
</p>
<p>
Not that the variables are <em>not</em> initialised; all that happens is that their old values are stored ready to be restored when these local variables go 'out of scope'.
</p>
<p>
Local variables remain in effect ('in scope') during the current command string. (It might help to think of it as treating each command string like a procedure in BASIC.)
</p>
<h3><a name="S11.4.2"></a>11.4.2 Configuration variables</h3>
<p>
In addition to the variables described above, Zap has a special set of variables called <a name="i4"></a>c-vars; this stands for <em>configuration variables</em>. These are variables which are used to configure how a command, or a particular part of Zap, operates. For instance, the <a name="i5"></a><em>StrongHelp</em> support in <a name="i6"></a><em>ZapText</em> uses the c-var <code>HelpSearchPath</code> to configure the order in which the <a name="i7"></a><em>StrongHelp</em> manuals are searched.
</p>
<p>
Note that these are not accessible as normal Zap variables; they are mentioned here merely for completeness.
</p>
<p>
For more information on <a name="i8"></a>c-vars, see <a href="Chapter12#S12.3.6">section 12.3.6</a>.
</p>
<h2><a name="S11.5"></a>11.5 Conditional constructs</h2>
<p>
We're almost into heavy territory, but don't give up, because one of the most useful features of the command language is about to be introduced: conditional constructs. These do things only if certain conditions hold, and in particular the <code>IF</code> construct is very useful in keystrokes.
</p>
<p>
Conditional constructs may be nested.
</p>
<h3><a name="S11.5.1"></a>11.5.1 <code>IF</code></h3>
<p>
The syntax of the <code>IF</code> construct is as follows:
</p>
<pre><code>     IF &lt;condition&gt;:&lt;command(s)&gt;:[ELSE:&lt;command(s)&gt;:]ENDIF
</code></pre>
<p>
The <code>ELSE</code> bit is optional - don't use it if you don't need it. The condition for an <code>IF</code> is an expression, so you can put things like functions in it:
</p>
<pre><code>     IF (@CHAR=@TABCHAR OR @CHAR=32):RIGHT:ENDIF
</code></pre>
<p>
Move the cursor right if it's on a tab or a space.
</p>
<p>
One of the most useful functions for this is <code>@IN</code>, which takes a comma-separated list of expressions. It returns true if the first element is the same as any one of the later ones (all elements must be of the same type):
</p>
<pre><code>     IF (@IN(@MODEN,"basic","code")=0):UPDATEWINDOW:ENDIF
</code></pre>
<p>
Redraw the window if not in BASIC or Code mode.
</p>
<h3><a name="S11.5.2"></a>11.5.2 <code>CASE</code></h3>
<p>
<code>CASE</code> can be used instead of a whole chain of <code>IF</code> constructs. The syntax is:
</p>
<pre><code>     CASE &lt;expression&gt;:
             WHEN &lt;list of expressions&gt;:&lt;command(s)&gt;:
             WHEN &lt;list of expressions&gt;:&lt;command(s)&gt;:
             ...
             DEFAULT:&lt;command(s)&gt;:
     ENDCASE
</code></pre>
<p>
The <code>&lt;list of expressions&gt;</code> for <code>WHEN</code> must be of the same type as the <code>&lt;expression&gt;</code> in the <code>CASE</code> command - in other words, you can either check for all strings, or all numbers, depending on what's in your <code>CASE</code> command.
</p>
<p>
The <code>&lt;list of expressions&gt;</code> for <code>WHEN</code> is comma separated; if the expression in the <code>CASE</code> statement matches any of those in the <code>WHEN</code> statement, the commands in that <code>WHEN</code> 'block' (up until the next <code>WHEN</code>) are executed. If no <code>WHEN</code> expressions match, the <code>DEFAULT</code> commands are executed.
</p>
<p>
This acts more or less identically to BASIC's <code>CASE</code> construct, except that if the <code>CASE</code> expression matches in more than one <code>WHEN</code>, all matching <code>WHENs</code> have their commands executed - unlike BASIC where only the first match is executed.
</p>
<p>
If you want functionality like C's <code>switch()</code> construct, then you can use <code>CWHEN</code> instead of <code>WHEN</code>; if the immediately preceding <code>CWHEN</code> or <code>WHEN</code> contained a matching expression, the commands for <em>this</em> <code>CWHEN</code> will also be executed. Otherwise <code>CWHEN</code> works as for <code>WHEN</code>.
</p>
<p>
You can break out of a <code>CASE</code> block using <code>BREAK</code> (useful if you have lots of <code>CWHEN</code> statements and you want to prevent fallthrough from the one you're in at the moment, but also want subsequent matching <code>CWHEN</code> expressions to have their commands executed).
</p>
<p>
You can break out of the <code>CASE</code> statement using <code>CONTINUE</code> (so no more <code>WHEN</code> or <code>CWHEN</code> matches will be considered).
</p>
<p>
For more information, you should read the internal help for each of these commands. For instance, to see the help on the <code>CASE</code> command, use <code>HELPCOM "CASE"</code>, or <code>c\ c "CASE"</code>.
</p>
<h2><a name="S11.6"></a>11.6 Looping constructs</h2>
<p>
Now we consider looping. This is useful if you want to do something to, say, every line in a file, or every character in the selection. Many of these operations may already have commands dedicated to them which will almost certainly be faster - check before embarking on something complicated using Zap's command language, which can be quite slow at times.
</p>
<p>
Note that infinite loops are very easy to get into - use <code>Alt+Escape</code> to break out if something looks like it's taking too long and might have become stuck.
</p>
<p>
Looping constructs may be nested.
</p>
<h3><a name="S11.6.1"></a>11.6.1 <code>WHILE</code></h3>
<pre><code>WHILE &lt;condition&gt;:&lt;command(s)&gt;:ENDWHILE
</code></pre>
<p>
The condition is a Zap expression, as you'd expect; if the condition is true, the loop is executed. On reaching the <code>ENDWHILE</code> command, control returns to the <code>WHILE</code> command and the test is done again. This continues until the condition is false. (So if the condition is false to start off with, the commands never get executed.)
</p>
<h3><a name="S11.6.2"></a>11.6.2 <code>REPEAT</code></h3>
<pre><code>REPEAT:&lt;command(s)&gt;:UNTIL &lt;condition&gt;
</code></pre>
<p>
The condition is a Zap expression; if the condition is false, control returns to the <code>REPEAT</code> command. This continues until the condition is true. (So if the condition is false throughout, the commands will be executed once; contrast this to the <code>WHILE</code> construct, above.)
</p>
<h2><a name="S11.7"></a>11.7 Examples</h2>
<p>
This concludes our foray into the Zap command language. To make life easier, and give some pre-built (and tested!) ways of using it to do useful things, here are a set of examples. Be warned that while the earlier ones are fairly simple, the later ones are significantly more complex.
</p>
<p>
Note that the examples are given broken over several lines - this isn't possible in Zap. It is done here simply for readability.
</p>
<h3><a name="S11.7.1"></a>11.7.1 Simple conditional</h3>
<p>
Firstly, a relatively simple conditional. This does a variety of different tabbing actions depending on the mode you're in. For this, you'll need <a name="i9"></a><em>ZapUtil</em> installed (<code>@CURSORCOLUMN</code> is in <a name="i10"></a><em>ZapUtil</em>; <code>MJE_REINDENT</code> is in <a name="i11"></a><em>ZapMJE</em>, but so are the C, C++ and Java modes - the command won't be needed unless we're using one of these modes, and then it will be there already).
</p>
<pre><code> CASE (@MODEN):
   WHEN ("code"):
     NOTIFYUSER "Tab isn't a useful action in code mode!"
     ; WHEN, so this will now drop to the ENDCASE :
   WHEN ("c","c++"):
     IF (@CURSORCOLUMN &gt; 0):
       TAB:CONTINUE ; Drop to the ENDCASE :
     ENDIF:
   CWHEN ("java") ; drops through from the above
     (providing the IF condition wasn't true) :
     MJE_REINDENT ; reindent the line according to context :
   WHEN ("basic"):INSERT "  " ; make it do a little spacing :
   DEFAULT : TAB ; just the normal Tab action :
 ENDCASE
</code></pre>
<p>
In C and C++ modes, if you're not right at the left-hand edge of the window, it will perform the normal tabbing action - otherwise it will reindent the line. It will always reindent the line for Java mode; for BASIC it inserts a couple of spaces (<a name="i12"></a>tabbing doesn't work normally in BASIC mode - see <a href="#S11.7.4">section 11.7.4</a> below for how to do a more sophisticated tab in BASIC mode). In Code mode it displays a brief error message, and in all other modes it does the normal action of <code>Tab</code>.
</p>
<h3><a name="S11.7.2"></a>11.7.2 Simple loop</h3>
<p>
Finding a simple loop without using conditionals is difficult. However one comes up: <a name="i13"></a><em>ZapDS</em> contains a number of commands which perform bitwise operations on the byte or word at the cursor. The following EORs the selection with a given value. You'll also need <a name="i14"></a><em>ZapUtil</em> for the functions. The rather gruesome bit of string manipulation at the beginning is to extract the window and start of the selection from <code>@SELECTION,</code> which also gives you the end of the selection. The function is known to return three comma-separated hexadecimal numbers, nine characters each (eight plus a leading '&amp;'). In general it isn't advised to do things like this because of what might happen if the function changes; however in this case it's fairly guaranteed to remain constant.
</p>
<p>
(Note that really this should be wrapped in <code>IF (@SELANYWHERE):...:ENDIF</code> - it's rather unsafe as it is, and will fall over with an error if there isn't a selection. However, in the interests of trying to find a simple example of a loop on its own which is also useful ...)
</p>
<pre><code>CURSOR $(@SELECTION LEFT 19):
WHILE (@INSELECTION):
  DS_EOR "60" ; EOR with 60 :
ENDWHILE
</code></pre>
<p>
Note that we might want to preserve the position of the cursor over this routine: you can either use marks (dropping a mark at the beginning, executing the command, and then doing <code>LASTMARK</code> to go back to where you were), or grab the cursor into a variable using <code>SET (pos=@CURSOR)</code>. Then you can restore using <code>CURSOR $(@$pos)</code>. Note that <code>CURSOR</code> and <code>@CURSOR</code> are in <a name="i15"></a><em>ZapUtil</em>.
</p>
<h3><a name="S11.7.3"></a>11.7.3 'For'-style loop and static evaluation</h3>
<p>
Zap doesn't have an equivalent of BASIC's <code>FOR ... TO ... STEP ... NEXT</code> (C's <code>for(,,){}</code>) construct. However you can simulate it using <code>WHILE</code>. This example also demonstrates the difference between static and dynamic expression evaluation. Note that you have to do this in two stages, because the static evaluation is done while parsing the command string - so unless the variable n is already set, you get an error.
</p>
<pre><code>SET (n=32)
</code></pre>
<pre><code>WHILE (@#n&lt;127):
  CHAR #(@#n)  ; dynamic :
  CHAR #=(@#n) ; static  :
  SET (n=@#n+1):
ENDWHILE
</code></pre>
<p>
This will insert the ASCII characters from 32 (<code>SPC</code> - space) to 126 (<code>~</code>), separated by spaces. An alternate way of doing it, which can be done in one go, is to wrap the <code>WHILE</code> loop in a <code>COMMAND</code> call:
</p>
<pre><code>SET (n=32):
COMMAND (
  WHILE (@#n&lt;127):
    CHAR #(@#n)  ; dynamic :
    CHAR #=(@#n) ; static  :
    SET (n=@#n+1):
  ENDWHILE
)
</code></pre>
<h3><a name="S11.7.4"></a>11.7.4 Loop and conditional</h3>
<p>
Let's try to get a better tabbing action for BASIC mode - don't forget that <a name="i16"></a>tabbing itself doesn't work normally in BASIC. We'd like to indent, using spaces, to the next tab stop - where there's a tab stop every eight characters. For this, you'll need <a name="i17"></a><em>ZapUtil</em> for the <code>@CURSORCOLUMN</code> function.
</p>
<pre><code>IF (@MODEN = "basic"):
  SET (cur=@CURSORCOLUMN):
  IF ((@#cur MOD 8) = 0) ; absolutely on a tab stop - 
    insert eight spaces straight off:
    INSERT "        " :
  ELSE:
    SET (nexttab=((@#cur / 8) + 1) * 8):
    WHILE ((@CURSORCOLUMN &lt;&gt; @#nexttab)
           AND (@CURSORCOLUMN &gt;= @#cur)):
      INSERT " ":
    ENDWHILE:
  ENDIF:
ENDIF
</code></pre>
<p>
The <code>... AND (@CURSORCOLUMN &gt;= @#cur)</code> will stop us if something has gone too wrong and we wind up earlier on on the line (or a subsequent line) than we started. This could happen with wrapping, for instance. Alternatively, we could have used <code>... AND (@CURSORCOLUMN &gt; 0)</code>, since if it was <em>exactly</em> 0, the branch which inserts exactly eight spaces would have been taken - because (0 MOD 8) = 0.
</p>
<p>
Exercise for the reader: this is actually a terribly inefficient way of doing the job. It can be done simply using INSERT, @CURSORCOLUMN, and parameter evaluation, plus the check that we're in BASIC mode at the start.
</p>
<hr>
<p>
The next section in the manual is <a href="Chapter12#C12">chapter 12</a>, which looks at how to customise Zap to suit your specific needs.
</p>
<p>
Alternatively, you could move on to <a href="Chapter13#C13">chapter 13</a>, which introduces a number of useful extensions to Zap. In particular, it looks at <a name="i18"></a><em>ZapSpell</em> (an interface to the Computer Concepts' spell checker), and introduces Olly Betts' invaluable <a name="i19"></a><em>line editor</em>.
</p>

<hr><address><a href='/copyright'>&copy; Copyright Zap Developers 1992-2004</a>. All Rights Reserved.
</address></body>
</html>
