3

How do I get key-chords to work with evil and alternate input-methods?

I enabled Korean input by M-x set-input-method and chose korean-hangul, which I found from following the first few instructions from this Emacs Wiki.

I am using evil-mode, which I really enjoy, but my custom "smash escape" function does not work. The function allows me to exit insert state by quickly pressing jk or kj. Here are the functions:

;; Set 'kj' to exit insert mode
(define-key evil-insert-state-map "k" #'cofi/maybe-exit-kj)
(evil-define-command cofi/maybe-exit-kj ()
  :repeat change
  (interactive)
  (let ((modified (buffer-modified-p)))
    (insert "k")
    (let ((evt (read-event (format "Insert %c to exit insert state" ?j)
               nil 0.5)))
      (cond
       ((null evt) (message ""))
       ((and (integerp evt) (char-equal evt ?j))
    (delete-char -1)
    (set-buffer-modified-p modified)
    (push 'escape unread-command-events))
       (t (setq unread-command-events (append unread-command-events
                          (list evt))))))))

(define-key evil-insert-state-map "j" #'cofi/maybe-exit-jk)
(evil-define-command cofi/maybe-exit-jk ()
  :repeat change
  (interactive)
  (let ((modified (buffer-modified-p)))
    (insert "j")
    (let ((evt (read-event (format "Insert %c to exit insert state" ?k)
               nil 0.5)))
      (cond
       ((null evt) (message ""))
       ((and (integerp evt) (char-equal evt ?k))
    (delete-char -1)
    (set-buffer-modified-p modified)
    (push 'escape unread-command-events))
       (t (setq unread-command-events (append unread-command-events
                          (list evt))))))))

My attempt was to substitute j and k with the corresponding Korean characters. Here is my attempt at re-implementing the kj smash escape, where the character is bound to k and the character is bound to j:

(define-key evil-insert-state-map "ㅏ" #'cofi/maybe-exit-ㅏㅓ)
;; Set 'ㅏㅓ' to exit insert mode
(evil-define-command cofi/maybe-exit-ㅏㅓ ()
  :repeat change
  (interactive)
  (let ((modified (buffer-modified-p)))
    (insert "ㅏ")
    (let ((evt (read-event (format "Insert %c to exit insert state" ?ㅓ)
               nil 0.5)))
      (cond
       ((null evt) (message ""))
       ((and (integerp evt) (char-equal evt ?ㅓ))
    (delete-char -1)
    (set-buffer-modified-p modified)
    (push 'escape unread-command-events))
       (t (setq unread-command-events (append unread-command-events
                          (list evt))))))))

All I did was substitute j and k with and , respectively. Unfortunately, it does not work. Any suggestions on how to proceed?

1 Answer 1

2

First of all, I presume you're aware of key-chord (see also this SO thread). I've never used it, and have hazy memories that it doesn't always interact well with evil.

This answer is 95% of the way there. The last snag looks like it's in the actual binding of the key, but I don't know how to fix it because I don't know how Korean input methods work.

Here's a version using Arabic (helpful, right?) that does work; I've left comments on which lines you need to change to switch it over to Korean:

(evil-define-command cofi/maybe-exit-kj ()
  :repeat change
  (interactive)
  (let ((modified (buffer-modified-p)))
    (self-insert-command 1)
    (let ((evt (read-event (format "Insert %c to exit insert state"
                                   (if (equal current-input-method
                                              "arabic") ; "korean-hangul"
                                       ?ؤ               ; ?ㅓ
                                     ?j))
                           nil 0.5)))
      (cond
       ((null evt) (message ""))
       ((and (integerp evt) (memq evt '(?j ?ؤ))) ; '(?j ?ㅓ)
        (delete-char -1)
        (set-buffer-modified-p modified)
        (push 'escape unread-command-events))
       (t
        (setq unread-command-events (append unread-command-events
                                            (list evt))))))))

Now: it turns out that you also need to bind the key in the relevant alphabet to this function as well (with ر standing in for the k):

(define-key evil-insert-state-map "ر" #'cofi/maybe-exit-kj) ; "ㅏ"

It looks like the problem is with the define-key part:

(defun test-my-key ()
  (interactive)
  (self-insert-command 1)
  (message "This key works!")
  (sit-for 2))

(define-key evil-insert-state-map "a" #'test-my-key)
(define-key evil-insert-state-map "ㅏ" #'test-my-key)

Now, when entering a, it self-inserts an a into the buffer, but you don't get anything when entering -- I presume because Emacs is waiting for you to complete the character with another key? At any rate, you'll know better how to deal with Korean input methods, so will be able to adjust the function as needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.