2020-09-04 | 5 minutes reading
Picotui, the most understandable TUI library out there
Searching for the right one
I have been using several TUI libraries... curses, urwid, Npyscreen and also some non Python ones. The story is always the same. Library is written using catasthrophic api, obsolete paradigms and with no simple way of extending existing code. The code is often very hard to understand. So I went on a quest to find the most understandable one, that will suit my needs. I crunched throught a bunch of them and then found picotui. It is very small python TUI library, that does not use curses as a rendering engine, it also does not optimize screen refresh bandwith, but comes with decent set of widgets and whole code is in 9 files. There are also no tests, there is no documentation and also very little comments in the code. I almost forgot, author defines it as an experimental WIP project and based on his activity on github, its development and support is virtually non existent. That being said, after I went through most of the code and after building some examples, I can say, that it is still the best library out there when it comes to extendability and ability to understant basic architectural patterns.
Every widget extends Screen class. Screen defines basic utilities for rendering widgets on the terminal screen. So you get the screen size, tty init and dispose, mouse support toggle, rendering functions for several types of borders and boxes, cursor manipulations, character attributes manipulation functions, character write support and hooks for screen redraw and screen resize. That's basically it. Then you get set of abstract widgets built on top of the Screen class: base widget, focusable widget, editable widget, choice widget and item selection widget. Base widget adds key and mouse input handling, primitive support for events and default loop function. The rest of mentioned widgets extend the base widget and add only very little on top. This is the common abstraction layer for all widget implementations: label, frame, button, check box, radio, list box, popup list, drop down, single and multi line entry, combo box and editor. There is also support for menus and dialogs. There are even some common dialog implementations like confirmation dialog, or single input dialog. The most complex widget is Editor, with its extended variants EditorExt, Viewer, LineEditor or versions with some kind of color support. Editor will let you write text that will be wrapped when you reach end of the widget height. It also handles enter, delete and backspace keys for new line and deletion, but it ends there. No support for home, end or tab keys. You also can not init Editor straight with given text, you will have to split it to lines and you also are responsible for keeping an eye on correct line height and therefore splitting on the right place (not in the middle of the word or url)
Basic logic is the same as in any other TUI library and that is the loop. Loop is an infinite cycle that waits for input. When it comes, it will be processed by your logic, loop iteration then finishes and it waits again for another input. Every widget has its loop, but in most cases, your application will not use the native widget loop, but it will run some kind of your custom wrapping loop function instead, that will choose which widget will consume the input. Second important fact is, that in most cases, you need to manage screen redrawing by yourself. Widgets do redraw themselves when using their native API functions, but in most real world usecases, you will have to redraw some other widgets that relies on the one that consumed the input too. Picotui also lacks any automated layouting system, you will have to statically position (and reposition) every widget on your screen. The current screen size can be obtained from Screen class.
If you are building TUI applicattion that would run locally, or remotely using stable average internet connection. If you care about extendability and simplicity. If you want to understand libraries you are using as a building blocks for your project. If you don't mind learning directly from the code with no dev support available. Then this is the TUI library for you. It will take you day or two to grasp the concepts and functionalities, but then you will be able to work with it as if it is direct part of your project. I have customized it to my liking too. Based on what it delivers, it will be necessary in most real world scenarios. I have wrapped some of the native widgets with borders, added text wrapping support to Editor, switched controlling key bindings to vim like bindings and rewrote two of my personal apps with it, finally understanding how and why it is doing what it does without hours of surfing internet to find the answers.