Smoothing out the shell with Nacar

Published on 2022-04-29

Laying the foundations for my umpteenth three-tier web application, I worked my way through the shibboleths of a modern app — containerisation, a decoupled frontend, secrets stored in the environment. These best practices offered reassurance that I was doing the Right Thing™; that any eventual business logic would sit atop a base of concrete reinforced by steel rods forged in the fires of thousands of botched migration rollbacks, endpoint outages, and cache invalidation woes.

As glad as I was for these conventions, once I started to write application code I found the ergonomics of regularly interacting with this digital bedrock lacking. In the early, iterative stage of such a project it quickly becomes tiresome to recall the same management commands over and over.

In parallel to this I was introducing two new colleagues to a slew of systems. To ease them into these I cobbled together a Bash script that displayed a helpful set of management commands for a given project and, listening for the relevant shortcut, executed them. This provided a quick introduction to common tasks and avoided overwhelming them with the specifics and myriad flags of the tools such systems are built on.

Turning my attention back to the greenfield project, inspiration struck.

Surely it would make more sense to build for the general case? These were common scenarios scores of developers faced, that I myself would keep facing. I could create a tool that could both alleviate the tedium of invoking recurrent tasks and also offer guardrails to newcomers, removing some of the anxiety surrounding joining a project.

Nacar is the answer that I have built to the above question. It is a tool that accepts simple YAML blueprints anyone can write and spits out lightweight Bash scripts that produce keyboard-navigable text interfaces.
I find myself putting the resulting Nacar apps in the root of web application projects and using them as a control surface, an accessible starting point where common tasks are but a keystroke away.

Nacar showcase

A YAML blueprint (left) and the resulting Bash Nacar app running in the terminal (right).

A blueprint for a Nacar app is a simple YAML file that defines a hierarchy of screens, the links between said screens, and the commands available for invocation from a given screen. For instance, you might define a top-level 'Test' screen under which you group related commands (such as running unit tests, Selenium tests, generating a report, etc.).

Nacar is comprised of the following modules:

File I/O
Parses YAML files as input and writes in-memory representations of Nacar apps out as executable files. It is responsible for interacting with the filesystem, setting permissions on resulting apps, and handling any I/O exceptions.
Blueprint schema
The schema module defines the rules a parsed blueprints must adhere to before it can be accepted by a translator. Schemas are JSON-like objects that define the hierarchy and rules of an acceptable blueprint. Sub-schemas are modular objects used in a composable manner in the main schema to validate recurring entities such as screens or screen links.
Validator
Nacar's validator is built on top of the Cerberus validator and checks for issues which would make the translator's job impossible, such as duplicates in the screen namespace or recursive screen linkage. It does this by accepting the rules defined in the JSON-like schema, plus more complex ones expressed as small functions.
Translators
Translators take an in-memory representation of a blueprint and turn it into a Nacar application written in a target language. The itranslator.py interface defines the methods a translator should implement, making it easy to create new ones that will output Nacar apps in a language different to that of the canonical translator, which produces Bash scripts.

Nacar is a response to a need, and it is an exercise in metaprogramming, being a program that generates other programs. Building Nacar has given me a new perspective in my approach to code, particularly with regard to the importance of clean, modular design. Future posts will delve into the specifics of what writing the modules listed above has taught me.

You are welcome to try Nacar out — any and all feedback is appreciated.


Main image made by remixing Bootstrap Icons (MIT license).
Dropcap background: Venetian pattern (ca. 1868-70) by William Morris, licensed under CC0.