tui:   Terminal UI for Racket
1 Installation
2 Quick Start
3 API Conventions
3.1 Prefix:   behavior
3.2 Suffix:   side effects
3.3 Rule 1:   put /   format symmetry
3.4 Rule 2:   argument order
3.5 Rule 3:   three color tiers are isomorphic
3.6 Standard API categories
4 Lifecycle
with-tui
with-tui-nobuffer
with-tui-nobuffer-echo
tui-init
tui-exit
tui-init-no-buffer
tui-exit-no-buffer
tui-init-no-buffer-echo
tui-exit-no-buffer-echo
enable-mouse!
disable-mouse!
enable-bracketed-paste!
disable-bracketed-paste!
5 Output
put
put-string
put-bytes
put-byte
put-char
put-newline
put-format-bytes
format-newline
put-at
put-at!
5.1 Cursor
cursor-up
cursor-down
cursor-left
cursor-right
cursor-move
cursor-col
cursor-home
cursor-hide
cursor-show
put-cursor-save
put-cursor-restore
5.2 Screen and lines
screen-clear
screen-clear-below
screen-clear-above
line-clear
line-clear-right
line-clear-left
buffer-alt-enable
buffer-alt-disable
5.3 Flush mode
set-immediate-mode!
set-buffered-mode!
flush!
6 Colors
put-fg
put-bg
put-rgb-fg
put-rgb-bg
put-rgb-fg-bg
put-256-fg
put-256-bg
put-reset
6.1 Positioned colors
put-fg-at
put-fg-at!
put-bg-at
put-bg-at!
put-rgb-fg-at
put-rgb-fg-at!
put-rgb-bg-at
put-rgb-bg-at!
put-rgb-fg-bg-at
put-rgb-fg-bg-at!
put-256-fg-at
put-256-fg-at!
put-256-bg-at
put-256-bg-at!
6.2 Escape-only variants
put-fg-base
put-bg-base
put-rgb-fg-base
put-rgb-bg-base
put-rgb-fg-bg-base
put-256-fg-base
put-256-bg-base
put-bold
put-dim
put-italic
put-underline
put-blink
put-reverse
7 Styles
7.1 Usage
style-define!
style-apply!
style-reset
style->bytes
put-styled
put-styled-at
put-styled-at!
put-styled-bold
put-styled-bold-at
put-styled-bold-at!
put-styled-dim
put-styled-dim-at
put-styled-dim-at!
put-styled-italic
put-styled-italic-at
put-styled-italic-at!
put-styled-underline
put-styled-underline-at
put-styled-underline-at!
put-styled-blink
put-styled-blink-at
put-styled-blink-at!
put-styled-reverse
put-styled-reverse-at
put-styled-reverse-at!
7.2 Color and attribute constructors
color-fg
color-bg
color256-fg
color256-bg
color-rgb-fg
color-rgb-bg
color-fg*
color-bg*
attr-bold
attr-dim
attr-italic
attr-underline
attr-blink
attr-reverse
7.3 Color mode
use-256color!
use-16color!
use-color-auto!
7.4 Built-in styles
8 Format functions
format-cursor-move
format-cursor-up
format-cursor-down
format-cursor-left
format-cursor-right
format-cursor-col
format-cursor-home
format-cursor-hide
format-cursor-show
format-cursor-save
format-cursor-restore
format-screen-clear
format-screen-clear-below
format-screen-clear-above
format-line-clear
format-line-clear-right
format-line-clear-left
format-buffer-alt-enable
format-buffer-alt-disable
format-reset
format-bold
format-dim
format-italic
format-underline
format-blink
format-reverse
format-content
format-fg
format-bg
format-rgb-fg
format-rgb-bg
format-rgb-fg-bg
format-256-fg
format-256-bg
format-fg-base
format-bg-base
format-rgb-fg-base
format-rgb-bg-base
format-rgb-fg-bg-base
format-256-fg-base
format-256-bg-base
format-styled
format-styled*
format-styled-at
format-styled-at!
format-styled-bold
format-styled-bold-at
format-styled-bold-at!
format-styled-dim
format-styled-dim-at
format-styled-dim-at!
format-styled-italic
format-styled-italic-at
format-styled-italic-at!
format-styled-underline
format-styled-underline-at
format-styled-underline-at!
format-styled-blink
format-styled-blink-at
format-styled-blink-at!
format-styled-reverse
format-styled-reverse-at
format-styled-reverse-at!
format-content-at
format-content-at!
format-fg-at
format-fg-at!
format-bg-at
format-bg-at!
format-rgb-fg-at
format-rgb-fg-at!
format-rgb-bg-at
format-rgb-bg-at!
format-256-fg-at
format-256-fg-at!
format-256-bg-at
format-256-bg-at!
format-rgb-fg-bg-at
format-rgb-fg-bg-at!
9 Input
9.1 High-level:   build-input and event loops
build-input
9.1.1 Callback arguments
9.1.2 Example
loop-input
loop-input-noblock
loop-input/  stop
loop-input-noblock/  stop
9.2 Low-level:   read-event
read-event
read-event-noblock
event-null?
event-key?
event-utf8?
event-seq?
event-ctrl?
event-alt?
event-mod-seq?
event-resize?
event-up?
event-down?
event-left?
event-right?
event-del?
event-insert?
event-home?
event-end?
event-pageup?
event-pagedown?
event-backtab?
event-touch?
event-mouse?
event-paste?
event-tab?
event-space?
event-backspace?
event-enter?
event-escape?
ctrl->char
alt->char
mod-seq->char
event->string
event->byte
9.3 Mouse
mouse-press?
mouse-release?
mouse-move?
mouse-scroll?
mouse-left?
mouse-middle?
mouse-right?
scroll-up?
scroll-down?
mouse-x
mouse-y
get-mouse-pos
mouse-modifiers
9.4 Resize
get-resize-rows
get-resize-cols
get-resize-size
10 Terminal
terminal?
enter-raw-mode!
exit-raw-mode!
enter-raw-mode-keep-echo!
call-with-terminal-reply
make-stdin-evt
get-window-size
resize-monitor-start
resize-monitor-stop
make-resize-evt
11 Cursor state
current-cursor-row
current-cursor-col
set-cursor!
get-cursor
update-cursor!
12 Configuration constants
ESCDELAY
CSI-MAX-BYTES
PASTE-MAX-BYTES
UTF8-READ-TIMEOUT
PASTE-READ-TIMEOUT
13 Complete example
14 Implementation notes
9.3

tui: Terminal UI for Racket🔗ℹ

lu96-wow

 (require tui) package: racket-tui

A small terminal UI library for Linux: raw-mode terminal control, mouse and true-color support, bracketed paste, and window-resize events.

Linux only. This library binds directly to Linux termios, signalfd and ioctl. Loading tui on other operating systems raises an error, because the FFI symbols do not exist. Only xterm / qterminal have been tested.

    1 Installation

    2 Quick Start

    3 API Conventions

      3.1 Prefix: behavior

      3.2 Suffix: side effects

      3.3 Rule 1: put / format symmetry

      3.4 Rule 2: argument order

      3.5 Rule 3: three color tiers are isomorphic

      3.6 Standard API categories

    4 Lifecycle

    5 Output

      5.1 Cursor

      5.2 Screen and lines

      5.3 Flush mode

    6 Colors

      6.1 Positioned colors

      6.2 Escape-only variants

    7 Styles

      7.1 Usage

      7.2 Color and attribute constructors

      7.3 Color mode

      7.4 Built-in styles

    8 Format functions

    9 Input

      9.1 High-level: build-input and event loops

        9.1.1 Callback arguments

        9.1.2 Example

      9.2 Low-level: read-event

      9.3 Mouse

      9.4 Resize

    10 Terminal

    11 Cursor state

    12 Configuration constants

    13 Complete example

    14 Implementation notes

1 Installation🔗ℹ

Install from the package index:

raco pkg install tui

or directly from GitHub:

raco pkg install https://github.com/lu96-wow/racket-tui.git

2 Quick Start🔗ℹ

(require tui)
 
(with-tui
 (λ ()
   (screen-clear)
   (cursor-hide)
   (put-rgb-fg 255 100 0 "Hello TUI!")
   (put-at 5 10 "Direct output")
   (sleep 2)))

3 API Conventions🔗ℹ

The whole API follows two naming tables (prefix, suffix) and three rules (put/format symmetry, argument order, three color tiers). Once these are known, most function names and signatures can be derived without looking them up.

3.1 Prefix: behavior🔗ℹ

Prefix

 

Meaning

 

Example

put-

 

Immediate terminal output (flushes by default)

 

put-string

format-

 

Return bytes without outputting; batch with @racket[put-bytes]

 

format-cursor-move

cursor- screen- line- buffer-

 

Cursor / screen / line / alt-buffer operations (immediate)

 

cursor-move

clr-

 

16-color foreground constructor (shorthand for @racket[(color-fg n)])

 

clr-red

bclr-

 

16-color background constructor

 

bclr-blue

attr-

 

SGR attribute constructor (thunk that emits the escape sequence)

 

attr-bold

color- color256- color-rgb-

 

Color constructors (thunks, for @racket[style-define!])

 

color256-fg

style-

 

Style system

 

style-define!

event-

 

Input-event predicates and accessors

 

event-key?

current-

 

Parameters or tracked cursor variables

 

current-cursor-row

3.2 Suffix: side effects🔗ℹ

Suffix

 

Meaning

 

Example

!

 

Side effects: updates the tracked cursor / terminal mode

 

put-at!

?

 

Predicate, returns boolean

 

terminal?

-at

 

Positioned (@racket[row] @racket[col] first); DECSC/DECRC so the tracked cursor is untouched

 

put-fg-at

-at!

 

Positioned and updates the tracked cursor

 

put-fg-at!

-base

 

Escape sequence only: no content, no reset

 

put-fg-base

3.3 Rule 1: put / format symmetry🔗ℹ

Almost every capability has both a put- form (immediate output) and a format- form (returns bytes), with identical arguments:

(put-fg 1 "x")
(put-rgb-fg-at 1 1 255 0 0 "x")
(put-cursor-save)

Exceptions (by design):

3.4 Rule 2: argument order🔗ℹ

  • The content v (string / bytes / char / number) is always the last argument.

  • Positioned functions take row col first.

  • Color arguments come in the middle: n for 16/256 colors; r g b for RGB; fr fg fb br bg bb (foreground then background) for foreground+background.

(put-rgb-fg-bg-at row col fr fg fb br bg bb v)

3.5 Rule 3: three color tiers are isomorphic🔗ℹ

The 16-color, 256-color and RGB tiers are same-named and same-shaped; only the color argument differs (n / n / r g b):

(put-fg n v)           (put-256-fg n v)           (put-rgb-fg r g b v)
(put-fg-at r c n v)    (put-256-fg-at r c n v)    (put-rgb-fg-at r c r g b v)
(put-fg-base n)        (put-256-fg-base n)        (put-rgb-fg-base r g b)

Knowing any one tier, the other two can be derived.

3.6 Standard API categories🔗ℹ

Category

 

Representative functions

Lifecycle

 

with-tui tui-init enable-mouse!

Basic output

 

put put-bytes put-newline

Positioned output

 

put-at put-at!

Cursor

 

cursor-move put-cursor-save

Screen / line / buffer

 

screen-clear line-clear buffer-alt-enable

Colors

 

put-fg put-rgb-fg put-256-fg

Styles

 

style-define! put-styled color-fg

Format (returns bytes)

 

format-fg format-cursor-move

Input

 

read-event build-input loop-input

Terminal

 

terminal? enter-raw-mode! get-window-size

Cursor tracking

 

current-cursor-row set-cursor! update-cursor!

Config constants

 

ESCDELAY PASTE-MAX-BYTES

4 Lifecycle🔗ℹ

All three with-tui entry points are plain functions taking a thunk. They use dynamic-wind internally, so the terminal is always restored whether the body returns normally or raises an exception. Exceptions from the body propagate outward; they are never swallowed.

procedure

(with-tui body)  any

  body : (-> any)
Enters raw mode with the alternate screen buffer, runs body, then restores the terminal (raw mode off, alt buffer disabled, mouse and bracketed paste off, cursor shown, colors reset).

procedure

(with-tui-nobuffer body)  any

  body : (-> any)
Like with-tui, but stays in the main screen buffer (no alternate buffer), so output is visible after the program exits.

procedure

(with-tui-nobuffer-echo body)  any

  body : (-> any)
Like with-tui-nobuffer, but keeps terminal echo enabled. Useful when the terminal must display typed input while the program reads keys.

procedure

(tui-init)  void?

Initializes the terminal in raw mode with the alternate screen buffer. Raises an error if the current input port is not a terminal. If initialization fails partway, already-changed terminal state is rolled back before the error is re-raised.

procedure

(tui-exit)  void?

Restores the terminal to its pre-tui-init state. Idempotent: each cleanup step is defensive, so one failing step prints a warning without stopping the remaining cleanup.

procedure

(tui-init-no-buffer)  void?

procedure

(tui-exit-no-buffer)  void?

Like tui-init / tui-exit, but without the alternate screen buffer.

procedure

(tui-init-no-buffer-echo)  void?

procedure

(tui-exit-no-buffer-echo)  void?

Like tui-init-no-buffer, but keeps terminal echo enabled.

procedure

(enable-mouse!)  void?

Enables mouse event tracking (SGR mode).

procedure

(disable-mouse!)  void?

Disables mouse event tracking.

procedure

(enable-bracketed-paste!)  void?

Enables bracketed paste mode.

procedure

(disable-bracketed-paste!)  void?

Disables bracketed paste mode.

Do not call (exit) inside a with-tui body: it terminates the process without running cleanup, leaving the terminal in raw mode. Use a running? flag plus loop-input/stop instead.

5 Output🔗ℹ

All put- functions write to the current output port immediately (one flush per call) by default; use set-buffered-mode! to batch.

procedure

(put v)  void?

  v : any/c
Prints v using ~a formatting.

procedure

(put-string s)  void?

  s : string?

procedure

(put-bytes bs)  void?

  bs : bytes?

procedure

(put-byte b)  void?

  b : byte?

procedure

(put-char c)  void?

  c : char?

procedure

(put-newline)  void?

Prints the terminal newline (CRLF in raw mode, LF otherwise).

procedure

(put-format-bytes part ...)  void?

  part : bytes?
Concatenates byte-string parts (typically values of format- functions) and writes them in one call.

procedure

(format-newline)  bytes?

Returns the terminal newline as a byte string.

procedure

(put-at row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c
Prints v at row×col without disturbing the tracked cursor position (the terminal saves and restores the cursor).

procedure

(put-at! row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c
Like put-at, but updates the tracked cursor position to row×col.

5.1 Cursor🔗ℹ

procedure

(cursor-up n)  void?

  n : exact-nonnegative-integer?

procedure

(cursor-down n)  void?

  n : exact-nonnegative-integer?

procedure

(cursor-left n)  void?

  n : exact-nonnegative-integer?

procedure

(cursor-right n)  void?

  n : exact-nonnegative-integer?

procedure

(cursor-move row col)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?

procedure

(cursor-col n)  void?

  n : exact-nonnegative-integer?

procedure

(cursor-home)  void?

procedure

(cursor-hide)  void?

procedure

(cursor-show)  void?

procedure

(put-cursor-save)  void?

Saves the cursor position (DECSC).

procedure

(put-cursor-restore)  void?

Restores the saved cursor position (DECRC).

5.2 Screen and lines🔗ℹ

procedure

(screen-clear)  void?

procedure

(screen-clear-below)  void?

procedure

(screen-clear-above)  void?

procedure

(line-clear)  void?

procedure

(line-clear-right)  void?

procedure

(line-clear-left)  void?

procedure

(buffer-alt-enable)  void?

procedure

(buffer-alt-disable)  void?

5.3 Flush mode🔗ℹ

procedure

(set-immediate-mode!)  void?

Every put- call flushes immediately (the default).

procedure

(set-buffered-mode!)  void?

put- calls only buffer output; flush manually with flush!.

procedure

(flush!)  void?

Flushes buffered output.

6 Colors🔗ℹ

Colors come in three flavors: 16-color ANSI, 256-color, and true color (RGB). The put- variants print content in that color and reset after.

procedure

(put-fg n v)  void?

  n : (integer-in 0 15)
  v : any/c

procedure

(put-bg n v)  void?

  n : (integer-in 0 15)
  v : any/c

procedure

(put-rgb-fg r g b v)  void?

  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(put-rgb-bg r g b v)  void?

  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(put-rgb-fg-bg fr fg fb br bg bb v)  void?

  fr : byte?
  fg : byte?
  fb : byte?
  br : byte?
  bg : byte?
  bb : byte?
  v : any/c

procedure

(put-256-fg n v)  void?

  n : (integer-in 0 255)
  v : any/c

procedure

(put-256-bg n v)  void?

  n : (integer-in 0 255)
  v : any/c

procedure

(put-reset)  void?

Resets all styling (the put- counterpart of format-reset).

6.1 Positioned colors🔗ℹ

The -at variants print in color at a fixed position. Like put-at, they use DECSC/DECRC so the tracked cursor is untouched; the -at! variants update the tracked cursor position instead.

procedure

(put-fg-at row col n v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 15)
  v : any/c

procedure

(put-fg-at! row col n v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 15)
  v : any/c

procedure

(put-bg-at row col n v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 15)
  v : any/c

procedure

(put-bg-at! row col n v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 15)
  v : any/c

procedure

(put-rgb-fg-at row col r g b v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(put-rgb-fg-at! row col r g b v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(put-rgb-bg-at row col r g b v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(put-rgb-bg-at! row col r g b v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(put-rgb-fg-bg-at row col fr fg fb br bg bb v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  fr : byte?
  fg : byte?
  fb : byte?
  br : byte?
  bg : byte?
  bb : byte?
  v : any/c

procedure

(put-rgb-fg-bg-at! row col fr fg fb br bg bb v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  fr : byte?
  fg : byte?
  fb : byte?
  br : byte?
  bg : byte?
  bb : byte?
  v : any/c

procedure

(put-256-fg-at row col n v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 255)
  v : any/c

procedure

(put-256-fg-at! row col n v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 255)
  v : any/c

procedure

(put-256-bg-at row col n v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 255)
  v : any/c

procedure

(put-256-bg-at! row col n v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 255)
  v : any/c

6.2 Escape-only variants🔗ℹ

The -base variants emit only the escape sequence, without content or reset; the attribute variants emit the corresponding SGR sequence:

procedure

(put-fg-base n)  void?

  n : (integer-in 0 15)

procedure

(put-bg-base n)  void?

  n : (integer-in 0 15)

procedure

(put-rgb-fg-base r g b)  void?

  r : byte?
  g : byte?
  b : byte?

procedure

(put-rgb-bg-base r g b)  void?

  r : byte?
  g : byte?
  b : byte?

procedure

(put-rgb-fg-bg-base fr fg fb br bg bb)  void?

  fr : byte?
  fg : byte?
  fb : byte?
  br : byte?
  bg : byte?
  bb : byte?

procedure

(put-256-fg-base n)  void?

  n : (integer-in 0 255)

procedure

(put-256-bg-base n)  void?

  n : (integer-in 0 255)

procedure

(put-bold)  void?

procedure

(put-dim)  void?

procedure

(put-italic)  void?

procedure

(put-underline)  void?

procedure

(put-blink)  void?

procedure

(put-reverse)  void?

7 Styles🔗ℹ

Styles are named bundles of color and attribute thunks. Define them once, then apply by name. style-define! registers every style in both a 256-color and a 16-color registry; the active registry is selected by current-registry (see use-color-auto!).

7.1 Usage🔗ℹ

(style-define! 'fancy clr-yellow bclr-blue attr-bold attr-underline)
 
(put-styled 'fancy "Combined style")
(put-styled-at  5 10 'fancy "fixed")
(put-styled-at! 5 10 'fancy "cursor")
 
 
(put-format-bytes
 (format-styled 'title "Title")
 (format-styled 'info "body text"))

The two registries give automatic 256/16-color fallback: plain color-fg/attr-bold register the same value in both, while color-fg* and color-bg* take separate values for each:

(style-define! 'status (color-fg* 46 2) attr-bold)

style->bytes returns the precomputed escape bytes for a style; it is what format-styled uses internally. An undefined style name is a no-op: it produces empty bytes without raising an error.

procedure

(style-define! name spec ...)  void?

  name : symbol?
  spec : procedure?
Registers name from color/attribute thunks such as color-fg, color-bg, attr-bold, or color-fg*.

procedure

(style-apply! name)  void?

  name : symbol?
Applies the style currently registered under name (no-op if unknown).

procedure

(style-reset)  void?

Resets all styling.

procedure

(style->bytes name)  bytes?

  name : symbol?
Returns the escape-sequence bytes for name.

procedure

(put-styled name v)  void?

  name : symbol?
  v : any/c
Prints v in style name, then resets.

procedure

(put-styled-at row col name v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  name : symbol?
  v : any/c

procedure

(put-styled-at! row col name v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  name : symbol?
  v : any/c

procedure

(put-styled-bold v)  void?

  v : any/c

procedure

(put-styled-bold-at row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-bold-at! row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-dim v)  void?

  v : any/c

procedure

(put-styled-dim-at row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-dim-at! row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-italic v)  void?

  v : any/c

procedure

(put-styled-italic-at row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-italic-at! row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-underline v)  void?

  v : any/c

procedure

(put-styled-underline-at row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-underline-at! row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-blink v)  void?

  v : any/c

procedure

(put-styled-blink-at row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-blink-at! row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-reverse v)  void?

  v : any/c

procedure

(put-styled-reverse-at row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(put-styled-reverse-at! row col v)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c
Attribute-styled output: bold, dim, italic, underline, blink, reverse, each with -at (fixed position, cursor untouched) and -at! (updates tracked cursor) variants. The put- counterparts of format-styled-bold and friends.

7.2 Color and attribute constructors🔗ℹ

procedure

(color-fg n)  procedure?

  n : (integer-in 0 15)

procedure

(color-bg n)  procedure?

  n : (integer-in 0 15)

procedure

(color256-fg n)  procedure?

  n : (integer-in 0 255)

procedure

(color256-bg n)  procedure?

  n : (integer-in 0 255)

procedure

(color-rgb-fg r g b)  procedure?

  r : byte?
  g : byte?
  b : byte?

procedure

(color-rgb-bg r g b)  procedure?

  r : byte?
  g : byte?
  b : byte?

procedure

(color-fg* c256 c16)  color-thunk?

  c256 : (integer-in 0 255)
  c16 : (integer-in 0 15)
A two-registry color: uses c256 when the 256-color registry is active, c16 otherwise.

procedure

(color-bg* c256 c16)  color-thunk?

  c256 : (integer-in 0 255)
  c16 : (integer-in 0 15)

procedure

(attr-bold)  void?

procedure

(attr-dim)  void?

procedure

(attr-italic)  void?

procedure

(attr-underline)  void?

procedure

(attr-blink)  void?

procedure

(attr-reverse)  void?

7.3 Color mode🔗ℹ

procedure

(use-256color!)  void?

Selects the 256-color style registry.

procedure

(use-16color!)  void?

Selects the 16-color style registry.

procedure

(use-color-auto!)  void?

Selects the registry based on the COLORTERM / TERM environment variables. Called automatically by tui-init.

7.4 Built-in styles🔗ℹ

The following styles are pre-registered by the library:

  • Basic: 'red 'green 'blue 'yellow 'cyan 'magenta 'white

  • Levels: 'error 'warning 'info 'success

  • Text: 'title 'subtitle 'heading 'border 'border-bold

  • Widgets: 'button 'button-hover 'button-pressed 'button-disabled

  • Menus: 'menu-item 'menu-selected 'menu-key 'menu-shortcut

  • Lists: 'list-item 'list-selected 'list-alternate

  • Dialogs: 'dialog-title 'dialog-body 'dialog-button 'dialog-highlight

  • Status: 'status-bar 'status-good 'status-warning 'status-bad

  • Input: 'input-normal 'input-focus 'input-error

  • Misc: 'cursor 'selection 'scroll-track 'scroll-thumb

8 Format functions🔗ℹ

The format- functions return byte strings without writing anything. They are meant to be collected and written in one batch with put-format-bytes or put-bytes. Each value-taking variant appends content and a style reset, so format-reset is only needed once at the end of a batch.

procedure

(format-cursor-move row col)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?

procedure

(format-cursor-up n)  bytes?

  n : exact-nonnegative-integer?

procedure

(format-cursor-down n)  bytes?

  n : exact-nonnegative-integer?

procedure

(format-cursor-left n)  bytes?

  n : exact-nonnegative-integer?

procedure

(format-cursor-right n)  bytes?

  n : exact-nonnegative-integer?

procedure

(format-cursor-col n)  bytes?

  n : exact-nonnegative-integer?

procedure

(format-cursor-home)  bytes?

procedure

(format-cursor-hide)  bytes?

procedure

(format-cursor-show)  bytes?

procedure

(format-cursor-save)  bytes?

procedure

(format-cursor-restore)  bytes?

procedure

(format-screen-clear)  bytes?

procedure

(format-screen-clear-below)  bytes?

procedure

(format-screen-clear-above)  bytes?

procedure

(format-line-clear)  bytes?

procedure

(format-line-clear-right)  bytes?

procedure

(format-line-clear-left)  bytes?

procedure

(format-buffer-alt-enable)  bytes?

procedure

(format-buffer-alt-disable)  bytes?

procedure

(format-reset)  bytes?

procedure

(format-bold)  bytes?

procedure

(format-dim)  bytes?

procedure

(format-italic)  bytes?

procedure

(format-underline)  bytes?

procedure

(format-blink)  bytes?

procedure

(format-reverse)  bytes?

procedure

(format-content v)  bytes?

  v : any/c
Converts v to a byte string (bytes pass through, strings become UTF-8, other values use ~a).

procedure

(format-fg n v)  bytes?

  n : (integer-in 0 15)
  v : any/c

procedure

(format-bg n v)  bytes?

  n : (integer-in 0 15)
  v : any/c

procedure

(format-rgb-fg r g b v)  bytes?

  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(format-rgb-bg r g b v)  bytes?

  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(format-rgb-fg-bg fr fg fb br bg bb v)  bytes?

  fr : byte?
  fg : byte?
  fb : byte?
  br : byte?
  bg : byte?
  bb : byte?
  v : any/c

procedure

(format-256-fg n v)  bytes?

  n : (integer-in 0 255)
  v : any/c

procedure

(format-256-bg n v)  bytes?

  n : (integer-in 0 255)
  v : any/c

procedure

(format-fg-base n)  bytes?

  n : (integer-in 0 15)

procedure

(format-bg-base n)  bytes?

  n : (integer-in 0 15)

procedure

(format-rgb-fg-base r g b)  bytes?

  r : byte?
  g : byte?
  b : byte?

procedure

(format-rgb-bg-base r g b)  bytes?

  r : byte?
  g : byte?
  b : byte?

procedure

(format-rgb-fg-bg-base fr fg fb br bg bb)  bytes?

  fr : byte?
  fg : byte?
  fb : byte?
  br : byte?
  bg : byte?
  bb : byte?

procedure

(format-256-fg-base n)  bytes?

  n : (integer-in 0 255)

procedure

(format-256-bg-base n)  bytes?

  n : (integer-in 0 255)

procedure

(format-styled name v)  bytes?

  name : symbol?
  v : any/c

procedure

(format-styled* name v)  bytes?

  name : symbol?
  v : any/c
Like format-styled, but without the trailing reset.

procedure

(format-styled-at row col name v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  name : symbol?
  v : any/c

procedure

(format-styled-at! row col name v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  name : symbol?
  v : any/c

procedure

(format-styled-bold v)  bytes?

  v : any/c

procedure

(format-styled-bold-at row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-bold-at! row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-dim v)  bytes?

  v : any/c

procedure

(format-styled-dim-at row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-dim-at! row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-italic v)  bytes?

  v : any/c

procedure

(format-styled-italic-at row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-italic-at! row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-underline v)  bytes?

  v : any/c

procedure

(format-styled-underline-at row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-underline-at! row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-blink v)  bytes?

  v : any/c

procedure

(format-styled-blink-at row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-blink-at! row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-reverse v)  bytes?

  v : any/c

procedure

(format-styled-reverse-at row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-styled-reverse-at! row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-content-at row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-content-at! row col v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  v : any/c

procedure

(format-fg-at row col n v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 15)
  v : any/c

procedure

(format-fg-at! row col n v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 15)
  v : any/c

procedure

(format-bg-at row col n v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 15)
  v : any/c

procedure

(format-bg-at! row col n v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 15)
  v : any/c

procedure

(format-rgb-fg-at row col r g b v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(format-rgb-fg-at! row col r g b v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(format-rgb-bg-at row col r g b v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(format-rgb-bg-at! row col r g b v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  r : byte?
  g : byte?
  b : byte?
  v : any/c

procedure

(format-256-fg-at row col n v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 255)
  v : any/c

procedure

(format-256-fg-at! row col n v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 255)
  v : any/c

procedure

(format-256-bg-at row col n v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 255)
  v : any/c

procedure

(format-256-bg-at! row col n v)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  n : (integer-in 0 255)
  v : any/c

procedure

(format-rgb-fg-bg-at row col fr fg fb br bg bb)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  fr : byte?
  fg : byte?
  fb : byte?
  br : byte?
  bg : byte?
  bb : byte?

procedure

(format-rgb-fg-bg-at! row col fr fg fb br bg bb)  bytes?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?
  fr : byte?
  fg : byte?
  fb : byte?
  br : byte?
  bg : byte?
  bb : byte?

9 Input🔗ℹ

9.1 High-level: build-input and event loops🔗ℹ

procedure

(build-input [#:char on-char 
  #:utf-char on-utf-char 
  #:ctrl on-ctrl 
  #:alt on-alt 
  #:mod-char on-mod-char 
  #:mod-key on-mod-key 
  #:tab on-tab 
  #:backtab on-backtab 
  #:space on-space 
  #:enter on-enter 
  #:backspace on-backspace 
  #:escape on-escape 
  #:up on-up 
  #:down on-down 
  #:left on-left 
  #:right on-right 
  #:delete on-delete 
  #:insert on-insert 
  #:home on-home 
  #:end on-end 
  #:pageup on-pageup 
  #:pagedown on-pagedown 
  #:mouse-press on-mouse-press 
  #:mouse-release on-mouse-release 
  #:mouse-move on-mouse-move 
  #:mouse-scroll on-mouse-scroll 
  #:paste on-paste 
  #:resize on-resize 
  #:null on-null 
  #:any on-any]) 
  (-> symbol? bytes? (or/c #f (list/c boolean? boolean? boolean?)) any)
  on-char : (or/c (-> integer? any) #f) = #f
  on-utf-char : (or/c (-> string? any) #f) = #f
  on-ctrl : (or/c (-> char? any) #f) = #f
  on-alt : (or/c (-> char? any) #f) = #f
  on-mod-char : (or/c (-> char? boolean? boolean? boolean? any) #f)
   = #f
  on-mod-key : (or/c (-> symbol? boolean? boolean? boolean? any) #f)
   = #f
  on-tab : (or/c (-> any) #f) = #f
  on-backtab : (or/c (-> any) #f) = #f
  on-space : (or/c (-> any) #f) = #f
  on-enter : (or/c (-> any) #f) = #f
  on-backspace : (or/c (-> any) #f) = #f
  on-escape : (or/c (-> any) #f) = #f
  on-up : (or/c (-> any) #f) = #f
  on-down : (or/c (-> any) #f) = #f
  on-left : (or/c (-> any) #f) = #f
  on-right : (or/c (-> any) #f) = #f
  on-delete : (or/c (-> any) #f) = #f
  on-insert : (or/c (-> any) #f) = #f
  on-home : (or/c (-> any) #f) = #f
  on-end : (or/c (-> any) #f) = #f
  on-pageup : (or/c (-> any) #f) = #f
  on-pagedown : (or/c (-> any) #f) = #f
  on-mouse-press : (or/c (-> symbol? exact-nonnegative-integer? exact-nonnegative-integer? (list/c boolean? boolean? boolean?) any) #f)
   = #f
  on-mouse-release : (or/c (-> symbol? exact-nonnegative-integer? exact-nonnegative-integer? (list/c boolean? boolean? boolean?) any) #f)
   = #f
  on-mouse-move : (or/c (-> exact-nonnegative-integer? exact-nonnegative-integer? (list/c boolean? boolean? boolean?) any) #f)
   = #f
  on-mouse-scroll : (or/c (-> symbol? exact-nonnegative-integer? exact-nonnegative-integer? (list/c boolean? boolean? boolean?) any) #f)
   = #f
  on-paste : (or/c (-> bytes? any) #f) = #f
  on-resize : (or/c (-> exact-positive-integer? exact-positive-integer? any) #f)
   = #f
  on-null : (or/c (-> any) #f) = #f
  on-any : (or/c (-> symbol? bytes? (or/c #f (list/c boolean? boolean? boolean?)) any) #f)
   = #f
Builds an event handler from callback keywords. Every keyword is optional; events without a handler fall through to #:any, or are ignored. The returned function has the signature (type data mods) ... and can be passed to loop-input or called directly.

Event dispatch priority (built in): null > resize > paste > mouse > tab/backtab/space/enter/backspace/escape > arrows > function keys > ctrl > alt > mod-seq > utf8 > char > any.

Modified events (mod-seq) split into two categories:
  • Modified characters (e.g. Ctrl+Alt+x, encoded as ESC [ 27;7;120~) go to #:mod-char with the character.

  • Modified navigation keys (e.g. Ctrl+Up, encoded as ESC [ 1;5A) go to #:mod-key with a key symbol such as 'up or 'home. If #:mod-key is not provided they fall back to #:mod-char.

9.1.1 Callback arguments🔗ℹ

All keywords are optional; an event without a matching callback falls through to #:any, or is ignored if #:any is absent. Callback argument types:

Keyword

 

Callback

 

Argument types

#:char

 

(ch)

 

ch integer?, ASCII value 0-255 (e.g. 97 = a).

#:utf-char

 

(str)

 

str string?, one UTF-8 character (e.g. "你").

#:ctrl

 

(ch)

 

ch char?, #\A to #\Z for Ctrl+A to Ctrl+Z.

#:alt

 

(ch)

 

ch char?, the character typed with Alt.

#:mod-char

 

(ch ctrl? alt? shift?)

 

ch char?; ctrl? alt? shift? boolean?, each modifier pressed.

#:mod-key

 

(key ctrl? alt? shift?)

 

key symbol?, one of 'up 'down 'left 'right 'home 'end 'pageup 'pagedown 'insert 'del 'backtab; plus the three boolean? modifiers.

#:tab

 

()

 

No arguments

#:backtab

 

()

 

Shift+Tab, no arguments

#:space

 

()

 

No arguments

#:enter

 

()

 

No arguments

#:backspace

 

()

 

No arguments

#:escape

 

()

 

No arguments

#:up

 

()

 

Arrow up, no arguments

#:down

 

()

 

No arguments

#:left

 

()

 

No arguments

#:right

 

()

 

No arguments

#:delete

 

()

 

No arguments

#:insert

 

()

 

No arguments

#:home

 

()

 

No arguments

#:end

 

()

 

No arguments

#:pageup

 

()

 

No arguments

#:pagedown

 

()

 

No arguments

#:mouse-press

 

(button x y mods)

 

button symbol?, 'left 'middle 'right; x y exact-nonnegative-integer? coordinates; mods (list/c boolean? boolean? boolean?) = (list ctrl? alt? shift?).

#:mouse-release

 

(button x y mods)

 

Same as #:mouse-press

#:mouse-move

 

(x y mods)

 

x y coordinates; mods modifier triple.

#:mouse-scroll

 

(dir x y mods)

 

dir symbol?, 'up or 'down.

#:paste

 

(data)

 

data bytes?, pasted content.

#:resize

 

(rows cols)

 

rows cols exact-positive-integer?.

#:null

 

()

 

No input available (noblock loop)

#:any

 

(type data mods)

 

type symbol?; data bytes?; mods (or/c #f (list/c boolean? boolean? boolean?)). Fallback for every unhandled event.

9.1.2 Example🔗ℹ

(define handler
  (build-input
    #:char     (lambda (ch)      (printf "key '~a'\n" (integer->char ch)))
    #:ctrl     (lambda (ch)      (printf "Ctrl+~a\n" ch))
    #:mod-char (lambda (ch ctrl? alt? shift?)
                 (printf "~a~a~a~a\n"
                         (if ctrl? "Ctrl+" "")
                         (if alt? "Alt+" "")
                         (if shift? "Shift+" "")
                         ch))
    #:mod-key  (lambda (key ctrl? alt? shift?)
                 (printf "~a~a~a~a\n"
                         (if ctrl? "Ctrl+" "")
                         (if alt? "Alt+" "")
                         (if shift? "Shift+" "")
                         key))
    #:mouse-press (lambda (button x y mods)
                    (printf "~a ~a (~a,~a)\n"
                            (car mods)
                            button x y))
    #:paste  (lambda (data) (printf "pasted ~a bytes\n" (bytes-length data)))
    #:resize (lambda (rows cols) (printf "~ax~a\n" rows cols))))

syntax

(loop-input handler ...)

Reads events forever and calls each handler function with (values type data mods) per event. Macro that expands to a loop.

syntax

(loop-input-noblock handler ...)

syntax

(loop-input/stop stop-expr handler ...)

Like loop-input, but re-evaluates stop-expr after each event and stops when it is true.

syntax

(loop-input-noblock/stop stop-expr handler ...)

9.2 Low-level: read-event🔗ℹ

procedure

(read-event)  
symbol?
bytes?
(or/c #f (list/c boolean? boolean? boolean?))
Reads one input event from the terminal, blocking until input arrives. Returns (values type data mods):

  • type a symbol (see the predicates below).

  • data event payload: key byte, UTF-8 bytes, mouse detail list, paste bytes, or (rows . cols) for resize.

  • mods #f (no modifiers) or (list ctrl? alt? shift?) for modified keys and mouse events.

procedure

(read-event-noblock)

  
symbol?
bytes?
(or/c #f (list/c boolean? boolean? boolean?))
Like read-event, but returns immediately with 'null when no input is available.

procedure

(event-null? type)  boolean?

  type : symbol?

procedure

(event-key? type)  boolean?

  type : symbol?

procedure

(event-utf8? type)  boolean?

  type : symbol?

procedure

(event-seq? type)  boolean?

  type : symbol?

procedure

(event-ctrl? type)  boolean?

  type : symbol?

procedure

(event-alt? type)  boolean?

  type : symbol?

procedure

(event-mod-seq? type)  boolean?

  type : symbol?

procedure

(event-resize? type)  boolean?

  type : symbol?

procedure

(event-up? type)  boolean?

  type : symbol?

procedure

(event-down? type)  boolean?

  type : symbol?

procedure

(event-left? type)  boolean?

  type : symbol?

procedure

(event-right? type)  boolean?

  type : symbol?

procedure

(event-del? type)  boolean?

  type : symbol?

procedure

(event-insert? type)  boolean?

  type : symbol?

procedure

(event-home? type)  boolean?

  type : symbol?

procedure

(event-end? type)  boolean?

  type : symbol?

procedure

(event-pageup? type)  boolean?

  type : symbol?

procedure

(event-pagedown? type)  boolean?

  type : symbol?

procedure

(event-backtab? type)  boolean?

  type : symbol?

procedure

(event-touch? type)  boolean?

  type : symbol?

procedure

(event-mouse? type)  boolean?

  type : symbol?

procedure

(event-paste? type)  boolean?

  type : symbol?
Predicates on the event type returned by read-event.

procedure

(event-tab? type data)  boolean?

  type : symbol?
  data : bytes?

procedure

(event-space? type data)  boolean?

  type : symbol?
  data : bytes?

procedure

(event-backspace? type data)  boolean?

  type : symbol?
  data : bytes?

procedure

(event-enter? type data)  boolean?

  type : symbol?
  data : bytes?

procedure

(event-escape? type data)  boolean?

  type : symbol?
  data : bytes?
Predicates that also check the key byte in data.

procedure

(ctrl->char data)  (or/c char? #f)

  data : bytes?
Returns the letter of a Ctrl+letter event.

procedure

(alt->char data)  (or/c char? #f)

  data : bytes?
Returns the character of an Alt+character event.

procedure

(mod-seq->char data)  (or/c char? #f)

  data : bytes?
Returns the character of a Ctrl+Alt+character event.

procedure

(event->string data)  string?

  data : bytes?
Decodes UTF-8 event data to a string.

procedure

(event->byte data)  byte?

  data : bytes?
Extracts a single byte from event data.

9.3 Mouse🔗ℹ

procedure

(mouse-press? detail)  boolean?

  detail : list?

procedure

(mouse-release? detail)  boolean?

  detail : list?

procedure

(mouse-move? detail)  boolean?

  detail : list?

procedure

(mouse-scroll? detail)  boolean?

  detail : list?

procedure

(mouse-left? detail)  boolean?

  detail : list?

procedure

(mouse-middle? detail)  boolean?

  detail : list?

procedure

(mouse-right? detail)  boolean?

  detail : list?

procedure

(scroll-up? detail)  boolean?

  detail : list?

procedure

(scroll-down? detail)  boolean?

  detail : list?
Predicates on the mouse detail list carried in data.

procedure

(mouse-x detail)  exact-nonnegative-integer?

  detail : list?

procedure

(mouse-y detail)  exact-nonnegative-integer?

  detail : list?

procedure

(get-mouse-pos detail)  
exact-nonnegative-integer?
exact-nonnegative-integer?
  detail : list?

procedure

(mouse-modifiers detail)  (listof symbol?)

  detail : list?

9.4 Resize🔗ℹ

procedure

(get-resize-rows data)  exact-positive-integer?

  data : (cons/c exact-positive-integer? exact-positive-integer?)

procedure

(get-resize-cols data)  exact-positive-integer?

  data : (cons/c exact-positive-integer? exact-positive-integer?)

procedure

(get-resize-size data)  
exact-positive-integer?
exact-positive-integer?
  data : (cons/c exact-positive-integer? exact-positive-integer?)

10 Terminal🔗ℹ

procedure

(terminal?)  boolean?

True when the current input port is a terminal (isatty).

procedure

(enter-raw-mode!)  void?

Turns off canonical mode and echo, disables signal generation, and enables extended input processing. Used internally by tui-init.

procedure

(exit-raw-mode!)  void?

Restores the saved terminal state.

procedure

(enter-raw-mode-keep-echo!)  void?

Raw mode but keeps echo on. Used internally by tui-init-no-buffer-echo.

procedure

(call-with-terminal-reply thunk)  any

  thunk : (-> any)
Runs thunk with a timeout such that a terminal reply (for example from a DSR query) can be read without hanging.

procedure

(make-stdin-evt)  evt?

A synchronizable event that is ready when stdin has input.

procedure

(get-window-size [fd])  
(or/c exact-positive-integer? #f)
(or/c exact-positive-integer? #f)
  fd : exact-integer? = 1
Returns the terminal size as (values rows cols), or (values #f #f) if the ioctl fails. fd defaults to stdout.

procedure

(resize-monitor-start)  void?

Starts a background thread watching for SIGWINCH; resizes are reported as 'resize events by read-event.

procedure

(resize-monitor-stop)  void?

Stops the resize monitor.

procedure

(make-resize-evt)  evt?

A synchronizable event that is ready when the terminal has been resized.

11 Cursor state🔗ℹ

The library tracks the cursor position in two parameters; -at functions update it.

value

current-cursor-row : exact-nonnegative-integer?

The tracked cursor row (1-based).

value

current-cursor-col : exact-nonnegative-integer?

The tracked cursor column (1-based).

procedure

(set-cursor! row col)  void?

  row : exact-nonnegative-integer?
  col : exact-nonnegative-integer?

procedure

(get-cursor)  
exact-nonnegative-integer?
exact-nonnegative-integer?

procedure

(update-cursor!)  
exact-nonnegative-integer?
exact-nonnegative-integer?
Sends a DSR query (ESC[6n) and parses the terminal’s reply to refresh the tracked cursor position.

12 Configuration constants🔗ℹ

value

ESCDELAY : real?

Timeout between bytes of an escape sequence (seconds), used to distinguish a lone ESC key press from a control sequence. Default 0.05.

value

CSI-MAX-BYTES : exact-positive-integer?

Maximum CSI sequence length before truncation. Default 32.

value

PASTE-MAX-BYTES : exact-positive-integer?

Maximum bracketed-paste length. Default 1048576 (1 MiB).

value

UTF8-READ-TIMEOUT : real?

Timeout for reading UTF-8 continuation bytes. Default 0.5.

value

PASTE-READ-TIMEOUT : real?

Timeout between bytes while reading a paste. Default 1.0.

13 Complete example🔗ℹ

(require tui)
 
(define (draw-ui)
  (define buffer
    (bytes-append
     format-screen-clear
     (format-cursor-move 0 0)
     (format-rgb-fg 255 255 0) #"=== TUI Demo ===" format-reset
     (format-cursor-move 2 0)
     (format-rgb-fg 0 255 0) #"Press 'q' to quit" format-reset
     (format-cursor-move 4 0)
     (format-rgb-fg 255 0 0) #"Hello, TUI!" format-reset
     (format-cursor-move 6 0)
     (format-256-fg 46 "UTF-8 support: 你好世界") format-reset))
  (put-bytes buffer))
 
(with-tui
 (λ ()
   (cursor-hide)
   (define running? #t)
   (define handler
     (build-input
      #:char (lambda (ch)
               (when (= ch (char->integer #\q))
                 (set! running? #f)))))
   (define (render-and-handle type data mods)
     (handler type data mods)
     (draw-ui))
   (loop-input/stop (not running?) render-and-handle)))

14 Implementation notes🔗ℹ

The termios struct layout and flag constants in base/terminal/base.rkt are hardcoded (previously generated by compiling a C program). The values come from the kernel’s asm-generic/termbits.h and are identical across mainstream Linux architectures (x86, arm, aarch64, riscv, ppc, mips, sparc). TERMIOS-SIZE is fixed at 60, which is safe for both glibc and musl. The only exception is the alpha architecture, which is not supported.