Appendix: The Dictionary Format

This is Aerick's video on remaining Plover lessons and the dictionary file format:

Aerick's 3rd Plover Video

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.):

0BackSpaceediaeresisF29igraveKP_NextMulti_keyplussectiony
1barEdiaeresisF3IgraveKP_Page_DownMultipleCandidateplusminusSelectY
2BeginegraveF30InsertKP_Page_UpmultiplyPreviousCandidatesemicolonyacute
3braceleftEgraveF31jKP_PriornPrintShift_LYacute
4bracerightEisu_ShiftF32JKP_RightNPriorShift_Lockydiaeresis
5bracketleftEisu_ToggleF33kKP_SeparatorNextqShift_Ryen
6bracketrightEndF34KKP_SpacenobreakspaceQSingleCandidatez
7BreakequalF35Kana_LockKP_SubtractnotsignquestionslashZ
8brokenbarEscapeF4Kana_ShiftKP_TabntildequestiondownspaceZenkaku
9cethF5KanjiKP_UpNtildequotedblssharpZenkaku_Hankaku
aCEthF6KatakanalnumbersignquoteleftsterlingZen_Koho
ACancelETHF7KP_0LNum_LockquoterightSuper_L 
aacuteCaps_LockexclamF8KP_1L1orSuper_R 
AacuteccedillaexclamdownF9KP_2L10ORSys_Req 
acircumflexCcedillaExecuteFindKP_3L2oacuteR1t 
AcircumflexcentfgKP_4L3OacuteR10T 
acuteClearFGKP_5L4ocircumflexR11Tab 
adiaeresiscolonF1graveKP_6L5OcircumflexR12thorn 
AdiaeresiscommaF10greaterKP_7L6odiaeresisR13threequarters 
aeControl_LF11guillemotleftKP_8L7OdiaeresisR14threesuperior 
AEControl_RF12hKP_9L8ograveR15Touroku 
agravecopyrightF13HKP_AddL9onehalfR2twosuperior 
AgravecurrencyF14HankakuKP_BeginLeftonequarterR3u 
Alt_LdF15HenkanKP_DecimallessonesuperiorR4U 
Alt_RDF16Henkan_ModeKP_DeleteLinefeedordfeminineR5uacute 
ampersanddedillaF17Hiragana_KatakanaKP_DividemoslashR6ucircumflex 
apostrophedegreeF18HomeKP_DownMotildeR7udiaeresis 
aringDeleteF19Hyper_LKP_EndmacronpR8ugrave 
AringdiaeresisF2Hyper_RKP_EnterMae_KohoPR9Ugrave 
asciicircumdivisionF20hyphenKP_EqualmasculinePage_DownRedounderscore 
asciitildedollarF21iKP_F1MassyoPage_UpregisteredUndo 
asteriskDownF22IKP_F2MenuparagraphReturnUp 
ateF23iacuteKP_F3Meta_LparenleftRightv 
atildeEF24IacuteKP_F4Meta_RparenrightRomajiV 
AtildeeacuteF25icircumflexKP_HomeminusPausesw 
bEacuteF26IcircumflexKP_InsertMode_switchpercentSW 
BecircumflexF27idiaeresisKP_Leftmuperiodscript_switchx 
backslashEcircumflexF28IdiaeresisKP_MultiplyMuhenkanperiodcenteredScroll_LockX 

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}",