Subject: bug#9923: 24.0.91; `where-is' does not find recentf menu items (cmds, not files)

From: Juri Linkov <[email-masked]>
Date: Sun, 05 Dec 2021 20:04:28 +0200

> but now noticed that after typing 'C-h m' it fails with:
>
> Debugger entered--Lisp error: (args-out-of-range 1786)
>   mouse-posn-property((#<window 178 on *scratch*> 1786 (0 . 0) 0) context-menu-function)
>   context-menu-map()
>   (lambda (_) (context-menu-map))(ignore)
>   where-is-internal(ignore nil t)
>   #f(compiled-function (sym) #<bytecode -0x1145d1e4eb4c2a6>)(ignore)
>   help-fns--list-local-commands()
>   describe-mode()
>   funcall-interactively(describe-mode)
>   command-execute(describe-mode)

This bug still exists in emacs-28:

emacs-28 -Q
1. context-menu-mode
2. C-h C-n M->
3. C-h m

Debugger entered--Lisp error: (args-out-of-range #<buffer *Help*> 1 37446)
  parse-partial-sexp(1 37446)
  syntax-ppss(37446)
  context-menu-region((keymap #("Context Menu" 0 12 (hide t)) (separator-undo "--") (separator-region "--")) 109)
  #f(compiled-function (fun) #<bytecode -0x1ee96643fef4b180>)(context-menu-region)
  run-hook-wrapped(#f(compiled-function (fun) #<bytecode -0x1ee96643fef4b180>) context-menu-region)
  context-menu-map()
  (lambda (_) (context-menu-map))(ignore)
  where-is-internal(ignore nil t)
  #f(compiled-function (sym) #<bytecode -0x1403be359693d56a>)(ignore)
  help-fns--list-local-commands()
  describe-mode()
  funcall-interactively(describe-mode)
  call-interactively(describe-mode nil nil)
  command-execute(describe-mode)

I don't know if this is the right fix, but it avoids
the error by explicitly switching to window-buffer
when context-menu is called by describe-mode:

diff --git a/lisp/mouse.el b/lisp/mouse.el
index 30fe5e99ff..851da77ce0 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -488,14 +488,15 @@ context-menu-region
       `(menu-item "All"
                   ,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'buffer))
                   :help "Mark the whole buffer for a subsequent cut/copy"))
-    (when (let* ((pos (posn-point (event-end click)))
-                 (char (when pos (char-after pos))))
-            (or (and char (eq (char-syntax char) ?\"))
-                (nth 3 (save-excursion (syntax-ppss pos)))))
-      (define-key-after submenu [mark-string]
-        `(menu-item "String"
-                    ,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'string))
-                    :help "Mark the string at click for a subsequent cut/copy")))
+    (with-current-buffer (window-buffer)
+      (when (let* ((pos (posn-point (event-end click)))
+                   (char (when pos (char-after pos))))
+              (or (and char (eq (char-syntax char) ?\"))
+                  (nth 3 (save-excursion (syntax-ppss pos)))))
+        (define-key-after submenu [mark-string]
+          `(menu-item "String"
+                      ,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'string))
+                      :help "Mark the string at click for a subsequent cut/copy"))))
     (define-key-after submenu [mark-line]
       `(menu-item "Line"
                   ,(lambda (e) (interactive "e") (mark-thing-at-mouse e 'line))
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 30b6edf0d9..bf1f619858 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -93,7 +93,9 @@ prog-context-menu
     'mark-whole-buffer)
 
   ;; Include text-mode select menu only in strings and comments.
-  (when (nth 8 (save-excursion (syntax-ppss (posn-point (event-end click)))))
+  (when (nth 8 (save-excursion
+                 (with-current-buffer (window-buffer)
+                   (syntax-ppss (posn-point (event-end click))))))
     (text-mode-context-menu menu click))
 
   menu)

An alternative is the patch that I proposed earlier:

diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 2c7956d968..85f305617d 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1898,6 +1898,8 @@ help-fns--list-local-commands
     (mapatoms
      (lambda (sym)
        (when (and (commandp sym)
+                  ;; Ignore 'ignore'.
+                  (not (eq sym 'ignore))
                   ;; Ignore aliases.
                   (not (symbolp (symbol-function sym)))
                   ;; Ignore everything bound.