Using Groups
Groups provide a facility for grouping related rules, similar to functions in other programming languages. When used effectively, groups can reduce the size and complexity of your keyboards significantly.
Groups can match on context only, or on context and keystroke. The context-only groups can be very useful for pre- and post-processing rules, such as reordering stacked diacritics.
In Keyman 15.0 and later versions, groups can also be read-only. This is important for contexts where emitting output is not possible, such as when a new context is selected.
Only the first rule in the group that matches will be fired. There are two
special rules, match
and
nomatch
that will then fire if a rule is either
matched or not matched, respectively. The criteria for not matching is a little
more nuanced, however, as a keystroke is deemed to have not matched only if it
would have generated a character anyway, so F1 would not fire the
nomatch
rule, unlike a character key.
Rules in a group have a special order. They are ordered first by length of context, with longest context first, and then by line order in the file. This slightly non-intuitive ordering makes it much simpler to group rules according to their function, rather than necessarily by their priority.
The examples below show the three types of groups.
group(mygroup) c context only
'a' > 'b'
group(mygroup) readonly c read only
'a' > context set(aPressed = '1')
group(mygroup) using keys c context and keystroke
'a' + 'a' > 'c'
using keys
clause
To tell Keyman that the group should include key processing, you should include
the using keys
section of the statement; if that is left out, the group checks
the context only. The keystroke will remain the same during processing; you can
have many groups that each use using keys
, and the keystroke will be the same
for all of them. The key section of a rule (including the +
sign) is not valid
for context processing groups.
readonly
clause
Read-only groups are new in Keyman 15. They are used primarily from NewContext
and PostKeystroke
entry points, and indicate that text output is not permitted
from rules within the group. The purpose of these groups is typically to change
the current layer of the touch keyboard, or perform similar state updates.
use()
statements in a read-only group may only reference
other read-only groups.
An implicit context
statement is added to the front of
every rule output in a read-only group, if it is not already present, to ensure
that the input context is not modified. As it is not legal to have an empty
output, you may use the context
statement, not the nul
statement on the
right-hand side of an otherwise empty output.
In a read-only group, only the following output statements are permitted:
call()
- the custom function must not attempt to do any outputcontext
- only at the start of the outputuse()
- use otherreadonly
groupsset()
reset()
save()
See Casing Support for a comprehensive example of how read-only groups are used.
use
statement
The use()
statement allows you move into another group
when a rule is matched. All output from the current group preceding the use()
statement is processed into the context before the subsequent group is entered
(although it is not sent to the application until processing finishes for the
current keystroke). For example:
c This example prohibits two vowels in a row
store(vowel) 'aeiouAEIOU'
begin Unicode > use(precheck)
group(precheck)
any(vowel) > context use(precedingVowel)
nomatch > use(main) c Preceding character is not a vowel. Do normal processing.
group(precedingVowel) using keys
+ any(vowel) > beep
nomatch > use(main) c This key is not a vowel. Do normal processing.
group(main) using keys
c Main processing goes here
Some important things to note from this example:
The first rule (any(vowel) > context use(precedingVowel)
) uses the
context
statement to copy the matched context to the
output, so that Keyman can move it back into the context for use with the
precedingVowel
group. If you do not do this, the context will be dropped
before precedingVowel
is used, and the character will be deleted from the
screen.
Note: the match
rule will not be fired if the rule in the group that
was matched includes a use()
statement in its output. A workaround for this
situation is to duplicate the match
rule output in the output of rules that
contain use()
statements. A more comprehensive solution may be included in
future versions of the language.
Empty final group
If the final group processed is a context and keystroke group (using keys
),
and there is no nomatch
rule, and the keystroke is not matched in the group,
the keystroke will be output to the screen, regardless of whether or not it was
matched in earlier groups.
This can be used for example if you want to process a change at the end of a word which might be the last word in a line or in a text field, where the user presses Enter or Tab:
group(main) using keys
+ 's' > 'σ'
'σ + [K_ENTER] > 'ς' use(final)
group(final) using keys
c Empty final group causes keystroke to be emitted
Statements and rules used with groups
The following statements and special rules are used with groups:
begin
rule
: Defines the starting group for the keyboard layout
group()
statement
: Starts a new group of rules
match
rule
: A system rule that is fired when another rule in the group is matched
nomatch
rule
: A system rule that is fired when no rule is matched
return
statement
: Stops processing of the current keystroke
use()
statement
: Starts processing in another group