Do you like ncurses? Do you like JavaScript? If yes, you will love Blessed; a Node.js library to create highly interactive and rich text-based user interfaces.
GUI vs CLI vs TUI
Graphical User Interfaces (GUIs) are great in terms of design and usability, but they are quite poor when it comes to automation and performance. For complex operations, it is much easier to write a shell script with Bash than programming macros to interact with graphical components. Of course, sometimes we have to test GUIs. But do we need to automate heavy ones when we just want to manipulate files and perform basic operations? The answer is obviously NO.
However, a Command Line Interface (CLI) is not very user-friendly. For this reason, we might need a better interface, without sacrificing too much performance. Here comes the Text-based User Interface (TUI)…
The principle is simple: we are still in a terminal, we are still in a textual environment, but here we can create visual layouts using widgets. Graphical components are lightweight and can be used to reproduce layouts we can find on most desktop or web applications.
Specifications
Let’s say we want to get some information about a user. We need to know:
- The full name (first name + last name) of the user
- His favorite text editors among “Vim”, “Emacs”, “Atom” and “Brackets”
- If he likes Blessed or not
- If he has some comments to share
Basic CLI implementation with Bash
To get user input, we can create a Bash script and use the read
command. A possible (but very basic) implementation could look like this:
|
If I run the script and provide all relevant information, a data.txt
file is generated with the following content:
|
This solution is acceptable if we do not need a sophisticated interface. But to shine in society, we may need something more advanced… Blessed comes to the rescue!
Advanced TUI implementation with Blessed
Here is the layout we are going to build programmatically:
Importing modules
Here we use the CommonJS syntax. We need two modules only: blessed and fs.
|
Creating a screen object
Just like the scene in three.js, we need a primary object to render something on screen. With Blessed, this is easy to memorize because it is actually the screen object (which has a render()
method). The following code creates a screen object called “Blessed form” with smart CSR (change-scroll-region) for a more efficient rendering:
|
Because we are building a TUI, we can set global key bindings to interact more easily with our interface. A must-have is a shortcut that allows us to quit instead of killing the current shell session. By convention, we will press Q to quit:
|
Configuring widgets
Creating user interfaces with Blessed is not very hard, but extremely verbose and declarative. The library makes an intensive use of the object specifier pattern (aka options object).
It sometimes happens that a constructor is given a very large number of parameters. This can be troublesome because it can be very difficult to remember the order of the arguments. In such cases, it can be much friendlier if we write the constructor to accept a single object specifier instead. That object contains the specification of the object to be constructed.
Douglas Crockford, JavaScript: The Good Parts
In fact, Blessed is based on widgets (text inputs, checkboxes, radio buttons, etc.) that can be configured quite precisely. As an example, here we create the form and its first text box:
|
Blessed positioning is a bit less convenient and powerful than CSS positioning, but we do not have the same constraints for a web page and a terminal app. For a TUI, absolute positioning does the job quite well…
Handling events
To submit or reset the form, we have two main buttons: submit
& reset
. These buttons must trigger the appropriate form action. It could be done like so:
|
When the form is submitted, we have to parse its data properly and write the result to a file. When it is reset, we just send a message (a toast):
|
Done!
Full implementation
If your environment is properly set up, you can run the following script with node
:
|
Conclusion
Building an advanced TUI may be a long process. Sometimes a raw CLI program is better, but if usability really matters, Blessed can be an interesting option and a good alternative to ncurses.
By the way, in the use case presented here, there is no validation at all: not in our Bash script, nor in our Blessed script. If you want a good exercise, maybe you can try to implement it…