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.
Demo
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"}
sh-clojure.demo)
; 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.