Terminal Syntax Highlighting

Posted September 12, 2007

I know, I keep going on about syntax highlighting. I promise I’ll stop (at least for a while) after this post.

My latest highlighty adventure should be of more general interest than the last few, though. See, this time it’s not about highlighting code on some website. It’s about highlighting code in the place programmers spend the second-most amount of time: the terminal1.

Even though I use Emacs, I haven’t gotten the hang of the built-in shell. It’s cool and reasonably functional, but it chokes on stuff like colored output and cursor positioning. So I tend to switch between Emacs and gnome-terminal.

When I’m using the terminal, I occasionally want to examine files or diffs or whatever. For this, I use less. less is in general an excellent little pager, but I’ve always been a little miffed that it didn’t have any way of highlighting syntax.

So I decided to take it into my own hands. It turns out that less will, with the -R option, display colors if the input sent to it is colored. Thus, as long as I had a way of doing the syntax highlighting before sending it to less, I was home free.

Unfortunately, cursory Googling didn’t reveal any such utility. So I decided to make one myself.

I’d played with terminal formatting before. Although there’s not a wide selection of formatting options available, it’s reasonably straightforward to color stuff. There are just a bunch of escape sequences that, when printed, tell the terminal to start formatting the text a certain way.

So in order to get terminal highlighting, I had to have some way of taking a blob of code and surrounding the right bits with the right formatting characters.

I decided to go with the CodeRay highlighter that I use for this blog. Not only am I most familiar with it, but it has a nice plugin system for new syntaxes and new output formats.

So I whipped up an encoder that outputs terminal-formatted text. Here’s a Pastie. Save that as lib/coderay/encoders/term.rb or just require it along with CodeRay and you’re good to go.

Of course, writing out coderay #{syntax} -term < #{file} | less is a little annoying, so I also wrote up a quick shell script to take care of that for me. I’ve got that Pastied, too.

This script (I call it color-less, but have pager aliased to it) works almost the same as less, with a couple exceptions. First, you can specify the syntax like so:

color-less =ruby Rakefile

Put explicitly, to specify the syntax, use =#{syntax} as the first argument. The equals sign is there to distinguish it from the normal less arguments.

color-less will try to autodetect the format based on the filename, but only if the filename is the first argument. If the syntax is specified, the filename should still be the second argument. Otherwise, the syntax highlighting won’t work.

For your edification, here are a couple more usage examples:

color-less tetris.c --quiet
svn diff | color-less =diff

1 The most amount of time is, of course, spent in the text editor. The web browser occasionally displaces these two, but only if you’re learning a new language or API (or spending too much time on Reddit).

Make your comments snazzy with Textile!