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
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,29 @@ In order to load the standard configuration file from Leiningen, add the
:as everything} ;; 27 spaces, falls back to 1 space
```

* `:max-column-alignment-width` -
a positive integer that limits which keys participate in column
alignment. Keys whose end column is at or within N are aligned
together; keys that end past column N are not padded and receive a
single space before their value. Defaults to nil (no limit).
**Experimental.**

```clojure
;; Input:
{:a 1
:abcde 2
:abcdefg 3
:long-name 4}

;; With :align-map-columns? true and :max-column-alignment-width 7:
;; :a and :abcde end at or within column 7 and align together;
;; :abcdefg and :long-name end past column 7 and are not padded
{:a 1 ;; ends within column 7, padded to value column
:abcde 2 ;; ends at column 7, sets the value column
:abcdefg 3 ;; ends past column 7, 1 space
:long-name 4} ;; ends past column 7, 1 space
```

* `:blank-lines-separate-alignment?` -
true if cljfmt should treat blank lines as separators when aligning
columns. When enabled, alignment groups are separated by blank lines,
Expand Down
39 changes: 25 additions & 14 deletions cljfmt/src/cljfmt/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@
:align-single-column-lines? false
:aligned-forms default-aligned-forms
:max-column-alignment-gap nil
:max-column-alignment-width nil
:blank-line-forms blank-line-forms
:blank-lines-separate-alignment? false
:extra-aligned-forms {}
Expand Down Expand Up @@ -670,13 +671,16 @@
(defn- count-spaces [zloc]
(if (space? zloc) (node-str-length zloc) 0))

(defn- pad-to-position [zloc start-position {max-gap :max-column-alignment-gap}]
{:pre [(or (nil? max-gap) (pos-int? max-gap))]}
(let [delta (- start-position (margin zloc))]
(if max-gap
(let [old-gap (count-spaces (z/left* zloc))
new-gap (+ old-gap delta)]
(pad-node zloc (if (> new-gap max-gap) (- 1 old-gap) delta)))
(defn- pad-to-position [zloc start-position {max-gap :max-column-alignment-gap
align-width :max-column-alignment-width}]
Comment on lines +674 to +675

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you wrap this at 80 characters? i.e.:

(defn- pad-to-position
  [zloc start-position {max-gap     :max-column-alignment-gap
                        align-width :max-column-alignment-width}]

{:pre [(or (nil? max-gap) (pos-int? max-gap))
(or (nil? align-width) (pos-int? align-width))]}
(let [old-gap (count-spaces (z/left* zloc))
delta (- start-position (margin zloc))
new-gap (+ old-gap delta)]
(if (or (< new-gap 1)
(and max-gap (> new-gap max-gap)))
(pad-node zloc (- 1 old-gap))
(pad-node zloc delta))))

(defn- edit-column [zloc column f]
Expand Down Expand Up @@ -707,17 +711,24 @@
(recur (z/right* zloc) 0 acc)
(recur (z/right* zloc) (inc col) (f zloc col acc)))))))

(defn- column-start-position [zloc col opts]
(let [reduce-fn (if (:blank-lines-separate-alignment? opts)
(defn- column-start-position
[zloc col {align-width :max-column-alignment-width
align-singles? :align-single-column-lines?
separate? :blank-lines-separate-alignment?}]
(let [reduce-fn (if separate?
reduce-column-group
reduce-columns)
maximizer (fn [zloc c max-pos]
collector (fn [zloc c positions]
(if (and (= c (dec col))
(or (:align-single-column-lines? opts)
(or align-singles?
(not (single-column-line? zloc))))
(max max-pos (node-end-position zloc))
max-pos))]
(inc (reduce-fn zloc maximizer 0))))
(conj positions (node-end-position zloc))
positions))
positions (reduce-fn zloc collector [])
threshold (when align-width (+ (apply min 0 positions) align-width))]
(inc (apply max 0 (if threshold
(filter #(<= % threshold) positions)
positions)))))

(defn- align-one-column
[zloc col {:keys [blank-lines-separate-alignment?] :as opts}]
Expand Down
4 changes: 4 additions & 0 deletions cljfmt/src/cljfmt/main.clj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
:default (:max-column-alignment-gap defaults)
:parse-fn #(cond-> % (string? %) parse-long)
:id :max-column-alignment-gap]
[nil "--max-column-alignment-width"
:default (:max-column-alignment-width defaults)
:parse-fn #(cond-> % (string? %) parse-long)
:id :max-column-alignment-width]
[nil "--[no-]ansi"
:default (:ansi? defaults)
:id :ansi?]
Expand Down
41 changes: 41 additions & 0 deletions cljfmt/test/cljfmt/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -3193,6 +3193,47 @@
{:align-map-columns? true
:max-column-alignment-gap 5}))))

(deftest test-max-column-alignment-width
(testing "form: anchor demoted until all keys fit within width"
(is (reformats-to?
["(let [a 1"
" abcde 2"
" abcdefg 3"
" long-name 4]"
" [a abcde abcdefg long-name])"]
["(let [a 1"
" abcde 2"
" abcdefg 3"
" long-name 4]"
" [a abcde abcdefg long-name])"]
{:align-form-columns? true
:max-column-alignment-width 11})))
(testing "map: anchor demoted until all keys fit within width"
(is (reformats-to?
["{:a \"x\""
" :abcde \"y\""
" :abcdefg \"z\""
" :long-key \"w\"}"]
["{:a \"x\""
" :abcde \"y\""
" :abcdefg \"z\""
" :long-key \"w\"}"]
{:align-map-columns? true
:max-column-alignment-width 7})))
(testing "composing both flags refines alignment further"
(is (reformats-to?
["{:x \"a\""
" :abc \"b\""
" :abcde \"c\""
" :long-key \"d\"}"]
["{:x \"a\""
" :abc \"b\""
" :abcde \"c\""
" :long-key \"d\"}"]
{:align-map-columns? true
:max-column-alignment-width 7
:max-column-alignment-gap 3}))))

(deftest test-realign-form
(is (= "
{:x 1
Expand Down
Loading