diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index fe3863db810..b01df8512b7 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -1848,10 +1848,11 @@ Manual}. @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}. +@code{fill-paragraph} and @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 diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el index bb10890141d..4ab639497ec 100644 --- a/lisp/textmodes/fill.el +++ b/lisp/textmodes/fill.el @@ -1641,77 +1641,63 @@ spaces. The variable `fill-column' controls the width for filling. Return the `fill-prefix' used for filling. -For more details about semantic linefeeds, see `fill-paragraph-semlf'." - (interactive (progn - (barf-if-buffer-read-only) - (list (region-beginning) - (region-end) - (if current-prefix-arg 'full)))) - (unless (memq justify '(t nil none full center left right)) - (setq justify 'full)) - - (let ((from (min from to)) - (to (max from to)) - pfx) - (goto-char from) - (with-restriction (line-beginning-position) to - (let ((fill-column (point-max))) - (setq pfx (or (save-excursion - (fill-region-as-paragraph-default (point) - (point-max) - nil - nosqueeze - squeeze-after)) - ""))) - (while (not (eobp)) - (let ((fill-prefix pfx)) - (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) - (insert "\n") - (insert pfx)))) - (unless (eobp) (forward-char 1)) - pfx)) - -(defun fill-paragraph-semlf (&optional justify) - "Fill paragraph at or after point using semantic linefeeds. -Refill text putting a newline character after each sentence, calling -`forward-sentence' to find the ends of sentences. If -`sentence-end-double-space' is non-nil, period followed by one space is -not the end of a sentence. - -If JUSTIFY is non-nil (interactively, with prefix argument), justify as -well. The variable `fill-column' controls the width for filling. - -Return the `fill-prefix' used for filling. - -You can use this function as the value of `fill-paragraph-function', so -`fill-paragraph' and other filling commands will use it. +This function can be assigned to `fill-region-as-paragraph-function' to +override how functions like `fill-paragraph' and `fill-region' fill +text. For more details about semantic linefeeds, see `https://sembr.org/' and `https://rhodesmill.org/brandon/2012/one-sentence-per-line/'." (interactive (progn (barf-if-buffer-read-only) - (list (if current-prefix-arg 'full)))) - (unless (memq justify '(t nil none full center left right)) - (setq justify 'full)) + (list (region-beginning) + (region-end) + (if current-prefix-arg 'full)))) - (save-excursion - (let ((to (progn - (fill-forward-paragraph 1) - (backward-word) - (end-of-line) - (point))) - (from (progn - (fill-forward-paragraph -1) - (forward-word) - (beginning-of-line) - (point)))) - (fill-region-as-paragraph-semlf from to justify)))) + (let ((from (min from to)) + (to (copy-marker (max from to) t)) + pfx) + (goto-char from) + (let ((fill-column (point-max))) + (setq pfx (or (save-excursion + (fill-region-as-paragraph-default (point) + to + nil + nosqueeze + squeeze-after)) + ""))) + (while (< (point) to) + (let ((fill-prefix pfx)) + (fill-region-as-paragraph-default (point) + (min to + (save-excursion + (forward-sentence) + (point))) + justify + t)) + (when (and (> (point) (line-beginning-position)) + (< (point) (line-end-position)) + (< (point) to)) + (delete-horizontal-space) + (insert "\n") + (insert pfx))) + pfx)) + +(defun fill-paragraph-semlf (&optional justify region) + "Fill paragraph at or after point using semantic linefeeds. +Refill text putting a newline character after each sentence. + +If JUSTIFY is non-nil (interactively, with prefix argument), justify as +well. The REGION argument is non-nil if called interactively; in that +case, if Transient Mark mode is enabled and the mark is active, fill the +active region. + +See `fill-paragraph' and `fill-region-as-paragraph-semlf' for more +details." + (interactive (progn + (barf-if-buffer-read-only) + (list (if current-prefix-arg 'full) t))) + + (let ((fill-region-as-paragraph-function #'fill-region-as-paragraph-semlf)) + (fill-paragraph justify region))) ;;; fill.el ends here diff --git a/test/lisp/textmodes/fill-resources/semlf-emacs-lisp-mode.erts b/test/lisp/textmodes/fill-resources/semlf-emacs-lisp-mode.erts index fe71ee32c1a..1623b0dcf8a 100644 --- a/test/lisp/textmodes/fill-resources/semlf-emacs-lisp-mode.erts +++ b/test/lisp/textmodes/fill-resources/semlf-emacs-lisp-mode.erts @@ -59,12 +59,12 @@ the comment. ;; eiusmod tempor. Incididunt ut labore et dolore magna aliqua. Ut ;; enim ad minim veniam, quis nostrud exercitation ullamco laboris ;; nisi ut. - +;; ;; |Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed ;; do eiusmod tempor. Incididunt ut labore et dolore magna ;; aliqua. Ut enim ad minim veniam, quis nostrud exercitation ;; ullamco laboris nisi ut. - +;; ;; Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do ;; eiusmod tempor. Incididunt ut labore et dolore magna aliqua. Ut ;; enim ad minim veniam, quis nostrud exercitation ullamco laboris @@ -74,12 +74,12 @@ the comment. ;; eiusmod tempor. Incididunt ut labore et dolore magna aliqua. Ut ;; enim ad minim veniam, quis nostrud exercitation ullamco laboris ;; nisi ut. - +;; ;; Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed ;; do eiusmod tempor. ;; Incididunt ut labore et dolore magna aliqua. Ut enim ad minim ;; veniam, quis nostrud exercitation ullamco laboris nisi ut. - +;; ;; Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do ;; eiusmod tempor. Incididunt ut labore et dolore magna aliqua. Ut ;; enim ad minim veniam, quis nostrud exercitation ullamco laboris diff --git a/test/lisp/textmodes/fill-resources/semlf-fill-paragraph-function.erts b/test/lisp/textmodes/fill-resources/semlf-fill-paragraph-function.erts deleted file mode 100644 index 467e7401cf5..00000000000 --- a/test/lisp/textmodes/fill-resources/semlf-fill-paragraph-function.erts +++ /dev/null @@ -1,12 +0,0 @@ -Name: fill-paragraph-function - -=-= -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do -eiusmod tempor. Incididunt ut labore et dolore magna aliqua. Ut enim -ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. -=-= -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do -eiusmod tempor. -Incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut. -=-=-= diff --git a/test/lisp/textmodes/fill-resources/semlf-fill-region.erts b/test/lisp/textmodes/fill-resources/semlf-fill-region.erts new file mode 100644 index 00000000000..231019a082a --- /dev/null +++ b/test/lisp/textmodes/fill-resources/semlf-fill-region.erts @@ -0,0 +1,25 @@ +Point-Char: | + +Name: fill-region-as-paragraph-function + +=-= +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. +=-=-= diff --git a/test/lisp/textmodes/fill-tests.el b/test/lisp/textmodes/fill-tests.el index 310d374a7ad..e1839fd6884 100644 --- a/test/lisp/textmodes/fill-tests.el +++ b/test/lisp/textmodes/fill-tests.el @@ -147,47 +147,54 @@ eius. Foo"))) (beginning-of-line) (point)))))) -(ert-deftest fill-test-fill-paragraph-semlf () - "Test the `fill-paragraph-semlf' function." +(ert-deftest fill-test-semlf-fill-region () + "Test `fill-region' with `fill-region-as-paragraph-semlf'." + (ert-test-erts-file (ert-resource-file "semlf-fill-region.erts") + (lambda () + (setq-local fill-region-as-paragraph-function + #'fill-region-as-paragraph-semlf) + (fill-region + (point) + (progn + (goto-char (point-max)) + (forward-line -1) + (beginning-of-line) + (point)))))) + +(ert-deftest fill-test-semlf () + "Test semantic-linefeed filling." (ert-test-erts-file (ert-resource-file "semlf.erts") (lambda () (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-fill-paragraph-function () - "Test `fill-paragraph-semlf' as `fill-paragraph-function'." - (ert-test-erts-file (ert-resource-file "semlf-fill-paragraph-function.erts") - (lambda () - (setq-local fill-paragraph-function #'fill-paragraph-semlf) - (fill-paragraph)))) - -(ert-deftest fill-test-fill-paragraph-semlf-justify () - "Test the JUSTIFY parameter of the `fill-paragraph-semlf' function." +(ert-deftest fill-test-semlf-justify () + "Test semantic-linefeed filling with text justification." (ert-test-erts-file (ert-resource-file "semlf-justify.erts") (lambda () (fill-paragraph-semlf 'justify)))) -(ert-deftest fill-test-fill-paragraph-semlf-sentence-end-double-space () - "Test the `fill-paragraph-semlf' function with `sentence-end-double-space'." +(ert-deftest fill-test-semlf-sentence-end-double-space () + "Test semantic-linefeed filling with `sentence-end-double-space'." (ert-test-erts-file (ert-resource-file "semlf-sentence-end-double-space.erts") (lambda () (setq-local sentence-end-double-space nil) (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-fill-column () - "Test the `fill-paragraph-semlf' function with `fill-column'." +(ert-deftest fill-test-semlf-fill-column () + "Test semantic-linefeed filling with `fill-column'." (ert-test-erts-file (ert-resource-file "semlf-fill-column.erts") (lambda () (setq-local fill-column 35) (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-punctuation-marks () - "Test the `fill-paragraph-semlf' function with different punctuation marks." +(ert-deftest fill-test-semlf-punctuation-marks () + "Test semantic-linefeed filling with different punctuation marks." (ert-test-erts-file (ert-resource-file "semlf-punctuation-marks.erts") (lambda () (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-twice () - "Test to run the `fill-paragraph-semlf' function twice." +(ert-deftest fill-test-semlf-twice () + "Test filling the same text twice using semantic linefeeds." (ert-test-erts-file (ert-resource-file "semlf-twice.erts") (lambda () (goto-char (point-min)) @@ -195,50 +202,50 @@ eius. Foo"))) (goto-char (point-min)) (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-fill-prefix () - "Test the `fill-paragraph-semlf' function with different fill prefixes." +(ert-deftest fill-test-semlf-fill-prefix () + "Test semantic-linefeed filling with different fill prefixes." (ert-test-erts-file (ert-resource-file "semlf-fill-prefix.erts") (lambda () (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-indented-block () - "Test the `fill-paragraph-semlf' function with an indented block." +(ert-deftest fill-test-semlf-indented-block () + "Test semantic-linefeed filling with an indented block." (ert-test-erts-file (ert-resource-file "semlf-indented-block.erts") (lambda () (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-revert () - "Test that the `fill-paragraph-semlf' function can be reverted." +(ert-deftest fill-test-semlf-revert () + "Test that semantic-linefeed filling can be reverted." (ert-test-erts-file (ert-resource-file "semlf-revert.erts") (lambda () (fill-paragraph) - (fill-paragraph-semlf) + (fill-paragraph-semlf) (fill-paragraph)))) -(ert-deftest fill-test-fill-paragraph-semlf-emacs-lisp-mode () - "Test the `fill-paragraph-semlf' function with `emacs-lisp-mode'." +(ert-deftest fill-test-semlf-emacs-lisp-mode () + "Test semantic-linefeed filling with `emacs-lisp-mode'." (ert-test-erts-file (ert-resource-file "semlf-emacs-lisp-mode.erts") (lambda () (emacs-lisp-mode) (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-c-mode () - "Test the `fill-paragraph-semlf' function with `c-mode'." +(ert-deftest fill-test-semlf-c-mode () + "Test semantic-linefeed filling with `c-mode'." (ert-test-erts-file (ert-resource-file "semlf-c-mode.erts") (lambda () (c-mode) (fill-paragraph-semlf)))) -(ert-deftest fill-test-fill-paragraph-semlf-org-mode () - "Test the `fill-paragraph-semlf' function with `org-mode'." +(ert-deftest fill-test-semlf-org-mode () + "Test semantic-linefeed filling with `org-mode'." (ert-test-erts-file (ert-resource-file "semlf-org-mode.erts") (lambda () (org-mode) (fill-paragraph-semlf)))) (declare-function markdown-mode "markdown-mode") -(ert-deftest fill-test-fill-paragraph-semlf-markdown-mode () - "Test the `fill-paragraph-semlf' function with `markdown-mode'." +(ert-deftest fill-test-semlf-markdown-mode () + "Test semantic-linefeed filling with `markdown-mode'." (skip-unless (functionp 'markdown-mode)) (ert-test-erts-file (ert-resource-file "semlf-markdown-mode.erts") (lambda ()