terminal
Portable terminal interaction library
https://github.com/lpeterse/haskell-terminal#readme
LTS Haskell 23.1: | 0.2.0.0 |
Stackage Nightly 2024-12-27: | 0.2.0.0 |
Latest on Hackage: | 0.2.0.0 |
BSD-3-Clause licensed by Lars Petersen
Maintained by [email protected]
This version can be pinned in stack with:
terminal-0.2.0.0@sha256:de6770ecaae3197c66ac1f0db5a80cf5a5b1d3b64a66a05b50f442de5ad39570,2977
Module documentation for 0.2.0.0
Depends on 8 packages(full list with versions):
Used by 1 package in nightly-2024-11-29(full list with versions):
terminal
terminal is a driver library for ANSI terminals like xterm.
Features
- Abstract monadic interfaces for different concerns: Write code that is only allowed to print
to the screen using the
MonadColorPrinter m => m ()
constraint! - A monad transformer
TerminalT
which implements all of the interfaces. Either use it directly or include it in your monad transformer stack and lift/derive the functions you need. - Unicode support by design (assuming all terminals understand UTF-8; Windows support is implemented separately).
- Supports the
Text
instead ofString
movement without being to radical about it. - Windows support:
- Windows 10 finally supports ANSI escape sequences and the Windows Console now essentially behaves like an xterm.
- Windows 8, Windows 7 and older is not supported. Windows 7’s support officially ended in 2015 and the extended support will end in 2020. As this is a hobby project aiming at enthusiasts, I have no intention to bloat this code base with all the quirks necessary to make it work on older versions of Windows.
- Unicode is fully supported on Windows for input and output and independant of unreliably hacks like changing the code page. A Unicode compatible console font needs to be configured.
- A very small set of dependencies, most of which are likely to be included in every Haskell project anyway.
- No dependency on terminfo (see below).
- Rich event handling (partly inspired by vty):
- Keyboard events (all control codes and escape sequences are mapped to a useful set of keys and modifiers).
- Mouse events (TODO on Linux).
- Screen resize events.
- Window focus events.
- Interrupt events.
- Event handling is implemented using STM instead of
IO
which makes it very easy to wait for several events simultaneously or combine it with custom or external events like timeouts.
- Proper signal handling (Ctrl+C):
- When using the standard terminal, the library will hook the interrupt signal (or something equivalent e.g. on Windows). Incoming interrupts are passed to the application code and can be dispatched and processed. A supervisor thread assures that the application gets killed on a second interrupt when the application is non-responsive. This resembles the default behavior of GHC’s RTS and a lot of work has been invested to make this mechanism work reliably.
- Integrates the relatively new prettyprinter library. Nicely formatted and colorful output requires nothing more than a few combinators.
To use or not to use terminfo
The terminfo library is a binding to libtinfo.
libtinfo is a library that queries a database (usually below /usr/share/terminfo
)
to determine the specifica and necessary control codes for interacting with a given
terminal.
Unfortunately, it is a reocurring source of issues:
- https://github.com/commercialhaskell/stack/issues/1012
- https://github.com/purescript/purescript/issues/2176
- https://ghc.haskell.org/trac/ghc/ticket/8746?cversion=0&cnum_hist=2
- https://ghc.haskell.org/trac/ghc/ticket/13210
Arguments in favor of terminfo:
- Would allow to support all terminals in existence.
- It’s “the standard”.
Arguments against terminfo:
- Static linking and stand-alone binaries:
Apart from eventual linking issues, terminfo has a runtime dependency on the
terminfo database. This might be an issue when the environment is restricted
(
chroot
environment or if the process shall not be allowed to interact with the file system for security reasons). - terminfo offers more than 500 capabilities. Only a very small part of it is actually needed and since there is no legacy code to support there is no real reason to expose more than a small subset of capabilities that is supported by all terminals (-> ANSI sequences).
- Claim: All relevant terminals support and understand the relevant ANSI escape sequences and/or try to behave like xterm. Terminals that don’t are not relevant.
- Is it really necessary to support something like tvi925 (Televideo 925, around 1982)? I honor that terminfo takes the burden to maintain the definition files for such historical hardware, but I doubt that anyone would miss it if we decide not to support it.
For now, I decided to not use terminfo and see how well it works. This decision might be revised in the future. The API won’t be affected by it.
How terminal compares to..
ansi-terminal
- ansi-terminal offers very similar primitives for printing to the terminal and controlling the cursor.
- It also achieves doing this in portable way (very good Windows support, no terminfo requirement on Linux/Posix).
- It doesn’t offer mechanisms for event processing.
- Its operations live in
IO
(control code output is possible as well) and assume that the terminal is either connected tostdin/stdout
or to a handle.
ansi-wl-pprint
- ansi-wl-pprint is an extension library to ansi-terminal. It offers a Wadler-Leyen pretty-printer adapted to the needs of terminal screens (colors and text formatting).
- terminal has a dependency on the more generic prettyprinter in order to offer the same features and make pretty and colorful terminal output the default rather than an exception.
Haskeline
- haskeline is a pure-Haskell readline replacement.
- Its primary job is offering a line editing interface and it does this very well.
- Like terminal it offers a monad transformer interface to the user (
InputT
). - It does signal handling (Ctrl+C, Ctrl+D).
- It has a dependency on terminfo in order to support a broad range of terminals (especially those that are non-ANSI).
- It offers operations for printing to the terminal which pass control codes unescaped.
- It might be interesting to investigate whether terminal could be used as an alternative backend for haskeline.
vty
- vty is a library that serves
as a foundation for curses-like applications (full-screen terminal applications
like
vim
orhtop
). - It is very similar to
terminal
(especially the event processing has been inspired by vty): It completely abstracts away the details and quirks of communication with different terminals and offers a canonical interface to the user. - Its scope is wider than that of terminal:
- vty has the concept of
Images
that can be assembled and manipulated by the user. The library keeps track of the changes and computes minimal changesets which it then transmits to the terminal.
- vty has the concept of
- Compared to terminal it (currently) has the following shortcomings:
- Lack of Windows support (there has been a call to arms recently; I’d be happy if my findings with terminal could help improve the situation with vty).
- Dependency on
terminfo
. - No proper signal handling.
brick
- brick is library on top of vty. Its scope is different from what terminal does.
Changes
Changelog for terminal
0.2.0.0 Lars Petersen [email protected] 2019-02-10
- Fixes several inconsistencies and improves the API (heavily breaks previous API)
0.1.0.0 Lars Petersen [email protected] 2019-01-22
- Initial release