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.
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.
TrackBacks
No trackbacks, yet.
Trackbacks are closed for this story.
Comments
-
On Thursday, 8 Apr 2010 02:41, Sam Aaron wrote the following:
Having had first hand experience of writing highlighting lexers for very dynamic languages (for example, I've written a few for Ioke), I understand the pain and struggle you've had to endure to achieve this. Well Done!
If you ever feel crazy again, perhaps you might port sh-clojure to Python's Pygments which is the syntax highlighting tool used by GitGub...
-
On Friday, 23 Apr 2010 07:56, Daniel Solano Gómez wrote the following:
Sam:
Thank you. Pygments already seems to have a lexer for Clojure. I took a look at it, and it does not seem too bad overall. How do you think it can be improved?
-
On Thursday, 9 Feb 2012 19:56, daveloyall wrote the following:
This might be a stupid question, but did you just FIX regular expressions in JavaScript? Is you RegExp.exec something that could be published separately?
-
On Thursday, 9 Feb 2012 21:03, Daniel Solano Gómez wrote the following:
Well, I wouldn't say that I fixed regular expressions in JavaScript. It's been some time (nearly two years) since I wrote the code. I recall doing a lot of searching around to figure out how write that code, especially since I'm no JavaScript expert.
If I recall correctly, my code is a specialised implementation of what I found at sites like <http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript>. If you'd really like to reuse my code without the LGPL or EPL, please e-mail me at <daniel at solanogomez.org>.
Comments are closed for this story.