4

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.

ReneFroger
  • 3,855
  • 22
  • 63
  • 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](http://emacs.stackexchange.com/a/14335/253)). 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 `cì`. – ReneFroger Jul 31 '15 at 11:22

1 Answers1

3

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)
PythonNut
  • 10,243
  • 2
  • 29
  • 75
  • 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 03 '15 at 21:13