* Buffer-local key-translation-map
@ 2023-12-14 23:30 Spencer Baugh
2023-12-23 8:50 ` Eli Zaretskii
0 siblings, 1 reply; 5+ messages in thread
From: Spencer Baugh @ 2023-12-14 23:30 UTC (permalink / raw)
To: emacs-devel
Is it OK to have key-translation-map be a buffer-local variable?
If there's a key translation in function-key-map which I wish to change
on a per-buffer basis, is it correct to delete that key translation from
function-key-map and add it back in a buffer-local key-translation-map?
More context:
In graphical frames, Emacs maps <escape> to ESC with function-key-map.
evil-mode users would usually prefer for this to not happen; they never
want to hit <escape> and have it be potentially interpreted as the start
of a key sequence. (For example, if an evil-mode user types C-x
<escape>, they would prefer that the key sequence be aborted, not that
it be interpreted as potentially the start of C-x M-: or other such
bindings)
The most obvious way to do this is simply:
(define-key function-key-map (kbd "<escape>") nil)
However, this affects all buffers identically. A user might want to
have some buffers in evil-mode (really evil-local-mode) and some not;
or, more likely, a user might want to make use of "Emacs state", which
allows disabling all evil-mode keybindings in a per-buffer way. For
such buffers, <escape> should still map to ESC.
So then, the next obvious thought is to run:
(setq-local function-key-map
(define-keymap :parent function-key-map
"<escape>" nil))
in any buffer which wants to use evil-mode keybindings, and therefore
disable mapping <escape> to ESC.
However, function-key-map and local-function-key-map cannot be
buffer-local variables.
But luckily key-translation-map can! So then we could just move the
translation of <escape> to ESC to be in key-translation-map, where it
can be overridden buffer-locally. Which looks like:
(define-key function-key-map (kbd "<escape>") nil)
(define-key key-translation-map (kbd "<escape>") (kbd "ESC"))
;; in evil-mode buffers
(setq-local key-translation-map
(define-keymap :parent key-translation-map
"<escape>" nil))
This seems to work fine. But is this supported? Is there a better way
to do this?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Buffer-local key-translation-map
2023-12-14 23:30 Buffer-local key-translation-map Spencer Baugh
@ 2023-12-23 8:50 ` Eli Zaretskii
2023-12-23 15:39 ` Stefan Monnier
0 siblings, 1 reply; 5+ messages in thread
From: Eli Zaretskii @ 2023-12-23 8:50 UTC (permalink / raw)
To: Spencer Baugh, Stefan Monnier; +Cc: emacs-devel
Stefan, any comments?
> From: Spencer Baugh <sbaugh@janestreet.com>
> Date: Thu, 14 Dec 2023 18:30:28 -0500
>
>
> Is it OK to have key-translation-map be a buffer-local variable?
>
> If there's a key translation in function-key-map which I wish to change
> on a per-buffer basis, is it correct to delete that key translation from
> function-key-map and add it back in a buffer-local key-translation-map?
>
> More context:
>
> In graphical frames, Emacs maps <escape> to ESC with function-key-map.
> evil-mode users would usually prefer for this to not happen; they never
> want to hit <escape> and have it be potentially interpreted as the start
> of a key sequence. (For example, if an evil-mode user types C-x
> <escape>, they would prefer that the key sequence be aborted, not that
> it be interpreted as potentially the start of C-x M-: or other such
> bindings)
>
> The most obvious way to do this is simply:
>
> (define-key function-key-map (kbd "<escape>") nil)
>
> However, this affects all buffers identically. A user might want to
> have some buffers in evil-mode (really evil-local-mode) and some not;
> or, more likely, a user might want to make use of "Emacs state", which
> allows disabling all evil-mode keybindings in a per-buffer way. For
> such buffers, <escape> should still map to ESC.
>
> So then, the next obvious thought is to run:
>
> (setq-local function-key-map
> (define-keymap :parent function-key-map
> "<escape>" nil))
>
> in any buffer which wants to use evil-mode keybindings, and therefore
> disable mapping <escape> to ESC.
>
> However, function-key-map and local-function-key-map cannot be
> buffer-local variables.
>
> But luckily key-translation-map can! So then we could just move the
> translation of <escape> to ESC to be in key-translation-map, where it
> can be overridden buffer-locally. Which looks like:
>
> (define-key function-key-map (kbd "<escape>") nil)
> (define-key key-translation-map (kbd "<escape>") (kbd "ESC"))
> ;; in evil-mode buffers
> (setq-local key-translation-map
> (define-keymap :parent key-translation-map
> "<escape>" nil))
>
> This seems to work fine. But is this supported? Is there a better way
> to do this?
>
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Buffer-local key-translation-map
2023-12-23 8:50 ` Eli Zaretskii
@ 2023-12-23 15:39 ` Stefan Monnier
2024-01-17 19:52 ` Spencer Baugh
0 siblings, 1 reply; 5+ messages in thread
From: Stefan Monnier @ 2023-12-23 15:39 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Spencer Baugh, emacs-devel
> Is it OK to have key-translation-map be a buffer-local variable?
The purpose of `key-translation-map` is rather unclear nowadays.
It's not used very much. So in principle it's a risk, but in practice
it's unlikely you'll get bitten.
> If there's a key translation in function-key-map which I wish to change
> on a per-buffer basis, is it correct to delete that key translation from
> function-key-map and add it back in a buffer-local key-translation-map?
In general no, since the two work differently.
> In graphical frames, Emacs maps <escape> to ESC with function-key-map.
> evil-mode users would usually prefer for this to not happen;
If `evil-mode` defines bindings that start with `escape`, then the
`function-key-map` mapping will (or at least should) have no effect.
> they never want to hit <escape> and have it be potentially interpreted
> as the start of a key sequence. (For example, if an evil-mode user
> types C-x <escape>, they would prefer that the key sequence be
> aborted, not that it be interpreted as potentially the start of C-x
> M-: or other such bindings)
Hmm...
> The most obvious way to do this is simply:
> (define-key function-key-map (kbd "<escape>") nil)
The less obvious way could be something like:
(define-key function-key-map (kbd "<escape>")
`(menu-item "" ,(kbd "ESC")
:filter ,(lambda (cmd) (unless evil-mode cmd))))
> So then, the next obvious thought is to run:
>
> (setq-local function-key-map
> (define-keymap :parent function-key-map
> "<escape>" nil))
>
> in any buffer which wants to use evil-mode keybindings, and therefore
> disable mapping <escape> to ESC.
>
> However, function-key-map and local-function-key-map cannot be
> buffer-local variables.
I can't see any technical reason why `function-key-map` can't be
buffer-local (tho it comes with the same caveats as
`key-translation-map`, and even more so because it's used more
commonly).
Stefan
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Buffer-local key-translation-map
2023-12-23 15:39 ` Stefan Monnier
@ 2024-01-17 19:52 ` Spencer Baugh
2024-01-17 22:54 ` Stefan Monnier
0 siblings, 1 reply; 5+ messages in thread
From: Spencer Baugh @ 2024-01-17 19:52 UTC (permalink / raw)
To: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> In graphical frames, Emacs maps <escape> to ESC with function-key-map.
>> evil-mode users would usually prefer for this to not happen;
>
> If `evil-mode` defines bindings that start with `escape`, then the
> `function-key-map` mapping will (or at least should) have no effect.
>
>> they never want to hit <escape> and have it be potentially interpreted
>> as the start of a key sequence. (For example, if an evil-mode user
>> types C-x <escape>, they would prefer that the key sequence be
>> aborted, not that it be interpreted as potentially the start of C-x
>> M-: or other such bindings)
>
> Hmm...
>
>> The most obvious way to do this is simply:
>> (define-key function-key-map (kbd "<escape>") nil)
>
> The less obvious way could be something like:
>
> (define-key function-key-map (kbd "<escape>")
> `(menu-item "" ,(kbd "ESC")
> :filter ,(lambda (cmd) (unless evil-mode cmd))))
That works great, indeed.
The filter I'm using now for evil-mode is:
(define-key function-key-map (kbd "<escape>")
`(menu-item "" ,(kbd "ESC") :filter
,(lambda (cmd) (when (or (null evil-local-mode) (eq evil-state 'emacs)) cmd))))
>> So then, the next obvious thought is to run:
>>
>> (setq-local function-key-map
>> (define-keymap :parent function-key-map
>> "<escape>" nil))
>>
>> in any buffer which wants to use evil-mode keybindings, and therefore
>> disable mapping <escape> to ESC.
>>
>> However, function-key-map and local-function-key-map cannot be
>> buffer-local variables.
>
> I can't see any technical reason why `function-key-map` can't be
> buffer-local (tho it comes with the same caveats as
> `key-translation-map`, and even more so because it's used more
> commonly).
function-key-map can be buffer-local, yes. But nothing actually uses
that variable. Its only use is to set the parent of
local-function-key-map at startup. And local-function-key-map can't be
buffer-local because it's a SYMBOL_FORWARDED to the current kboard
object.
This could be changed of course, perhaps by making function-key-map not
actually the parent of local-function-key-map, and teaching key
translation that if lookup in local-function-key-map fails, it should do
lookup in function-key-map.
Or maybe the parent of local-function-key-map could be changed to a
symbol instead of a direct reference?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Buffer-local key-translation-map
2024-01-17 19:52 ` Spencer Baugh
@ 2024-01-17 22:54 ` Stefan Monnier
0 siblings, 0 replies; 5+ messages in thread
From: Stefan Monnier @ 2024-01-17 22:54 UTC (permalink / raw)
To: Spencer Baugh; +Cc: emacs-devel
> function-key-map can be buffer-local, yes. But nothing actually uses
> that variable. Its only use is to set the parent of
> local-function-key-map at startup.
Oh, right.
> This could be changed of course, perhaps by making function-key-map not
> actually the parent of local-function-key-map, and teaching key
> translation that if lookup in local-function-key-map fails, it should do
> lookup in function-key-map.
Maybe, but it can be tricky. The more reliable way would be to first
create a composed keymap using both `local-function-key-map` and
`function-key-map`, and then look *this* up.
> Or maybe the parent of local-function-key-map could be changed to a
> symbol instead of a direct reference?
But a symbol standard for the keymap in the `symbol-function` slot, not
in the `symbol-value` slot, it still can't be buffer-local.
We could add a similar indirection via `symbol-value`, of course.
Not sure it's worth the trouble (I've toyed with the idea a few times,
but each time, it seemed to cover only some of the needs, and the
remaining problems were still significant, so it wasn't all that
useful, IIRC).
Stefan
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-01-17 22:54 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-14 23:30 Buffer-local key-translation-map Spencer Baugh
2023-12-23 8:50 ` Eli Zaretskii
2023-12-23 15:39 ` Stefan Monnier
2024-01-17 19:52 ` Spencer Baugh
2024-01-17 22:54 ` Stefan Monnier
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).