From 3789b7b843ec417ae3be5d0f24409559a46bcc93 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Fri, 16 Jun 2017 22:55:52 +0200 Subject: [PATCH 1/2] Have `cl-letf' restore buffer-local status (Bug#26624) * lisp/emacs-lisp/gv.el (buffer-local-value): Record and restore whether the variable was buffer-local; used for `cl-letf'. * test/lisp/emacs-lisp/gv-tests.el (gv-tests--bug26624): Add unit test. --- lisp/emacs-lisp/gv.el | 15 +++++++++--- test/lisp/emacs-lisp/gv-tests.el | 51 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 test/lisp/emacs-lisp/gv-tests.el diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el index c5c12a6414..a614d675af 100644 --- a/lisp/emacs-lisp/gv.el +++ b/lisp/emacs-lisp/gv.el @@ -372,9 +372,18 @@ setf (gv-define-setter window-point (v &optional w) `(set-window-point ,w ,v)) (gv-define-setter window-start (v &optional w) `(set-window-start ,w ,v)) -(gv-define-setter buffer-local-value (val var buf) - (macroexp-let2 nil v val - `(with-current-buffer ,buf (set (make-local-variable ,var) ,v)))) +(gv-define-expander buffer-local-value + (lambda (do var buf) + (macroexp-let2* nil ((var var) (buf buf)) + (funcall do + `(if (local-variable-p ,var ,buf) + (buffer-local-value ,var ,buf) + #1='#:unbound) + (lambda (val) + `(with-current-buffer ,buf + (if (eq ,val #1#) + (kill-local-variable ,var) + (set (make-local-variable ,var) ,val)))))))) (gv-define-expander alist-get (lambda (do key alist &optional default remove) diff --git a/test/lisp/emacs-lisp/gv-tests.el b/test/lisp/emacs-lisp/gv-tests.el new file mode 100644 index 0000000000..b49c12ddf2 --- /dev/null +++ b/test/lisp/emacs-lisp/gv-tests.el @@ -0,0 +1,51 @@ +;;; gv-tests.el --- unit tests for gv.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Unit tests for lisp/emacs-lisp/gv.el. + +;;; Code: + +(defvar gv-tests--var 'default "Test variable.") + +(ert-deftest gv-tests--bug26624 () + "Checks that Bug#26624 is fixed." + (with-temp-buffer + (let ((var-calls 0) (buf-calls 0)) + (should (equal (buffer-local-value 'gv-tests--var (current-buffer)) + 'default)) + (should-not (local-variable-p 'gv-tests--var)) + (should-not (local-variable-if-set-p 'gv-tests--var)) + (cl-letf (((buffer-local-value + (progn (cl-incf var-calls) 'gv-tests--var) + (progn (cl-incf buf-calls) (current-buffer))) + 'unbound)) + (should (equal (buffer-local-value 'gv-tests--var (current-buffer)) + 'unbound)) + (should (local-variable-p 'gv-tests--var)) + (should (local-variable-if-set-p 'gv-tests--var))) + (should (equal (buffer-local-value 'gv-tests--var (current-buffer)) + 'default)) + (should-not (local-variable-p 'gv-tests--var)) + (should-not (local-variable-if-set-p 'gv-tests--var)) + (should (equal var-calls 1)) + (should (equal buf-calls 1))))) + +;;; gv-tests.el ends here -- 2.13.1