Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ In order to load the standard configuration file from Leiningen, add the

Defaults to `:community`

* `:ignore-lines-with-only-uneval-tags?` -
true if cljfmt should preserve linebreaks after `#_` uneval tags that
appear on their own line. When true (default), `#_` followed by a newline
will not be moved to the same line as the following form. When false,
`#_` tags will be formatted onto the same line as the form they comment
out. Defaults to true.

* `:indent-line-comments?` -
true if cljfmt should align whole-line `;;` comments with the code.
Defaults to false.
Expand Down
55 changes: 35 additions & 20 deletions cljfmt/src/cljfmt/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,23 @@
(defn- comment? [zloc]
(some-> zloc z/node n/comment?))

(defn- surrounding-whitespace? [zloc]
(defn- uneval? [zloc]
(= (z/tag zloc) :uneval))

(defn- surrounding-whitespace? [zloc opts]
(and (not (top? zloc))
(clojure-whitespace? zloc)
(not (and (:ignore-lines-with-only-uneval-tags? opts)
(z/linebreak? zloc)
(nil? (z/left* zloc))
(uneval? (z/up* zloc))))
(or (and (nil? (z/left* zloc))
;; don't convert ~ @ to ~@
(not (unquote-deref? (z/right* zloc)))
;; ignore space before comments
(not (comment? (z/right* zloc))))
(nil? (z/skip z/right* clojure-whitespace? zloc)))))

(defn remove-surrounding-whitespace [form]
(transform form edit-all surrounding-whitespace? z/remove*))

(defn- element? [zloc]
(and zloc (not (z/whitespace-or-comment? zloc))))

Expand Down Expand Up @@ -209,9 +213,6 @@
(defn- coll-indent [zloc]
(-> zloc z/leftmost* margin))

(defn- uneval? [zloc]
(= (z/tag zloc) :uneval))

(defn- index-of [zloc]
(->> (iterate z/left zloc)
(remove uneval?)
Expand All @@ -236,11 +237,24 @@
:cursive (cursive-two-space-list-indent? zloc)
:zprint (zprint-two-space-list-indent? zloc)))

(defn- first-form-in-line? [zloc]
(if-let [zloc (z/left* zloc)]
(if (space? zloc)
(recur zloc)
(or (z/linebreak? zloc) (comment? zloc)))
true))

(defn- list-indent [zloc context]
(if (> (index-of zloc) 1)
(-> zloc z/leftmost* z/right margin)
(cond-> (coll-indent zloc)
(two-space-list-indent? zloc context) inc)))
(let [idx (index-of zloc)
has-uneval-before? #(and (= idx 1) (-> zloc z/left* uneval?))]
(if (or (> idx 1) (has-uneval-before?))
(let [first-arg (-> zloc z/leftmost* z/right)]
(cond-> (margin first-arg)
(not (or (not (uneval? first-arg)) (first-form-in-line? first-arg)))
inc))
(cond-> (coll-indent zloc)
(two-space-list-indent? zloc context)
inc))))

(def indent-size 2)

Expand Down Expand Up @@ -340,14 +354,6 @@
(z/leftmost zloc)
(repeat n z/right)))

(defn- first-form-in-line? [zloc]
(and (some? zloc)
(if-let [zloc (z/left* zloc)]
(if (space? zloc)
(recur zloc)
(or (z/linebreak? zloc) (comment? zloc)))
true)))

(defn- block-indent [zloc key idx context]
(when (form-matches-key? zloc key context)
(let [zloc-after-idx (some-> zloc (nth-form (inc idx)))]
Expand Down Expand Up @@ -378,6 +384,7 @@
:extra-blank-line-forms {}
:extra-indents {}
:function-arguments-indentation :community
:ignore-lines-with-only-uneval-tags? true
:indent-line-comments? false
:indentation? true
:indents default-indents
Expand Down Expand Up @@ -405,6 +412,12 @@
(when (form-matches-key? zloc sym context)
(list-indent zloc context))))

(defn remove-surrounding-whitespace
([form]
(remove-surrounding-whitespace form default-options))
([form opts]
(transform form edit-all #(surrounding-whitespace? % opts) z/remove*)))

(defn- make-indenter [[key opts] context]
(apply some-fn (map (partial indenter-fn key context) opts)))

Expand Down Expand Up @@ -433,6 +446,8 @@
(reader-conditional? gp) (coll-indent zloc)
(#{:list :fn} tag) (custom-indent zloc indents context)
(= :meta tag) (indent-amount (z/up zloc) indents context)
(= :uneval tag) (cond-> (margin (z/up zloc))
(not (first-form-in-line? (z/up zloc))) inc)
:else (coll-indent zloc))))

(defn- indent-line [zloc indents context]
Expand Down Expand Up @@ -827,7 +842,7 @@
(cond-> (:remove-consecutive-blank-lines? opts)
remove-consecutive-blank-lines)
(cond-> (:remove-surrounding-whitespace? opts)
remove-surrounding-whitespace)
(remove-surrounding-whitespace opts))
(cond-> (:insert-missing-whitespace? opts)
insert-missing-whitespace)
(cond-> (:remove-multiple-non-indenting-spaces? opts)
Expand Down
3 changes: 3 additions & 0 deletions cljfmt/src/cljfmt/main.clj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
:validate [#{:community :cursive :zprint}
"Must be one of community, cursive, or zprint"]
:id :function-arguments-indentation]
[nil "--[no-]ignore-lines-with-only-uneval-tags"
:default (:ignore-lines-with-only-uneval-tags? defaults)
:id :ignore-lines-with-only-uneval-tags?]
[nil "--[no-]indentation"
:default (:indentation? defaults)
:id :indentation?]
Expand Down
155 changes: 154 additions & 1 deletion cljfmt/test/cljfmt/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,160 @@
["#?(:cljs (bar 1) :clj (foo 2))"]))
(is (reformats-to?
["#?@(:cljs[foo bar] :clj[baz quux])"]
["#?@(:cljs [foo bar] :clj [baz quux])"]))))
["#?@(:cljs [foo bar] :clj [baz quux])"])))

(testing "uneval on own line"
(is (reformats-to?
["#_"
"(defn foobar []"
" (do-this)"
" (let [x 1]"
" (with-blah []"
" (stuff))))"]
["#_"
"(defn foobar []"
" (do-this)"
" (let [x 1]"
" (with-blah []"
" (stuff))))"]
{:ignore-lines-with-only-uneval-tags? true}))
(is (reformats-to?
["#_"
"{:foo :bar}"]
["#_"
"{:foo :bar}"]
{:ignore-lines-with-only-uneval-tags? true}))
(is (reformats-to?
["(foo #_"
" bar"
" baz)"]
["(foo #_"
" bar"
" baz)"]
{:ignore-lines-with-only-uneval-tags? true}))
(testing "uneval on same line still gets whitespace"
(is (reformats-to?
["(foo #_bar baz)"]
["(foo #_bar baz)"]
{:ignore-lines-with-only-uneval-tags? true})))
(testing "multiple unevals on own lines"
(is (reformats-to?
["#_"
"(defn foo [])"
"#_"
"(defn bar [])"]
["#_"
"(defn foo [])"
"#_"
"(defn bar [])"]
{:ignore-lines-with-only-uneval-tags? true})))
(testing "uneval with vector"
(is (reformats-to?
["#_"
"[1 2 3]"]
["#_"
"[1 2 3]"]
{:ignore-lines-with-only-uneval-tags? true})))
(testing "uneval with map"
(is (reformats-to?
["#_"
"{:a 1"
" :b 2}"]
["#_"
"{:a 1"
" :b 2}"]
{:ignore-lines-with-only-uneval-tags? true})))
(testing "uneval as function argument"
(is (reformats-to?
["(foo"
" #_"
" bar"
" baz)"]
["(foo"
" #_"
" bar"
" baz)"]
{:ignore-lines-with-only-uneval-tags? true}))
(testing "with more than one argument"
(is (reformats-to?
["(foo"
" #_"
" x"
" y"
" z)"]
["(foo"
" #_"
" x"
" y"
" z)"]
{:ignore-lines-with-only-uneval-tags? true}))))
(testing "uneval before closing paren"
(is (reformats-to?
["(foo bar"
" #_"
" baz)"]
["(foo bar"
" #_"
" baz)"]
{:ignore-lines-with-only-uneval-tags? true})))
(testing "multiple unevals inline"
(is (reformats-to?
["(foo #_ bar #_ baz qux)"]
["(foo #_bar #_baz qux)"]
{:ignore-lines-with-only-uneval-tags? true})))
(testing "uneval with reader conditional"
(is (reformats-to?
["#_"
"#?(:clj (foo)"
" :cljs (bar))"]
["#_"
"#?(:clj (foo)"
" :cljs (bar))"]
{:ignore-lines-with-only-uneval-tags? true})))
(testing "uneval with cursive indentation"
(is (reformats-to?
["(foo"
" #_"
" bar"
" baz)"]
["(foo"
" #_"
" bar"
" baz)"]
{:function-arguments-indentation :cursive
:ignore-lines-with-only-uneval-tags? true})))
(testing "uneval inline with cursive indentation"
(is (reformats-to?
["(foo #_"
" bar"
" baz)"]
["(foo #_"
" bar"
" baz)"]
{:function-arguments-indentation :cursive
:ignore-lines-with-only-uneval-tags? true})))
(testing "uneval with zprint indentation"
(is (reformats-to?
["(foo"
" #_"
" bar"
" baz)"]
["(foo"
" #_"
" bar"
" baz)"]
{:function-arguments-indentation :zprint
:ignore-lines-with-only-uneval-tags? true})))
(testing "uneval inline with zprint indentation"
(is (reformats-to?
["(foo #_"
" bar"
" baz)"]
["(foo #_"
" bar"
" baz)"]
{:function-arguments-indentation :zprint
:ignore-lines-with-only-uneval-tags? true})))))

(deftest test-consecutive-blank-lines
(is (reformats-to?
Expand Down
Loading