ashinn / chibi-scheme

Official chibi-scheme repository
Other
1.21k stars 142 forks source link

Unexpected Behavior of `with-raw-io` from `stty.sld`. #901

Closed clartaq closed 1 year ago

clartaq commented 1 year ago

The doc string for with-raw-io says it enables the handling of "raw" terminal io as would be needed for a terminal application.

However, as written, it does not allow access to the ^S, ^Q, ^O, or ^V characters.

Modifying the procedure to include the ixon symbol in the call to with-stty allows access to ^S and ^Q when they are typed.

Awhile ago, I wrote a gist for Chez Scheme using the cfmakeraw function/macro to set up the parameters for raw mode in that dialect.

Examining the source for cfmakeraw and the discussion of VDISCARD and VLNEXT here, I suspect that the iexten flag needs to be added for ^O and ^V to be handled correctly. But that symbol is commented out in the stty.scm file.

Is the current behavior actually the intended behavior?

Am I mistaken in what symbols to add to the with-stty call to handle ^O and ^V as I would like (pass them through to the program)?

Here's a small program I cobbled together to test which characters can be detected.

;;;
;;; detect-keystrokes.scm -- experiments to detect keystrokes in raw
;;; mode.
;;;

(import (scheme base)
        (scheme write)
        (scheme process-context)

        (chibi stty))

;;------------------------------------------------------------------------------
;; Procedures for convenient printing.
;;

;; Return #t if the character is an ASCII control character, false
;; otherwise.
(define (char-control? c)
  (let ((char-num (char->integer c)))
    (or (= char-num 127)
        (< char-num 32))))

;; If c is a control character, it is converted into a two-character
;; string that indicates its special status by preceding it with a
;; "^".
(define (char->readable c)
  (cond
   ((char-control? c)
    (string #\^ (integer->char (+ 64 (char->integer c)))))
   ((char=? c #\space)
    "#\space")
   (else
    (string c))))

;; Display a series of arguments followed by a newline.
(define (println . args)
  (for-each display args)
  (newline))

;; When in raw mode, lines need to be ended with CR/LF pairs to act
;; like normal printing.
(define (println-in-raw . args)
  (for-each display args)
  (display (string #\return #\newline)))

;;------------------------------------------------------------------------------

(define (quit? c)
  (if (char=? c #\q)
      (begin
        (println "Finished  because c = " (char->readable c))
        #t)
      #f))

(define (process-keystroke)
  (let ((c (read-char)))
    (println-in-raw "char: " (char->readable c))
    (when (quit? c)
      (exit))))

(define (my-with-raw-io port thunk)
  (with-stty '(not icanon isig echo ixon) thunk port))

(println "detect-keystrokes.scm -- type some keys, quit by typing 'q'.")
(my-with-raw-io (current-input-port)
             (lambda ()
               (let loop ()
                 (process-keystroke)
                 (loop))))