Screwtape

Screwtape at

Today, I spent some time investigating terminal UI libraries. You know, the kind of library that lets you draw coloured text to your terminal, and tells you which key the user pressed. Turns out, it's a lot messier than I imagined.

curses is the grandaddy, of course. It supports Every Terminal Ever, it's available on every platform, it's wicked-smart about updating the screen, what's not to like? Well, because it supports Every Terminal Ever, the API has this odd fascination with colour-pairs instead of just setting foreground and background colours. It doesn't support mouse-drag events, or any mouse events past column 224, or keyboard events involving the Alt modifier, or the true-colour output that some terminals support these days. And on top of everything else, the API is weird and archaic to modern eyes—definitely a product of its era.

But curses gets its wide compatibility from terminfo, right? So we'll just write to the libterminfo API and build our own abstractions on top. We'll lose the cleverness of curses, but we'll get the features we want, right? Right? Unfortunately, terminfo has a weird dynamic-typing thing going on: for a given terminal, a given capability can be a boolean, integer, string, or a string-template, and you just have to assume what it's going to be, you can't query it, so you don't want to venture too far outside the well-known capabilities terminfo defines. Worse, terminfo doesn't support as much as you'd like. Some keys have regular and shifted capabilies (for example, "key_left" and "key_sleft" for the Left arrow and Shift-Left respectively), most do not. Terminfo supports ~60 function keys, so typically Shift-F1 is mapped to F13 (or F11), Ctrl-F1 to F25 (or F21), etc. There's a sequence for mouse input, but it assumes details of the traditional xterm mouse protocol, so you're stuck with the 224-column limit.

Most other libraries are built on top of curses, or are just designed to support very basic formatting and positioning, so they're not much good for the general case of full-screen terminal applications.

One library that seems to be well designed is libtermkey - it only deals with input, but it deals with it the right way: you feed in bytes, you get out UTF-8 strings, key symbols with modifiers, or mouse events (autodetecting what protocol is in use). Unfortunately, libtermkey is officially deprecated, although it does see minor development work.

libtermkey's official replacement is libtickit, by the same author. Unfortunately, that library has only just (in early April 2017) reach version 0.1, and is not yet widely available. Time will tell whether it becomes the One True Text UI library.


clacke@libranet.de ❌ likes this.

clacke@libranet.de ❌, clacke@libranet.de ❌ shared this.

Looks like a messy topic =)

JanKusanagi at 2017-04-23T15:39:31Z