The following, which I relinquish into the public domain and certify is original to me, takes a string and reformats it as Clojure code, returning a string. It behaves similarly to the Enclojure reformatter, but: 1. Outside string literals and comments, it will take care of all spacing. 2. Comments get one space before and one after the ; before the comment text. If the comment text originally started with a space none is inserted after the ;. 3. If two comments are on successive lines and the second can be aligned with the first by inserting additional spaces before the ;, the comments are aligned in this manner; exception to item 2. 4. Delimiters in character literals (e.g. \{) don't screw up the indenting of susbequent lines.
Note that this doesn't use the reader, which at first blush would seem to make things simpler. But using the reader would clobber comments, expand #() and the like, and fail if the input contained unbalanced delimiters. The below code appears to indent the same as Enclojure in the face of unbalanced delimiters. As a little demonstration, the code below appears as formatted by itself: (defn format-code [string] (loop [s string col 0 dstack [] out [] space nil incl false insl false incm false lwcr false sups true cmindent nil] (if-let [c (first s)] ; test comment 1 { ; ) (let [r (rest s) ; test comment 2 ( [ begins "([{" ends ")]}" ; test comment 3 " ; delim-indents (zipmap begins [1 0 0]) ; test comment 4 delim-ends (zipmap ends begins) sups-char? #{\' \` \~ \@ \#} ; characters to suppress indent (fn [] ; spaces after (if (or (empty? r) (empty? dstack)) [\newline] (into [\newline] (repeat (let [[delim pos] (peek dstack)] (+ pos (delim-indents delim))) \space)))) conc (fn [c] (if sups [c] (conj space c))) pop-d (fn [stack c] (if (empty? stack) [] (let [ps (pop stack)] (if (empty? ps) [] (if (= (first (peek stack)) (delim-ends c)) ps (recur ps c))))))] (cond incm (let [nl (or (= c \newline) (= c \return)) spc (Character/isWhitespace c) cc (if nl (indent) (if spc (if-not sups [c]) [c]))] (recur r (if nl (dec (count cc)) (+ col (count cc))) dstack (into out cc) nil false false (if-not nl incm) (= c \return) nl cmindent)) (= c \") (let [cc (if (or incl insl) [c] [\space c])] (recur r (+ col (count cc)) dstack (into out cc) (if (and insl (not incl)) [\space]) false (if incl insl (not insl)) false false false cmindent)) (or incl insl) (recur r (if (or (= c \newline) (= c \return)) 0 (inc col)) dstack (conj out c) nil (and insl (not incl) (= c \\)) insl false false false cmindent) (= c \;) (let [padding (if sups 0 1) padding (if cmindent (max padding (- cmindent col)) padding) padding (repeat padding \space) padding (concat padding [\; \space])] (recur r (+ col (count padding)) dstack (into out padding) nil false false true false true (+ col (count padding) -2))) (= c \\) (let [cc (if sups [c] [\space c])] (recur r (+ col (count cc)) dstack (into out cc) nil true false false false false cmindent)) (or (and (= c \newline) (not lwcr)) (= c \return)) (let [i (indent)] (recur r (dec (count i)) dstack (into out i) nil false false false (= c \return) true nil)) (= c \newline) (recur r col dstack out nil false false false false true cmindent) (Character/isWhitespace c) (recur r col dstack out [\space] false false false false sups cmindent) (delim-indents c) (let [cc (if sups [c] [\space c]) cn (count cc)] (recur r (+ col cn) (conj dstack [c (+ col cn)]) (into out cc) nil false false false false true cmindent)) (delim-ends c) (recur r (inc col) (pop-d dstack c) (conj out c) [\space] false false false false false cmindent) :else (let [cc (conc c)] (recur r (+ col (count cc)) dstack (into out cc) nil false false false false (sups-char? c) cmindent)))) (apply str out)))) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---