I have a Rebol2 console app (Rebol Core) which I would like to disable the keyboard character echo to the console. The app is run from a minimal Linux kernel/initramfs, and is started by busybox inittab (not from terminal). It has a minimal console user interface using ansi codes for color, etc., and responds to menu selections via single key presses. To 'quiet' the console, I have the cursor turned off, and don't see the output of the key presses (until recently).
I previously thought I had the problem solved by calling 'stty -echo' within Rebol, but it actually does not work as I just discovered- there is one function that takes 5-10 seconds and can see the echoed key presses while waiting for the function to complete.
I'm not quite sure why I only see the echoed characters while this one function is running, but it is the only function which takes any amount of time. The keyboard is polled by opening the console:// in binary mode, waiting for a key press, then a switch statement to choose the function. The reading of the keys in binary/console seem to 'consume' the key echo-
minimal example, pressing 'a'-
cons: open/binary console://
first cons
== 97
(the value is returned as I want, and the char is not echoed, which is good- I think in most functions my keys are 'consumed' in the get-key loop, but the longer function does not get a chance to 'consume' them, and end up echoing to the console)
Is there some way to disable the console character echo inside Rebol2? I have looked in system/console and system/ports/input,output, but don't see anything obvious. My current workaround is to simply change the text color to match the background so any key presses are not visible while the specific function runs.
here is a minimal example of what I'm doing-
get-key: func [ /local cons ch ][
cons: open/binary console://
ch: lowercase to-string to-char first cons
all [ equal? ch "^[" append ch copy/part cons 2 ]
close cons
ch
]
forever [
switch get-key [
;up arrow
"^[[A" [ some-function1 ]
;down arrow
"^[[B" [ some-function2 ]
;enter
"^M" [ some-function3 ]
;quit
"q" [ break ]
]
]
The forever loop seems to 'consume' the keyboard input (nothing echoed), but if one of the functions takes any amount of time, any keyboard input will get echoed to the screen wherever the cursor happens to be. In most cases I never see any echoed characters as the time between calling get-key is minimal. I would also note that the echoed characters do not also show up in the subsequent call to get-key.
update-
here is a better sample of code to see the problem-
get-key: has [ cons ch ][
cons: open/binary console://
ch: lowercase to-string to-char first cons
prin rejoin [ "<" ch ">" ] ;show get-key chars
ch
]
long-func: does [ call/wait {sleep 10} ]
reb-func: does [ wait 10 ]
forever [
switch get-key [
"f" [ long-func ]
"r" [ reb-func ]
"q" [ break ]
]
]
I figured out that my 'long' function is using call's which can take a few seconds, so the problem arises when a call is used.
The above code, when run will show that keys are echoed only because they are printed in the get-key function (brackets), when the long-func is running, then keys are echoed outside of get-key (no brackets), and when done the get-key will process those keys also. Or simply run 'call/wait {sleep 10}' and you will get echoed keys while waiting, and also get the sames keys echoed by Rebol when the call returns. Keys are not echoed when reb-func runs, and get-key will process all buffered keys when reb-func is done. The keyboard input is being handled twice when call is used.
I have tried redirecting stdin/stdout in the call command (in the call string command, like at bash prompt), but have not found a combo that works. (My actual code runs call with /output/error to capture all output).
The rearranged console code is not necessary (and all keys are cached no matter which arrangement is used), although the ability to add an awake function is nice to know. In my real code, the get-key has a '/timeout t' option where I can do a 'wait [ cons t ]' and return a string (for extended key codes like up arrow) or none, which means I can also flush the console input before my switch get-key (so any keys pressed while running functions get flushed).
forever [
while [ get-key/timeout 0.1 ][] ;flush
switch get-key [ ;wait for key
...
The 'stty -echo' works well in the example given, and would seem to solve my problem, but I still see a few characters echoed if I press a bunch of keys while the long functions are running (I inserted {stty -echo; } in all commands). Somehow, in the Rebol call creating of processes (fork/exec I assume), tty input/output can still 'leak' i/o characters. Or maybe one of the programs called is opening a tty even though it inherits the file descriptors of the parent.
Here is what I ended up doing- changing the way I call commands so they run in background, but still wait for them to complete.
;used by other funcs to parse output of commands
set 'cmd-output "" ;output from 'call' commands
set 'cmd-error "" ;error from 'call commands
set 'cmd func [ str [string!] /local ret ][
--old--
;clear previous
cmd-output: copy ""
cmd-error: copy ""
;--new--
write %out ""
write %err ""
attempt [ delete %ret ]
;--old--
;ret: call/wait/output/error str cmd-output cmd-error
;--new-- stdout->out stderr->err exitcode->ret
call rejoin [ str { >out 2>err; echo -n $? > ret} ]
;wait for return code, (up to 20 seconds, should be plenty)
loop 200 [ all [ exists? %ret break ] wait 0.1 ]
cmd-output: read %out
cmd-error: read %err
ret: to-integer read %ret
--old--
;debug-cmd writes info to a logfile
debug-cmd str ret
ret
]
This works, as I cannot get any (unwanted) characters to show on the screen as before (and I guess it proves those characters were coming from the called processes).