Subject: bug#34080: 27.0.50, 26.1; undocumented key bindings for *vc-diff*

From: Juri Linkov <[email-masked]>
Date: Thu, 15 May 2025 19:54:25 +0300

>>> +;; List key bindings for describe-mode
>>> +(put 'diff-hunk-next :advertised-binding [tab])
>>> +(put 'diff-hunk-prev :advertised-binding [(shift tab)])
>>> +
>>
>> I tried this patch, but `M-x describe-mode' in a *vc-diff* buffer did
>> not seem to care that much -- it listed diff-hunk-prev on M-p and ESC
>> <backtab> and -next on C-M-i/M-n only, with or without this patch.
>>
>> Is :advertised-binding not working here, or is ... er ... something else
>> wrong?  The actual bindings are:
>>
>>     ("\t" . diff-hunk-next)
>>     ([backtab] . diff-hunk-prev)
>
> Searching the code base, :advertised-binding is meant to affect
> where-is-internal, and only that function, I think.
> But it does seem to be broken:
>
>     (progn (put 'diff-hunk-next :advertised-binding "n") ; or '("n")
>            (with-current-buffer "*vc-diff*"
>              (mapcar #'key-description
>                      (where-is-internal 'diff-hunk-next))))
>
>     => ("TAB" "n" "C-M-i" "M-n" "<menu-bar> <diff> <Next Hunk>")
>
> i.e. there is no prioritisation for the "n" binding.
> Indeed, TAB comes first.
>
> Then it seems like a separate issue why the "TAB" binding is not
> appearing in 'M-x describe-mode'.  So there are two problems here.

There is no 'n' binding in 'diff-mode-map'.  'n' inherited
from 'diff-mode-shared-map' becomes 'M-n' (via the ESC prefix).
And its advertised-binding works correctly:

  (put 'diff-hunk-next :advertised-binding "\M-n")
  (substitute-command-keys "Type `\\<diff-mode-map>\\[diff-hunk-next]'.")
  => #("Type ‘M-n’." 6 9 (font-lock-face help-key-binding face help-key-binding))