Subject: bug#72229: (setq overriding-terminal-local-map nil) in isearch-done

From: Juri Linkov <[email-masked]>
Date: Tue, 23 Jul 2024 09:32:21 +0300

> Michael Heerdegen via "Bug reports for GNU Emacs, the Swiss army knife
> of text editors" <[email-masked]> writes:
>
>> exiting isearch always explicitly sets `overriding-terminal-local-map'
>> to nil.  This will interfere with any other users of
>> `overriding-terminal-local-map', including any active transient maps.
>>
>> Wouldn't a less radical means suffice?  If isearch really must _set_,
>> i.e., completely override that variable, why not restore the original
>> value?
>
> Juri, what's your opinion on this?

Indeed, you are right, `isearch-done' should restore the original value.
The existing variable `isearch--saved-overriding-local-map' can't be used,
so a similar variable should be added like in this patch:

diff --git a/lisp/isearch.el b/lisp/isearch.el
index dc9edf267f2..697dcdbb3d8 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -972,6 +972,7 @@ isearch-hidden
 ;; The value of input-method-function when isearch is invoked.
 (defvar isearch-input-method-function nil)
 
+(defvar isearch--saved-local-map nil)
 (defvar isearch--saved-overriding-local-map nil)
 
 ;; Minor-mode-alist changes - kind of redundant with the
@@ -1321,6 +1322,7 @@ isearch-mode
   (setq	isearch-mode " Isearch")  ;; forward? regexp?
   (force-mode-line-update)
 
+  (setq isearch--saved-local-map overriding-terminal-local-map)
   (setq overriding-terminal-local-map isearch-mode-map)
   (run-hooks 'isearch-mode-hook)
   ;; Remember the initial map possibly modified
@@ -1439,10 +1444,12 @@ isearch-update
 
 (defun isearch-done (&optional nopush edit)
   "Exit Isearch mode.
+Called by all commands that terminate isearch-mode.
 For successful search, pass no args.
 For a failing search, NOPUSH is t.
 For going to the minibuffer to edit the search string,
-NOPUSH is t and EDIT is t."
+NOPUSH is t and EDIT is t.
+If NOPUSH is non-nil, we don't push the string on the search ring."
 
   (when isearch-resume-in-command-history
     (add-to-history 'command-history
@@ -1460,9 +1467,7 @@ isearch-done
       (setq isearch--current-buffer nil)
       (setq cursor-sensor-inhibit (delq 'isearch cursor-sensor-inhibit))))
 
-  ;; Called by all commands that terminate isearch-mode.
-  ;; If NOPUSH is non-nil, we don't push the string on the search ring.
-  (setq overriding-terminal-local-map nil)
+  (setq overriding-terminal-local-map isearch--saved-local-map)
   ;; (setq pre-command-hook isearch-old-pre-command-hook) ; for lemacs
   (setq minibuffer-message-timeout isearch-original-minibuffer-message-timeout)
   (isearch-dehighlight)
@@ -2676,7 +2681,7 @@ isearch-mouse-2
 is bound to outside of Isearch."
   (interactive "e")
   (let ((w (posn-window (event-start click)))
-        (binding (let ((overriding-terminal-local-map nil)
+        (binding (let ((overriding-terminal-local-map isearch--saved-local-map)
                        ;; Key search depends on mode (bug#47755)
                        (isearch-mode nil))
                    (key-binding (this-command-keys-vector) t))))

> A little more forward looking:
>
> In such situations I often get this thought: if the variable was
> replaced with a function accepting zero arguments, then we could use
> `add-function' and `remove-function' to control the return value of the
> "binding".
>
> I know the advice mechanism has the reputation of only being suitable
> for end user customization/hacks, but in cases like this one we could
> make the modification of the value more explicit and controllable.
> Dealing with interferences would be forced to be taken into account more
> directly , and we would get some useful mechanisms like priorities or
> looking at the context out of the box.
>
> We could also invent some even better mechanism, maybe.  But in this
> case binding variables doesn't look like an optimal approach at least.

This mechanism looks like a variable watcher enabled by `add-variable-watcher'.
So you could add a watcher that conditionally controls variable modifications.