HTML Terminal Snapshots

April 9, 2016

In preparation for my future posts, I needed to devise a way to export the output of terminal commands to formatted HTML (including colors). While I’m sure some terminal emulators out there already provide such a feature, I wanted my own portable solution that anyone could use.

First attempt

⌘+C, ⌘+V

My research first led me to an OS X only version. The clipboard management of OS X has support for rich text copy and paste, through the RTF format. I could just run a command in the Terminal application, copy and paste the output to TextEdit, and save as an HTML file.

Although this solution worked, it had major caveats:

  1. It is a tedious process and can’t be automated
  2. The generated HTML output is not really helpful for this blog:
    • All colors and properties defined in generated styles in <head>
    • Automatically generated style names makes it impossible to paste multiple snapshots in a single post
    • Not in a <pre> tag, spaces are wrapped in styled spans
  3. Not really portable!

An answer from the experts

Thankfully after reading some posts on StackOverflow, I discovered a very nifty tool called ansifilter1, which translates ANSI escape codes (we’re gonna see a lot more of these in future posts :)2 to either formats such as HTML, RTF and even LaTeX.

What’s more, ansifilter generates clean HTML, uses <pre> and can produce either a standalone HTML file or only the contents of the <pre> tag. I can now present to you, anytime I want, glorious terminal snapshots:

0
1
2
3
4
5
6
7
8
$ cowsay -e '>o' 'Howdy, readers!' | lolcat -F 0.4
 _________________ 
< Howdy, readers! >
 ----------------- 
        \   ^__^
         \  (>o)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

All I had to do now was to create some useful aliases:

1
2
alias html="ansifilter -H -f"
alias copyhtml="html | pbcopy"

Running any command and piping its output to copyhtml would now place a nicely colored HTML output in my clipboard, ready to paste anywhere. Piping to html would output the formated HTML to stdout enabling you to further pipe into other commands.

The last step to make this process even quicker with Hugo, my blog builder, was to create a template to avoid having to manually wrap my pasted snippet with opening and closing tags for the formatting:

0
1
2
3
4
5
6
7
$ pless layouts/shortcodes/term.html
<table class="highlighttable">
    <tr>
        <td>
            <pre>{{ .Inner }}</pre>
        </td>
    </tr>
</table>

(pless is a custom command that has a less behavior while highlighting code syntax with pygments, more on that in later posts!)

Thanks to that template, I now have a really nice work flow for writing my Markdown posts:

  • Run the command I want to demo, pipe it to copyhtml
  • Go to my Markdown article, open a {{< term >}} tag
  • Paste
  • ???
  • Profit!

Clever pipes

In actuality, I had to cheat to produce the above example (sorry). Some programs like ls or lolcat will detect if their stdout is connected to a tty or not, stripping all ANSI escape codes in the latter case.

Enter the unbuffer command from the expect3 software suite:

unbuffer disables the output buffering that occurs when program output is redirected from non-interactive programs.

The commands I really ran were:

1
2
3
cowsay -e '>o' 'Howdy, readers!' > tmp
unbuffer lolcat -F 0.4 tmp | copyhtml
rm tmp

But, for most cases, command | copyhtml is enough :)


  1. ansifilter is available on brew if you’re on a Mac [return]
  2. http://www.xkcd.com/541/ [return]
  3. Also available on brew [return]
comments powered by Disqus