Clojure's pretty printer (clojure.pprint) takes unformatted code like this:
(defn fib ([n] (fib n 1 0)) ([n a b] (if (= n 0) a (fib (dec n) (+ a b) a))))
And makes it nice, like this.
(defn fib
([n] (fib n 1 0))
([n a b]
(if (= n 0)
a
(fib (dec n) (+ a b) a))))
I'd like to put some source in a web page, so I'd like it to be pretty-printed. But I'd also like to wrap each form in a set of < span > tags with a unique ID so I can manipulate the representation with javascript. That is, I want to turn
(foo bar baz)
into
<span id="001">(<span id="002">foo</span> <span id="003">bar</span> <span id="004">baz</span>)</span>
But I still want the resulting forms to be indented like the pretty printer would, so that the code that actually gets displayed looks right.
Some of the documentation for the pretty printer mentions that it can take custom dispatch functions, but I can't find anything about what they do or how to define them. Is it possible to do what I want with such a beast, and if so can someone provide me with some information on how to do it?
It's possible, but I think it's much more work than you expect. You'll work with source code pprint/dispatch and modify functions that are already here.
You'll surely need with-pprint-dispatch. This function uses given dispatch function to execute body:
Look for function
code-dispatch
and see it's definition:As you can see, there is special function for each collection type. I just picked list and vector and my dispatch function looks like this:
Now, look for
pprint-code-list
,pprint-vector
andpprint-simple-default
. Two of them usepprint-logical-block
with keywords:prefix
and:suffix
- that's the place where you insert additional string (the rest of function will be the same). Don't forget to define some counter for span numbering:With all this setup, I called:
Or you can print it into string:
And I have to mention again that for printing some real code, you would have to modify all functions for all data types. So- it's possible? Yes. Worth the effort? I doubt it.