Skip to content

Instantly share code, notes, and snippets.

@lpeterse
Last active January 14, 2018 20:47
Show Gist options
  • Save lpeterse/4f2785c3fb2545f81f37882b3491b846 to your computer and use it in GitHub Desktop.
Save lpeterse/4f2785c3fb2545f81f37882b3491b846 to your computer and use it in GitHub Desktop.
ANSI terminal interface in Haskell

Goal

A library that..

  • offers a portable interface for writing interactive terminal applications
  • favours portability and simplicity over performance and features
  • supports most modern software terminals (not the old tube things in the museum)
  • behaves the same on all ANSI-compliant terminals (+ extra code for Windows i.e. via ansi-terminal)
  • has a minimal set of dependencies
  • does not use terminfo
  • can handle Unicode (assuming that the terminal is unicode-enabled is fine though)
  • is threadsafe
  • somehow integrates with a with a pretty-printer (i.e. ansi-wl-pprint) for coloured output etc.
  • does exception/signal handling, interruptible asynchronous execution of subtasks
  • shall be good enough that GHCI could work on top of it
  • shall not only work for the local terminal but also for remote terminals via inband signalling over streams (i.e. SSH)

Literature

Existing libraries

haskeline

  • essentially a readline replace with various goodies (vim modes etc)
  • used by ghci
  • supports various terminal types and platforms
  • depends on terminfo which is not threadsafe and a portability issue (linking etc)
  • code is complicated (for my taste)
  • dependencies: base, bytestring, containers, directory, filepath, process, stm, terminfo, transformers, unix, Win32

terminfo

  • a binding to the libtinfo (*nix only)
  • not threadsafe, not portable, only supports terminals in local terminfo database
  • dependencies: base + libtinfo (via FFI)

ansi-terminal

  • a quite miminal and portable way to control modern terminals with ANSI escape codes instead of terminal specific control codes
  • not tied to the stdout (can be used with Handles or pure as well)
  • Windows support (using system calls)
  • dependencies: base, base-compat, colour, containers, process, Win32

ansi-wl-pprint

  • a really nice pretty-printer that generates output disgestable for ANSI-compliant terminals
  • it would be nice if the pretty printer would be separate from the encoding / output driver
  • dependencies: base, ansi-terminal, semigroups

vty

  • a terminal GUI library in the niche of ncurses
  • features:
    • UTF-8 support
    • virtual terminal state tracking and computation of minimal changesets
    • window resize support
    • multi-column glyphs (what is this?)
  • missing features:
    • signal handling
    • Windows support (!)
  • does several things that could be separated:
    • handles terminal control (via terminfo)
    • decodes keyboard keys
    • supplies a rich interface for building graphical terminal applications
  • dependencies: ..... blaze-builder, parsec, terminfo, text, bytestring ......

Input Key Encoding

Key ASCII Code(s) Comment
CTRL+C 3 END OF TEXT Causes SIGINT (is not transmitted in-band)
CTRL+D 4 END OF TRANSMISSION
CTRL+J 10 LINEFEED ENTER is alias
CTRL+M 13 CARRIAGE RETURN
CTRL+[ 27 ESCAPE
CTRL+\ 28 FILE SEPARATOR Causes SIGQUIT (is not transmitted in-band)
CTRL+_ 31 UNIT SEPARATOR
DEL 127 BACKSPACE The backspace key (not the DEL key)
... ... ... ...
F1 27, 91, 49, 49, 126
F2 27, 91, 49, 50, 126
F3 27, 91, 49, 51, 126
F4 27, 91, 49, 52, 126
F5 27, 91, 49, 53, 126
F6 27, 91, 49, 55, 126
F7 27, 91, 49, 56, 126
F8 27, 91, 49, 57, 126
F9 27, 91, 50, 48, 126
F10 27, 91, 50, 49, 126
F11 27, 91, 50, 51, 126
F12 27, 91, 50, 52, 126
ALT+A 27, 97
ALT+B 27, 98
ALT+C 27, 99
ALT+D 27, 100
...
ALT+Z 27, 122
DEL 27,91,51,126 The DEL key

SSH terminal modes

urxvt:

[129,0,0,150,0,128,0,0,150,0,1,0,0,0,3,2,0,0,0,28,3,0,0,0,127,4,0,0,0,21,5,0,0,0,4,6,0,0,0,0,7,0,0,0,0,8,0,0,0,17,9,0,0,0,19,10,0,0,0,26,12,0,0,0,18,13,0,0,0,23,14,0,0,0,22,18,0,0,0,15,30,0,0,0,1,31,0,0,0,0,32,0,0,0,0,33,0,0,0,0,34,0,0,0,0,35,0,0,0,0,36,0,0,0,1,37,0,0,0,0,38,0,0,0,1,39,0,0,0,0,40,0,0,0,0,41,0,0,0,1,42,0,0,0,1,50,0,0,0,1,51,0,0,0,1,52,0,0,0,0,53,0,0,0,1,54,0,0,0,1,55,0,0,0,1,56,0,0,0,0,57,0,0,0,0,58,0,0,0,0,59,0,0,0,1,60,0,0,0,1,61,0,0,0,1,62,0,0,0,0,70,0,0,0,1,71,0,0,0,0,72,0,0,0,1,73,0,0,0,0,74,0,0,0,0,75,0,0,0,0,90,0,0,0,1,91,0,0,0,1,92,0,0,0,0,93,0,0,0,0,0]

xterm:

[129,0,0,150,0,128,0,0,150,0,1,0,0,0,3,2,0,0,0,28,3,0,0,0,8,4,0,0,0,21,5,0,0,0,4,6,0,0,0,0,7,0,0,0,0,8,0,0,0,17,9,0,0,0,19,10,0,0,0,26,12,0,0,0,18,13,0,0,0,23,14,0,0,0,22,18,0,0,0,15,30,0,0,0,0,31,0,0,0,0,32,0,0,0,0,33,0,0,0,0,34,0,0,0,0,35,0,0,0,0,36,0,0,0,1,37,0,0,0,0,38,0,0,0,1,39,0,0,0,0,40,0,0,0,0,41,0,0,0,0,42,0,0,0,1,50,0,0,0,1,51,0,0,0,1,52,0,0,0,0,53,0,0,0,1,54,0,0,0,1,55,0,0,0,1,56,0,0,0,0,57,0,0,0,0,58,0,0,0,0,59,0,0,0,1,60,0,0,0,1,61,0,0,0,1,62,0,0,0,0,70,0,0,0,1,71,0,0,0,0,72,0,0,0,1,73,0,0,0,0,74,0,0,0,0,75,0,0,0,0,90,0,0,0,1,91,0,0,0,1,92,0,0,0,0,93,0,0,0,0,0]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment