Skip to content

Instantly share code, notes, and snippets.

@jturner314 jturner314/core.clj
Created Sep 30, 2012

Embed
What would you like to do?
Removes common indentation from a collection of lines. Written in response to http://jjinux.blogspot.com/2012/09/dart-algorithm-to-unindent-code.html
(ns dedent-text.core
(:use [clojure.string :only [blank?]]))
(defn all-equal?
"Returns the value if all values are equal, otherwise nil."
[& values]
(when (apply = values) (first values)))
(defn count-common-indentation
"Returns length of common indentation of strings."
[& strings]
(count (take-while #(and (not (nil? %)) (blank? (str %)))
(apply map all-equal? strings))))
(defn dedent-lines
"Returns a lazy seq of strs with the common indentation removed from lines.
Only considers indentation of nonblank lines, and sets blank lines to an
empty string."
[lines]
(if (empty? lines)
lines
(let [non-blank (remove blank? lines)
common-indent (apply count-common-indentation non-blank)]
(for [line lines]
(if (blank? line)
""
(subs line common-indent))))))
(ns dedent-text.core-test
(:use clojure.test
dedent-text.core))
(deftest dedent-lines-test
(testing "unindenting code"
(is (= (dedent-lines [" 1"
" 2"])
["1"
"2"])))
(testing "unindenting code where the first line is indented the most"
(is (= (dedent-lines ["\t 1"
"\t 2"
"\t 3"])
[" 1"
"2"
" 3"])))
(testing "doing nothing for unindented code"
(is (= (dedent-lines ["1"
"2"
"3"])
["1"
"2"
"3"])))
(testing "handling empty lists"
(is (= (dedent-lines [])
[])))
(testing "not trying to handle inconsistent indentation"
(is (= (dedent-lines ["\t1"
" 2"
" 3"
" 4"])
["\t1"
" 2"
" 3"
" 4"])))
(testing "handling really awkward short lines"
(is (= (dedent-lines [" 1"
"2"])
[" 1"
"2"])))
(testing "handling blank lines and lines with only indentation"
(is (= (dedent-lines [" 1"
""
" "
" 2"])
["1"
""
""
" 2"]))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.