Skip to content

Commit 71ff856

Browse files
committed
add :break-on-max-column-alignment-width? option
1 parent 2f4affc commit 71ff856

3 files changed

Lines changed: 100 additions & 11 deletions

File tree

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,28 @@ In order to load the standard configuration file from Leiningen, add the
339339
:long-name 4} ;; ends past column 7, 1 space
340340
```
341341

342+
* `:break-on-max-column-alignment-width?` -
343+
true if cljfmt should move a value onto its own line, indented under
344+
the keys, when its key ends past the column set by
345+
`:max-column-alignment-width`, rather than falling back to a single
346+
space on the same line. Has no effect unless
347+
`:max-column-alignment-width` is also set. Defaults to false.
348+
**Experimental.**
349+
350+
```clojure
351+
;; Input:
352+
{:a 1
353+
:bb 2
354+
:ccccccc 3}
355+
356+
;; With :align-map-columns? true, :max-column-alignment-width 4,
357+
;; and :break-on-max-column-alignment-width? true:
358+
{:a 1 ;; ends within column 4, padded to value column
359+
:bb 2 ;; ends at column 4, sets the value column
360+
:ccccccc ;; ends past column 4, value moves to its own line
361+
3}
362+
```
363+
342364
* `:blank-lines-separate-alignment?` -
343365
true if cljfmt should treat blank lines as separators when aligning
344366
columns. When enabled, alignment groups are separated by blank lines,

cljfmt/src/cljfmt/core.cljc

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@
386386
:max-column-alignment-width nil
387387
:blank-line-forms blank-line-forms
388388
:blank-lines-separate-alignment? false
389+
:break-on-max-column-alignment-width? false
389390
:extra-aligned-forms {}
390391
:extra-blank-line-forms {}
391392
:extra-indents {}
@@ -671,16 +672,31 @@
671672
(defn- count-spaces [zloc]
672673
(if (space? zloc) (node-str-length zloc) 0))
673674

674-
(defn- pad-to-position [zloc start-position {max-gap :max-column-alignment-gap
675-
align-width :max-column-alignment-width}]
676-
{:pre [(or (nil? max-gap) (pos-int? max-gap))
677-
(or (nil? align-width) (pos-int? align-width))]}
675+
(defn- break-to-own-line [zloc]
676+
(let [indent (coll-indent zloc)]
677+
(-> zloc
678+
z/left*
679+
(z/replace* (n/newlines 1))
680+
z/right*
681+
(z/insert-left* (whitespace indent)))))
682+
683+
(defn- pad-to-position [zloc {:keys [position threshold]}
684+
{max-gap :max-column-alignment-gap
685+
break? :break-on-max-column-alignment-width?}]
686+
{:pre [(or (nil? max-gap) (pos-int? max-gap))]}
678687
(let [old-gap (count-spaces (z/left* zloc))
679-
delta (- start-position (margin zloc))
680-
new-gap (+ old-gap delta)]
681-
(if (or (< new-gap 1)
682-
(and max-gap (> new-gap max-gap)))
688+
delta (- position (margin zloc))
689+
new-gap (+ old-gap delta)
690+
key-end (- (margin zloc) old-gap)]
691+
(cond
692+
(and break? threshold (> key-end threshold))
693+
(break-to-own-line zloc)
694+
695+
(or (< new-gap 1)
696+
(and max-gap (> new-gap max-gap)))
683697
(pad-node zloc (- 1 old-gap))
698+
699+
:else
684700
(pad-node zloc delta))))
685701

686702
(defn- edit-column [zloc column f]
@@ -726,9 +742,10 @@
726742
positions))
727743
positions (reduce-fn zloc collector [])
728744
threshold (when align-width (+ (apply min 0 positions) align-width))]
729-
(inc (apply max 0 (if threshold
730-
(filter #(<= % threshold) positions)
731-
positions)))))
745+
{:position (inc (apply max 0 (if threshold
746+
(filter #(<= % threshold) positions)
747+
positions)))
748+
:threshold threshold}))
732749

733750
(defn- align-one-column
734751
[zloc col {:keys [blank-lines-separate-alignment?] :as opts}]

cljfmt/test/cljfmt/core_test.cljc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,6 +3234,56 @@
32343234
:max-column-alignment-width 7
32353235
:max-column-alignment-gap 3}))))
32363236

3237+
(deftest test-break-on-max-column-alignment-width
3238+
(testing "form: the one outlier value is moved to its own line, indented under the bindings"
3239+
(is (reformats-to?
3240+
["(let [a 1"
3241+
" bb 2"
3242+
" ccccccc 3]"
3243+
" body)"]
3244+
["(let [a 1"
3245+
" bb 2"
3246+
" ccccccc"
3247+
" 3]"
3248+
" body)"]
3249+
{:align-form-columns? true
3250+
:max-column-alignment-width 8
3251+
:break-on-max-column-alignment-width? true})))
3252+
(testing "map: the one outlier value is moved to its own line, indented under the keys"
3253+
(is (reformats-to?
3254+
["{:a \"x\""
3255+
" :bb \"y\""
3256+
" :ccccccc \"z\"}"]
3257+
["{:a \"x\""
3258+
" :bb \"y\""
3259+
" :ccccccc"
3260+
" \"z\"}"]
3261+
{:align-map-columns? true
3262+
:max-column-alignment-width 4
3263+
:break-on-max-column-alignment-width? true})))
3264+
(testing "no effect when :max-column-alignment-width is not set"
3265+
(is (reformats-to?
3266+
["{:x 1"
3267+
" :longer 2}"]
3268+
["{:x 1"
3269+
" :longer 2}"]
3270+
{:align-map-columns? true
3271+
:max-column-alignment-gap 5
3272+
:break-on-max-column-alignment-width? true})))
3273+
(testing "value already on its own line is left alone (idempotent)"
3274+
(is (reformats-to?
3275+
["{:a 1"
3276+
" :bb 2"
3277+
" :ccccccc"
3278+
" 3}"]
3279+
["{:a 1"
3280+
" :bb 2"
3281+
" :ccccccc"
3282+
" 3}"]
3283+
{:align-map-columns? true
3284+
:max-column-alignment-width 4
3285+
:break-on-max-column-alignment-width? true}))))
3286+
32373287
(deftest test-realign-form
32383288
(is (= "
32393289
{:x 1

0 commit comments

Comments
 (0)