Saturday, March 10, 2012

deansi: ANSI colors to html in Python

Let me introduce you deansi, a python module to convert ansi terminal codes to html.

Lately, I am doing some refactorings, enhancements and fixes on TestFarm which lacked of care from us, regardless we use it for CLAM, for our daily work at Barcelona Media, and even to control the status of the unit tests of our students assignments. The testing framework we use for our tests, MiniCppUnit, relies on ANSI colors to highlight the important bits at the terminal output. Sadly, ANSI codes have the opposite effect when you look at that output from the Testfarm summary pages, it gets all quite screwed up.

I gave from granted that there were a common python library or recipe to convert ANSI color codes to html i could use. But i just found this recipe and, in fact, I modified Testfarm to use it, but it seems it is not that reliable and the code had to be extended to do quite basic things. So I decided to spike a test driven developed converter.

I made the module available at GitHub. Its features are:

  • Supports most 'm' codes (colors and attributes).
  • Fully stylable. It generates a default stylesheet but you can redefine the rules in many ways. For example you can make the colors be different in different containers within the same page (a case i need for TestFarm) or setting style properties for combination of active attributes.
  • It is test driven developed and back2back tested, so it is quite reliable, and in the long term features can be extended being quite sure we are not breaking existing functionality.
  • Unlike the recipe i found, it does not expect a given pair of starting and closing codes. It is implemented as an state machine, a new span tag is created at every attribute set change having as many html classes as attributes are active at that moment.
  • You can use it as module or as a command line tool although command line usage is quite minimal (pipe or single input file parameter)

How it works? If you use it as a python module, you can use it that way:

import deansi

html_template = """\
.ansi_terminal {{ background-color: #222; color: #cfc; }}
<div class="ansi_terminal">{ansiText}</div>
ansiInput = "\033[31mHello World!!\033[m"

print html_template.format(
defaultStyle = deansi.styleSheet(),
ansiText = deansi.deansi(ansiInput),
You can change the colors displayed adding style rules after the default ones, for example if you want to change the yellow color when the ansi bright attribute apply, and not to apply bold font (the default) you can say:
.ansi_yellow.ansi_bright { color: #FF7; font-weight: inherit; }

If you want several behaviours in the same html you can use css magic like that:
.my_own_ansi_enviroment .ansi_inverse { font-style: italic; border: none; }

I look forward applying it to TestFarm soon so all the miss-conversions are fixed.

Update: During my first search i didn't notice ansi2html. It is quite similar to deansi.

Update 2: Now its applied to testfarm, take a look at the output by clicking on one of the red executions (which should not exist but shit happens).