]> git.eshelyaron.com Git - emacs.git/commitdiff
Add variable `fill-region-as-paragraph-function'
authorRoi Martin <jroi.martin@gmail.com>
Tue, 17 Jun 2025 08:45:13 +0000 (10:45 +0200)
committerEshel Yaron <me@eshelyaron.com>
Wed, 23 Jul 2025 20:08:25 +0000 (22:08 +0200)
Add the variable `fill-region-as-paragraph-function' to provide
a way to override how functions like `fill-region' fill text.
* doc/lispref/text.texi (Filling): Document
`fill-region-as-paragraph-function' variable.
* doc/emacs/text.texi (Fill Commands): Reference
`fill-region-as-paragraph-function' variable.
* lisp/textmodes/fill.el (fill-region-as-paragraph-function):
Add variable.
(fill-region-as-paragraph): Convert into
`fill-region-as-paragraph-function' wrapper.
(fill-region-as-paragraph-default): Rename old
`fill-region-as-paragraph' function.
(fill-region-as-paragraph-semlf): Update calls to
`fill-region-as-paragraph-default'.
(fill-region): Add reference to `fill-region-as-paragraph-function'
in doc string.
* test/lisp/textmodes/fill-tests.el (fill-test-fill-region): Add
test case for the `fill-region' function.
* test/lisp/textmodes/fill-resources/fill-region.erts: Add test
data.  (Bug#78816)

(cherry picked from commit 99ec286d7803fa59f770013a2135f23918510103)

doc/emacs/text.texi
doc/lispref/text.texi
lisp/textmodes/fill.el
test/lisp/textmodes/fill-resources/fill-region.erts [new file with mode: 0644]
test/lisp/textmodes/fill-tests.el

index 2950618f35fe9faed52c77f554240f374ffd0734..09fa846be326cec7508df33d0615e564ad7cba68 100644 (file)
@@ -600,12 +600,15 @@ can also call @kbd{M-x fill-region} to specifically fill the text in
 the region.
 
 @findex fill-region-as-paragraph
+@vindex fill-region-as-paragraph-function
   @kbd{M-q} and @code{fill-region} use the usual Emacs criteria for
 finding paragraph boundaries (@pxref{Paragraphs}).  For more control,
-you can use @kbd{M-x fill-region-as-paragraph}, which refills
-everything between point and mark as a single paragraph.  This command
-deletes any blank lines within the region, so separate blocks of text
-end up combined into one block.
+you can use @kbd{M-x fill-region-as-paragraph}, which refills everything
+between point and mark as a single paragraph.  The behavior of this
+command is controlled by the variable
+@code{fill-region-as-paragraph-function}.  By default, it deletes any
+blank lines within the region, so separate blocks of text end up
+combined into one block.
 
 @cindex justification
   A numeric argument to @kbd{M-q} tells it to @dfn{justify} the text
index 0b3698240f17f36141de2b766b7b357881b8d7c4..dff979c92c590426deeb3ed7f0789ba47d914619 100644 (file)
@@ -1739,7 +1739,12 @@ described above.
 
 @deffn Command fill-region-as-paragraph start end &optional justify nosqueeze squeeze-after
 This command considers a region of text as a single paragraph and fills
-it.  If the region was made up of many paragraphs, the blank lines
+it.  The behavior of this command is controlled by the variable
+@code{fill-region-as-paragraph-function}, with the default
+implementation being @code{fill-region-as-paragraph-default}, which is
+described in detail below.
+
+If the region was made up of many paragraphs, the blank lines
 between paragraphs are removed.  This function justifies as well as
 filling when @var{justify} is non-@code{nil}.
 
@@ -1843,6 +1848,14 @@ paragraphs actually moved.  The default value of this variable is
 Manual}.
 @end defvar
 
+@defvar fill-region-as-paragraph-function
+This variable provides a way to override how functions like
+@code{fill-region} fill text.  Its value should be a function, which
+should accept the arguments defined by @code{fill-region-as-paragraph}
+and return the fill prefix used for filling.  The default value of this
+variable is @code{fill-region-as-paragraph-default}.
+@end defvar
+
 @defvar use-hard-newlines
 If this variable is non-@code{nil}, the filling functions do not delete
 newlines that have the @code{hard} text property.  These hard
index 1583ba4df0516fe1246d3e730d4fd2c2d9dec7ac..bb10890141d6bbfc05704181d4b52d348c2937b4 100644 (file)
@@ -647,8 +647,8 @@ The break position will be always after LINEBEG and generally before point."
     (indent-line-to (current-left-margin))
     (put-text-property beg (point) 'face 'default)))
 
-(defun fill-region-as-paragraph (from to &optional justify
-                                     nosqueeze squeeze-after)
+(defun fill-region-as-paragraph-default (from to &optional justify
+                                             nosqueeze squeeze-after)
   "Fill the region as if it were a single paragraph.
 This command removes any paragraph breaks in the region and
 extra newlines at the end, and indents and fills lines between the
@@ -800,6 +800,39 @@ space does not end a sentence, so don't break a line there."
       ;; Return the fill-prefix we used
       fill-prefix)))
 
+(defvar fill-region-as-paragraph-function #'fill-region-as-paragraph-default
+  "Function to fill the region as if it were a single paragraph.
+It should accept the arguments defined by `fill-region-as-paragraph' and
+return the `fill-prefix' used for filling.")
+
+(defun fill-region-as-paragraph (from to &optional justify
+                                     nosqueeze squeeze-after)
+  "Fill the region as if it were a single paragraph.
+The behavior of this command is controlled by the variable
+`fill-region-as-paragraph-function', with the default implementation
+being `fill-region-as-paragraph-default'.
+
+The arguments FROM and TO define the boundaries of the region.
+
+The optional third argument JUSTIFY, when called interactively with a
+prefix arg, is assigned the value `full'.
+When called from Lisp, JUSTIFY can specify any type of justification;
+see `default-justification' for the possible values.
+Optional fourth arg NOSQUEEZE non-nil means not to make spaces between
+words canonical before filling.
+Fifth arg SQUEEZE-AFTER, if non-nil, should be a buffer position; it
+means canonicalize spaces only starting from that position.
+See `canonically-space-region' for the meaning of canonicalization of
+spaces.
+
+It returns the `fill-prefix' used for filling."
+  (interactive (progn
+                (barf-if-buffer-read-only)
+                (list (region-beginning) (region-end)
+                      (if current-prefix-arg 'full))))
+  (funcall fill-region-as-paragraph-function
+           from to justify nosqueeze squeeze-after))
+
 (defsubst skip-line-prefix (prefix)
   "If point is inside the string PREFIX at the beginning of line, move past it."
   (when (and prefix
@@ -1061,7 +1094,10 @@ if variable `use-hard-newlines' is on).
 Return the `fill-prefix' used for filling the last paragraph.
 
 If `sentence-end-double-space' is non-nil, then period followed by one
-space does not end a sentence, so don't break a line there."
+space does not end a sentence, so don't break a line there.
+
+The variable `fill-region-as-paragraph-function' can be used to override
+how paragraphs are filled."
   (interactive (progn
                 (barf-if-buffer-read-only)
                 (list (region-beginning) (region-end)
@@ -1621,19 +1657,19 @@ For more details about semantic linefeeds, see `fill-paragraph-semlf'."
     (with-restriction (line-beginning-position) to
       (let ((fill-column (point-max)))
         (setq pfx (or (save-excursion
-                        (fill-region-as-paragraph (point)
-                                                  (point-max)
-                                                  nil
-                                                  nosqueeze
-                                                  squeeze-after))
+                        (fill-region-as-paragraph-default (point)
+                                                          (point-max)
+                                                          nil
+                                                          nosqueeze
+                                                          squeeze-after))
                       "")))
       (while (not (eobp))
         (let ((fill-prefix pfx))
-         (fill-region-as-paragraph (point)
-                                   (progn (forward-sentence) (point))
-                                   justify
-                                    nosqueeze
-                                    squeeze-after))
+         (fill-region-as-paragraph-default (point)
+                                           (progn (forward-sentence) (point))
+                                           justify
+                                            nosqueeze
+                                            squeeze-after))
         (when (and (> (point) (line-beginning-position))
                   (< (point) (line-end-position)))
          (delete-horizontal-space)
diff --git a/test/lisp/textmodes/fill-resources/fill-region.erts b/test/lisp/textmodes/fill-resources/fill-region.erts
new file mode 100644 (file)
index 0000000..95e0824
--- /dev/null
@@ -0,0 +1,23 @@
+Point-Char: |
+
+Name: fill region
+
+=-=
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.  Incididunt ut labore et dolore magna aliqua.
+
+|Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.  Incididunt ut labore et dolore magna aliqua.
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.  Incididunt ut labore et dolore magna aliqua.
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.  Incididunt ut labore et dolore magna aliqua.
+=-=
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.  Incididunt ut labore et dolore magna aliqua.
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
+eiusmod tempor.  Incididunt ut labore et dolore magna aliqua.
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
+eiusmod tempor.  Incididunt ut labore et dolore magna aliqua.
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.  Incididunt ut labore et dolore magna aliqua.
+=-=-=
index 8fbd9919bad0622ff27666da02f0f524eb409599..40095fc99417d755bb4a0584d12abd6d82147afd 100644 (file)
@@ -122,6 +122,17 @@ eius. Foo")))
   ;; w
 ")))
 
+(ert-deftest fill-test-fill-region ()
+  "Test the `fill-region' function."
+  (ert-test-erts-file (ert-resource-file "fill-region.erts")
+                      (lambda ()
+                       (fill-region
+                         (point)
+                         (progn
+                           (goto-char (point-max))
+                           (forward-line -1)
+                           (beginning-of-line)
+                           (point))))))
 
 (ert-deftest fill-test-fill-region-as-paragraph-semlf ()
   "Test the `fill-region-as-paragraph-semlf' function."