Subject: Re: binding to "cp" without breaking "c" Newsgroups: gmane.emacs.vim-emulation Date: Saturday 7th June 2014 10:09:12 UTC (over 2 years ago) Am 07.06.2014 09:45, schrieb Justin M. Keyes: > Hi, > > I'm trying to bind a command to the "unused namespace" that happens to > start with "c". By "unused namespace" I mean things like "cp" or "co" > for which there is no valid text object or motion. In Vim, you can > bind "cow" and it does not affect the behavior of "cdw", "ciw", etc, > because "o" is not defined as a text object. For example, in > unimpaired.vim[1], "cow" toggles word-wrap. I would like to do this in > emacs evil, so I tried: > > (define-key evil-normal-state-map (kbd "c o w") 'toggle-truncate-lines) > > It reports "eval-region: Key sequence c p w starts with non-prefix key > c". But I don't want to unbind "c" because then I can't use the > evil-change operator. Something like this is currently not possible. That's because of the way Emacs key-sequences and Evil operators work: The parsing of a key-sequence does not happen when the sequence is complete but in steps. "c" is bound to the command `evil-change`, so when "c" is typed Emacs immediately executes `evil-change` without waiting for further keys (i.e., the decision which command has to be executed is taken as soon as "c" is typed--that's also the reason why you cannot define a command "c" and another "cp" in the same keymap: a keymap is a lookup-table and "c" can either be mapped to a command or to another keymap, not both). What Evil does is to manually wait for further keys before the body of `evil-change` is executed. This happens in the `interactive` form of `evil-change` (and each other operator--in fact, the magic behind `evil-define-operator` is to automatically generate an appropriate interactive form). This second key-sequence is looked up in `evil-operator-state-map` (and inherited keymaps like `evil-motion-state-map`). If the sequence completely defines a (motion) command, this command is executed and used to build the range parameter for the operator. Then the body of the operator is executed (with that range). So there is a real limitation of key sequence in Evil. What you could to, however, is to provide a "fake" motion, that executes whatever you want but does not execute the operator's body: ``` (defun my-command () (interactive) (do-what-you-want) (setq evil-inhibit-operator t)) (define-key evil-operator-state-map "p" 'my-command) ``` The important thing is the last line, which causes Evil to not execute the operators body. However, this would cause "p" to work with *any* operator. But you're free to do whatever you want in your command, so you could dispatch depending on the current operator: ``` (defun my-command () (interactive) (case evil-this-operator (evil-change (do-what-you-want)) (evil-delete (do-something-else)) (t (keyboard-quit))) (setq evil-inhibit-operator t)) ``` > I tried defining a custom operator, but after looking at the evil > source code I couldn't figure out how to hook into evil-change to > preserve its behavior while listening for "o" and then routing it > somewhere else. Maybe you can do something with advice tricks, too, or some temporary keymaps together with `unread-command-events`. The suggestion above is only one possibility. But as I said, there is no direct support for what you want because of Emacs keymaps and/or the current implementation. Best regards, Frank |
|||