Defining Functions
Function Calls
Vocola supports user-defined functions as well as built-in functions. If you
find yourself copying an action sequence for use in several commands, defining
a function can make the commands more concise and understandable. (This is also
possible using the built-in function HeardWord, but creating your own function
makes for clearer code and faster execution.)
For example, in the Netscape/Mozilla mailer it's useful to define commands
to move around in the "summary" window (which shows a one-line summary
of each e-mail message). Here we define the function goToSummary to
make sure the summary window has the focus:
goToSummary() :=
SetMousePosition(4, 7) # Window's bottom left edge
SetMousePosition(2, 15, -45) # Bottom left of folder list
ButtonClick() # Folder list now has focus
{Tab_3}; # Summary pane now has focus
|
The left side of the definition specifies the function's name (goToSummary)
and arguments (none in this case). The right side of the definition is a standard
Vocola action sequence. Here we position the mouse over the bottom left corner
of the mailer window, move up and to the right slightly to be over the folder
list panel, click the mouse so the folder list has focus, and finally press
the tab key three times so the summary window has focus.
Now we can define 3 commands using this function. Saying "Final Message"
moves to the last message in the summary. Saying "First Unread" moves
to the first unread message. And saying for example "Summary 3 Up"
moves to the summary window and up three messages:
Final Message = goToSummary() {End};
First Unread = goToSummary() {End}n;
Summary 1..20 (Up|Down) = goToSummary() {$2_$1}; |
Each of these commands uses our function goToSummary, making them
shorter and clearer than if each had to include that function's actions explicitly.
Defining Functions with Arguments
You can also specify arguments when defining a function. For example, here's
a function which switches to the nth application on the Windows taskbar:
switchToTaskBar(number) := SendSystemKeys( {Ctrl+Esc} )
{Tab_2}{Right_$number}{Left} " ";
|
This function, switchToTaskBar, is defined to take the single argument
number (indicating which taskbar slot to switch to). {Ctrl+Esc}
opens the start menu (just to get focus on the taskbar), and {Tab_2}
moves to the first application. Then $number (referring to the function
argument) is used to move right the specified number of slots. Finally, sending
a "space" keystroke makes the selected application active. (Note that
this function works in Windows XP -- a slightly different version is needed
for Windows 2000.)
Now we can use this function in several commands. Let's say that Microsoft
Word is the third application from the left on the taskbar. Saying "Switch
to 3" makes Word the active application. Saying "Close 3" closes
Word. And saying "Copy to 3" copies everything from the current application
and switches to Word:
<n> := 1..20;
Switch to <n> = switchToTaskBar($1);
Close <n> = switchToTaskBar($1) {Alt+F4};
Copy to <n> = {Ctrl+a}{Ctrl+c} switchToTaskBar($1);
|
Each of these commands uses the variable <n> to specify a number
between 1 and 20, which is then passed to the switchToTaskBar function
to specify the target application.
Multiple Arguments and Nested Function Calls
Here's another example, defining two functions which each take 2 arguments.
First is the function moveBy, which moves the mouse a distance (x,y)
from the current position. Note that it uses the built-in Vocola function Eval
to multiply each coordinate by 15, providing more convenient units than pixels.
(I have rulers taped to my screen in these units, thanks to Kim Patch's idea.
With this approach you can place the mouse anywhere on a large screen by speaking
only 2-digit numbers, which are recognized much more reliably than 3-digit numbers.
See the file _vocola.vcl in the shipping Vocola samples for more examples.)
moveBy is used twice by the next function, moveWindowBy,
which moves the current window a specified distance (x,y) in these same 15-pixel
units.
moveBy(x,y) := SetMousePosition(2, Eval(15*$x), Eval(15*$y));
moveWindowBy(x,y) :=
SetMousePosition(4,1) # Top window edge, center
moveBy(0,1) # Down into title bar
RememberPoint() # Store initial drag point
moveBy($x,$y) # Move by given amount
DragToPoint(); # Do the drag
|
Note again that a function's arguments may be referenced in its action sequence
using "$". That's $x and $y in these functions.
Now here are two commands using moveWindowBy, allowing you to say
for example "Window 10 Up"or "Window 20 Right" to move the
current window:
<n> := 0..99;
Window <n> ( Up='-' | Down='+') = moveWindowBy(0, $2$1);
Window <n> (Left='-' | Right='+') = moveWindowBy($2$1, 0); |
Note here how a function argument can be built from two variables. When you
say "Window 10 Up", the first variable term <n> has
the value "10" and the second variable term has the value
"-". These are concatenated by the double reference $2$1
to form the final function call moveWindowBy(0, -10).
|