reddit / emacs
Why won't the key rebind????
Dekula · 2022-02-20 19:21
I would like to bind C-h/j/k/l to move emacs windows (evil normal mode).
Binding globally, every one of these works except C-k. It will NOT move to the upper window in either Eshell or term, normal mode or no. I tried to use bind\* from use-package, I tried general, I tried so many things I've lost count, but I can't use C-k for the real shell or the Eshell. Why is this, and is there a sane way around it? For now I've settled down on using arrows:
```
(general-define-key
:states 'normal
"<left>" 'windmove-left
"<right>" 'windmove-right
"<down>" 'windmove-down
"<up>" 'windmove-up)
```
But I am not happy about it. Doubly so because I just don't understand why no override works.
TLDR: It was evil-collection.
HM0880 · 2022-02-20 21:41
You can find what `C-k` is bound to in Eshell by running `C-h k` for the `describe-key` function and then running `C-k`. By default in Eshell, `C-k` runs the command `kill-line`.
Eshell sometimes needs keybindings to be specified in the `eshell-mode-map` so try
`(define-key eshell-mode-map (kbd "C-k") 'Dekula-window-move-function-here)`.
I do not have advice for Term since I do not use it.
arthurno1 · 2022-02-20 21:52
> I can't use C-k for the real shell or the Eshell.
In my Emacs, it deletes the line in eshell and any other buffer, so it is bound in the global-map.
> Binding globally, every one of these works except C-k. It will NOT move to the upper window in either Eshell
Try this:
(define-key global-map (kbd "C-k") #'windmove-up)
Works fine with eshell here.
For the term you have first to switch it into "line mode" with C-c C-j. Then it works. In line mode, Emacs treats your term buffer as an ordinary buffer, but you can still execute shell commands when you press the return key at the end of the line. You switch back to "character mode" by pressing C-c C-k.
By the way, have you noticed that if you use ijkl, instead of hjkl, it would be a "right version" of "wasd" keys. You could have i/k which are vertical to each other to move up/down, and j/l to move left right. If you are used to playing computer games. That would also leave C-h for Emacs built-in help which is quite useful. I know Evil users are used to hjkl, so feel free to ignore. It's just a little remark.
arthurno1 · 2022-02-20 22:11
> Eshell sometimes needs keybindings to be specified in the eshell-mode-map
Yes, if you want your bindings to take precedence over those in global-map. In this case, the Op wishes to have a global binding so he should certainly define those in either global map, or if he has new enough Emacs, use the new minor mode windmove-mode since minor modes take precedence over global map too.
Dekula · 2022-02-21 01:31
>(define-key global-map (kbd "C-k") #'windmove-up)
eval-buffer: Wrong type argument: keymapp, nil
Weird, eh? I guess I need to start vanilla emacs without anything, because yeah, I should have mentioned this won't work.
Dekula · 2022-02-21 01:32
This doesn't work for me :(
I guess it could be some weird interaction from a billion packages or who knows what. Next step is to try vanilla emacs and emacs on other computers I guess, it's very odd.
HM0880 · 2022-02-21 02:14
Yes, a little weird. Time for `emacs -Q` :)
arthurno1 · 2022-02-21 06:52
When yo press C-h k and than C-k, what does it says? Which function is it bound to?
Edit:
> eval-buffer: Wrong type argument: keymapp, nil
Ok, can you place your cursor after the last parenthesis on this line:
(define-key global-map (kbd "C-k") #'windmove-up)| <-- like this
and then press C-x C-e, or type M-: (define-key global-map (kbd "C-k") #'windmove-up) RET and see how it works. Post error message if there is any.
If you eval-buffer, than your error could be anywhere in the buffer, long before you ever reached that line that is supposed to set you C-k binding which causes Emacs to bail out from evaluation.
HM0880 · 2022-02-21 13:22
Got it. For GNU Emacs 28.0.50, adding the keybinding to `eshell-mode-hook` works.
(add-hook 'eshell-mode-hook
(lambda ()
(define-key eshell-mode-map (kbd "C-k") #'windmove-up)))
Without using `eshell-mode-hook`, I got the "keymapp" error too.
Dekula · 2022-02-21 13:32
>(define-key global-map (kbd "C-k") #'windmove-up)
```
C-k runs the command eshell-previous-prompt, which is an interactive
compiled Lisp function in ‘em-prompt.el’.
It is bound to C-k, g k, \[ \[, <visual-state> C-k, <normal-state> C-k,
C-c C-p, <visual-state> g k, <visual-state> \[ \[, <normal-state> g k,
<normal-state> \[ \[.
(eshell-previous-prompt N)
Move to end of Nth previous prompt in the buffer.
See ‘eshell-prompt-regexp’.
```
This is when I describe the key in Eshell, after doing the global-map keybinding, which completes without error. It's like it's being completely ignored.
Dekula · 2022-02-21 13:33
This doesn't want to work either, though it will at least not give an error. I should have mentioned, I'm on 27.2.
Dekula · 2022-02-21 13:36
Thanks everyone for the help.
The issue is with evil-collection. After disabling the plugins, and re-enabling, evil-collection is the culprit. Now I have to do some digging, but sanity is at least partly restored.
HM0880 · 2022-02-21 14:47
The `eshell-mode-hook` works on Emacs 25.2.2. I am evaluating the `eshell-mode-hook` command in `*scratch*` and *then* opening a new instance of Eshell. The order of operations is important.
arthurno1 · 2022-02-21 14:59
It is not ignored, you have re-bound C-k in eshell-mode-map which takes precedence in eshell-mode as it should. You have either some other package that makes that binding for you, or you have bounded it yourself elsewhere in your setup. I don't see that function bound in my eshell, and I haven't customized shortcuts for eshell, so I believe that function is not bound by default. Anyway you can just unset the key in eshell-mode-map.
In your eshell, you can type this:
(keymap-local-unset "C-k")
Place your cursor after the last parenthesis and press C-x C-e. That should remove key binding from eshell-mode-map, so your global binding will be active.
Check your setup where you define that key for eshell, and remove it from your setup, so you don't have it installed next time Emacs starts as well. Hope it helps :).