Skip to content

Commit ca5faa0

Browse files
committed
Add custom fill-paragraph function to respect docstrings
1 parent 3ca382c commit ca5faa0

4 files changed

+112
-0
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
- [#42]: Fix font locking of definitions with metadata
1111
- [#42]: Fix indentation of definitions with metadata
1212
- Fix semantic indentation of quoted functions
13+
- Add custom `fill-paragraph-function` which respects docstrings similar to
14+
`clojure-mode`.
1315

1416
## 0.2.2 (2024-02-16)
1517

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ To make forms inside of `(comment ...)` forms appear as top-level forms for eval
5252
(setq clojure-ts-toplevel-inside-comment-form t)
5353
```
5454

55+
### Fill paragraph
56+
57+
To change the maximal line length used by `M-x prog-fill-reindent-defun` (also
58+
bound to `M-q` by default) to reformat docstrings and comments it's possible to
59+
customize `clojure-ts-fill-paragraph` variable (by default set to the value of
60+
Emacs' `fill-paragraph` value).
61+
62+
Every new line in the docstrings is indented by
63+
`clojure-ts-docstring-fill-prefix-width` number of spaces (set to 2 by default
64+
which matches the `clojure-mode` settings).
65+
5566
## Rationale
5667

5768
[clojure-mode](https://github.com/clojure-emacs/clojure-mode) has served us well

clojure-ts-mode.el

+37
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,21 @@ itself."
9797
:safe #'booleanp
9898
:package-version '(clojure-ts-mode . "0.2.1"))
9999

100+
(defcustom clojure-ts-docstring-fill-column fill-column
101+
"Value of `fill-column' to use when filling a docstring."
102+
:type 'integer
103+
:safe #'integerp
104+
:package-version '(clojure-ts-mode . "0.2.3"))
105+
106+
(defcustom clojure-ts-docstring-fill-prefix-width 2
107+
"Width of `fill-prefix' when filling a docstring.
108+
The default value conforms with the de facto convention for
109+
Clojure docstrings, aligning the second line with the opening
110+
double quotes on the third column."
111+
:type 'integer
112+
:safe #'integerp
113+
:package-version '(clojure-ts-mode . "0.2.3"))
114+
100115
(defvar clojure-ts--debug nil
101116
"Enables debugging messages, shows current node in mode-line.
102117
Only intended for use at development time.")
@@ -863,6 +878,27 @@ forms like deftype, defrecord, reify, proxy, etc."
863878
'(semantic fixed)
864879
clojure-ts-indent-style)))))
865880

881+
(defun clojure-ts--docstring-fill-prefix ()
882+
"The prefix string used by `clojure-ts--fill-paragraph'.
883+
It is simply `clojure-ts-docstring-fill-prefix-width' number of spaces."
884+
(make-string clojure-ts-docstring-fill-prefix-width ? ))
885+
886+
(defun clojure-ts--fill-paragraph (&optional justify)
887+
"Like `fill-paragraph', but can handler Clojure docstrings.
888+
If JUSTIFY is non-nil, justify as well as fill the paragraph."
889+
(let ((current-node (treesit-node-at (point))))
890+
(if (clojure-ts--match-docstring nil current-node nil)
891+
(let ((fill-column (or clojure-ts-docstring-fill-column fill-column))
892+
(fill-prefix (clojure-ts--docstring-fill-prefix))
893+
(beg-doc (treesit-node-start current-node))
894+
(end-doc (treesit-node-end current-node)))
895+
(save-restriction
896+
(narrow-to-region beg-doc end-doc)
897+
(fill-paragraph justify)))
898+
(or (fill-comment-paragraph justify)
899+
(fill-paragraph justify)))
900+
t))
901+
866902
(defconst clojure-ts--sexp-nodes
867903
'("#_" ;; transpose-sexp near a discard macro moves it around.
868904
"num_lit" "sym_lit" "kwd_lit" "nil_lit" "bool_lit"
@@ -963,6 +999,7 @@ See `clojure-ts--font-lock-settings' for usage of MARKDOWN-AVAILABLE."
963999
(keyword string char symbol builtin type)
9641000
(constant number quote metadata doc)
9651001
(bracket deref function regex tagged-literals)))
1002+
(setq-local fill-paragraph-function #'clojure-ts--fill-paragraph)
9661003
(when (boundp 'treesit-thing-settings) ;; Emacs 30+
9671004
(setq-local treesit-thing-settings clojure-ts--thing-settings)))
9681005

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
;;; clojure-ts-mode-fill-paragraph-test.el --- -*- lexical-binding: t; -*-
2+
3+
;; Copyright (C) 2025 Roman Rudakov
4+
5+
;; This file is not part of GNU Emacs.
6+
7+
;; This program is free software; you can redistribute it and/or modify
8+
;; it under the terms of the GNU General Public License as published by
9+
;; the Free Software Foundation, either version 3 of the License, or
10+
;; (at your option) any later version.
11+
12+
;; This program is distributed in the hope that it will be useful,
13+
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
;; GNU General Public License for more details.
16+
17+
;; You should have received a copy of the GNU General Public License
18+
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
20+
;;; Commentary:
21+
22+
;; The unit test suite of CLojure TS Mode
23+
24+
;;; Code:
25+
26+
(require 'clojure-ts-mode)
27+
(require 'buttercup)
28+
29+
(describe "clojure-ts--fill-paragraph"
30+
(it "should reformat only the docstring"
31+
(with-clojure-ts-buffer "(ns foo)
32+
33+
(defn hello-world
34+
\"This is a very long docstring that should be reformatted using fill-paragraph function.\"
35+
[]
36+
(pringln \"Hello world\"))"
37+
(goto-char 40)
38+
(prog-fill-reindent-defun)
39+
(expect (buffer-substring-no-properties (point-min) (point-max))
40+
:to-equal
41+
"(ns foo)
42+
43+
(defn hello-world
44+
\"This is a very long docstring that should be reformatted using
45+
fill-paragraph function.\"
46+
[]
47+
(pringln \"Hello world\"))")))
48+
49+
(it "should reformat normal comments properly"
50+
(with-clojure-ts-buffer "(ns foo)
51+
52+
;; This is a very long comment that should be reformatted using fill-paragraph function."
53+
(goto-char 20)
54+
(prog-fill-reindent-defun)
55+
(expect (buffer-substring-no-properties (point-min) (point-max))
56+
:to-equal
57+
"(ns foo)
58+
59+
;; This is a very long comment that should be reformatted using
60+
;; fill-paragraph function."))))
61+
62+
;;; clojure-ts-mode-fill-paragraph-test.el ends here

0 commit comments

Comments
 (0)