Advanced Keyboard Creation
Whenever you want to do much more in a keyboard than simple character substitution, you will generallyneed to make use of advanced features such as stores, deadkeys, and multiple groups. The tutorial hasalready shown some basic usage of stores and deadkeys, but has not covered other possibilities of theiruse. In this topic we will examine a keyboard that demonstrates some other usesof stores and deadkeys, and introduces the use of multiple groups for complex processing.
The keyboard we will examine is IPAMenu.kmn(found in the Keyman Developer Samples folder), which containsthe beginnings of a menu-based keyboard for using the International Phonetic Alphabet (IPA). Youwill need a Unicode font with IPA characters (such as Lucida Sans Unicode orCode2000) to properly use this keyboard, but you should beable to follow the code even without. For more information about the IPA,see The International Phonetic Association.
Most of the IPA glyphs are modifications of glyphs from the Latin alphabet, used to represent differingsounds used in language. Because of this, it seemed reasonable to place all glyphs derived from a on thea key, and so on. We have implemented a few of the vowel symbols in this keyboard:
Overview of the keyboard
The basic operation of the keyboard is the displaying of a menu when a key is pressed, followed by the outputof a single character when the user makes a selection from that menu with a number key.The first thing to notice is the organisation of most of the input and output into stores:(Note that you will need a Unicode font that has IPA characters to view this example correctly)
store( choices ) '1234567890'store( a_menu ) '[1æ 2a 3ɑ 4ɐ 5ʌ 6ɒ]'store( e_menu ) '[1ɛ 2ɜ 3ə 4e 5ɘ 6ɚ 7ɝ 8ɞ]'store( o_menu ) '[1o 2ø 3ɔ]'store( a_chars ) 'æaɑɐʌɒ' dk(a_err) dk(a_err) dk(a_err) dk(a_err)store( e_chars ) 'ɛɜəeɘɚɝɞ' dk(e_err) dk(e_err)store( o_chars ) 'oøɔ' dk(o_err) dk(o_err) dk(o_err) dk(o_err) dk(o_err) dk(o_err) dk(o_err)
An important point to notice is the use of deadkeys in these stores: this is a new feature for Keyman 6.2;we'll explain their purpose here later.
The next thing that stands out is that the file has six separate groups, four of which handle keystrokesand two which manipulate context only:
group( first )group( main ) using keysgroup( final )group( a_group ) using keysgroup( e_group ) using keysgroup( o_group ) using keys
Primary Operation of the Keyboard
When a key is pressed, execution begins at the group indicated by the begin statement, in this casethe first group. Because this group does not specify using keys, it is limited to contextmanipulation only: the output of this rule is dependent only on what came before the current keystroke, andbecomes the context for any further groups that are called from this one.
Let's suppose the a key has been pressed with no context. The first group will have nothing tomatch on, so the nomatch rule fires and passes control to the main group. Here the a keyis matched, and the a_menu store is output, displaying the menu of a-like characters.Now the user is presented with a menu of options to choose from. Suppose he types 1. Once again thefirst group gains control first, but this time matches the first rule, with the a_menu stringon the context, so control is passed to the a_menu group to handle the keystroke. Here the 1 ismatched as an entry in the choices store, and the corresponding character in the a_chars store -in this case Ã¦ - is output. Finally, control goes from here to the final group, which fails tomatch anything in the context (which now includes the output from the previous group).
One issue this keyboard has to deal with is if the user tries to select an option that's not in the menu -when this happens, it should beep and remain at the menu, so the user can try again. Also, if the user wants todismiss the menu, we should allow the use of Backspace to delete it - this is simply done with a rule matching[K_BKSP] and outputting nul.There are two rules which handle the user selecting a nonexistent option: if the current menu has fewer than10 entries, the user can press a number key indicating a menu entry that is not there - this situation willbe matched by the any(choices) rule. The other occasion is if the user presses any other key which is notvalid for selecting a menu option. This is handled by the nomatch rule in the group. For both these caseswe want the output to be the same: a beep, and remain at the menu. To do this we will use deadkeys as errorflags, one for each menu. By padding the a_char, e_char, o_char stores to 10 characters with thesedeadkeys, the output for this first situation will be the error flag. Similarly, we can output these deadkeysin the nomatch rules, to mark an error.The actual error handling is now done with the final group, which matches the error flags on the outputand outputs the beep and the appropriate menu again.
Although this example went nowhere near the limits of what can be done with multiple groups, it gave ademonstration of some of the ways multiple groups can be made to interact for more powerful processing. You should now have some understanding of the use of advanced features in Keyman Developer, and be ableto begin using them to improve your keyboards.