Wednesday, 07 April 2010

New Clojure Brush for SyntaxHighlighter

I was looking over Stuart Halloway’s labrepl recently, and I was irritated by the poor quality of the syntax highlighting. As I looked into it, it turns out that it uses SyntaxHighlighter, a popular JavaScript-based code syntax highlighter.

The old Clojure brush

SyntaxHighlighter depends on plug-ins called brushes to provide language-specific highlighting based on regular expressions. The brush used by labrepl has a few deficiencies, namely:

  • Keyword highlighting would break at hyphens
  • Form highlighting included only a subset of the basic Clojure functions and macros
  • A name such as my-println would be incorrectly highlighted.

Annoyed by these short-comings, I decided to try my hand at developing a better brush for Clojure.

Developing the new Clojure brush

I encountered a number of hurdles to develop the new brush. Clojure’s extremely flexible naming makes it difficult to create regular expressions to match names. Names such as *out* contain characters that must be escaped, and names such as every? have characters that keep you from being able to use the word boundary zero-width assertions.

Moreover, JavaScript’s regular expression engine is limited. In particular, it lacks support for lookbehind zero-width assertions. Luckily, JavaScript is a dynamically-typed language, and I was able to simulate the RegExp.exec method as if it supported lookbehinds.

The new Clojure brush

So, I am now announcing version 0.9 of sh-clojure, my new SyntaxHighlighter brush for Clojure. It is licensed under the LGPL, like SyntaxHighlighter, and the source is available on GitHub.

Some of the features of this new brush include highlighting of:

  • Special forms
  • All forms from clojure.core of Clojure 1.1
  • Number, character, boolean, and nil values
  • Strings and regular expressions
  • Parentheses and other syntax elements such as reader macros for collections and type hinting
  • Special highlighting for quoted and unquoted symbols

You can download it now from GitHub either as a tarball or as a zip file.


If you have JavaScript enabled, the following code should be highlighted using sh-clojure. If not, it should fall back to my default code block formatting.

(ns #^{:doc "This is a demo of my new Clojure brush for SyntaxHighlighter"
       :author "Daniel Solano Gómez"}

; Including the obligatory ‘Hello, world!’
(defn say-hello
  "A simple function that says hello."
   (say-hello "world"))
  ([#^String who]
   (if (re-matches #"^Mr. [A-Z]$" who)
     (println (str "Good afternoon, " who "."))
     (println (str "Hello, " who "!")))))

(defn average
  [& nums]
  (/ (reduce + nums) (count nums)))

Feedback welcome

I released sh-clojure as version 0.9 as I imagine there may be a bug or two that have escape me. Feel free to file an issue on GitHub or leave a comment here if you run into any problems or would like to suggest a new feature.