How use (read-char) to read individual characters from the console?
Hi, In using read-char I get results only on a per input line basis. I was trying to switch the input console to byte/character mode instead of line buffered, though I didn't get any result with this. Any thought or suggestion? Mikael
Afficher les réponses par date
Mikael, you need to change the tty mode :
(tty-mode-set! (repl-input-port) #t #f #t #f 0)
The booleans indicate various settings (ctrl-c handling, input echo, raw input, raw output). On UNIX, this changes the terminal's line discipline. On Windows, it changes the console mode. Marc On 2013-01-02, at 11:59 AM, Mikael <mikael.rcv@gmail.com> wrote:
Hi,
In using read-char I get results only on a per input line basis. I was trying to switch the input console to byte/character mode instead of line buffered, though I didn't get any result with this.
Any thought or suggestion?
Mikael
_______________________________________________ Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Aha neat! Just for reference to anyone who may want to use this to make a nice console-based Tetris etc., while in this tty mode repl-input-port *cannot* be used to drive the REPL. Though, it is ctrl+c sensitive. ( Using the REPL in this mode does not do eval when pressing enter anymore, does not echo input, and when using any arrow keys shows:
*** ERROR IN (console)@8.1 -- Illegal character: #\esc
) So here's a nice example of 'clean' use of this feature:
(begin (tty-mode-set! (repl-input-port) #t #f #t #f 0) (write (read-char)) (force-output) (write (read-char)) (force-output)(write (read-char)) (force-output)(write (read-char)) (force-output)(write (read-char)) (force-output)(write (read-char)) (force-output) (tty-mode-set! (repl-input-port) #t #t #f #f 0)) #\newline#\esc#\[#\A#\esc#\[>
Rather for completeness, how can add hooks to the switching of activity from the user code to Gambit REPL (on CTRL+C or exception) and back (by ,c)? By adding hooks to that that switch the TTY between read-char-friendly mode and REPL-friendly, people can also debug their console-based Tetris:es nicely. With warm regards, Mikael 2013/1/2 Marc Feeley <feeley@iro.umontreal.ca>
Mikael, you need to change the tty mode :
(tty-mode-set! (repl-input-port) #t #f #t #f 0)
The booleans indicate various settings (ctrl-c handling, input echo, raw input, raw output).
On UNIX, this changes the terminal's line discipline. On Windows, it changes the console mode.
Marc
On 2013-01-02, at 11:59 AM, Mikael <mikael.rcv@gmail.com> wrote:
Hi,
In using read-char I get results only on a per input line basis. I was trying to switch the input console to byte/character mode instead of line buffered, though I didn't get any result with this.
Any thought or suggestion?
Mikael
_______________________________________________ Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
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. 2013/1/2 Mikael
Aha neat!
Just for reference to anyone who may want to use this to make a nice console-based Tetris etc., while in this tty mode repl-input-port *cannot* be used to drive the REPL. Though, it is ctrl+c sensitive.
( Using the REPL in this mode does not do eval when pressing enter anymore, does not echo input, and when using any arrow keys shows:
*** ERROR IN (console)@8.1 -- Illegal character: #\esc
)
So here's a nice example of 'clean' use of this feature:
(begin (tty-mode-set! (repl-input-port) #t #f #t #f 0) (write (read-char)) (force-output) (write (read-char)) (force-output)(write (read-char)) (force-output)(write (read-char)) (force-output)(write (read-char)) (force-output)(write (read-char)) (force-output) (tty-mode-set! (repl-input-port) #t #t #f #f 0)) #\newline#\esc#\[#\A#\esc#\[>
Rather for completeness, how can add hooks to the switching of activity from the user code to Gambit REPL (on CTRL+C or exception) and back (by ,c)?
By adding hooks to that that switch the TTY between read-char-friendly mode and REPL-friendly, people can also debug their console-based Tetris:es nicely.
With warm regards, Mikael
2013/1/2 Marc Feeley <feeley@iro.umontreal.ca>
Mikael, you need to change the tty mode :
(tty-mode-set! (repl-input-port) #t #f #t #f 0)
The booleans indicate various settings (ctrl-c handling, input echo, raw input, raw output).
On UNIX, this changes the terminal's line discipline. On Windows, it changes the console mode.
Marc
On 2013-01-02, at 11:59 AM, Mikael <mikael.rcv@gmail.com> wrote:
Hi,
In using read-char I get results only on a per input line basis. I was trying to switch the input console to byte/character mode instead of line buffered, though I didn't get any result with this.
Any thought or suggestion?
Mikael
_______________________________________________ Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
On 2013-01-02, at 6:05 PM, Mikael <mikael.rcv@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
participants (2)
-
Marc Feeley -
Mikael