package notty

  1. Overview
  2. Docs

Parse and decode escape sequences in character streams.

Input events

type key = [
  1. | `Escape
  2. | `Enter
  3. | `Tab
  4. | `Backspace
  5. | `Insert
  6. | `Delete
  7. | `Home
  8. | `End
  9. | `Arrow of [ `Up | `Down | `Left | `Right ]
  10. | `Page of [ `Up | `Down ]
  11. | `Function of int
]

A selection of extra keys on the keyboard.

type button = [
  1. | `Left
  2. | `Middle
  3. | `Right
  4. | `Scroll of [ `Up | `Down ]
]

Mouse buttons.

type mods = [ `Meta | `Ctrl | `Shift ] list

Modifier state.

type event = [
  1. | `Key of [ key | `Uchar of uchar ] * mods
  2. | `Mouse of [ `Press of button | `Drag | `Release ] * (int * int) * mods
]

Things that terminals say to applications.

  • `Key (k, mods) is keyboard input.

    k is either a special key, or `Uchar u where u is uchar. This value is guaranteed not to be a control character, and is safe to use in constructing images.

    mods are the extra modifier keys.

  • `Mouse (event, (x, y), mods) is mouse input.

    event is the actual mouse event: button press, release, or motion of the mouse with buttons depressed.

    (x, y) are column and row position of the mouse. The origin is (1,1), the upper-left corner.

    Note Every `Press(`Left|`Middle|`Right) generates a corresponding `Release, but there is no portable way to detect which button was released. `Scroll(`Up|`Down) presses are not followed by releases.

Terminal input protocols are historical cruft, and heavily overload the ASCII range. For instance:

  • It is impossible to distinguish lower- and upper-case ASCII characters if Ctrl is pressed;
  • several combinations of key-presses are aliased as special keys; and
  • in a UTF-8 encoded stream, there is no representation for non-ASCII characters with modifier keys.

This means that many values that inhabit the event type are impossible, while some reflect multiple different user actions. Limitations include:

  • `Shift is reported only with special keys, and not all of them.
  • `Meta and `Control are reported with mouse events, key events with special keys, and key events with values in the ranges 0x40-0x5f (@ to _) and 0x60-0x7e (` to ~). If Ctrl is pressed, the higher range is mapped into the lower range.
  • Terminals will variously under-report modifier key state.

Perform own experiments before relying on elaborate key combinations.

Decoding filter

Simple IO-less terminal input processor. It can be used for building custom terminal input abstractions.

type t

Input decoding filter.

The filter should be fed strings, which it first decodes from UTF-8, and then extracts the input events.

Malformed UTF-8 input bytes and unrecognized escape sequences are silently discarded.

val create : unit -> t

create () is a new, empty filter.

val input : t -> bytes -> int -> int -> unit

input t buffer i len feeds len bytes of string into t, starting from position len.

len = 0 signals the end of input.

buffer is immediately processed and can be reused after the call returns.

val next : t -> [ event | `Await | `End ]

next t is the next event in the filter's input stream:

  • #event, an input event.
  • `Await if the filter needs more input.
  • `End if the input had ended.
val pending : t -> bool

pending t is true if a call to next, without any intervening input, would not return `Await.

Low-level parsing

Warning The parsing interface is subject to change.

Implementation of small parts of ECMA-35 and ECMA-48, as needed by terminal emulators in common use.

val decode : uchar list -> event list

decode us are the events encoded by us.

us are assumed to have been generated in a burst, and the end of the list is taken to mean a pause. Therefore, decode us1 @ decode us2 <> decode (us1 @ us2) if us1 ends with a partial escape sequence, including a lone \x1b.

Unsupported escape sequences are silently discarded.

OCaml

Innovation. Community. Security.