Skip to content

Conversation

camsaul
Copy link
Contributor

@camsaul camsaul commented Oct 20, 2025

Resolves #374

@camsaul camsaul force-pushed the fix-blank-lines-in-defs branch 3 times, most recently from 61fae52 to 3de65e9 Compare October 20, 2025 22:55
@weavejester
Copy link
Owner

Thanks for the PR. Is there any reason to limit this to definition forms? What if we instead had options:

  • :remove-blank-lines-in-forms?
  • :forms-allowed-blank-lines

The latter should include cond, comment and let.

Additionally, what if we narrowed down where the blank lines were allowed, as in let the pairs would only be in the first argument.

{let     #{0}
 cond    :all
 comment :all}

@camsaul
Copy link
Contributor Author

camsaul commented Oct 20, 2025

Is there any reason to limit this to definition forms?

I guess it's not really limited to definition forms, it removes blank lines anywhere except the top level, I just wasn't sure what to call this so I tried to match the naming of the rule in the Community Style Guide https://guide.clojure.style/#no-blank-lines-within-def-forms . But that's not quite the same as what this does so I'll change it

what if we narrowed down where the blank lines were allowed

For binding vectors this builds on the recently-added :[extra-]binding-forms stuff, so for let currently just the binding vector can keep extra newlines, and for stuff like cond it's limited to the top-level of the form instead (nested forms inside cond still get considered separately). I think there's some advantage to this because you don't need to specify the binding forms for everything twice if you're also using :align-binding-columns?. Does that work? I can tweak it if you still want something more fine-grained

@camsaul camsaul force-pushed the fix-blank-lines-in-defs branch from 3de65e9 to 68c4bb1 Compare October 20, 2025 23:50
@camsaul camsaul changed the title Remove blank lines in defs Remove blank lines in forms Oct 20, 2025
@camsaul camsaul force-pushed the fix-blank-lines-in-defs branch from 68c4bb1 to 0e99679 Compare October 20, 2025 23:51
@camsaul
Copy link
Contributor Author

camsaul commented Oct 20, 2025

Updated the name of this to make it clearer that it works on all forms and not just def and friends

@camsaul camsaul force-pushed the fix-blank-lines-in-defs branch from 0e99679 to 6d32d9a Compare October 20, 2025 23:53
@weavejester
Copy link
Owner

weavejester commented Oct 21, 2025

Ideally we want to follow the least complex solution. Having both :binding-forms and :pairwise-forms affect which forms are allowed blank lines is more complex than having a single option to decide that. Additionally, there are forms like comment where one reasonably might want blank lines, yet this is neither a binding form nor a pairwise form.

In fact, this has led me to reconsider :binding-forms for the same reason. I'm thinking I'll change those options to:

  • :align-form-columns?
  • :aligned-forms
  • :extra-aligned-forms

And for this feature, I think it would be best to have:

  • :remove-blank-lines-in-forms?
  • :blank-line-forms
  • :extra-blank-line-forms

This way the options are isolated and therefore more predictable.

@camsaul
Copy link
Contributor Author

camsaul commented Oct 21, 2025

Makes sense. I'll rework this PR later today

@camsaul camsaul force-pushed the fix-blank-lines-in-defs branch from 6d32d9a to b5f7bb0 Compare October 21, 2025 18:37
@camsaul
Copy link
Contributor Author

camsaul commented Oct 21, 2025

Alright @weavejester I think I made all the changes you suggested, please take another look

Copy link
Owner

@weavejester weavejester left a comment

Choose a reason for hiding this comment

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

Thanks for the PR. I've reviewed the code and have some suggestions/improvements.

Comment on lines +717 to +725
(defn remove-blank-lines-in-forms
[form blank-line-forms alias-map]
(let [ns-name (find-namespace (z/of-node form))
context {:alias-map alias-map, :ns-name ns-name}]
(transform
form
edit-all
#(blank-line-in-form? % blank-line-forms context)
replace-blank-lines-in-forms)))
Copy link
Owner

Choose a reason for hiding this comment

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

This could be a little more concise:

(defn remove-blank-lines-in-forms [form blank-line-forms alias-map]
  (let [ns-name     (find-namespace (z/of-node form))
        context     {:alias-map alias-map, :ns-name ns-name}
        blank-line? #(blank-line-in-form? % blank-line-forms context)]
    (transform form edit-all blank-line? replace-blank-lines-in-forms)))

Comment on lines +690 to +694
(defn- blank-line-rule [zloc blank-line-forms context]
(when-let [form-symb (form-symbol zloc)]
(some blank-line-forms
[(remove-namespace form-symb)
(fully-qualified-symbol form-symb context)])))
Copy link
Owner

Choose a reason for hiding this comment

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

Use form-matches-key? here. Something more like:

(defn- blank-lines-allowed-in-form? [zloc blank-line-forms context]
  (and (z/list? (z/up zloc))
       (some (fn [[k indexes]]
               (and (form-matches-key? zloc k context)
                    (or (= :all indexes)
                        (contains? (set indexes) (dec (index-of zloc)))))
             blank-line-forms)))

In fact, we could use the same logic for both forms with blank lines and forms we need to align. So let's do something like:

(defn- matching-form? [zloc forms context]
  (and (z/list? (z/up zloc))
       (some (fn [[k indexes]]
               (and (form-matches-key? zloc k context)
                    (or (= :all indexes)
                        (contains? (set indexes) (dec (index-of zloc)))))
             forms)))

This replaces aligned-form?.

Comment on lines +696 to +712
(defn- blank-line-in-form? [zloc blank-line-forms context]
(and (z/linebreak? zloc)
(> (count-newlines zloc) 1)
(cond
(z/list? (z/up zloc))
(not= (blank-line-rule zloc blank-line-forms context) :all)

(z/list? (z/up (z/up zloc)))
(let [index (dec (index-of (z/up zloc)))
rule (blank-line-rule
(z/up zloc)
blank-line-forms
context)
allowed-indexes (if (set? rule)
rule
#{})]
(not (allowed-indexes index))))))
Copy link
Owner

Choose a reason for hiding this comment

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

This doesn't seem like it'll work for an arbitrary nesting depth. What we want to do is determine whether the zloc represents multiple newlines, and then iterate up the tree until we hit root (nil), checking if any containing form is also a matching form.

Comment on lines +714 to +715
(defn- replace-blank-lines-in-forms [zloc]
(z/replace zloc (n/newline-node "\n")))
Copy link
Owner

Choose a reason for hiding this comment

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

A more accurate name for the function is replace-with-single-newline, as that's what it does, rather than what it's for.

" (sequential? x)"
" :seq)"]]
(is (reformats-to? form form {:remove-blank-lines-in-forms? true
:extra-indents '{better-cond.core/cond* [[:block 0]]}
Copy link
Owner

Choose a reason for hiding this comment

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

Keep lines to 80 characters or less, even in tests.

Comment on lines +1263 to +1265
;; I don't think it's appropriate to second-guess things like map formatting
;; at this point, I'd rather error on the side of being too conservative in
;; what we rewrite
Copy link
Owner

Choose a reason for hiding this comment

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

I think this comment can be removed.


* `:remove-blank-lines-in-forms?` - whether to remove blank lines inside forms
per the [community style
recommendation](https://guide.clojure.style/#no-blank-lines-within-def-forms).
Copy link
Owner

Choose a reason for hiding this comment

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

Use an external URL to this link, like [community style recommendation][no-blank-lines].

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.

Support removing blank lines in definition forms

2 participants