aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ponce2024-08-22 16:56:11 +0200
committerEli Zaretskii2024-08-31 11:21:42 +0300
commitb930a698f2ba4e8b5878a4b604098e1201796b7f (patch)
tree4273bddec57e45aed422c55930049f3ff0d54cea
parentb25da8729dd853e352a147583a7b24699283d4d9 (diff)
downloademacs-b930a698f2ba4e8b5878a4b604098e1201796b7f.tar.gz
emacs-b930a698f2ba4e8b5878a4b604098e1201796b7f.zip
New macro `with-work-buffer'.
* lisp/emacs-lisp/subr-x.el (work-buffer--list) (work-buffer-limit): New variables. (work-buffer--get, work-buffer--release): New function. (with-work-buffer): New macro. (Bug#72689) * etc/NEWS: Announce 'with-work-buffer'.
-rw-r--r--etc/NEWS7
-rw-r--r--lisp/emacs-lisp/subr-x.el47
2 files changed, 54 insertions, 0 deletions
diff --git a/etc/NEWS b/etc/NEWS
index faf9a963d39..dc70eb25de7 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -321,6 +321,13 @@ language A.
321If supplied, 'string-pixel-width' will use any face remappings from 321If supplied, 'string-pixel-width' will use any face remappings from
322BUFFER when computing the string's width. 322BUFFER when computing the string's width.
323 323
324---
325*** New macro 'with-work-buffer'.
326This macro is similar to the already existing macro `with-temp-buffer',
327except that it does not allocate a new temporary buffer on each call,
328but tries to reuse those previously allocated (up to a number defined by
329the new variable `work-buffer-limit', which defaults to 10).
330
324+++ 331+++
325** 'date-to-time' now defaults to local time. 332** 'date-to-time' now defaults to local time.
326The function now assumes local time instead of Universal Time when 333The function now assumes local time instead of Universal Time when
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 058c06bc5f6..3347c802f68 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -336,6 +336,53 @@ This construct can only be used with lexical binding."
336 (cl-labels ((,name ,fargs . ,body)) #',name) 336 (cl-labels ((,name ,fargs . ,body)) #',name)
337 . ,aargs))) 337 . ,aargs)))
338 338
339(defvar work-buffer--list nil)
340(defvar work-buffer-limit 10
341 "Maximum number of reusable work buffers.
342When this limit is exceeded, newly allocated work buffers are
343automatically killed, which means that in a such case
344`with-work-buffer' becomes equivalent to `with-temp-buffer'.")
345
346(defsubst work-buffer--get ()
347 "Get a work buffer."
348 (let ((buffer (pop work-buffer--list)))
349 (if (buffer-live-p buffer)
350 buffer
351 (generate-new-buffer " *work*" t))))
352
353(defun work-buffer--release (buffer)
354 "Release work BUFFER."
355 (if (buffer-live-p buffer)
356 (with-current-buffer buffer
357 ;; Flush BUFFER before making it available again, i.e. clear
358 ;; its contents, remove all overlays and buffer-local
359 ;; variables. Is it enough to safely reuse the buffer?
360 (erase-buffer)
361 (delete-all-overlays)
362 (let (change-major-mode-hook)
363 (kill-all-local-variables t))
364 ;; Make the buffer available again.
365 (push buffer work-buffer--list)))
366 ;; If the maximum number of reusable work buffers is exceeded, kill
367 ;; work buffer in excess, taking into account that the limit could
368 ;; have been let-bound to temporarily increase its value.
369 (when (> (length work-buffer--list) work-buffer-limit)
370 (mapc #'kill-buffer (nthcdr work-buffer-limit work-buffer--list))
371 (setq work-buffer--list (ntake work-buffer-limit work-buffer--list))))
372
373;;;###autoload
374(defmacro with-work-buffer (&rest body)
375 "Create a work buffer, and evaluate BODY there like `progn'.
376Like `with-temp-buffer', but reuse an already created temporary
377buffer when possible, instead of creating a new one on each call."
378 (declare (indent 0) (debug t))
379 (let ((work-buffer (make-symbol "work-buffer")))
380 `(let ((,work-buffer (work-buffer--get)))
381 (with-current-buffer ,work-buffer
382 (unwind-protect
383 (progn ,@body)
384 (work-buffer--release ,work-buffer))))))
385
339;;;###autoload 386;;;###autoload
340(defun string-pixel-width (string &optional buffer) 387(defun string-pixel-width (string &optional buffer)
341 "Return the width of STRING in pixels. 388 "Return the width of STRING in pixels.