susam / devil

Emacs minor mode that intercepts and translates keystrokes to provide a modifier-free non-modal editing experience
https://susam.github.io/devil/
Other
169 stars 10 forks source link

Can't use C-M-S-v and other translations involving shift. #4

Closed jshholland closed 1 year ago

jshholland commented 1 year ago

I want to use C-M-S-v to invoke scroll-other-window-down but devil calls the binding associated with C-M-v (scroll-other-window) instead:

Devil: Devil waking up
Devil: Trying to execute key: , m
Devil: Ignoring incomplete key: , m => C-M-
Devil: Trying to execute key: , m V
Devil: Found current-prefix-arg: nil; this-command: scroll-other-window; last-command: eval-expression; last-repeatable-command: eval-expression
Devil: Executing key: , m V => C-M-V => scroll-other-window
funcall-interactively: End of buffer
Devil: Mode is t in  *Minibuf-1*
Devil: Mode is t in  *Minibuf-0*
Devil: Mode is t in  *Minibuf-1*
Devil: Devil waking up
Devil: Trying to execute key: , m
Devil: Ignoring incomplete key: , m => C-M-
Devil: Trying to execute key: , m v
Devil: Found current-prefix-arg: nil; this-command: scroll-other-window; last-command: ido-exit-minibuffer; last-repeatable-command: ido-exit-minibuffer
Devil: Executing key: , m v => C-M-v => scroll-other-window
funcall-interactively: End of buffer

Similarly the smartparens mappings for C-S-a etc are inaccessible.

I suspect there is a way to work around this with suitable customisation of devil's configuration variables, but I'd expect this to work out of the box.

susam commented 1 year ago

@jshholland The Devil key sequence , m v translates to C-M-v and this is expected according to the default translation rules (see C-h v devil-translations RET). According to the default translation rules, we need to type , m S-v if we want C-M-S-v.

There is currently no default translation rule that maps a Devil input to the S- modifier key. I find that S- keys are located at convenient positions on the keyboard and with proper touch-typing, I do not find typing the S- along with another key to be troublesome. However, one could add their own translation rule to translate a non-modifier key to S- too.

As far as the key sequences C-M-v and C-M-s-v are concerned, if we do configure Devil to translate , m v to C-M-S-v, how would we then type C-M-v in a simple manner? It makes sense to me that , m v translates to C-M-v and a different key sequence like , m S-v (or something else of your choice) translates to C-M-S-v.

jshholland commented 1 year ago

I am typing , m S-v (shown as , m V capital V) in the logs, but it's still being translated to C-M-v. I don't have many super-based key combinations, but if I do try typing , m s-c (s-v is intercepted by my WM) that is translated correctly to C-M-s-c. So there is something going wrong with translating shifted keys, at least in my installation.

I'm using Emacs 28.2 with devil-mode 0.3.0 from MELPA Stable.

susam commented 1 year ago

@jshholland Thanks for the clarification. You are right. I am able to reproduce the behaviour exactly as you have described. My apologies for not noticing earlier that , m V translates to C-M-V and invokes scroll-other-window. I agree that , m V should invoke C-M-S-v and call the scroll-other-window-down command.

It seems like this could be achieved using the following translation rules:

(dotimes (i 26)
  (let ((letter (char-to-string (+ ?a i))))
    (add-to-list 'devil-translations (cons (upcase letter) (concat "S-" letter)))))

The above translation rules do translate , m V to C-M-S-v and invoke scroll-other-window-down successfully. I'll play with this a little more and decide exactly at which layer these translations should go and then have this translation available in Devil by default. Thank you, very much, for creating this issue. This was an oversight. It will be fixed in a future release.

susam commented 1 year ago

With some more work on this, I realized that while the loop provided in my previous comment resolves the issue for key sequences like C-M-S-v, it creates new problems for key sequences like M-V. Emacs handles key-chords with uppercase letters differently when the modifiers exclude C-, i.e., when the C- does not belong to the modifiers pressed, Emacs recognizes that the modified key is an uppercase letter. Only when the modifier includes C-, we see that key sequences like C-M-V and C-M-v are treated similarly.

Therefore, a proper fix has now been developed for this issue and the fix is available since commit c45ab99 (24 May 2023). The core translation logic has been enhanced to look for key chords with C- and uppercase letters, and then translate such key chords to C- and S- + lowercase letter. Strictly speaking, lowercasing the letter was unnecessary because like I mentioned both uppercase and lowercase letters are treated similarly when C- is involved but I did it anyway to maintain consistency with Emacs key sequence formats. Introducing the S- during the translation, of course, is the actual fix.

This fix is also now available since version 0.4.0 of Devil. Thank you, once again, for reporting this issue. This issue report helped to improve this package.