Appendix: The Dictionary Format

This appendix draws heavily from Josh Lifton's 2010 Plover Guide.

The Basics

The Plover dictionary file is in JSON format, essentially a bunch of key/value pairs. Each pair is separated from the next by a comma, and the key and the value are each in double quotes, and separated from each other by a colon. And the entire dictionary is enclosed in a single pair of curly braces:

{
"KEYSTROKE": "output",
"KEYSTROKE2": "output2",
"KEYSTROKE3": "output3"
}

Note that the last entry in the dictionary file has no trailing comma.

In the keystroke portion of each entry, a hyphen is used to disambiguate which side of the keyboard has a particular key:

"SK-D": "asked",
"SKW-D": "asked",
"SK-R": "asker",
"SK-RS": "askers",

Note that the hyphen does not indicate multiple keystrokes. When stroking SK-D, you would press the S, K, and D keys at the same time.

To indicate multiple strokes, the keystroke portion of each entry uses a forward slash:

"AS/KAPBS": "askance",
"AS/SKAPBS": "askance",
"A/SK-D": "asked",
"A/SKAOU": "askew",
"AS/KAOU": "askew",
"AS/SKAOU": "askew",
"SK/-G": "asking",

Some entries have lots of strokes:

"HREBG/TRO/EPB/SEF/HRO/TKPWRAPL": "electroencephalogram",

An entry can output more than just a single word. In the output portion of the entry, use blank spaces to create strings of words to output:

"TP-FS": "all of a sudden",
"TPHUFRB": "area under the curve",
"SPHABGT": "as a matter of fact",
"HRAEURPBLG": "ladies and gentlemen of the jury",

Aside from spaces and letters, you can use numerals, and any of '.'-$%:,/()&=>?*' in the output portion of an entry.

"AOEU/KWRAOE": "i.e.",
"UD": "you'd",
"AUP/TO/TKAEUT": "up-to-date",
"TK-PL": "quot;",
"TPEUF/PERS": "5%",
"KHRPB": ":",
"ETS/ETS/ETS": "et cetera, et cetera, et cetera",
"HA*F": "1/2",
"TPHAUBL": "(inaudible)",
"KW-RBGS/TPHA*": "Q&A",
"KW-L": "=",
"TKPWR*PB": ">",
"STPHU": "you?",
"STA*R": "*",

Note that the above characters aren't special in any way. They are simply output by Plover, exactly like other entries.

To use the double quote '"' character in the output portion of an entry, you need to precede it with a backslash '\':

"KWOT": "\"",

The above entry isn't in the dictionary file because it's not very useful. As it is, Plover treats it like any other word, and inserts spaces before and after. So if you stroke SAEU/KWOT/HEU/KWOT/TO/HEUPL, Plover will produce 'say " hi " to him' instead of 'say "hi" to him'.

Introduction To Commands

To get special behaviors from certain characters, you must enclose them in curly braces within the output portion of an entry. For example, '{.}' tells Plover to output a period followed by a space, and then capitalize the first letter of whatever word the user types next:

"TP-PL": "{.}",

Likewise, '{?}' does the same with the question mark, and '{!}' does the same with an exclamation mark:

"H-F": "{?}",
"SKHRAPL": "{!}",

These characters wrapped in curly braces do not have to take up the whole output by themselves. They can be combined with regular text and other curly braced characters:

"-RBGS/TOS/STPH": "{,}does it{?}",

The above entry attaches a comma to the previous word, then adds a space, and the words "does it", then adds a question mark, then adds a space and forces Plover to capitalize the next word. For example, stroke EUT/TKOPBT/HURT/-RGBS/TOS/STPH to produce 'it doesn't hurt, does it?'

Note that any blank spaces surrounding the curly braces are ignored. So, the above entry produces the exact same output as:

"-RBGS/TOS/STPH": " {,} does it {?} ",

If you don't necessarily want to add punctuation, but you still want Plover to capitalize the first letter of whatever the user types next, put '{-|}' at the end of the output portion of the entry:

"TKR*FPLT": "Dr.{-|}",

In the above entry, it's not the '.' outside of curly braces, but the '{-|}', that causes the first letter of the next word to be capitalized. So to get 'Dr. King', you could stroke TKR*FPLT/KEUPBG.

Notice that in the above example, there's a space between the 'Dr.' and the 'King'. This has nothing to do with either the '.' or the '{-|}'. This is simply Plover inserting a space before each next word, as usual.

Just as the '{-|}' command  forces the first letter of the next word to be capitalized, so the '{>}' command forced the first letter of the next word to be lowercase:

"KEYSTROKE": "{>}",

Normally, stroking KO*EUPBG produces 'King'. But if you stroke the above entry first, and then stroke KO*EUPBG, it produces 'king'.

It's possible to suppress the space between words, using '{^}'. Consider if the 'king' entry used this:

"KEUPBG": "{^}king",

Now stroking TKR*FPLT/KEUPBG would produce 'Dr.King' instead of 'Dr. King'. The '{-|}' from the previous entry causes 'King' to be capitalized, while the '{^}' in this entry suppresses the space between 'Dr.' and 'King'.

You could get a similar effect by moving the '{^}' from the start of the 'king' entry to the end of the 'Dr.' entry.

"KEUPBG": "king",
"TKR*FPLT": "Dr.{-|}{^}",

Now TKR*FPLT/KEUPBG  will still produce 'Dr.King' with no space between 'Dr.' and 'King'. But the same effect will now be achieved for other doctors as well. So, TKR*FPLT/HOUS produces 'Dr.House', and TKR*FPLT/WHO produces 'Dr.Who'.

If you like this space-suppressing effect in general, but just not for a specific case, you can force Plover to output a space, using '{ }' (a blank space wrapped between curly braces).

"KEUPBG": "{ }king",
"TKR*FPLT": "Dr.{-|}{^}",

Now, TKR*FPLT/HOUS will still produce 'Dr.House' and TKR*FPLT/WHO will still produce 'Dr.Who', but TKR*FPLT/KEUPBG will produce 'Dr. King', with a space between 'Dr.' and 'King'.

Notice that the second stroke overrode the first. The TKR*FPLT stroke instructs Plover to suppress the following space, but then the KEUPBG stroke tells Plover to add it back in again.

Extended {^} Commands

In the previous section, we saw how '{^}' could be used to suppress the space between a word and its neighbor in either direction. In fact, this is the foundation of a very powerful feature of Plover - the ability to support prefix and suffix strokes.

"K*EUL": "{kilo^}",

In the above entry, the '^' is on the right, and suppresses the space between the 'kilo' and the next word. It has the effect of turning the 'kilo' into a prefix that you can prepend onto any word. So K*EUL/KEUPBG produces 'kiloking', K*EUL/HOUS produces 'kilohouse', and K*EUL/WHO produces 'kilowho'.

Or consider the opposite case:

"-G": "{^ing}"

In the above entry, the '^' is on the left, and suppresses the space between the 'ing' and the previous word. It has the effect of turning the 'ing' into a suffix that you can append onto any word. So KEUPBG/-G produces 'kinging', and HOUS/-G produces 'housing', and WHO/-G produces 'whoing'.

But wait! There was something unexpected in one of those examples. Why didn't HOUS/-G produce 'houseing' instead of 'housing' How did Plover know to drop the final 'e' before adding the 'ing'?

In fact, Plover recognizes four special suffixes - '-ed', '-ing', '-er', and '-s':

"-D": "{^ed}",
"-G": "{^ing}",
"*ER": "{^er}"
"-S": "{^s}",

These four suffix strokes have special logic in the Plover engine itself that has nothing to do with the dictionary file, and that cause them to do the right thing when used at the end of most words. So HEUT/-G produces 'hitting' with a doubled 't', while KAOEP/-G produces 'keeping' with only a single 'p'. The Plover engine understands the English rules for adding these suffixes to words.

Other suffix strokes simply append their suffix to the existing word as stroked.

"KRAES": "{^cracy}",

The above suffix has no logic internal to the Plover engine, and simply appends 'cracy' to whatever word came before. So KEUPBG/-KRAES produces 'kingcracy', HOUS/-KRAES produces 'housecracy', and WHO/-KRAES produces 'whocracy'.

Prefixes and suffixes can be combined without any root word:

"EUD/KWRO": "{idio^}",
"KRAES": "{^cracy}",

The above two entries can be stroked together as EUD/KWRO/KRAES to produce 'idiocracy'.

It's also possible to use the '^' at both ends of an entry, to suppress the space on both sides:

"K*UPL": "{^-cum-^}",

Using the above entry, it's possible to stroke PHURD/K*UPL/S-DZ to produce 'murder-cum-suicide'.

The '^' is a general-purpose command. It can be used wherever you'd like to suppress a previous or subsequent word break:

"SKWR-RBGS": "{^...}{ }{-|}",

The above entry produces the ellipses, followed by a space, and capitalizing the following word. It can be used when the ellipses are intended to end a sentence. So you could stroke HE/WAS/TKPWOPB/SKWR-RBGS/WE/HREFT/-T/TPHELGT/TKAEU to produce 'He was gone... We left the next day.'

An example of a case where word breaks must be routinely altered is when using quotes.

"KR-GS": "{^~|\"}",
"KW-GS": "{~|\"^}",

These are the dictionary entries for the closing quote and the opening quote. For example, stroke SAEU/KW-GS/HEU/KR-GS/TO/HEUPL to produce 'say "hi" to him'.

The '~|' tells Plover to maintain capitalization after the quote. If one does KPA/KW-GS/HEL/HROE the result is '"Hello'; however, if one were to do KPA/S-P/HEL/HROE the result would be ' hello' as the KPA capitalization is no longer in effect. 

Sometimes you want punctuation on the inside of the quote, sometimes on the outside. Personally, I put punctuation on the inside when quoting human speech, and outside when quoting computer speech. Plover supports both approaches:

"KR-GS/TP-PL": "{^\"}{^}.{^ ^}{-|}",
"TP-PL/KR-GS": "{^}.{^\"}{^ ^}{-|}",

The first entry suppresses a space after the previous word, then adds the double quote character, then suppresses the space after that and adds the period character, then adds a space, and capitalizes the first letter of whatever word comes next. So for example, stroke AOUS/KW-GS/TKPW*/R*/E*/P*/KR-GS/TP-PL/EUT/WORBGS to produce 'use "grep". It works'. 

The second entry does the same, but outputs the period before the double quote character. So for example, stroke SAEU/KW-GS/HEU/TP-PL/KR-GS/TKPWO/OPB to produce 'say "hi." Go on'.

The {&} Glue Command

The '&' command is similar to the '^' command. It always suppresses spaces on both the left and the right sides of the output; but only for neighboring strokes that are also '&' glue commands. This is the foundation of Plover's fingerspelling support.

"P*": "{&p}",
"*EU": "{&i}",
"T*": "{&t}",

These are the dictionary entries for the fingerspelled letters 'p', 'i', and 't'. To fingerspell the word 'pit', you could stroke P*/*EU/T*. To type 'snake pit city' you could stroke STPHAEUBG/P*/*EU/T*/STEU.

Notice that 'snake' and 'city' are not joined with 'pit' into 'snakepitcity', because the entries for 'snake' and 'city' don't contain the '&' glue command, while the strokes for the letters 'p', 'i', and 't' do:

"STPHAEUBG": "snake",
"STEU": "city",

Also notice that the '&' character has no special power in the dictionary file, outside of curly braces:

"HED/PH-PBD/SHOULD/ERS": "Head & Shoulders",

In the above entry, the '&' in the output portion of the entry is just a regular ampersand. It only becomes a glue command inside curly braces. So when you stroke HED/PH-PBD/SHOULD/ERS, you get the exact output 'Head & Shoulders'.

Raw {#} Keyboard Inputs

A lot of computer software takes keyboard command sequences, and often these sequences use keys like CTRL, ESC, SHIFT, NumLock, F7, and so on. Plover allows you to define strokes that simulate pressing any key on the keyboard, in any simultaneous combination and in any sequential order. This feature can give you tremendous power over your computer, but it also comes with dangerous caveats. As we've seen, Plover will unhesitatingly guess at the meaning of a stroke, then back up and replace that stroke with another. If your software can't tolerate commands that back up and change, then you'll need to make sure none of the strokes for these commands have any conflicting matches in the dictionary file. And since the dictionary file changes over time as you refine it, you'll need to make sure no conflicts emerge over time.

Before explaining how to encode raw keyboard input, it may be useful to see the full list of available key names. These correspond exactly to the traditional names of key codes that a keyboard can send into to the computer.

Available Key Names

The following is the full set of keys that may be referenced with the '{#}' command in Plover (note that the Super_L and Super_R keys correspond to the command keys in OSX.):

0 BackSpace ediaeresis F29 igrave KP_Next Multi_key plus section y
1 bar Ediaeresis F3 Igrave KP_Page_Down MultipleCandidate plusminus Select Y
2 Begin egrave F30 Insert KP_Page_Up multiply PreviousCandidate semicolon yacute
3 braceleft Egrave F31 j KP_Prior n Print Shift_L Yacute
4 braceright Eisu_Shift F32 J KP_Right N Prior Shift_Lock ydiaeresis
5 bracketleft Eisu_Toggle F33 k KP_Separator Next q Shift_R yen
6 bracketright End F34 K KP_Space nobreakspace Q SingleCandidate z
7 Break equal F35 Kana_Lock KP_Subtract notsign question slash Z
8 brokenbar Escape F4 Kana_Shift KP_Tab ntilde questiondown space Zenkaku
9 c eth F5 Kanji KP_Up Ntilde quotedbl ssharp Zenkaku_Hankaku
a C Eth F6 Katakana l numbersign quoteleft sterling Zen_Koho
A Cancel ETH F7 KP_0 L Num_Lock quoteright Super_L  
aacute Caps_Lock exclam F8 KP_1 L1 o r Super_R  
Aacute ccedilla exclamdown F9 KP_2 L10 O R Sys_Req  
acircumflex Ccedilla Execute Find KP_3 L2 oacute R1 t  
Acircumflex cent f g KP_4 L3 Oacute R10 T  
acute Clear F G KP_5 L4 ocircumflex R11 Tab  
adiaeresis colon F1 grave KP_6 L5 Ocircumflex R12 thorn  
Adiaeresis comma F10 greater KP_7 L6 odiaeresis R13 threequarters  
ae Control_L F11 guillemotleft KP_8 L7 Odiaeresis R14 threesuperior  
AE Control_R F12 h KP_9 L8 ograve R15 Touroku  
agrave copyright F13 H KP_Add L9 onehalf R2 twosuperior  
Agrave currency F14 Hankaku KP_Begin Left onequarter R3 u  
Alt_L d F15 Henkan KP_Decimal less onesuperior R4 U  
Alt_R D F16 Henkan_Mode KP_Delete Linefeed ordfeminine R5 uacute  
ampersand dedilla F17 Hiragana_Katakana KP_Divide m oslash R6 ucircumflex  
apostrophe degree F18 Home KP_Down M otilde R7 udiaeresis  
aring Delete F19 Hyper_L KP_End macron p R8 ugrave  
Aring diaeresis F2 Hyper_R KP_Enter Mae_Koho P R9 Ugrave  
asciicircum division F20 hyphen KP_Equal masculine Page_Down Redo underscore  
asciitilde dollar F21 i KP_F1 Massyo Page_Up registered Undo  
asterisk Down F22 I KP_F2 Menu paragraph Return Up  
at e F23 iacute KP_F3 Meta_L parenleft Right v  
atilde E F24 Iacute KP_F4 Meta_R parenright Romaji V  
Atilde eacute F25 icircumflex KP_Home minus Pause s w  
b Eacute F26 Icircumflex KP_Insert Mode_switch percent S W  
B ecircumflex F27 idiaeresis KP_Left mu period script_switch x  
backslash Ecircumflex F28 Idiaeresis KP_Multiply Muhenkan periodcentered Scroll_Lock X  

Key Sequences

To define a dictionary entry that will send a series of keystrokes to your computer, list all the keys within the '{#}' command, separated by spaces:

"KEYSTROKE": "{#w h i l e parenleft parenright Return braceleft Return space space space space Return braceright Return Up Up End}",

The above entry will produce:

'while()
{
   
_
}'

In the above output, the cursor is placed at the line between the curly braces, at the far right.

Any '{#}' command may be interspersed with other commands:

"KEYSTROKE": "{^} {#h i space t h e} {#r e}",

The above entry will prevent Plover from adding a space after the previous word, and will then output 'hi there'. Note that the word 'there' is not output as 'the re'. Plover does not automatically insert spaces between two '{#}' commands.

Holding Shift Keys

To define an entry that uses one of the shift keys, first include the name the shift key, then in parentheses put the names of the sequence of keys to press and release:

"KEYSTROKE": "{#Shift_L(h a p) p y}",

The above entry will produce 'HAPpy'. It was as if you first held down the left shift key, then pressed and released the "h", "a", and "p" keys in succession; then released the left shift key, and finally pressed and released the "p" and "y" keys in succession.

You may intersperse parenthesized shift-groups within any '{#}' command:

"KEYSTROKE": "{#Control_L(f) Shift_L(t)}",

The above entry is as if you

  1. held down the left CTRL key
  2. pressed and released the "f" key
  3. released the CTRL key
  4. held down the left shift key
  5. pressed and released the "t" key
  6. released the left shift key

Nesting For Arbitrary Combinations

It is also possible to nest parenthesized shift-groups, to simulate holding down more than one shift key at a time:

"KEYSTROKE": "{#Control_L(Alt_L(Delete))}",

The above entry might reboot some computers. It is as if you first held down the left CTRL key, then also held down the left ALT key, and then (with both of those keys held down) pressed and released the delete key.

The {Plover:} Control Commands

You can give commands to the Plover software to turn it on, off, add a new dictionary entry, and a few other things. In the following examples, replace "STROKE" with the actual key combinations you want to associate with each command.

Defaults are set for some of these commands in commands.json.

Add Translation

The ADD_TRANSLATION command pops up Plover's dictionary editing window. The introduction of this command is what brought Plover across the threshold and made it professionally usable.

"TKUPT": "{PLOVER:ADD_TRANSLATION}",

Notice that the TKUPT stroke is short for "dictionary update". It's the recommended stroke for this command.

The ADD_TRANSLATION command pops up a window that has input fields to add a new dictionary stroke and its desired output. Note that you can tab between the input and output fields using the Tab command (either via a Plover stroke or pressing the Tab key on the QWERTY keyboard). You may also accept the entry using the Enter command (also either via a Plover stroke or by pressing the Enter key on the QWERTY keyboard). Or, instead of pressing Enter, you may abort the new translation and close the pop-up interface using the Escape command (also either via a Plover stroke or by pressing the Esc key on the QWERTY keyboard).

Suspend

The SUSPEND command causes Plover to stop interpreting keystrokes as steno inputs and return to normal QWERTY mode.

"PHROF": "{PLOVER:SUSPEND}",

Resume

The RESUME command causes Plover to leave QWERTY mode and interpret keystrokes as steno inputs. Note that the keystroke to invoke the RESUME command does work when the keyboard is in QWERTY mode. That and the TOGGLE command are the only strokes that do.

"PHROPB": "{PLOVER:RESUME}",

Toggle

The TOGGLE command causes plover to enter QWERTY mode if it's in steno mode, and enter steno mode if it's in QWERTY mode. Note that Plover correctly interprets the keystroke to invoke the TOGGLE command regardless of which mode Plover is in at the time.

"PHROLG": "{PLOVER:TOGGLE}",

Configure

The CONFIGURE command pops up Plover's configuration window.

"KEYSTROKE5": "{PLOVER:CONFIGURE}",

Focus

The FOCUS command raises the Plover window and puts the cursor focus inside it; or if the window is minimized, Plover de-minimizes it and then raises it.

"KEYSTROKE6": "{PLOVER:FOCUS}",

Quit

The QUIT command causes the Plover process to terminate. The software exits entirely, leaving the keyboard in QWERTY mode.

"KEYSTROKE7": "{PLOVER:QUIT}",