Subject: bug#70938: 30.0.50; Edebug appropriates overriding-terminal-local-map

From: Michael Heerdegen <[email-masked]>
Date: Wed, 15 May 2024 17:24:24 +0200

Michael Heerdegen via "Bug reports for GNU Emacs, the Swiss army knife
of text editors" <[email-masked]> writes:

> #+begin_src emacs-lisp
> (progn
>   (set-transient-map (let ((m (make-sparse-keymap)))
>                        (define-key m [?^]
>                          (lambda () (interactive) (message "Hmm...")))
>                        m))
>   (let ((overriding-terminal-local-map nil))
>     (recursive-edit)))
> #+end_src

A possible approach that seems to fix the reported bug:

From 7f5db96e7d40fc3f71c82d7a004a21bc7515c81d Mon Sep 17 00:00:00 2001
From: Michael Heerdegen <[email-masked]>
Date: Wed, 15 May 2024 17:13:35 +0200
Subject: [PATCH] WIP: Fix Bug#70868 Edebug appropriates
 overriding-terminal-local-map

* lisp/subr.el (set-transient-map): Try to make the cleanup code more
reliable in case `overriding-terminal-local-map' gets shadowed: When the
added map is not present there, try to detect whether shadowing is
currently happening.  Delay the cleanup in this case.
---
 lisp/subr.el | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/lisp/subr.el b/lisp/subr.el
index 80c7ffe32bc..2f8809d706e 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -6573,12 +6573,25 @@ set-transient-map
          (clearfun (make-symbol "clear-transient-map"))
          (exitfun
           (lambda ()
-            (internal-pop-keymap map 'overriding-terminal-local-map)
-            (remove-hook 'pre-command-hook clearfun)
-            ;; Clear the prompt after exiting.
-            (when message (message ""))
-            (when set-transient-map-timer (cancel-timer set-transient-map-timer))
-            (when on-exit (funcall on-exit)))))
+            (cond
+             ((memq map overriding-terminal-local-map)
+              (internal-pop-keymap map 'overriding-terminal-local-map)
+              (remove-hook 'pre-command-hook clearfun)
+              ;; Clear the prompt after exiting.
+              (when message (message ""))
+              (when set-transient-map-timer (cancel-timer set-transient-map-timer))
+              (when on-exit (funcall on-exit)))
+             (;; FIXME: We rather want something like
+              ;; (variable-references-default-toplevel-value-p
+              ;;  'overriding-terminal-local-map)
+              (eq overriding-terminal-local-map
+                  (default-toplevel-value 'overriding-terminal-local-map))
+              ;; We are probably done:
+              (remove-hook 'pre-command-hook clearfun))
+             ;; If none of these conditions was fulfilled,
+             ;; overriding-terminal-local-map is currently shadowed - keep
+             ;; clearfun in 'pre-command-hook
+             ))))
     ;; Don't use letrec, because equal (in add/remove-hook) could get trapped
     ;; in a cycle. (bug#46326)
     (fset clearfun
--
2.39.2

Comments, corrections, enhancements and better ideas all very welcome.

Michael.