Copyright 2002-2015 Rick Mohr
 

Vocola supports calling user-defined functions as well as library functions. If you find yourself using the same action sequence in several commands, defining a function can make the commands more concise and understandable.

For example, consider these three commands to change font properties in Notepad:

Font Size 6..72           = {Alt+o}f WaitForWindow(font) {Alt+s} $1 {Enter};
Font (Arial|Courier)      = {Alt+o}f WaitForWindow(font) {Alt+f} $1 {Enter};
Font Style (Regular|Bold) = {Alt+o}f WaitForWindow(font) {Alt+y} $1 {Enter};

The first command sets the font size—{Alt+o} opens the "Format" menu, f chooses the "Font" option to activate the font panel, WaitForWindow(font) waits for the font panel to be frontmost, {Alt+s} puts focus in the "Size" field, $1 inserts the spoken size, and {Enter} closes the font panel. The other two commands work similarly, and most of the command actions are duplicated.

We can simplify the commands by defining a function to activate the font panel:

getFontPanel() := {Alt+o}f WaitForWindow(font);

This defines a function called getFontPanel which performs the first three actions of our commands. The commands can then be written more simply by calling this function:

Font Size 6..72           = getFontPanel() {Alt+s} $1 {Enter};
Font (Arial|Courier)      = getFontPanel() {Alt+f} $1 {Enter};
Font Style (Regular|Bold) = getFontPanel() {Alt+y} $1 {Enter};

These commands still contain some duplication. For maximum conciseness we could define our function differently, using arguments:

setFontProperty(field, value) := {Alt+o}f WaitForWindow(font) 
                                 {Alt+$field} $value {Enter};

With this function we generalize the idea of setting a font property, where the field argument specifies a field on the font panel and the value argument specifies the desired value. In the function's actions the references $field and $value retrieve the respective arguments. Using this function we can simplify our commands further:

Font Size 6..72           = setFontProperty(s, $1);
Font (Arial|Courier)      = setFontProperty(f, $1);
Font Style (Regular|Bold) = setFontProperty(y, $1);

Suggestion: name user-defined functions beginning with a lower-case letter to distinguish them from library function names (which begin with an upper-case letter).

The special user-defined function onLoad

If you define a function named onLoad, its actions will be executed whenever its containing command file is loaded.

As an example of why this might be desirable consider the Mozilla Thunderbird mailer. Its main window interprets single-character keystrokes as actions and doesn't require dictation, so it's desirable to disable dictation for that window. You can disable dictation for a window using the library function Dictation.DisableForWindow, so one approach would be to call that function from a "Disable Dictation" command and remember to speak that command when starting Thunderbird.

But a better approach is to call DisableForWindow from an onLoad function in the Vocola command file for Thunderbird. Whenever you start Thunderbird the command file will be loaded, the onLoad function will be executed, and dictation will be disabled automatically. Here's the function:

onLoad() := Dictation.DisableForWindow(thunderbird, Thunderbird);

Other than being called automatically at file load time, an onLoad function is no different than any other function. It can have multiple actions, call other functions, etc.