Scope of SRFI 205 and a slightly more complex POSIX/ANSI terminal API Lassi Kortela (06 Aug 2020 12:03 UTC)
Signal handling Lassi Kortela (06 Aug 2020 14:22 UTC)
Re: Signal handling Marc Nieper-Wißkirchen (06 Aug 2020 14:32 UTC)
Re: Signal handling John Cowan (06 Aug 2020 15:13 UTC)
Re: Signal handling Arthur A. Gleckler (06 Aug 2020 15:28 UTC)
Re: Signal handling John Cowan (06 Aug 2020 17:38 UTC)
Re: Signal handling Arthur A. Gleckler (06 Aug 2020 18:19 UTC)
Re: Signal handling Lassi Kortela (06 Aug 2020 18:35 UTC)
Re: Signal handling Amirouche Boubekki (06 Aug 2020 21:18 UTC)
Re: Signal handling Amirouche Boubekki (06 Aug 2020 21:23 UTC)
Re: Signal handling John Cowan (07 Aug 2020 02:56 UTC)
Re: Signal handling Marc Nieper-Wißkirchen (06 Aug 2020 15:32 UTC)
Re: Signal handling John Cowan (06 Aug 2020 16:38 UTC)
Re: Signal handling hga@xxxxxx (06 Aug 2020 14:33 UTC)
Signal handling with terminals Lassi Kortela (06 Aug 2020 14:54 UTC)
(missing)
UI event datatypes Lassi Kortela (06 Aug 2020 16:08 UTC)
Re: UI event datatypes John Cowan (06 Aug 2020 16:34 UTC)
Re: UI event datatypes Lassi Kortela (06 Aug 2020 16:57 UTC)
Re: UI event datatypes John Cowan (07 Aug 2020 21:30 UTC)
Re: UI event datatypes Lassi Kortela (08 Aug 2020 18:36 UTC)
Re: UI event datatypes John Cowan (09 Aug 2020 00:31 UTC)

Scope of SRFI 205 and a slightly more complex POSIX/ANSI terminal API Lassi Kortela 06 Aug 2020 12:03 UTC

What's the scope of SRFI 205? The current first draft is nice and
simple, and probably good as it is.

I designed a minimal API for dealing with ANSI terminal on Unix-like
systems a year or two ago. It's designed to read and write things from
and to the terminal, respecting things like ANSI control code
delimiters and timeouts, but leaves the composing of escape sequences
and interpretation of key codes completely up to the caller.

Below is roughly what it looks like. Let me know if you want something
at this level of abstraction in this SRFI, or if you want to keep it
simpler.

(terminal-get-size) => (width . height)

     struct winsize ws;
     ioctl(fd, TIOCGWINSZ, &ws);
     return cons(ws.ws_col, ws.ws_row);

(terminal-write-char char)
(terminal-write-string string)
(terminal-write-escape string)

     write-char and write-string are like those R7RS procedures, but
     make sure you don't accidentally write ASCII control characters
     (other than #\newline) as those may garble the terminal.

     write-escape writes the #x1B escape character followed by the
     escape string you gave. Since escape strings don't need to feature
     control characters either, we can use terminal-write-string
     internally to write them.

terminal-read-event [esc-timeout]

     Read the next "event" from the terminal, blocking as long as
     needed to get one.

     Event types:

     'control <char> where <char> is one of the graphic representations
              of an ASCII control char: @ A B C ... X Y Z [ \ ] ^ _

     'escape  <string> where <string> is the stuff after #x1B.
              there are fairly clear rules for where to cut out the
              part after the #x1B so the library can return one and
              only one complete escape code to the caller.

     'resize  the terminal was resized (SIGWINCH occurred), call
              (terminal-get-size) to find out its size.

     'char    <char> where <char> is a Unicode codepoint.

     There is no standard way to handle the Esc key. In general, any
     keypress Meta+X (on PC keyboards, Alt+X) is indistinguishable from
     pressing Esc, releasing it, and then separately pressing X. Both
     normally send the ASCII escape character (#x1B IIRC) followed by
     the character X. (There used to be a hack where pressing Meta/Alt
     set the high bit or "meta bit" in an ASCII character so you could
     disginguish Meta+X from Esc X but the high bit messes with Unicode
     whose encodings also need to use the high bit.)

     Different ways to treat Esc:

     * Vi-like. Esc is always a standalone Esc, never Meta+something.

     * Emacs-like. Esc is always Meta+something, never standalone. When
       we get an Esc, wait as long as needed to get the something key.

     * Hybrid. When we get an Esc, wait N milliseconds for another key.
       If another key X comes, assume Meta+X was pressed. If not,
       assume a standalone Esc was pressed.

     These can be covered by giving an `esc-timeout` argument to
     read-event:

     0      return immediately with a standalone esc, like vi
     >0     wait N milliseconds for another key
     #f     wait forever for another key, like emacs

SIGWINCH handler

     For a nice experience, terminal apps need to respond to resize.
     For that, we need a SIGWINCH Unix signal handler. As said many
     times on these lists, Signal handlers are notoriously unfun and
     liable to mess with anything they touch. It might be best to
     provide a (terminal-announce-resize) procedure that a
     user-installed signal handler can call to tell the terminal
     library to pass the `read-event` caller a resize event.

     Otherwise we need some kind of portable way to install a SIGWINCH
     handler, which may be difficult.