Substituting Actions
So far the spoken words in our alternative sets have been substituted directly
into our keystroke sequences. Actually it is more common to substitute
a different set of actions than the spoken words.
For example, suppose we want "Move Back" to move the cursor left and "Move
Forward" to move the cursor right. We can specify that this way:
Vocola: Move (Back=Left | Forward=Right) = {$1};
Say: Move Back
Sent: {Left}
Say: Move Forward
Sent: {Right}
|
The alternative set (Back=Left | Forward=Right) means you can
say either "Back" or "Forward", but the value substituted on the right hand
side will be Left or Right.
Here's another example. Mozilla's Thunderbird Mailer has several options for
sorting messages. This command allows you to change the sort by saying "Sort
by Date", "Sort by Sender", or "Sort by Subject":
Vocola: Sort by (Date=e | Sender=n | Subject=b) = {Alt+v}s $1;
Say: Sort by Date
Sent: {Alt+v}se
Say: Sort by Sender
Sent: {Alt+v}sn
|
This alternative set allows you to say "Date", "Sender", or "Subject", and
substitutes e, n, or b into the
keystroke sequence. (The keystroke {Alt+v} opens the "View" menu, s
opens the "Sort by" sub-menu, and the final letter chooses the sort option.)
Alternative sets with substitution provide an easy way to
define voice shortcuts for items such as files, folders, URLs,
or email addresses. For example, we can define the
variable <address> to contain a
list of email addresses and shortcuts to invoke them:
The command Address <address> allows you to say,
for example, "Address Bill" or "Address Voice Coder" to insert the desired
email address. The list can be modified over time to add new addresses.
An alternative and its substitution (e.g.,
Listen = [email protected]) is
actually a mini-command—"when I say this, send these
keystrokes". As with a command, the left-hand side may be an
alternative set and the right-hand side may contain a sequence
of actions. Prior to version 2.9, the left-hand side was not
allowed to contain variables or ranges, and the right-hand side
was not allowed to contain references.
Variables may be defined in any order — you do not need
to define a variable before you reference it. Variables may
also be defined in terms of other variables as long as you do
not create a recursive loop where a variable is defined,
however indirectly, in terms of itself.
Here's a more complicated example that uses these features.
This command opens a file from a list of favorite files, then
possibly goes to an interesting position:
Vocola:
open <my_file> [<position>] = openFile($1) $2;
<position> := ( end = {ctrl+end}
| line 1..99 = {ctrl+home}{down_$1}
| line 1..99 character 1..80 = {ctrl+home}{down_$1}{right_$2}
| at <my_landmark> = moveToLandmark($1)
);
<my_file> := ( foo = ~/foo.txt | ... );
<my_landmark> := ( contents | ... )
|
Here openFile
and moveToLandmark are assumed to be
user-defined Vocola functions
(see this section on defining
your own functions) that open a file and move to a landmark
within it respectively.
References (i.e., $1) refer to the
nth top level variable or alternative list in the command whose
actions they belong to, ignoring optional indicators.
Consider, for example, the following command:
Vocola:
foo <a> [<b> (<c> <d>=$2$1)] 1..10 = ...;
|
Here in the command's actions
(the ...
part), $1 refers
to <a>, $2
refers
to <b>, $3
refers to the entire alternative
list (<c> <d>=$2$1),
and $4 refers
to 1..10. It is not possible to
refer to <c> in the outer
command's actions. In the inner
command, <c>
<d>=$2$1, $1 refers
to <c> as you would expect.
Normally alternatives do not require
actions; however, alternatives containing a variable or inline
list plus one or more other terms require an action assignment
to tell Vocola how to combine the inputs. For example, the
following alternative requires an assignment:
<motion> := <direction> 1..10 = {$1_$2};