unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* 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).