3

I have the following setup for using comments:

(key-chord-define evil-normal-state-map "cc" 'comment-dwim-2)

This works fine. I can type cc to comment it out or comment out.

However, Web-mode works with an another function, because the comment syntax are differrent for languages like javascript or HTML. So I set up following keybinding for only web-mode in my setup:

(evil-define-key 'normal web-mode-map
  (kbd "cc") 'web-mode-comment-or-uncomment
)

But with the setup above I cannot use other Evil keybindings like cw or ctf anymore, because the keybinding above disabled them. Any suggestion for a way to use keychord in the evil-define-key, but for web-mode only? So that I can use another keys with operator c again, in web-mode only.

  • I think your second version using evil-define-key is clobbering the evil-change operator by binding the c prefix (see analogous discussion in this thread). You probably want to do a mode-specific or buffer-local key-chord-define (perhaps in a mode hook). – Dan Jul 30 '15 at 12:55
  • @Dan the problem with that, is that key-chord-define doesn't have any notion of normal-state and insert-state in Evil. This makes it not possible to typing cc fast in insert state. – ReneFroger Jul 30 '15 at 14:18
  • evil does, however, have local maps. Not sure if this will work, but try putting the following in your web-mode mode hook: (key-chord-define evil-normal-state-local-map "cc" #'web-mode-comment-or-uncomment). – Dan Jul 30 '15 at 14:23
  • I didn't help. However, I get the notification that evil-normal-state-local-map is a free variable, that propbably doesn't exist. And I don't see how this could be solving my issue. It's that the cc does disable the cw or . – ReneFroger Jul 31 '15 at 11:22
3
+50

Dan is correct, binding (kbd "cc") will clobber your evil-change binding.

One way to solve this is to look at the source of key-chord-define:

;;;###autoload
(defun key-chord-define (keymap keys command)
  "Define in KEYMAP, a key-chord of the two keys in KEYS starting a COMMAND. 
KEYS can be a string or a vector of two elements. Currently only elements
that corresponds to ascii codes in the range 32 to 126 can be used.
COMMAND can be an interactive function, a string, or nil.
If COMMAND is nil, the key-chord is removed."
  (if (/= 2 (length keys))
      (error "Key-chord keys must have two elements"))
  ;; Exotic chars in a string are >255 but define-key wants 128..255 for those
  (let ((key1 (logand 255 (aref keys 0)))
        (key2 (logand 255 (aref keys 1))))
    (if (eq key1 key2)
      (define-key keymap (vector 'key-chord key1 key2) command)
      ;; else
      (define-key keymap (vector 'key-chord key1 key2) command)
      (define-key keymap (vector 'key-chord key2 key1) command))))

So aha! It's clear that key-chord-define simply binds a special key-chord prefix. It also does some math for fancy chars, but we can bypass that since c is not one of them (ASCII code point 99).

One way to do what you want is then:

(evil-define-key 'normal web-mode-map
  (vector 'key-chord 99 99) #'web-mode-comment-or-uncomment)

However, there is one more optimization you can use, leveraging a slightly more advanced feature of kbd:

(evil-define-key 'normal web-mode-map
  (kbd "<key-chord> cc") #'web-mode-comment-or-uncomment)
  • 1
    PythonNut, thanks for your well written explaination. It enables me to solve my own problems in the future. It's well appreciated, I validated your answer as the right one. – ReneFroger Aug 3 '15 at 21:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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