1 \ *****************************************************************************
2 \ * Copyright (c) 2004, 2008 IBM Corporation
3 \ * All rights reserved.
4 \ * This program and the accompanying materials
5 \ * are made available under the terms of the BSD License
6 \ * which accompanies this distribution, and is available at
7 \ * http://www.opensource.org/licenses/bsd-license.php
10 \ * IBM Corporation - initial implementation
11 \ ****************************************************************************/
14 \ Implementation of ACCEPT. Using ECMA-48 for terminal control.
19 CREATE DOES> swap cells+ @ ?dup IF execute ELSE beep THEN ;
30 esc ." 8" accept-cur IF
31 csi base @ decimal accept-cur 0 .r base ! ." C"
36 accept-cur accept-len = IF EXIT THEN
38 accept-adr accept-len accept-cur /string type
42 : full-redraw-line ( -- )
43 accept-cur 0 to accept-cur move-cursor
44 accept-adr accept-len type
45 csi ." K" to accept-cur move-cursor
48 : redraw-prompt ( -- )
49 cr depth . [char] > emit
52 : insert-char ( char -- )
53 accept-len accept-max = IF drop beep EXIT THEN
54 accept-cur accept-len <> IF csi ." @" dup emit
55 accept-adr accept-cur + dup 1+ accept-len accept-cur - move
57 accept-adr accept-cur + c!
58 accept-cur 1+ to accept-cur
59 accept-len 1+ to accept-len redraw-line
63 accept-cur accept-len = IF beep EXIT THEN
64 accept-len 1- to accept-len
65 accept-adr accept-cur + dup 1+ swap accept-len accept-cur - move
84 accept-len 0= IF EXIT THEN
85 /his accept-len + alloc-mem
86 his-tail IF dup his-tail his>next ! ELSE dup to his-head THEN
87 his-tail over his>prev ! 0 over his>next ! dup to his-tail
88 accept-len over his>len ! accept-adr swap his>buf accept-len move
92 his-head BEGIN dup WHILE
93 cr dup his>buf over his>len @ type
94 his>next @ REPEAT drop
97 : select-history ( his -- )
99 dup his>len @ accept-max min dup to accept-len to accept-cur
100 his>buf accept-adr accept-len move ELSE
101 drop 0 to accept-len 0 to accept-cur THEN
110 \ tab completion state variables
115 \ compares two strings and returns the longest equal substring.
116 : $same-string ( addr-1 len-1 addr-2 len-2 -- addr-1 len-1' )
117 dup 0= IF \ The second parameter is not a string.
118 2drop EXIT \ bail out
120 rot min 0 0 -rot ( addr1 addr2 0 len' 0 )
121 DO ( addr1 addr2 len-1' )
124 = IF 1 + ELSE leave THEN
129 : $tab-sift-words ( text-addr text-len -- sift-count )
130 sift-compl-only >r true to sift-compl-only \ save sifting mode
132 last BEGIN @ ?dup WHILE \ loop over all words
133 $inner-sift IF \ any completions possible?
134 \ convert to lower case for user interface sanity
135 2dup bounds DO I c@ lcc I c! LOOP
136 ?tab-pressed IF 2dup type space THEN \ <tab><tab> prints possibilities
137 tab-last-adr tab-last-len $same-string \ find matching substring ...
138 to tab-last-len to tab-last-adr \ ... and save it
143 #sift-count 0 to #sift-count \ how many words were found?
144 r> to sift-compl-only \ restore sifting completion mode
147 \ 8< node sifting for tab completion on device tree nodes below this line 8<
151 10 new-stack device-stack
153 : (next-dev) ( node -- node' addr len )
156 dup child IF dup push child -rot EXIT THEN
157 dup peer IF peer -rot EXIT THEN
162 pop peer ?dup IF -rot EXIT THEN
167 : $inner-sift-nodes ( text-addr text-len node -- ... path-addr path-len true | false )
168 (next-dev) ( text-addr text-len node' path-addr path-len )
169 dup 0= IF drop false EXIT THEN
170 2dup 6 pick 6 pick find-isubstr ( text-addr text-len node' path-addr path-len pos )
172 #sift-count 1+ to #sift-count \ count completions
180 \ test function for (next-dev)
182 s" /" find-node BEGIN dup WHILE
190 \ node sifting wants its own pockets
191 create sift-node-buffer 1000 allot
192 0 value sift-node-num
194 sift-node-buffer sift-node-num 100 * +
195 sift-node-num 1+ dup 10 = IF drop 0 THEN
199 : $tab-sift-nodes ( text-addr text-len -- sift-count )
200 s" /" find-node BEGIN dup WHILE
201 $inner-sift-nodes IF \ any completions possible?
202 sift-node-buffer swap 2>r 2r@ move 2r> \ make an almost permanent copy without strdup
203 ?tab-pressed IF 2dup type space THEN \ <tab><tab> prints possibilities
204 tab-last-adr tab-last-len $same-string \ find matching substring ...
205 to tab-last-len to tab-last-adr \ ... and save it
209 #sift-count 0 to #sift-count \ how many words were found?
213 : $tab-sift ( text-addr text-len -- sift-count )
214 ?tab-pressed IF beep space THEN \ cosmetical fix for <tab><tab>
216 dup IF bl rsplit dup IF 2swap THEN ELSE 0 0 THEN >r >r
218 0 dup to tab-last-len to tab-last-adr \ reset last possible match
219 current-node @ IF \ if we are in a node?
221 $tab-sift-words to #sift-count \ search in current node first
222 2r> \ fetch text to complete, again
225 current-node @ >r 0 set-node \ now search in global words
226 $tab-sift-words to #sift-count
229 \ concatenate previous commands
230 r> r> dup IF s" " $cat THEN tab-last-adr tab-last-len $cat
231 to tab-last-len to tab-last-adr \ ... and save the whole string
234 \ 8< node sifting for tab completion on device tree nodes above this line 8<
237 0 to accept-cur move-cursor ;
239 accept-cur ?dup IF 1- to accept-cur ( csi ." D" ) move-cursor THEN ;
241 delete-char ( redraw-line ) ;
243 accept-len to accept-cur move-cursor ;
245 accept-cur accept-len <> IF accept-cur 1+ to accept-cur csi ." C" THEN ;
247 accept-cur 0= IF beep EXIT THEN
248 handle-^B delete-char
251 accept-adr accept-len
254 redraw-prompt full-redraw-line
255 false to ?tab-pressed
257 tab-last-adr accept-adr tab-last-len move \ copy matching substring
258 tab-last-len dup to accept-len to accept-cur \ len and cursor position
259 full-redraw-line \ redraw new string
260 true to ?tab-pressed \ second tab will print possible matches
266 BEGIN accept-cur accept-len <> WHILE delete-char REPEAT ;
268 history redraw-prompt full-redraw-line ;
270 his-cur IF his-cur his>next @ ELSE his-head THEN
271 dup to his-cur select-history
274 his-cur IF his-cur his>prev @ ELSE his-tail THEN
275 dup to his-cur select-history
277 : handle-^Q \ Does not handle terminal formatting yet.
282 0 to accept-len 0 to accept-cur full-redraw-line ;
288 TABLE-EXECUTE handle-CSI
289 0 , ' handle-^P , ' handle-^N , ' handle-^F ,
290 ' handle-^B , 0 , 0 , 0 ,
291 ' handle-^A , 0 , 0 , ' handle-^E ,
298 TABLE-EXECUTE handle-meta
302 0 , 0 , 0 , ' handle-fn ,
305 0 , 0 , 0 , ' handle-CSI ,
322 key drop ( drops closing 7e ) handle-^A
330 dup 1f and handle-CSI
344 dup 1f and handle-meta
349 TABLE-EXECUTE handle-control
363 0 , \ ^M: enter: handled in main loop
375 0 , \ ^Y: insert save buffer
383 : (accept) ( adr len -- len' )
385 to accept-max to accept-adr
386 0 to accept-len 0 to accept-cur
392 dup 9 <> IF 0 to ?tab-pressed THEN \ reset state machine
393 dup 7f = IF drop 8 THEN \ Handle DEL as if it was BS. ??? bogus
394 dup bl < IF handle-control ELSE
396 dup a0 < IF 7f and handle-meta ELSE drop beep THEN
403 accept-len to accept-cur