Subject: bug#45329: 26.3; Provide equivalent of :filter for non-menu key bindings

From: Drew Adams <[email-masked]>
Date: Sat, 19 Dec 2020 17:20:01 -0800 (PST)

See Emacs bug #24237.  Using an extended menu item key binding you can
create a key binding that is "dynamic", or "dynamically conditional",
even for a keyboard key. 

By "dynamic" is meant that whether or not the key is effectively bound
(non-nil) and, if so, which command it is effectively bound to, can be
conditional according to the context current at the time the key is
used.

For "whether", instead of binding a key to a command whose definition
does something conditional ...

(defvar toto nil "...")

(defun foo ()
  (interactive)
  (and toto  (message "FOO")))

(global-set-key "\C-f" 'foo)

... you can move the condition to the key binding itself, that is, bind
the key conditionally:

(defun toto-filter (cmd) (and toto  cmd))

(global-set-key "\C-b" '(menu-item "" foo :filter toto-filter))
(global-set-key "\C-f" '(menu-item "" bar :filter toto-filter))

(defun foo () (interactive) (message "FOO"))
(defun bar () (interactive) (message "BAR"))

When `toto' is nil, `C-b' and `C-f' are unbound.

In this case, we made use of the same filter for two different key
bindings.  Both commands, `foo' and `bar', have bindings that are, in
effect, conditional on the value of variable `toto'.

Instead of a filter returning nil sometimes (which effectively means the
key isn't bound then), it can return different commands.

Several examples and some explanation are given in bug #24237.

The feature request is to provide this same capability without using an
extended menu item, because the KEY arg to `global-set-key' or
`define-key' need not have anything to do with a menu.  Let KEY be
associated with a filter.

How (e.g. syntax) to do that is up for grabs.  I don't have a strong
opinion about that.  Apparently Emacs doesn't want to just document the
above use case as is, i.e., advertise that you can use an extended menu
item for this.  Fair enough.

One possibility for doing this is to just allow the filter function as
an optional arg (similarly for `define-key'):

 (global-set-key KEY COMMAND &optional FILTER-FN) 

On the other hand, the REAL-BINDING part of the extended menu item can
also be somewhat useful: "it is only used in cases such as `where-is'",
as the static or nominal binding.  If we want to allow for that then
this could be the signature:

 (global-set-key KEY COMMAND &optional FILTER-FN NOMINAL-COMMAND) 

When this feature is documented in the Elisp manual it would make sense
to point out that FILTER-FN here is exactly as in an extended menu item.
(And if we include NOMINAL-COMMAND, mention that that corresponds to
the REAL-BINDING of an extended menu item.)

In GNU Emacs 26.3 (build 1, x86_64-w64-mingw32)
 of 2019-08-29
Repository revision: 96dd0196c28bc36779584e47fffcca433c9309cd
Windowing system distributor `Microsoft Corp.', version 10.0.18362
Configured using:
 `configure --without-dbus --host=x86_64-w64-mingw32
 --without-compress-install 'CFLAGS=-O2 -static -g3''