I’m going tell you the tale of oho, a program which is arguably the world’s greatest ANSI text to HTML converter, and how it solved a real business problem. I’m sharing this because, as a geek, it’s important to remember that you can frequently solve work needs, while having fun creating open source tools that interest you.
Side note: ANSI escape sequences are the things that cause text to be colored, bolded, etc when displayed in a terimnal.
One of the roles I played at One Door was that of Release Manager. The core of that task was figuring out what code was included in, or missing from, a release - and then communicating that info to the Project Managers and Scrum Masters. Most importantly, I needed to make it clear to them if there were things they should be concerned about.
I accomplished this by writing a series of small, focused, command line tools that embodied the Unix Philosophy and worked together to extract data from Git, Github, and Jira, then combine it into a report which was transmitted to the interested parties via Slack.
The larger releases presented a problem though. Project Managers didn’t really want to read through the status of 300+ tickets, or contemplate what unexpected commits might mean to their release. It was too daunting of a task, and they had enough things on their todo list.
One of the strategies I took to help address this was to highlight unimplemented tickets, or unexpected commits, in different colors. Unfortunately, there’s no good mechanism to get terminal colors into Slack. Colored text just isn’t supported. For multiple reasons, the right answer seemed to be to give them a PDF version of what I was seeing in the output of my tools.
I didn’t find any extant ANSI to PDF converters, but that wasn’t surprising. I did find a number of HTML to PDF converters though, and I knew you could convert ANSI to HTML. So, I set up an
ANSI -> HTML -> PDF pipeline and quickly discovered that my PDFs looked terrible. The problem was the HTML. Every existing ANSI to HTML converter had some aspect of it that made it just unusable. In one case, my half-page test grid of colors ended up being an unreadably small postage stamp in the corner once it made the final transition. Others didn’t actually support the various color codes very well.
Choosing a technology
aha (Ansi HTML Adapter) seemed the best of the available tools. It was written in C. I figured it was better (and faster) to debug and tweak something that was fast and mostly working, than it was to write something from scratch. Unfortunately, it’s source code was not up to my standards. It worked, but it wasn’t very readable, or commented, or well organized. It was more a stream of consciousness in code form. As I spent more time refactoring it, I realized that by the time I was done, I’d have a completely different codebase that was readable, and maintainable, but still not very extensible.
So, I began to write oho.
It was clear from my work refactoring aha that this was going to be a non-trivial codebase with multiple files. I wanted to write it in a language that would allow me to distribute it without people having to know anything about the ecosystem surrounding it. Ruby is terrible for that because you need to know about Gems, and Bundler, and most systems ship with old Ruby versions and… I wanted this to be simple for users. So, I needed a compiled language. Crystal met those requirements, and I’d been using it for a while and found it rather enjoyable, so that’s what I used.
Crystal produces Dynamically Linked executables (like most compiled languages) so distribution was just a matter of creating a Homebrew script (for Mac users) that told people’s computers where to download it and what dynamic libraries it dependend on. The same can be done for other systems with little difficulty.
Chicken Scheme would have been another choice I could have easily worked with, but beyond just producing a single executable, Crystal is less intimidating to most developers. Lisps are treated as exotic things with “too many parentheses.” I wanted something that could be easily enhanced by anyone in the Open Source community. Crystal looks very similar to Ruby (it’s essentially just Statically Typed Ruby), and organizes its code along lines that are familiar to most developers who use descendents of C (Ruby, Python, Java, etc). Crystal also has a decent testing framework built in. It could be better, but it gets the job done relatively painlessly.
So, I chose a language that would give me a single executable that required no knowledge of the language or ecosystem it was written in to install, would be easy to test, and easy to extend by people unfamiliar with the codebase. If I had it to do again, I might write it in Go, because of the Statically Linked executables it creates, along with easy cross-compilation.
In the end, I had a fast tool that I installed at work and began presenting the project managers with colorful PDFs for each release. Since then, I’ve added support for more esoteric escape sequences, and plan on continuing to do so in the future.
I also had fun writing it.