summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lispref/text.texi13
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/emacs-lisp/subr-x.el26
-rw-r--r--test/lisp/emacs-lisp/subr-x-tests.el38
4 files changed, 82 insertions, 0 deletions
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 41b3138a0dd..1e062be2c64 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -599,6 +599,19 @@ This command indents to the left margin if that is not zero.
The value returned is @code{nil}.
@end deffn
+@deffn Command ensure-empty-lines &optional number-of-empty-lines
+This command can be used to ensure that you have a specific number of
+empty lines before point. (An ``empty line'' is here defined as a
+line with no characters on it---a line with space characters isn't an
+empty line.) It defaults to ensuring that there's a single empty line
+before point.
+
+If point isn't at the beginning of a line, a newline character is
+inserted first. If there's more empty lines before point than
+specified, the number of empty lines is reduced. Otherwise it's
+increased to the specified number.
+@end deffn
+
@defvar overwrite-mode
This variable controls whether overwrite mode is in effect. The value
should be @code{overwrite-mode-textual}, @code{overwrite-mode-binary},
diff --git a/etc/NEWS b/etc/NEWS
index b039310afa8..7b4a29e1b66 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -56,6 +56,11 @@ This change also affects 'cl-macrolet', 'cl-flet*' and
This can be set to nil to inhibit translating upper case keys to lower
case keys.
++++
+** New command 'ensure-empty-lines'.
+This command increases (or decreases) the number of empty lines before
+point.
+
* Changes in Specialized Modes and Packages in Emacs 29.1
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 91ebbf9fb92..ecd3ca831e8 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -412,6 +412,32 @@ and return the value found in PLACE instead."
,(funcall setter val)
,val)))))
+;;;###autoload
+(defun ensure-empty-lines (&optional lines)
+ "Ensure that there's LINES number of empty lines before point.
+If LINES is nil or missing, a this ensures that there's a single
+empty line before point.
+
+Interactively, this command uses the numerical prefix for LINES.
+
+If there's already more empty lines before point than LINES, the
+number of blank lines will be reduced.
+
+If point is not at the beginning of a line, a newline character
+is inserted before adjusting the number of empty lines."
+ (interactive "p")
+ (unless (bolp)
+ (insert "\n"))
+ (let ((lines (or lines 1))
+ (start (save-excursion
+ (if (re-search-backward "[^\n]" nil t)
+ (+ (point) 2)
+ (point-min)))))
+ (cond
+ ((> (- (point) start) lines)
+ (delete-region (point) (- (point) (- (point) start lines))))
+ ((< (- (point) start) lines)
+ (insert (make-string (- lines (- (point) start)) ?\n))))))
(provide 'subr-x)
diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el
index 1d19496ba44..f9cfea888c7 100644
--- a/test/lisp/emacs-lisp/subr-x-tests.el
+++ b/test/lisp/emacs-lisp/subr-x-tests.el
@@ -638,5 +638,43 @@
(should (equal (string-chop-newline "foo\nbar\n") "foo\nbar"))
(should (equal (string-chop-newline "foo\nbar") "foo\nbar")))
+(ert-deftest subr-ensure-empty-lines ()
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo")
+ (goto-char (point-min))
+ (ensure-empty-lines 2)
+ (buffer-string))
+ "\n\nfoo"))
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo")
+ (ensure-empty-lines 2)
+ (buffer-string))
+ "foo\n\n\n"))
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo\n")
+ (ensure-empty-lines 2)
+ (buffer-string))
+ "foo\n\n\n"))
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo\n\n\n\n\n")
+ (ensure-empty-lines 2)
+ (buffer-string))
+ "foo\n\n\n"))
+ (should
+ (equal
+ (with-temp-buffer
+ (insert "foo\n\n\n")
+ (ensure-empty-lines 0)
+ (buffer-string))
+ "foo\n")))
+
(provide 'subr-x-tests)
;;; subr-x-tests.el ends here