Subject: bug#5293: 23.1; unload-feature on buffer-local hooks

From: Štěpán Němec <[email-masked]>
Date: Mon, 06 Apr 2020 21:17:34 +0200

On Mon, 06 Apr 2020 14:06:02 -0400
Stefan Monnier wrote:

>> @@ -299,7 +299,11 @@ unload-feature
>>                              ;; Known abnormal hooks etc.
>>  			    (memq x unload-feature-special-hooks)))
>>  	       (dolist (func removables)
>> -	         (remove-hook x func)))))
>> +	         (remove-hook x func)
>> +                 (save-current-buffer
>> +                   (dolist (buffer (buffer-list))
>> +                     (set-buffer buffer)
>> +                     (remove-hook x func t)))))))
>>            ;; Remove any feature-symbols from auto-mode-alist as well.
>>            (dolist (func removables)
>>              (setq auto-mode-alist
>
> Maybe instead of `(dolist (buffer (buffer-list))` within that big
> `mapatoms` within `(dolist (func removables)` (which is O(B*F*V) where
> B is the number of buffers, F is the number of functions and V is the
> number of hook vars), we should instead do it as:
>
>     (dolist (buffer (buffer-list))
>       (dolist (varvar (buffer-local-variables buffer))
                         ^^^^^^^^^^^^^^^^^^^^^^

Ha! Didn't know/think about that one, and indeed it makes a world of
difference. Thanks!

So I guess my defeatism will not prevail after all. Updated [2/3] attached.

-- 
Štěpán

>From fd9b67b10fcc9596fc1eeae50bb351ef235eea68 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20N=C4=9Bmec?= <[email-masked]>
Date: Mon, 6 Apr 2020 13:30:11 +0200
Subject: [PATCH 2/3 v2] unload-feature: Handle local hooks

Buffer-local hooks were introduced in

1994-09-30T20:47:13+00:[email-masked]
0e4d378b32 (add-hook): Initialize default value and local value.

but `unload-feature' has not been updated to handle them.

* lisp/loadhist.el (unload-feature): Handle local hooks.
---
 etc/NEWS         | 3 +++
 lisp/loadhist.el | 9 +++++++++
 2 files changed, 12 insertions(+)

diff --git a/etc/NEWS b/etc/NEWS
index 765a923bf7..fa90edc4d1 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -297,6 +297,9 @@ optional argument specifying whether to follow symbolic links.
 ** 'parse-time-string' can now parse ISO 8601 format strings,
 such as "2020-01-15T16:12:21-08:00".
 
+---
+** 'unload-feature' now also tries to undo additions to buffer-local hooks.
+
 
 * Changes in Emacs 28.1 on Non-Free Operating Systems
 
diff --git a/lisp/loadhist.el b/lisp/loadhist.el
index 60da00cceb..81576679c3 100644
--- a/lisp/loadhist.el
+++ b/lisp/loadhist.el
@@ -300,6 +300,15 @@ unload-feature
 			    (memq x unload-feature-special-hooks)))
 	       (dolist (func removables)
 	         (remove-hook x func)))))
+          (save-current-buffer
+            (dolist (buffer (buffer-list))
+              (pcase-dolist (`(,sym . ,val) (buffer-local-variables buffer))
+                (when (or (and (consp val)
+                               (string-match "-hooks?\\'" (symbol-name sym)))
+                          (memq sym unload-feature-special-hooks))
+                  (set-buffer buffer)
+                  (dolist (func removables)
+                    (remove-hook sym func t))))))
           ;; Remove any feature-symbols from auto-mode-alist as well.
           (dolist (func removables)
             (setq auto-mode-alist
-- 
2.26.0