From b7dc7517bdef46a080b3ca9b7ac8c2f34065da3d Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" Date: Wed, 18 Nov 2020 12:53:03 +0000 Subject: [PATCH] Fix handling of defcustom :local tag For discussion, see the following emacs-devel thread: https://lists.gnu.org/r/emacs-devel/2020-11/msg00734.html * lisp/custom.el (custom-declare-variable): Delay call to make-variable-buffer-local until after user option has been initialized with a value. Otherwise the user option may be initialized to nil. * test/lisp/custom-tests.el (custom--test-local-option) (custom--test-permanent-option): New :local user options. (custom-test-local-option): New test for defcustom :local keyword. --- lisp/custom.el | 10 +++++++--- test/lisp/custom-tests.el | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/lisp/custom.el b/lisp/custom.el index 885c486c5e..cdfd221216 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -157,7 +157,9 @@ custom-declare-variable (if (keywordp doc) (error "Doc string is missing")) (let ((initialize #'custom-initialize-reset) - (requests nil)) + (requests nil) + ;; Whether automatically buffer-local. + buffer-local) (unless (memq :group args) (custom-add-to-group (custom-current-group) symbol 'custom-variable)) (while args @@ -183,7 +185,7 @@ custom-declare-variable (put symbol 'safe-local-variable value)) ((eq keyword :local) (when (memq value '(t permanent)) - (make-variable-buffer-local symbol)) + (setq buffer-local t)) (when (eq value 'permanent) (put symbol 'permanent-local t))) ((eq keyword :type) @@ -205,7 +207,9 @@ custom-declare-variable (put symbol 'custom-requests requests) ;; Do the actual initialization. (unless custom-dont-initialize - (funcall initialize symbol default))) + (funcall initialize symbol default)) + (when buffer-local + (make-variable-buffer-local symbol))) (run-hooks 'custom-define-hook) symbol) diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el index 766e484498..e71b7913f0 100644 --- a/test/lisp/custom-tests.el +++ b/test/lisp/custom-tests.el @@ -151,4 +151,42 @@ custom-test-show-comment-preserves-changes (widget-apply field :value-to-internal origvalue) "bar")))))) +(defcustom custom--test-local-option 'initial + "Buffer-local user option for testing." + :group 'emacs + :type '(choice (const initial) (const changed)) + :local t) + +(defcustom custom--test-permanent-option 'initial + "Permanently local user option for testing." + :group 'emacs + :type '(choice (const initial) (const changed)) + :local 'permanent) + +(ert-deftest custom-test-local-option () + "Test :local user options." + ;; Initial default values. + (should (eq custom--test-local-option 'initial)) + (should (eq custom--test-permanent-option 'initial)) + (should (eq (default-value 'custom--test-local-option) 'initial)) + (should (eq (default-value 'custom--test-permanent-option) 'initial)) + (let ((obuf (current-buffer))) + (with-temp-buffer + ;; Changed buffer-local values. + (setq custom--test-local-option 'changed) + (setq custom--test-permanent-option 'changed) + (should (eq custom--test-local-option 'changed)) + (should (eq custom--test-permanent-option 'changed)) + (should (eq (default-value 'custom--test-local-option) 'initial)) + (should (eq (default-value 'custom--test-permanent-option) 'initial)) + (with-current-buffer obuf + (should (eq custom--test-local-option 'initial)) + (should (eq custom--test-permanent-option 'initial))) + ;; Permanent variable remains unchanged. + (kill-all-local-variables) + (should (eq custom--test-local-option 'initial)) + (should (eq custom--test-permanent-option 'changed)) + (should (eq (default-value 'custom--test-local-option) 'initial)) + (should (eq (default-value 'custom--test-permanent-option) 'initial))))) + ;;; custom-tests.el ends here -- 2.29.2