Repository navigation
Docstring indentation, option B (pick one of #167/#168): indent docstrings like clojure-mode - #168
Merged
bbatsov merged 1 commit intoNov 7, 2026
Conversation
3 of 4 tasks
clojure-mode moves a docstring line indented less than clojure-docstring-fill-prefix-width to that column and keeps deeper lines, so code examples keep their indentation and indent-region after M-q changes nothing. clojure-ts-mode left the lines alone when Markdown was in use, as they belong to the markdown-inline parser, which had no indentation rules, and moved every line to the column after the opening quote when it wasn't. The rule is registered for both parsers, and does nothing in a buffer without a markdown-inline parser.
bbatsov
force-pushed
the
docstring-indent-like-clojure-mode
branch
from
November 7, 2026 07:10
3c750b3 to
f45e34f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is one of two alternative PRs for the same problem: #167 leaves docstring text alone (like cljfmt), #168 indents docstrings like clojure-mode. Please merge at most one; we'll close the other.
indent-regionnever re-indents lines inside a docstring. Removes a rule.indent-regionapplies clojure-mode's docstring rule, with and without Markdown. Adds a rule for both parsers.indent-regionchanges the text of docstrings, and how it changes them depends onclojure-ts-use-markdown-inlineand on whether the markdown-inline grammar is installed. With Markdown on, only the closing"moves. With Markdown off, every line moves to the opening quote's column + 1, which flattens indented code examples and undoes whatM-qjust did.This PR indents docstring lines the way clojure-mode does, in both settings: a line indented less than
clojure-ts-docstring-fill-prefix-widthmoves to that column, a deeper line keeps its indentation, and blank lines stay blank. It uses the same prefix asM-q, soM-qfollowed byindent-regionchanges nothing.Background
We found this by comparing clojure-mode's and clojure-ts-mode's
indent-regionover 73 real-world files (as-is, and with indentation stripped), using a formatter that runsindent-regionin batch Emacs.What each tool does to a line inside a top-level docstring:
main, markdown-inline on (default)main, markdown-inline off"at col 0M-qjust filled (col 2)"→ quote col"→ quote colclojure-in-docstring-pis true, and that checks forfont-lock-doc-face. So in an unfontified (batch) buffer clojure-mode never touches docstrings and looks like cljfmt; in a normal fontified buffer it moves lines indented less thanclojure-docstring-fill-prefix-widthto that column and keeps deeper lines.treesit-language-ata content line ismarkdown-inline, andtreesit-simple-indent-ruleshas only aclojureentry, so those lines are left alone. The closing"belongs to the Clojure parser (parentstr_lit), soclojure-ts--match-docstringfires and anchors it at the opening quote.M-q:clojure-ts--fill-paragraphusesclojure-ts-docstring-fill-prefix-width(2) spaces from column 0, like clojure-mode. With Markdown off,indent-regionthen moves those lines to column 3.This PR matches clojure-mode in normal fontified buffers. #167 matches cljfmt instead.
How it works
clojure-ts--match-docstring-linefinds the Clojurestr_litat the line with(treesit-node-at bol 'clojure)and reusesclojure-ts--match-docstring, so it works whichever parser the line belongs to.column-0with an offset function: the line's current indentation or(length (clojure-ts--docstring-fill-prefix)), whichever is larger (0 for a blank line).clojure, and also formarkdown-inlinewhen Markdown is in use (clojure-ts--configured-indent-rulesnow getsmarkdown-available).Examples
Input:
clojure-ts-mode
main, markdown-inline on:clojure-ts-mode
main, markdown-inline off:With this PR (either setting), and clojure-mode 5.19 in a fontified buffer:
cljfmt (same as the input):
Tests
This PR adds a
Docstring indentationgroup, run once withclojure-ts-use-markdown-inlinenil and once with t (the t case is skipped withassumewhen the markdown-inline grammar isn't installed):should indent top-level docstrings like fontified clojure-mode: expected output taken from clojure-mode 5.19 in a fontified buffer. Fails onmainin both settings, passes with this PR.should use the absolute fill prefix in protocol-method docstrings: fails onmainin both settings, passes with this PR.should preserve docstrings after fill-paragraph(M-q, thenindent-region, with prefix widths 2 and 4): fails onmainwith Markdown off, passes with this PR.should preserve ordinary strings: a control; passes onmainand with this PR.How it was checked locally (Eldev isn't installed here, so these are the same steps run directly):
byte-compile-error-on-warngives no warnings; checkdoc is clean; the changed.elfiles are indented asemacs-lisp-modeindents them.Notes
M-qdoes, not from the opening quote. So in a nested docstring, such as a protocol method's, continuation lines go to column 2 even though the quote is deeper:fixedindentation style is unchanged; it never had a docstring rule.About this PR
The code, tests and this description were generated by an AI (Claude, by Anthropic), at @jasonjckn's request. If AI-generated contributions are a problem for this project, please feel free to close this PR and #167 right away.
M-x checkdocand fixed any warnings in the code you've written.