Skip to content

add max-column-anchor-gap to align columns to the gap instead of collapsing on row with short keys - #425

Open
sirmspencer wants to merge 1 commit into
weavejester:masterfrom
sirmspencer:ms-fix-gap-anchor-demotion
Open

add max-column-anchor-gap to align columns to the gap instead of collapsing on row with short keys#425
sirmspencer wants to merge 1 commit into
weavejester:masterfrom
sirmspencer:ms-fix-gap-anchor-demotion

Conversation

@sirmspencer

@sirmspencer sirmspencer commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

@weavejester I can't remember if you want an issue per PR, so I included the details here. I can make it an issue if you prefer.

LLM notice

I have reviewed all of what is being submitted. The PR description was partially generated with llm to show the current and expected.

Problem

Here, I am not sure if this is a bug or a differene in expected behavior so I went with a new flag.

When :max-column-alignment-gap is set, the alignment anchor is still the longest key in the form. Individual rows whose gap would exceed the limit fall back to a single space, but rows with medium-length keys are still extended all the way to the inflated anchor column. This produces inconsistent alignment: the shortest key falls back, medium keys over-extend, and the longest key (which caused the problem) sets the column for all of them.

Current behavior

Config: {:align-form-columns? true, :max-column-alignment-gap 5}

Input:

(let [a 1
      abcde 2
      abcdefg 3
      long-name 4]
  [a abcde abcdefg long-name])

Output — long-name stays as anchor; a falls back (gap 9 > 5); abcde and
abcdefg extend unnecessarily to the long-name column:

(let [a 1
      abcde     2
      abcdefg   3
      long-name 4]
  [a abcde abcdefg long-name])

The same behavior affects maps with :align-map-columns?.

Solution

This PR does not change the behavior of :max-column-alignment-gap. Instead it introduces a new flag, :max-column-anchor-gap, which applies the limit at anchor selection time rather than per row.

When :max-column-anchor-gap N is set, cljfmt selects the largest key for which every shorter key would need at most N spaces to align. Keys longer than the chosen anchor are not padded.

Expected behavior

Config: {:align-form-columns? true, :max-column-anchor-gap 5}

;; long-name (gap 8 from a) and abcdefg (gap 6 from a) exceed limit;
;; anchor demotes to abcde (gap for a = 4 ≤ 5)
(let [a     1
      abcde 2
      abcdefg 3
      long-name 4]
  [a abcde abcdefg long-name])

Composing both flags

The two flags are orthogonal and can be combined. :max-column-anchor-gap runs
first to select a conservative anchor; :max-column-alignment-gap then applies
per-row fallback to the result.

;; Config: {:align-map-columns? true
;;          :max-column-anchor-gap 5       ; long-key excluded; anchor = :abcde
;;          :max-column-alignment-gap 3}   ; further trims rows with gap > 3
;;
;; :x falls back (gap 4 > 3); :abc aligns (gap 3 = limit); :abcde is anchor
{:x "a"
 :abc   "b"
 :abcde "c"
 :long-key "d"}

Changes

  • New option :max-column-anchor-gap added to default-options (nil by default)
  • column-start-position applies cascade demotion when :max-column-anchor-gap is set
  • pad-to-position gains a guard for keys wider than the demoted anchor, preventing
    their spacing from collapsing to zero
  • README documents the new option and its relationship to :max-column-alignment-gap
  • New test-max-column-anchor-gap deftest with form, map, and compose cases

Comparison

Screen.Recording.2026-07-26.at.2.20.02.PM.mov

@sirmspencer
sirmspencer force-pushed the ms-fix-gap-anchor-demotion branch from 5a863c3 to 7d82f81 Compare July 26, 2026 16:30
@sirmspencer sirmspencer changed the title fix max-column-alignment-gap to demote anchor when gap limit exceeded add max-column-alignment-gap to demote anchor when gap limit exceeded Jul 26, 2026
@sirmspencer sirmspencer changed the title add max-column-alignment-gap to demote anchor when gap limit exceeded add max-column-anchor-gap to demote anchor when gap limit exceeded Jul 26, 2026
@sirmspencer sirmspencer changed the title add max-column-anchor-gap to demote anchor when gap limit exceeded add max-column-anchor-gap to align columns to the gap instead of collapsing on row with short keys Jul 26, 2026
@weavejester

Copy link
Copy Markdown
Owner

If I'm understanding this correctly, you're proposing a maximum column width size? Anything above the maximum width is separated by just a single space; anything equal to or below is padded as normal. Is that correct?

@sirmspencer
sirmspencer force-pushed the ms-fix-gap-anchor-demotion branch from 7d82f81 to 038815a Compare July 26, 2026 17:14
@sirmspencer

Copy link
Copy Markdown
Contributor Author

If I'm understanding this correctly, you're proposing a maximum column width size? Anything above the maximum width is separated by just a single space; anything equal to or below is padded as normal. Is that correct?

Yes, that is correct. Its specifically this current behavior that I find backwards:

(let [a 1
      abcde     2
      abcdefg   3
      long-name 4]
  [a abcde abcdefg long-name])

@weavejester

Copy link
Copy Markdown
Owner

In which case I think we want to call this something like :max-column-alignment-width, because this governs the maximum width of the column that should be aligned to. The "anchor" terminology you introduced to describe this feature was a little confusing to me, as you didn't define what exactly you meant by "anchor".

@sirmspencer

sirmspencer commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

In which case I think we want to call this something like :max-column-alignment-width, because this governs the maximum width of the column that should be aligned to. The "anchor" terminology you introduced to describe this feature was a little confusing to me, as you didn't define what exactly you meant by "anchor".

That sounds good to me. I was trying to stay with the "gap" term since the flags are related. The "anchor" would be the longest key that is dragging the gap bigger. Max anchor gap would be the max the anchor could add a gap. :max-column-alignment-width is better, it keeps the "max-column-alignment" part, I'll update.

@sirmspencer
sirmspencer force-pushed the ms-fix-gap-anchor-demotion branch 2 times, most recently from da3b56d to 806e54d Compare July 26, 2026 18:17
@sirmspencer

Copy link
Copy Markdown
Contributor Author

@weavejester I added a text animation video to the description for clarity

Comment thread cljfmt/src/cljfmt/core.cljc Outdated
@sirmspencer
sirmspencer force-pushed the ms-fix-gap-anchor-demotion branch 5 times, most recently from 5abfa5b to 7d73ba2 Compare July 27, 2026 17:00
Comment thread cljfmt/src/cljfmt/core.cljc Outdated
@weavejester

Copy link
Copy Markdown
Owner

Other than the previous comment, this looks fine. Once that comment is addressed I think we're ready to merge.

@sirmspencer
sirmspencer force-pushed the ms-fix-gap-anchor-demotion branch from 7d73ba2 to 2f4affc Compare August 7, 2026 17:05
@sirmspencer

Copy link
Copy Markdown
Contributor Author

@weavejester Updated. I have one more related rule to follow up, if you want to wait to release them all in a group. I'm going to add a rule to break the link if it exceeds this max width rule.

@weavejester

Copy link
Copy Markdown
Owner

No problem, I can wait.

This PR looks good, but I've noticed that the :max-column-alignment-width option hasn't been added to cljfmt.main as a command-line option (--max-column-alignment-width). Could you quickly add that in, then I'll merge.

Add a new :max-column-alignment-width option for column alignment.
Keys whose end column is at or within N participate in alignment;
keys that end past column N receive a single space and are not
padded.
@sirmspencer
sirmspencer force-pushed the ms-fix-gap-anchor-demotion branch from 2f4affc to ab54188 Compare August 8, 2026 21:50
@sirmspencer

Copy link
Copy Markdown
Contributor Author

No problem, I can wait.

This PR looks good, but I've noticed that the :max-column-alignment-width option hasn't been added to cljfmt.main as a command-line option (--max-column-alignment-width). Could you quickly add that in, then I'll merge.

@weavejester I added that in. Thanks for reviewing!

Comment on lines +674 to +675
(defn- pad-to-position [zloc start-position {max-gap :max-column-alignment-gap
align-width :max-column-alignment-width}]

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}]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants