[gambit-list] How use (read-char) to read individual characters from the console?
Marc Feeley
feeley at iro.umontreal.ca
Thu Jan 3 10:24:38 EST 2013
On 2013-01-02, at 6:05 PM, Mikael <mikael.rcv at gmail.com> wrote:
> Here's a read-char suitable for console games etc. .
>
> (define (nice-read-char)
> (tty-mode-set! (repl-input-port) #t #f #t #f 0)
> (let ((c (read-char)))
> (tty-mode-set! (repl-input-port) #t #t #f #f 0)
> (if (eq? c #\x) (raise "Escape to REPL")) ; CTRL-C replacement
> c))
>
> A version 2 of it would be to make it handle ctrl+c appropriately, currently that throws the console into a state as per the previous email.
A much simpler solution for your use case is to start gsi with the "-" option and put the current-input-port (stdin) in cooked mode, leaving the repl-input-port (the controlling terminal) alone:
% gsi -
> (tty-mode-set! (current-input-port) #t #f #t #f 0)
> (list (read-char) (read-char)) ;; after this I will type the keys 1 and 2 without enter
(#\1 #\2)
> ,q
That way you won't have to flip the mode back and forth when reading a raw character. Note that this works because with the "-" option, gsi will be in "batch mode" where it uses distinct ports for the current-input-port and the repl-input-port. When gsi is in interactive mode (without the "-" option or file names), the same port is used (the controlling terminal):
% gsi -
> (repl-input-port)
#<input-output-port #2 (console)>
> (current-input-port)
#<input-port #3 (stdin)>
> ,q
% gsi
Gambit v4.6.6
> (repl-input-port)
#<input-output-port #2 (console)>
> (current-input-port)
#<input-output-port #2 (console)>
> ,q
*** EOF again to exit
If your use case requires that the repl-input-port and current-input-port are the same, then you could use the following strategy which puts the tty in cooked mode only when the REPL reads a command:
(define (wrap-in-cooked-tty fn)
(lambda args
(cooked-tty)
(let ((result (apply fn args)))
(raw-tty)
result)))
(define (cooked-tty)
(tty-mode-set! (repl-input-port) #t #t #f #f 0))
(define (raw-tty)
(tty-mode-set! (repl-input-port) #t #f #t #f 0))
(raw-tty)
(let ((channel (##thread-repl-channel-get! (current-thread))))
(include "~~/lib/_gambit#.scm")
(macro-repl-channel-read-command-set!
channel
(wrap-in-cooked-tty (macro-repl-channel-read-command channel))))
Marc
More information about the Gambit-list
mailing list