emacs-evil / evil

The extensible vi layer for Emacs.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Arrow Keys behaves like in vi

sashs opened this issue · comments

Question

Arrow keys behaves like in vi instead of vim. This means, pressing any arrow key in normal mode results in a switch to insert mode and prints one of [A|B|C|D]. How can I achive vim like behavior?

Environment

Emacs version: Emacs 26.1
Operating System: RHEL 8
Evil version: 1.15.0
Evil installation type: manual
Graphical/Terminal: terminal
Tested in a make emacs session (see CONTRIBUTING.md): No

Reproduction steps

  • Start Emacs with evil-mode enabled
  • Press any error key

Expected behavior

Arrow left: cursor moves left
Arrow right: cursor moves right
Arrow up: cursor moves up
Arrow down: cursor moves down

Actual behavior

In normal mode switches to insert mode. In insert mode stays in insert mode.
Does always the following:
Arrow left: write D
Arrow right: write C
Arrow up: write A
Arrow down: write B

Further notes

I tried bind the movement actions (evil-forward-char, evil-backward-char, etc) explicitly to the arrow keys. That does not resolve the issue.

@sashs what terminal are you using?

I tried it with:

  • kitty
  • st
  • putty
  • tmux

If you press one of the arrows, and then do M-x view-lossage what does that buffer show?

ESC [evil-force-normal-state]
O [evil-open-above]
B [self-insert-command]
ESC [evil-normal-state]
O [evil-open-above]
B [self-insert-command]
ESC [evil-normal-state]
O [evil-open-above]
D [self-insert-command]
ESC [evil-normal-state]
O [evil-open-above]
A [self-insert-command]
ESC [evil-normal-state]
O [evil-open-above]
C [self-insert-command]
ESC [evil-normal-state]
: [evil-ex]
v [self-insert-command]
i [self-insert-command]
e [self-insert-command]
w [self-insert-command]
- [self-insert-command]
l [self-insert-command]
o [self-insert-command]
s [self-insert-command]
s [self-insert-command]
TAB [completion-at-point]
RET [exit-minibuffer]

M-x did not work. I had to leave the insert mode and use the vi command mode.
I pressed:

  • down
  • down
  • left
  • up
  • right

OK that's interesting. In my emacs, I get:

ESC O C
ESC O D

etc.
whereas you get

ESC
O
C
ESC
O
D

which means your emacs is seeing them as separate key codes, rather than combined. Also explains why it's behaving like you're opening a line above (O) and writing one of those letters. I'll have a dig. It's not something I've come across before.

Not intended as a permanent solution, but if you eval this:

(define-key input-decode-map "\eOD" [left])

Does that fix left arrow?

No. That doesn't help. Same behavior.

Hmm. I feel like it should help. Maybe it needs to be evaluated before evil is loaded? tbh, at this point I'm mostly just reading from here: https://www.gnu.org/software/emacs/manual/html_node/elisp/Translation-Keymaps.html and here: https://www.gnu.org/software/emacs/manual/html_node/elisp/Terminal_002dSpecific.html to give suggestions, as I'm no expert in this stuff. I'd suggest you read those pages and see if you can work out the problem. It seems to me this isn't really an evil problem. As long as emacs 1) understands what terminal is hosting it, 2) understands which event sequences mean what, and 3) translates/maps those sequences appropriately before any evil keymaps get their hands on them, then it should work. Hopefully someone else with more emacs-in-terminal expertise can chime in. Otherwise I'm out of ideas for now, sorry.

Many thanks.
It is an issue of evil since Emacs behaves as usual in emacs state. Only the evil states (normal, visual, insert etc) are not working correctly.

So I assume it is not an issue of the input-decode-map.

Ah, I see. As it does seem to be specific to evil, let's leave this issue open for a while, at least to remind me to take a look when I get some more time.

I upgraded to a newer version of evil mode (I was last using a version from three years ago) and it frankly simply doesn't work at all anymore--I can't even escape out of insert mode, for example--and I'm pretty sure it is related to this same issue (though I don't replicate the exact behavior as described, I did end up in some state finally where I got something similar printed while frantically trying to escape).

I went ahead and checked out the repository so I could quickly bisect this (on my emacs 26.3 install) using make emacs (without a .emacs, just in case; not sure if that matters) and the commit which seems to have broken everything is f003ca2. With that commit, pressing ESC from insert mode waits for a few seconds before eventually printing "ESC-" (as I guess it is waiting for some possible future meta key combination).

@axelf4 any thoughts?

Sorry, my fault, turns out the body argument of define-globalized-minor-mode:

(define-globalized-minor-mode GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)

was a recent addition not present in Emacs 26.3.

The following patch should resolve the issue:

From fb8944ef823e8cd346533ef850e234487900c517 Mon Sep 17 00:00:00 2001
From: Axel Forsman <axel@axelf.se>
Date: Tue, 14 Nov 2023 12:50:56 +0100
Subject: [PATCH] Fix define-globalized-minor-mode BODY in Emacs <27

This commit reintroduces the evil-mode advice that commit
f003ca28a9691d24a17866e5dce3e7866c9bb257 replaced with a BODY argument
to define-globalized-minor-mode, as that broke support for older
versions of Emacs since the BODY parameter was only recently
introduced in Emacs 27.
---
 evil-core.el | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/evil-core.el b/evil-core.el
index 23937e7..4190997 100644
--- a/evil-core.el
+++ b/evil-core.el
@@ -169,9 +169,10 @@ (defun evil-initialize ()
 (defalias 'evil--fundamental-mode #'fundamental-mode)
 
 ;;;###autoload (autoload 'evil-mode "evil" nil t)
-(define-globalized-minor-mode evil-mode
-  evil-local-mode evil-initialize
-  :group 'evil
+(define-globalized-minor-mode evil-mode evil-local-mode evil-initialize
+  :group 'evil)
+
+(defadvice evil-mode (after start-evil activate)
   ;; Hooks used to not run in Fundamental buffers (bug#23827), so
   ;; other measures are necessary to initialize Evil there. When Evil
   ;; is enabled globally, the default value of `major-mode' is set to
@@ -183,12 +184,12 @@ (define-globalized-minor-mode evil-mode
              (setq-default major-mode 'evil--fundamental-mode))
         (ad-enable-regexp "^evil")
         (ad-activate-regexp "^evil")
-        (evil-esc-mode 1))
+        (with-no-warnings (evil-esc-mode 1)))
     (when (eq (default-value 'major-mode) 'evil--fundamental-mode)
       (setq-default major-mode 'fundamental-mode))
     (ad-disable-regexp "^evil")
     (ad-update-regexp "^evil")
-    (evil-esc-mode -1)))
+    (with-no-warnings (evil-esc-mode -1))))
 
 (defun evil-change-state (state &optional message)
   "Change the state to STATE.
-- 
2.40.1

@tomdl89 Feel free to install the patch or do as you see fit.

FWIW, this patch does in fact fix my issue. I also see the original poster of this issue had Emacs 26.1, which continues to argue that this might also fix their problem (though I still haven't managed to replicate the specific described behavior).

Sorry for the delay on this. Merged to master.