Justin M. Keyes | 7 Jun 09:45 2014
Picon

binding to "cp" without breaking "c"

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.

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.

It seems like I'm missing something, I would think this is a common
task, but I haven't found any posts that address this.

Thanks for evil, it's superb!

[1] https://github.com/tpope/vim-unimpaired

Justin M. Keyes
(Continue reading)

Frank Fischer | 7 Jun 12:09 2014
Picon

Re: binding to "cp" without breaking "c"

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
(Continue reading)

Stefan Monnier | 13 Jun 21:54 2014
Picon

Re: binding to "cp" without breaking "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

I'm very much not familiar with Evil, so this may be completely
inapplicable, but an option might be to do the following:
- don't bind `c' to `evil-change'.
- instead, add various `c <foo>' bindings, to `evil-change' and change
  it so it uses last-command-event or this-single-command-keys to know
  which binding triggered it (instead of using something like
  `read-event' to wait for the next event).

-- Stefan
Frank Fischer | 18 Jun 17:35 2014
Picon

Re: binding to "cp" without breaking "c"

On 13.06.2014 21:54, Stefan Monnier wrote:
> I'm very much not familiar with Evil, so this may be completely
> inapplicable, but an option might be to do the following:
> - don't bind `c' to `evil-change'.
> - instead, add various `c <foo>' bindings, to `evil-change' and change
>   it so it uses last-command-event or this-single-command-keys to know
>   which binding triggered it (instead of using something like
>   `read-event' to wait for the next event).

This approach has some disadvantages:

* a count after the operator but before the motion would not work
anymore (something like c2w)
* the same has to be done for all other operators and for every new
operator to be defined

and possibly more. And it would be a big change, maybe not (yet) worth
the effort.

Best regards,
Frank
Jason Miller | 18 Jun 18:29 2014

Re: binding to "cp" without breaking "c"

It seems like the better fix would be to add a helper function that lets
you easily define key sequences that begin with an action.  Something
like the "fake-motion" suggested, but generalized for any leader key.

-Jason

On 17:35 Wed 18 Jun     , Frank Fischer wrote:
> On 13.06.2014 21:54, Stefan Monnier wrote:
> > I'm very much not familiar with Evil, so this may be completely
> > inapplicable, but an option might be to do the following:
> > - don't bind `c' to `evil-change'.
> > - instead, add various `c <foo>' bindings, to `evil-change' and change
> >   it so it uses last-command-event or this-single-command-keys to know
> >   which binding triggered it (instead of using something like
> >   `read-event' to wait for the next event).
> 
> This approach has some disadvantages:
> 
> * a count after the operator but before the motion would not work
> anymore (something like c2w)
> * the same has to be done for all other operators and for every new
> operator to be defined
> 
> and possibly more. And it would be a big change, maybe not (yet) worth
> the effort.
> 
> Best regards,
> Frank
> 
> 
(Continue reading)

Stefan Monnier | 19 Jun 04:12 2014
Picon

Re: binding to "cp" without breaking "c"

>> I'm very much not familiar with Evil, so this may be completely
>> inapplicable, but an option might be to do the following:
>> - don't bind `c' to `evil-change'.
>> - instead, add various `c <foo>' bindings, to `evil-change' and change
>> it so it uses last-command-event or this-single-command-keys to know
>> which binding triggered it (instead of using something like
>> `read-event' to wait for the next event).
> This approach has some disadvantages:
> * a count after the operator but before the motion would not work
> anymore (something like c2w)

Not sure how ugly it would end up, indeed.

But you could very well handle it with something like:

   (define-key map "c" operator-arg-map)
   (defvar operator-arg-map
     (let ((map (make-sparse-keymap)))
       (dotimes (i 10)
         (define-key map (vector (+ i ?0)) map))
       (define-key map [?w] 'my-command)
       map))

   (defun my-command (keys)
     (interactive (list (this-single-command-keys)))
     ... analyze keys to extract the count and the motion...
     ...)

It would probably introduce other changes to the behavior that you
didn't intend, and such "recursive maps" are sufficiently rare that you
(Continue reading)

Frank Fischer | 2 Jul 20:41 2014
Picon

Re: binding to "cp" without breaking "c"

Am 19.06.2014 04:12, schrieb Stefan Monnier:
> Not sure how ugly it would end up, indeed.
> 
> But you could very well handle it with something like:
> 
>    (define-key map "c" operator-arg-map)
>    (defvar operator-arg-map
>      (let ((map (make-sparse-keymap)))
>        (dotimes (i 10)
>          (define-key map (vector (+ i ?0)) map))
>        (define-key map [?w] 'my-command)
>        map))
> 
>    (defun my-command (keys)
>      (interactive (list (this-single-command-keys)))
>      ... analyze keys to extract the count and the motion...
>      ...)
> 
> It would probably introduce other changes to the behavior that you
> didn't intend, and such "recursive maps" are sufficiently rare that you
> might bump into Emacs bugs, so yes... not necessarily a good idea.

Another idea would be to multiplex operators (they are defined via
`evil-define-operator` anyway, so this should not be a problem).

If an operator is called (interactively), it does not execute its body
but simply activates a new minor mode (i.e., operator-state) in which
other keymaps are active (and possibly some prefix specific ones, e.g.,
one that is only active if the invoking key-sequence has been "c"). If
some (motion) command is executed in that state, the operator's body is
(Continue reading)


Gmane