diff options
| author | Daniel Mendler <mail@daniel-mendler.de> | 2025-03-07 16:58:10 +0100 |
|---|---|---|
| committer | Daniel Mendler <mail@daniel-mendler.de> | 2025-03-07 17:13:26 +0100 |
| commit | e5204b0807c987d4a7b1a9441158b80a3407b675 (patch) | |
| tree | e295ccb1c9494af403b26f91d56844b1a10813e1 | |
| parent | c833f2edcb68466bef53a6ea104371a26d6bc0c8 (diff) | |
compat-31: New macro with-work-buffer
| -rw-r--r-- | NEWS.org | 1 | ||||
| -rw-r--r-- | compat-31.el | 54 | ||||
| -rw-r--r-- | compat-tests.el | 9 | ||||
| -rw-r--r-- | compat.texi | 7 |
4 files changed, 71 insertions, 0 deletions
@@ -9,6 +9,7 @@ - compat-31: New macros =incf= and =decf=. - compat-31: New function =color-blend=. - compat-31: New function =completion-table-with-metadata=. +- compat-31: New macro =with-work-buffer=. - Drop support for Emacs 24.x. Emacs 25.1 is required now. In case Emacs 24.x support is still needed, Compat 30 can be used. diff --git a/compat-31.el b/compat-31.el index 59ea412..6b23b4c 100644 --- a/compat-31.el +++ b/compat-31.el @@ -94,5 +94,59 @@ METADATA should be an alist of completion metadata. See `(metadata . ,metadata) (complete-with-action action table string pred)))) +;;;; Defined in subr-x.el + +(compat-defvar work-buffer--list nil ;; <compat-tests:with-work-buffer> + "List of work buffers.") + +(compat-defvar work-buffer-limit 10 ;; <compat-tests:with-work-buffer> + "Maximum number of reusable work buffers. +When this limit is exceeded, newly allocated work buffers are +automatically killed, which means that in a such case +`with-work-buffer' becomes equivalent to `with-temp-buffer'.") + +(compat-defun work-buffer--get () ;; <compat-tests:with-work-buffer> + "Get a work buffer." + (let ((buffer (pop work-buffer--list))) + (if (buffer-live-p buffer) + buffer + ;; `generate-new-buffer' and `get-buffer-create' accept an + ;; INHIBIT-BUFFER-HOOKS argument on Emacs 28 and newer. + ;; Unfortunately it is hard or not possible to port this back. See + ;; issue <compat-gh:42>. + (static-if (>= emacs-major-version 28) + (generate-new-buffer " *work*" t) + (generate-new-buffer " *work*"))))) + +(compat-defun work-buffer--release (buffer) ;; <compat-tests:with-work-buffer> + "Release work BUFFER." + (if (buffer-live-p buffer) + (with-current-buffer buffer + (let ((inhibit-read-only t) deactivate-mark) + (erase-buffer)) + (delete-all-overlays) + (let (change-major-mode-hook) + ;; TODO Port back the KILL-PERMANENT argument from Emacs 29 + ;; Right now permanent variables are not killed. + (static-if (>= emacs-major-version 29) + (kill-all-local-variables t) + (kill-all-local-variables))) + (push buffer work-buffer--list))) + (when (> (length work-buffer--list) work-buffer-limit) + (mapc #'kill-buffer (nthcdr work-buffer-limit work-buffer--list)) + (setq work-buffer--list (ntake work-buffer-limit work-buffer--list)))) + +(compat-defmacro with-work-buffer (&rest body) ;; <compat-tests:with-work-buffer> + "Create a work buffer, and evaluate BODY there like `progn'. +Like `with-temp-buffer', but reuse an already created temporary +buffer when possible, instead of creating a new one on each call." + (declare (indent 0) (debug t)) + (let ((work-buffer (make-symbol "work-buffer"))) + `(let ((,work-buffer (work-buffer--get))) + (with-current-buffer ,work-buffer + (unwind-protect + (progn ,@body) + (work-buffer--release ,work-buffer)))))) + (provide 'compat-31) ;;; compat-31.el ends here diff --git a/compat-tests.el b/compat-tests.el index 5b12baf..6705620 100644 --- a/compat-tests.el +++ b/compat-tests.el @@ -1088,6 +1088,15 @@ (with-current-buffer inner (should-not (buffer-modified-p)))))))) +(ert-deftest compat-with-work-buffer () + (with-work-buffer + (should (string-match-p "\\` \\*work\\*" (buffer-name))) + (let ((outer (current-buffer))) + (with-work-buffer + (should (string-match-p "\\` \\*work\\*" (buffer-name))) + (let ((inner (current-buffer))) + (should-not (eq outer inner))))))) + (ert-deftest compat-insert-into-buffer () ;; Without optional compat--arguments (with-temp-buffer diff --git a/compat.texi b/compat.texi index 16ae3a9..c1b7701 100644 --- a/compat.texi +++ b/compat.texi @@ -3427,6 +3427,13 @@ older than 31.1. Note that due to upstream changes, it might happen that there will be the need for changes, so use these functions with care. +@c based on lisp/emacs-lisp/subr-x.el +@defmac with-work-buffer &rest body +Create a work buffer, and evaluate @var{body} there like @code{progn}. +Like @code{with-temp-buffer}, but reuse an already created temporary +buffer when possible, instead of creating a new one on each call. +@end defmac + @c copied from lispref/numbers.texi @defun plusp number This predicate tests whether its argument is positive, and returns |
