From ce03bf252ae9bff28a6def163cb3f4fa102e691a Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sat, 8 Mar 2025 18:24:26 +0100 Subject: [PATCH] Make second arg to defvar-local optional This change allows declaring a variable both special and buffer-local like so: (defvar-local foo) * lisp/subr.el (defvar-local): Make second argument optional. * test/lisp/subr-tests.el (subr-test-defvar-local): New test. * doc/lispref/variables.texi (Creating Buffer-Local): Document above change. * etc/NEWS: * lisp/mb-depth.el (minibuffer-depth-overlay): * lisp/minibuf-eldef.el (minibuf-eldef-initial-input) (minibuf-eldef-initial-buffer-length) (minibuf-eldef-showing-default-in-prompt, minibuf-eldef-overlay): * lisp/misc.el (list-dynamic-libraries--loaded-only-p): * lisp/simple.el (minibuffer-history-isearch-message-overlay): Use above new one-argument form of 'defvar-local'. --- doc/lispref/variables.texi | 2 +- etc/NEWS | 5 +++++ lisp/mb-depth.el | 3 +-- lisp/minibuf-eldef.el | 13 +++++-------- lisp/misc.el | 3 +-- lisp/simple.el | 3 +-- lisp/subr.el | 16 +++++++++++----- test/lisp/subr-tests.el | 10 ++++++++++ 8 files changed, 35 insertions(+), 20 deletions(-) diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index 46027edb041..f8a361aa7ce 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -1649,7 +1649,7 @@ on having separate values in separate buffers, then using @code{make-variable-buffer-local} can be the best solution. @end deffn -@defmac defvar-local variable value &optional docstring +@defmac defvar-local variable &optional value docstring This macro defines @var{variable} as a variable with initial value @var{value} and @var{docstring}, and marks it as automatically buffer-local. It is equivalent to calling @code{defvar} followed by diff --git a/etc/NEWS b/etc/NEWS index 4f0d052f1c3..926d426eaae 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1565,6 +1565,11 @@ and signal an error if they are given a non-number. They return non-nil if an integer is odd or even, respectively, and signal an error if they are given a non-integer. ++++ +** The 'defvar-local' macro second argument is now optional. +This means that you can now call it with just one argument, like +'defvar', to declare a variable both special, and buffer-local. + ** ERT *** Some experimental ERT macros are now considered stable. diff --git a/lisp/mb-depth.el b/lisp/mb-depth.el index 7c00f5b1989..5fc66a8c8db 100644 --- a/lisp/mb-depth.el +++ b/lisp/mb-depth.el @@ -50,8 +50,7 @@ the `minibuffer-depth-indicator' face." ;; An overlay covering the prompt. This is a buffer-local variable in ;; each affected minibuffer. ;; -(defvar minibuffer-depth-overlay) -(make-variable-buffer-local 'minibuffer-depth-overlay) +(defvar-local minibuffer-depth-overlay) ;; This function goes on minibuffer-setup-hook (defun minibuffer-depth-setup () diff --git a/lisp/minibuf-eldef.el b/lisp/minibuf-eldef.el index 4b72cd9511c..50ab2354214 100644 --- a/lisp/minibuf-eldef.el +++ b/lisp/minibuf-eldef.el @@ -88,19 +88,16 @@ should be displayed in its place.") ;;; The following are all local variables in the minibuffer ;; Input pre-inserted into the minibuffer before the user can edit it. -(defvar minibuf-eldef-initial-input) -(make-variable-buffer-local 'minibuf-eldef-initial-input) +(defvar-local minibuf-eldef-initial-input) + ;; and the length of the buffer with it inserted. -(defvar minibuf-eldef-initial-buffer-length) -(make-variable-buffer-local 'minibuf-eldef-initial-buffer-length) +(defvar-local minibuf-eldef-initial-buffer-length) ;; True if the current minibuffer prompt contains the default spec. -(defvar minibuf-eldef-showing-default-in-prompt) -(make-variable-buffer-local 'minibuf-eldef-showing-default-in-prompt) +(defvar-local minibuf-eldef-showing-default-in-prompt) ;; An overlay covering the default portion of the prompt -(defvar minibuf-eldef-overlay) -(make-variable-buffer-local 'minibuf-eldef-overlay) +(defvar-local minibuf-eldef-overlay) ;;; Hook functions diff --git a/lisp/misc.el b/lisp/misc.el index 85ba1649d21..b2422648744 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -262,8 +262,7 @@ variation of `C-x M-c M-butterfly' from url `https://xkcd.com/378/'." ;; A command to list dynamically loaded libraries. This useful in ;; environments where dynamic-library-alist is used, i.e., Windows -(defvar list-dynamic-libraries--loaded-only-p) -(make-variable-buffer-local 'list-dynamic-libraries--loaded-only-p) +(defvar-local list-dynamic-libraries--loaded-only-p) (defun list-dynamic-libraries--loaded (from) "Compute the \"Loaded from\" column. diff --git a/lisp/simple.el b/lisp/simple.el index 2d36062e9c2..32479f3c092 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -3235,8 +3235,7 @@ Return 0 if current buffer is not a minibuffer." ;; isearch minibuffer history (add-hook 'minibuffer-setup-hook 'minibuffer-history-isearch-setup) -(defvar minibuffer-history-isearch-message-overlay) -(make-variable-buffer-local 'minibuffer-history-isearch-message-overlay) +(defvar-local minibuffer-history-isearch-message-overlay) (defun minibuffer-history-isearch-setup () "Set up a minibuffer for using isearch to search the minibuffer history. diff --git a/lisp/subr.el b/lisp/subr.el index 110bebed789..932a22d3250 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -192,14 +192,20 @@ pair. (setq pairs (cdr (cdr pairs)))) (macroexp-progn (nreverse expr)))) -(defmacro defvar-local (var val &optional docstring) - "Define VAR as a buffer-local variable with default value VAL. +(defmacro defvar-local (symbol &rest args) + "Define SYMBOL as a buffer-local variable with default value VALUE. Like `defvar' but additionally marks the variable as being automatically -buffer-local wherever it is set." +buffer-local wherever it is set. +\n(fn symbol &optional value docstring)" (declare (debug defvar) (doc-string 3) (indent 2)) ;; Can't use backquote here, it's too early in the bootstrap. - (list 'progn (list 'defvar var val docstring) - (list 'make-variable-buffer-local (list 'quote var)))) + (let ((value (car-safe args)) + (docstring (car-safe (cdr-safe args)))) + (list 'progn + (if (zerop (length args)) + (list 'defvar symbol) + (list 'defvar symbol value docstring)) + (list 'make-variable-buffer-local (list 'quote symbol))))) (defun buffer-local-boundp (symbol buffer) "Return non-nil if SYMBOL is bound in BUFFER. diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 98fd1cad894..df330bf60fc 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -30,6 +30,16 @@ (require 'ert-x) (eval-when-compile (require 'cl-lib)) +(defvar-local subr-tests--local-var1) +(defvar-local subr-tests--local-var2 'hello) +(defvar-local subr-tests--local-var3 nil "Doc.") +(ert-deftest subr-test-defvar-local () + (should (local-variable-if-set-p 'subr-tests--local-var1)) + (should (local-variable-if-set-p 'subr-tests--local-var2)) + (should (eq subr-tests--local-var2 'hello)) + (should (local-variable-if-set-p 'subr-tests--local-var3)) + (should (get 'subr-tests--local-var3 'variable-documentation))) + (ert-deftest subr-test-apply-partially () (should (functionp (apply-partially #'identity))) (should (functionp (apply-partially #'list 1 2 3)))