Skip to content

Instantly share code, notes, and snippets.

@Jared314
Last active December 14, 2015 11:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jared314/5079619 to your computer and use it in GitHub Desktop.
Save Jared314/5079619 to your computer and use it in GitHub Desktop.
A get-indent function to get the amount of indention for the next line of clojure code, based on the previous line.
(def closing {\) \(
\} \{
\] \[})
(def opening [\( \{ \[])
(defn zero-or-more [x] (if (>= x 0) x 0))
(defn indent-exception? [[a b]] (not (and (= a \') (= b \())))
; warning: Very basic clojure language parsing. It does not handle strings.
(defn reverse-parse
([data] (reverse-parse data []))
([data starting-stack]
(loop [pos (dec (.length data))
stack starting-stack]
(if (< pos 0)
[pos stack]
(let [cur (.charAt data pos)]
(cond
(contains? closing cur) (recur (dec pos) (conj stack (closing cur)))
(= (peek stack) cur) (recur (dec pos) (pop stack))
(some {cur true} opening) [pos stack]
:else (recur (dec pos) stack)))))))
(defn get-indent [data]
(let [pos (first (reverse-parse data))]
(if (= pos -1)
(count (re-find #"^\s+" data)) ;match indent
(if (indent-exception? [(.charAt data (zero-or-more (dec pos))) (.charAt data pos)])
(let [m (re-matcher #"[,\s]+" (.substring data pos))]
(if (.find m)
(+ pos (.end m)) ;match first parameter position
pos))
(inc pos))))) ;match inside delimiter position
(get-indent "(defn thing [x]") ; => 6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment