key-translation-map not honored in Evil O state

epich avatarepich created an issue

Background:

Because C-c is one way of escaping in Vim, and because it is more ergonomic than C-g, I aim to use it for escaping insert state and keyboard-quit. I use this in my .emacs .

(defun my-esc (prompt)
  "Functionality for escaping generally.  Includes exiting Evil insert state and C-g binding. "
  (cond
   ((or (evil-insert-state-p) (evil-motion-state-p)) [escape])
   ;; This is the best way I could infer for now to have C-c work during evil-read-key.
   ((eq overriding-terminal-local-map evil-read-key-map) (keyboard-quit) (kbd ""))
   (t (kbd "C-g"))))
(define-key key-translation-map (kbd "C-c") 'my-esc)
(set-quit-char "C-c")

(As an aside, I've also created: (define-key evil-motion-state-map "cc" mode-specific-map) so I have my own means of getting the usual keymap bound to C-c.)

I've found this works in all cases except when I'm in the Operator Pending state.

Problem details:

When I do: d or = I enter the operator pending state and find C-g successfully exits.

However, I find that when I use C-c instead of C-g, it doesn't keyboard-quit. The output in the minibuffer indicates it is using C-c for key lookup and finding it bound to another keymap (presumably the global one). Why is the key-translation-map not translating the C-c to C-g before the key lookup in this Evil state?

Workaround:

I get the behavior I seek when I put this in my .emacs: (define-key evil-operator-state-map (kbd "C-c") 'keyboard-quit).

Comments (4)

  1. Frank Fischer
    • changed status to open

    Operator state is somehow special. When a command is called its interactive statement is responsible for getting the motion. This implies that the key sequence for the motion is read while the command is about being executed. In order to do this evil reads the key sequence manually and translates it using the currently active keymaps. I do not know for sure but it may be possible that this approach does not respect key-translation-map, which would explain the problem (if you're interested, the corresponding code is in the function evil-read-motion in file evil-common.el)

  2. epich

    I looked it over a little and found evil-read-motion calls evil-keypress-parser, then reads events iteratively using read-event. I put (read-event) in scratch and evaluated it. Inputting C-c returned 3 in the minibuffer and C-g quit the input. The Elisp manual (http://www.gnu.org/software/emacs/manual/html_mono/elisp.html#Translation-Keymaps) says that read-key-sequence uses the key-translation-map. I put (read-key-sequence) in scratch and evaluated it. Whether I type C-c or C-g, I see "^G" displayed in the minibuffer. Would read-key-sequence be appropriate for Evil to use in operator pending state?

  3. Frank Fischer

    Maybe, but there are probably some difficulties. First, evil advices read-key-sequence for some recording in the repeat system so there may be some interference. Second, using read-event allows to handle the escape-key (in terminals) specifically. Using read-key-sequence instead would require some other tricks because it only returns complete key sequences (one would have to add a special command bound to ESC to intercept the escape key and possibly re-read to complete input sequence in case of another event arriving, i.e. a M-<key> combination. Maybe the evil-esc can be used, but I don't know.)

    Another possibility would be to stay with read-event but do the translation manually. But this is not necessarily easier to do right.

  4. Log in to comment
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.