Closed FrankRuben closed 1 year ago
Thanks for this suggestion! I will have to look more at it, and I think it would be important to support files and pipes as well as the console. But using ReadConsoleInput
directly looks promising; it's not something I've tried before, and it seems to avoid problems that I've run into with other approaches for non-blocking input from the console.
After trying out this direction, I think it's probably not a good idea. This approach is something like stty raw -echo
in that it provides raw keys and doesn't echo them as a user types. To make it behave something like Unix input, we'd have to do something like implementing a command-line editor on Windows.
In contrast, it's easy to add support for 'avail
mode for input streams on Windows other than consoles. We can make 'avail
mode support pipes, including input piped from another process. And since Zuo is pretty good at running processes, that gives us an alternative solution: a subprocess can read from stdin (in blocking mode) one byte at a time and echo to its stdout, thus converting console input to pipe input.
;; bounce.zuo
#lang zuo
(let loop ()
(define s (fd-read (fd-open-input 'stdin) 1))
(unless (eq? s eof)
(display s)
(loop)))
;; main.zuo
#lang zuo
(define p (process (hash-ref (runtime-env) 'exe)
(at-source "bounce.zuo")
(hash 'stdout 'pipe)))
;; should burn a CPU as it busy-waits, and won't always
;; get a whole input line at once:
(let loop ()
(define s (fd-read (hash-ref p 'stdout) 'avail))
(unless (eq? s eof)
(unless (equal? s "")
(alert s))
(loop)))
Disclaimer: I'm not an expert on this - I just was so fascinated by Zuo's quick start time that I started to fiddle around with it for simple and fast standalone TUI-executables (yes, I've read that it is not meant for that...) and got stuck on the non-blocking user-input for Windows - and tried to use that given API, that I used elsewhere before.
So my main purpose was to support user-interaction, and the thought was to better have non-blocking console-input for Windows than to not having any non-blocking input for Windows at all, and I didn't even consider pipes or files.
After trying out this direction, I think it's probably not a good idea. This approach is something like
stty raw -echo
in that it provides raw keys and doesn't echo them as a user types.
There are various flags for the SetConsoleMode API, but the echo feature seems to be only allowed in combination with a line-input regime, which is exactly what I wanted to avoid.
To make it behave something like Unix input, we'd have to do something like implementing a command-line editor on Windows.
If I understand you correctly here, the restriction mentioned above that one would need a more sophisticated input layer to allow both non-blocking input and echoing - and without testing various console-flag combinations I would expect the same.
...alternative solution...
I need to play around with this, it's yet a bit above my current Zuo expert level :).
Anyway: thanks for considering this request, thanks for Zuo and thanks for the tremendous work on Racket.
I'm not sure whether that really helps and whether that diff below is the best way to bring that topic forward, but I hacked together Windows support for non-blocking
(fd-read ... 'avail)
.The code is all but nice - and that is only partly because the error handling is rather unwieldy - but it seems to work in the sense that
(fd-read ... 'avail)
now returns""
if no input is available or a string with the next char one available and whereas the other values for(fd-read ... amount)
to still behave as they did before.The changed code is behind cpp-define
FR_ADDED_WINCONSOLE
, so it should be simple to test with and without that change.If there is another way to help, please tell me so.