2 '(' TITLE MAP-LIST MODULE-LIST ? STATE-LIST ')'
11 '(' MAP-NAME RULE * ')'
17 '(' KEYSEQ MAP-ACTION * ')'
20 mtext | '(' [ symbol | integer ] * ')'
26 mtext | CANDIDATES | '(' ACTION-NAME ACTION-ARG * ')'
29 '(' CANDIDATE-GROUP * ')'
32 MTEXT is a short form of "(insert MTEXT)"
33 CANDIDATES is a short form of "(candidates CANDIDATE-GROUP *)")
36 'insert' | 'candidates' | 'delete' | 'select' | 'select-group'
37 | 'move' | 'mark' | 'pushback' | 'undo' | 'shift' | 'call'
40 integer | symbol | mtext | CANDIDATE-GROUP
43 mtext | '(' mtext * ')'
46 '@0' | '@1' | '@2' | '@3' | '@4' | '@5' | '@6' | '@7' | '@8' | '@9'
47 | '@<' | '@=' | '@>' | '@-' | '@+'
50 PREDEFINED-SYMBOL | symbol
55 CANDIDATE-GROUP-INDEX ::=
58 ;; The first five actions ('insert' .. 'select-group') are for
59 ;; editing a text in the preediting buffer. The buffer can keep
60 ;; multiple markers. Each marker is represented by a symbol, and
61 ;; keeps a position between characters in the preediting buffer.
63 ;; PREDEFINED-SYMBOL has special meanings when used as MARKER:
64 ;; '@0', '@1', ... '@9'
65 ;; The 0th, 1th, ... 9th position.
67 ;; The first, current, and end position.
69 ;; The previous and next position.
71 ;; PREDEFINED-SYMBOL has special meanings when used as CANDIDATE-INDEX:
72 ;; '@0', '@1', ... '@9'
73 ;; The 0th, 1th, ... 9th candidate of the current candidate group.
75 ;; The first, current, and end candidate of the current candidate
78 ;; The previous candidate. If the current candidate is the
79 ;; first of the current candidate group, the last candidate of
80 ;; the previous candidate group.
82 ;; The next candidate. If the current candidate is the last of
83 ;; the current candidate group, the first candidate of the
84 ;; previous candidate group.
86 ;; PREDEFINED-SYMBOL has special meanings when used as CANDIDATE-INDEX:
87 ;; '@0', '@1', ... '@9'
88 ;; The 0th, 1th, ... 9th candidate of the current candidate group.
90 ;; The first, current, and end candidate of the current candidate
93 ;; The previous candidate. If the current candidate is the
94 ;; first of the current candidate group, the last candidate of
95 ;; the previous candidate group.
97 ;; The next candidate. If the current candidate is the last of
98 ;; the current candidate group, the first candidate of the
99 ;; previous candidate group.
101 ;; PREDEFINED-SYMBOL has special meanings when used as
102 ;; CANDIDATE-GROUP-INDEX:
103 ;; '@0', '@1', ... '@9'
104 ;; The 0th, 1th, ... 9th candidate group.
106 ;; The first, current, and end candidate group.
108 ;; The previous and the next candidate group.
110 ;; (insert MTEXT) inserts MTEXT before @=.
112 ;; (candidates CANDIDATE-GROUP *) set the current candidates list
113 ;; to the list of arguments, set the current candidate group to the
114 ;; first argument, insert the first candidate of the current group
115 ;; before @=, and mark the inserted text as the current candidate.
116 ;; Each element of CANDIDATE-GROUP represents a candidate, i.e. if
117 ;; CANDIDATE-GROUP is MTEXT, each character in MTEXT is a
118 ;; candidate, if CANDIDATE-GROUP is a list of MTEXT, each MTEXT is
121 ;; (select CANDIDATE-INDEX) replaces the current candidate with
122 ;; what specified by CANDIDATE-INDEX. If a candidate of the
123 ;; different candidate group is specified, set the current
124 ;; candidate group to that group.
126 ;; (select-group CANDIDATE-GROUP-INDEX) sets the current candidate
127 ;; group to a group indicated by CANDIDATE-GROUP-INDEX, and relaces
128 ;; the current candiate with the candiate of the same index in the
131 ;; (delete MARKER) deletes characters between @= and the position
132 ;; specified by MARKER.
134 ;; (move MARKER) sets @= to the position of specified by MARKER.
136 ;; (mark MARKER) sets MARKER to the position of @=. MARKER must
137 ;; not be PREDEFINED-SYMBOL.
139 ;; (pushback) pushbacks the latest key events to the event queue.
141 ;; (undo) cancels the last key events.
143 ;; (shift STATE-NAME) shifts the current state to the state
144 ;; specified by STATE-NAME.
146 ;; (call FUNCTION ARG *) calls the function FUNCTION of an external
147 ;; module. FUNCTION must be defined in MODULE-LIST.
149 ;; The function is called with a property list (MPlist *) that has
150 ;; these properties in this order.
153 ;; mtext The current preedit text.
154 ;; symbol The current state name (MSymbol).
155 ;; The remaining properties (if any) are ARGs.
157 ;; The function must return a property list (MPlist *) that
158 ;; represents a list of ACTIONs to take.
161 '(' 'module' MODULE * ')'
164 '(' MODULE-NAME FUNCTION * ')'
173 '(' 'state' STATE * ')'
176 '(' STATE-NAME BRANCH * ')'
182 '(' [ MAP-NAME | 'nil' ] BRANCH-ACTION * ')'
184 ;; If MAP-NAME is specified, it must be a name of a map defined in
185 ;; MAP-LIST. Otherwise, BRANCH is the default branch of STATE.
199 ("bb" (("BB" "Bb"))))
202 ((Right) (select @+))))
207 (double (shift selection)))
211 ;; When this input method is loaded, the following state transition
212 ;; machine is created.
214 ;; STATE-TRANSITION-MACHINE ::=
215 ;; '(' STATE-NAME ROOT-MAP ')' *
216 ;; ROOT-MAP ::= TRANSITION-MAP
217 ;; TRANSITION-MAP ::=
218 ;; '(' INDEX [ KEY | 'nil' ]
219 ;; MAP-ACTIONS TRANSITION-MAPS BRANCH-ACTIONS ')'
220 ;; TRANSITION-MAPS ::=
221 ;; '(' TRANSITION-MAP * ')'
223 ;; '(' MAP-ACTION * ')'
224 ;; BRANCH-ACTIONS ::=
225 ;; '(' BRANCH-ACTION * ')'
229 ((#1 'a' ((insert "A")) nil nil)
230 (#2 'b' ((insert "B"))
231 ((#3 'b' ((candidates (("BB" "Bb")))) nil (shift selection)))
236 ((#5 'Left' ((delete @<) (select @-)) nil nil)
237 (#6 'Right' ((delete @<) (select @+)) nil nil))
240 ;; The state transition machine keeps these things:
241 ;; STATE: the current state, initially 'init'.
242 ;; MAP: current transition map, initially #0.
243 ;; PREEDIT: the preediting buffer, initially empty.
244 ;; MARKERS: the positions assigned to each marker, @= is initially 0.
245 ;; PRODUCED: the produced text, initially empty.
246 ;; CANDIDATE-LIST: the current candidate group list, initially NULL.
247 ;; CANDIDATE-GROUP: the current candidate group, initially NULL.
248 ;; CANDIDATE: the the current candidate, initially NULL.
250 ;; When MAP is changed to the root map of the initial state, PREEDIT
251 ;; is concatenated to PRODUCED and reset to empty. This way, the
252 ;; machine produces a text.
254 ;; The machine accepts one key KEY, handles it while updating internal
255 ;; information, and return 'nil' (if KEY is correctly handled) or KEY
256 ;; (if KEY can't be handled in the machine).
258 ;; Here we describes how the key sequence:
259 ;; 'a' 'b' 'b' 'Right' 'b' 'a'
260 ;; is handled by the machine and "aBbba" is produced.
264 ;; Lookup the transition maps of #0 for 'a' and find #1. Change MAP
265 ;; to #1. Perform its map actions. Now PREEDIT contains "a". As it
266 ;; has no sub transition maps, no branch actions, no state to shift,
267 ;; change MAP to #0, the root map of the current state.
269 ;; As we have changed MAP to the root map of the initial map,
270 ;; concatenate PREEDIT to PRODUCED, and reset PREEDIT to empty.
272 ;; Now we have consumed the key. As MAP has sub transition maps, wait
277 ;; Lookup #0 for 'b' and find #2. Change MAP to #2. Perform the map
278 ;; actions. Now, PREEDIT contains "B". As it has sub transition
279 ;; maps, and we have consumed the key, wait for the next key.
284 ;; Lookup #2 for 'b' and find #3. Cancel the change in PREEDIT done
285 ;; by the map actions of #2, and change MAP to #3. Perform the map
286 ;; actions. Now, PREEDIT is "BB", CANDIDATE-LIST is (("BB" "Bb")),
287 ;; CANDIDATE is "BB". As #3 has no sub transition maps and no branch
288 ;; actions, change STATE to 'selection' and change MAP to #4, the root
289 ;; map of 'selection'. As it has sub transition maps, and we have
290 ;; consumed the key. Wait for the next key.
294 ;; Lookup #4 for 'Right' and find #5. Change MAP to #5. Perform the
295 ;; map actions. Now PREEDIT is "Bb". As #5 has no sub transition
296 ;; maps, no branch actions, no state to shift, change MAP to #4 (the
297 ;; initial map of the current state 'selection'.
299 ;; As #4 has sub transition maps, and we have consumed the key. Wait
304 ;; Lookup #4 for 'b' and fail. As #4 has no branch maps, no shift to
305 ;; transit, change STATE to 'init', MAP to #0.
307 ;; As we have changed MAP to the root map of the initial map,
308 ;; concatenate PREEDIT to PRODUCED, and reset PREEDIT to empty. Now
309 ;; PRODUCED has "aBb".
311 ;; As we have not yet consumed the key 'b', handle it in MAP (#0).
313 ;; Lookup #0 for 'b' and find #2. Change MAP to #2. Perform the map
314 ;; actions. Now, PREEDIT contains "B". As it has sub transition
315 ;; maps, and we have consumed the key, wait for the next key.
317 ;; 'a' arrives. Lookup #2 for 'a' and fail. As #2 has no branch
318 ;; actions, no state to shift, Change MAP to #0, the root map of the
321 ;; As we have changed MAP to the root map of the initial map,
322 ;; concatenate PREEDIT to PRODUCED, and reset PREEDIT to empty. Now
323 ;; PRODUCED has "aBbb".
325 ;; As we have not yet consumed the key 'a', handle it in MAP (#0).
327 ;; Lookup #0 for 'a' and find #1. Change MAP to #1. Perform its map
328 ;; actions. Now PREEDIT contains "a". As it has no sub transition
329 ;; maps, no branch actions, no state to shift, change MAP to #0, the
330 ;; root map of the current state.
332 ;; As we have changed MAP to the root map of the initial map,
333 ;; concatenate PREEDIT to PRODUCED, and reset PREEDIT to empty. Now
334 ;; PRODUCED has "aBbba".
336 ;; Now we have consumed the key. As MAP has sub transition maps, wait