Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Key remaps #6631

Closed
buggymcbugfix opened this issue Jul 19, 2016 · 16 comments
Closed

Key remaps #6631

buggymcbugfix opened this issue Jul 19, 2016 · 16 comments

Comments

@buggymcbugfix
Copy link

OK, so I posted this in #6264, but not sure if anyone will notice it there, so posting again here:

I am a long-time Colemak user.

I would like to change as few keys as possible in spacemacs. I want to try a small cosmetic surgery that would implement the following behaviour:

Colemak Vim

From what I understand, this would require simply swapping j and k.

How should I best do this?

@d12frosted
Copy link
Collaborator

Hey,

I believe that keyboard-layout layer might help you with this. Just take a look how dvorak and bepo are configured. You could do something very similar.

@fmdkdd
Copy link
Contributor

fmdkdd commented Jul 25, 2016

Ah! A fellow Colemakian... ;)

I have a private layer that remaps HJKL to JKHL (so J is actually left and H is top in my configuration, unlike your drawing).

Basically, when I notice a wrong keybinding, I go to the source, copy its definition, and make my permutation into the code. It's a bit of a pain, especially after a large Spacemacs update, but it has been stable for months now.

I did that before keyboard-layout was around, and it 'works for me', so I never bothered to change it. Also, it seems keyboard-layout only permutes key for bindings defined by evil. Many layers use HJKL as movement mnemonics, like org, magit, or web-mode. When you are used to your permutation, you want that to be consistent across layers...

It's not as if we could just remap globally HJKL to JKHL, because sometimes these keys are not used as movement keys (C-j splits lines for instance). Ideally, all bindings that use HJKL as movement keys would be declared as such, and could all be overriden in a few lines of Elisp.

In the meantime, I hope my layer can save you some time.

@buggymcbugfix
Copy link
Author

Nice one, @fmdkdd — have installed your layer and it's working fine so far. Shall be testing it over the next few days and will keep you posted.

@StreakyCobra
Copy link
Contributor

@fmdkdd

Also, it seems keyboard-layout only permutes key for bindings defined by evil

Not true :-)

Many layers use HJKL as movement mnemonics, like org, magit, or web-mode. When you are used to your permutation, you want that to be consistent across layers...

True :-) and it's exactly what keyboard-layout is trying to do.

It's not as if we could just remap globally HJKL to JKHL, because sometimes these keys are not used as movement keys (C-j splits lines for instance). Ideally, all bindings that use HJKL as movement keys would be declared as such, and could all be overriden in a few lines of Elisp.

True :-) and it's exactly what keyboard-layout is trying to do.


keyboard-layout is like a (non-exhaustive) database of all packages using hjkl keys as a movement. This can be seen easily by looking at packages.el. It mostly contains for each packages which keys should be remapped. The org package is in there, as well as magit and a few others. This list of supported packages just ask to be completed. Each of these "configuation" is using a magic-like method "correct-keys" that swaps the given keys with the related one as listed in the corresponding per-layout remapping table

I made the layer as generic as I can given the complexity of the task. Think of border cases, like one layout that changes h with n… Then when n will be bound to the function of h, it will replace evil-search-next, so this has to be fixed for this layout but not for other layouts. It's why each configuration has a :common block that list the remapping that should be done by all keyboard-layouts (the list of all bindings of a package that represent movements) by using the magic correct-keys methods, and keyboard-layout specific blocs like :dvorak or :bepo that fixes the border cases and are only applied for the corresponding keyboard-layout.

Think of the keyboard-layout layer as a database of WHICH keybindings are representing movements for each packages and showing HOW to fix them in a proper way, that also provide some MAGIC functionalities that are guessing/remapping the keys for different keyboard-layouts :-)

BTW you have the basic steps to add a new keyboard layout listed there, it should be fairly easy to try how it works for colemak.

@fmdkdd
Copy link
Contributor

fmdkdd commented Sep 1, 2016

@StreakyCobra Ah! Sorry to spread misinformation. Like I said, I did my layer before keyboard-layout and did not investigate the matter furthermore, as it worked for me.

But now it seems keyboard-layout could simplify my burden (I dread the next Spacemacs update), if, as you say, it tries to do the right thing. I might take a look and maybe contribute a Colemak configuration.

Thanks for the clarification!

@fmdkdd
Copy link
Contributor

fmdkdd commented Sep 22, 2016

@StreakyCobra Hmm, I tried to add a colemak layout where HJKL becomes JKHL, like so:

(colemak . (("j" . "h")
            ("k" . "j")
            ("h" . "k")
            ("l" . "l")
            ;;
            ("h" . "j")
            ("j" . "k")
            ("k" . "h")
            ("l" . "l"))

So, if I understand that correctly, what I'm saying here is "J will be used for the movement H in every layer" (hence, J becomes backward-char), and so on for the first block; then the second block says "non-movement functions formerly bound to H will now be bound to J" and so on for the other letters.

Doing that will indeed remap HJKL to JKHL in normal-state and evilified buffers. However, it fails in magit, even though the configuration should be enabled by default (I didn't set kl-disabled-configurations nor kl-enabled-configurations). In magit, HJKL is back. When exiting the magit buffer (q), there's a warning saying that evil-magit-state does not exist.

Is this a bug?

Also, if I want to pursue this, how do I find the active keymap, or the keymap that binds a specific key, apart from looking at the source code of the package?

@StreakyCobra
Copy link
Contributor

So, if I understand that correctly, what I'm saying here is "J will be used for the movement H in every layer" (hence, J becomes backward-char), and so on for the first block; then the second block says "non-movement functions formerly bound to H will now be bound to J" and so on for the other letters.

Yes it's right.

Doing that will indeed remap HJKL to JKHL in normal-state and evilified buffers.

It's a good starting point :-)

However, it fails in magit, even though the configuration should be enabled by default (I didn't set kl-disabled-configurations nor kl-enabled-configurations). In magit, HJKL is back. When exiting the magit buffer (q), there's a warning saying that evil-magit-state does not exist.

Weird, I don't have this error message with bepo. I could understand that the remapping can fail, but this seems to be a problem with the evil-magit-state variable, so it should appear on my install too. Are you on develop with your packages up-to-date (i.e. Pressing [Update packages] on spacemacs home screen?)

Update: I just tested with your colemak definition, and h and k works in magit here, and are respectively bound to up and down. Note the layer is not remapping left/right as they are not useful movement in magit, and also because this avoid them overlapping magit default key bindings.

Update 2: You don't have excluded evil-magit, dare you? 😳

Update 3: Don't forget that all keyboard layout being different, they may differs from one to another, and may require some custom tweaks (:colemak in packages.el) package by package.

Also, if I want to pursue this, how do I find the active keymap, or the keymap that binds a specific key, apart from looking at the source code of the package?

It's the complicated fun part 😓 :

  1. Experience
  2. Trying to look directly into the keymaps related to the packages with SPC h d K (uppercase k)
  3. Using SPC h d k to find the function, and looking into the package source code.

But when packages are not following closely the best practices, or when some magic get into the practice (evilification for instance), etc. all this get messy, and the only way to find out is trial and error at the end. The timing when the tweak is loaded (:loading) plays an important role too. It's a mess. Good luck 😂

@fmdkdd
Copy link
Contributor

fmdkdd commented Sep 23, 2016

@StreakyCobra Ahh I had excluded evil-magit indeed. Good catch. Indeed it works now as intended now.

Sometimes SPC h d k reports the keymap, and sometimes it doesn't. It seems weird to me that Emacs is unable to tell me from which keymap it found the binding. Oh well.

I will check the bindings in other packages and then probably submit a Colemak binding PR. Thank you for your guidance.

@StreakyCobra
Copy link
Contributor

Sometimes SPC h d k reports the keymap, and sometimes it doesn't. It seems weird to me that Emacs is unable to tell me from which keymap it found the binding. Oh well.

https://github.com/syl20bnr/spacemacs/wiki/Keymaps-guide

☝️ Here is the reason why it's complicated 😂

@wbolster
Copy link

Evil users using Colemak may be interested in my evil-colemak-basics package, designed as a smart hybrid between Colemak and Qwerty. The docs explain the rationale quite extensively.

@namdnguyen
Copy link

Just to add another perspective, I wonder how common it is for Colemak users to remap keys for evil or vim navigation versus leaving them as they are and (re)learning evil navigation with Colemak. Perhaps, I am in the minority, but I switched to Colemak first, then switched from holy to evil mode, so I never learned evil navigation with qwerty home row. I read around to see what vim users were doing who made the switch to Colemak and eventually decided to remap nothing. See: Colemak and vim: “But what about h/j/k/l?” | a little place of calm

Seems to me that you can implement several different Colemak layouts in evil. How do you decide which layout to make the default? There doesn't seem to be an agreed upon method. I would guess that the layout (HJKL to HKJL) presented in the image above is probably a pretty common way to remap for Colemak. Here's an alternative method for using Colemak with evil.

No remap: keep HJKL in Colemak

PROS:

  • No changes to evil mappings required
  • Easy to use vim on other machines because you're not dependent on custom remapping

CONS:

  • Up and down are inverted on the keyboard

I like the versatility of being able to use vanilla vim when I need to. You don't have to mess with configuring all the evil keymaps. I've also become used to the inverted up and down keys. It's like natural scrolling on Apple products. Like any habit, it becomes second nature over time.

I am currently only setting ace-windows and avy keybindings in ~/.emacs.d/layers/+intl/keyboard-layout/packages.el in a forked spacemacs, to keep those keys on home row for Colemak.

(defun keyboard-layout/pre-init-ace-window ()
    ...
    :colemak
    (setq aw-keys '(?a ?r ?s ?t ?n ?e ?i ?o))
    ...
    
(defun keyboard-layout/pre-init-avy ()
    ...
    :colemak
    (setq-default avy-keys '(?a ?r ?s ?t ?n ?e ?i ?o))
    ...

@buggymcbugfix
Copy link
Author

@namdnguyen I've come to the same conclusion!

@drwebb
Copy link

drwebb commented Apr 18, 2017

Not sure this is the place to put this, but as a long time colemak user I wanted to share my agreement with the commit in 4461721.

The simple #{n, e, i, o} <=> #{h, j, k, l} mapping has been working well for me. I see so many more complicated switches, or ones that end up being swapped left one key.

@quangv
Copy link

quangv commented Feb 17, 2018

👍 for keyboard-layout 'colemak-hnei (currently on the develop branch)

I'm currently in the mist of VIM -> Spacemacs switch and keyboard-layout 'colemak-hnei has been sweet, thanks!

;; In my .spacemacs
(defun dotspacemacs/user-config ()
  ;; Faster Movements
  (define-key evil-normal-state-map "H" "5h")
  (define-key evil-normal-state-map "N" "5n")
  (define-key evil-normal-state-map "E" "5e")
  (define-key evil-normal-state-map "I" "5i")

  ;; Undo/Redo
  (define-key evil-normal-state-map "l" 'undo)
  (define-key evil-normal-state-map "L" 'undo-tree-redo)

  ;; Insert-mode
  (define-key evil-normal-state-map "u" 'evil-insert)
  )

for my updated version (https://github.com/quangv/.qv.space/blob/develop/.spacemacs#L311)

@mtourne
Copy link

mtourne commented Oct 10, 2018

I've been trying the key remap with a dvorak flavor by adding : (keyboard-layout :variables kl-layout 'dvorak) in my dotspacemacs-configuration-layers

One thing that is quite weird is that even though :

  • "n" which used to be for "next search term", it is now a movement key and "n" has been mapped to "k" which can be used for next-search
  • However "N" remains the key for prev-search, I would rather have it "K" for consistency

I've tried adding swapping the caps version as well but that didn't seem to work :

(dvorak
     . (("h" . "h")
        ("t" . "j")
        ("T" . "J")
        ("n" . "k")
        ("N" . "K")
        ("s" . "l")
        ("S" . "L")
        ;;
        ("h" . "h")
        ("j" . "t")
        ("J" . "T")
        ("k" . "n")
        ("K" . "N")
        ("l" . "s")
        ("L" . "S")
        ))

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Please let us know if this issue is still valid!

@github-actions github-actions bot added the stale marked as a stale issue/pr (usually by a bot) label Feb 29, 2020
@lebensterben lebensterben removed the stale marked as a stale issue/pr (usually by a bot) label Feb 4, 2022
@lebensterben lebensterben moved this from Answered, waiting to To close in Forum Feb 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Forum
  
To close
Development

No branches or pull requests

10 participants