4

I have the following definition in my init.el:

(define-key evil-motion-state-map (kbd "SPC j") #'evilem-motion-next-line)

This works if I want to do dSPCj, but I'd like to be able to do SPCdj as well. (Here, SPC is meant to take the place of the prefix argument or "count", which can come in either location. see evil-easymotion for a description of its behavior).

The naive solution

(define-key evil-normal-state-map (kbd "SPC d") (kbd "d SPC"))

Does not work for the same reason described in Emacs bind key to prefix. The solution to that question doesn't work for me because there is no prefix command to bind to, as all commands are hidden behind evil-delete.

Is there any way to accomplish this?

PythonNut
  • 10,243
  • 2
  • 29
  • 75

3 Answers3

4

Try the following, not sure if it will work.

(defun simulate-key-press (key)
  "Return a command that pretends KEY was presssed.
KEY must be given in `kbd' notation."
  `(lambda () (interactive)
     (setq prefix-arg current-prefix-arg)
     (setq unread-command-events (listify-key-sequence (read-kbd-macro ,key)))))

(define-key evil-normal-state-map (kbd "SPC d") (simulate-key-press "d SPC"))
Malabarba
  • 22,878
  • 6
  • 78
  • 163
1

So you want SPC to be a prefix key, which means binding it to a keymap. You want d to be bound in that map, and you want it too to be a prefix key, which means that you want to bind d to another keymap.

I don't see why you would want to do this, but if that's what you want to do then that's one way to do it.

(define-prefix-command 'space-map)
(define-key evil-normal-state-map (kbd "<SPC>") space-map)                                    

(define-prefix-command 'space-d-map)
(define-key space-map "d" space-d-map)                                    

(define-key space-d-map "j" 'evilem-motion-next-line)
Drew
  • 75,699
  • 9
  • 109
  • 225
  • 1
    It has to do with the way Vim works. We have our prefixes and keys, Vim has arguments, operators, and objects. In vim you say `3dw`: argument is `3`, the action is `delete`, and the object is `words`. In Vim, `3dw` does the same thing as `d3w`. Your answer does not take into account that the `d` is significant, it will just move the point, but not delete the region. That's why this problem is stickier than usual. – PythonNut Jun 25 '15 at 00:37
1

Mmh. But SPC in your example is not like a counter. It rather acts as a leader key for j: SPC j becomes a new unit, a motion that does "something related to j, but more advanced" (as a mnemonic), and is bound to #'evilem-motion-next-line. And - you don't usually break a leader-key combination in the same way you'd use a counter (what I'm saying is - I don't expect a leader to work the same way a counter does).

That said, what you want (with vim grammar power) translates (for me) as:
"Create a different operation, and map it to SPC d" - one that understands the j motion (and others). If done properly, it can happen that SPC d j will do the same thing as d SPC j :)

Although, IMHO, the "Vim way" would be to have SPC d j perform another operation. So that one can also type SPC d SPC j for example, with a meaningful result. So, instead of the redundancy (SPC d j = d SPC j), more functionality (SPC d j != d SPC j).

Although, I think in Emacs you probably can implement the leader key as a counter, since the counter is also a custom Evil implementation.

VanLaser
  • 576
  • 4
  • 11
  • I'm doing this for [evil-easymotion](https://github.com/PythonNut/evil-easymotion), where `SPC` means _I really want a count, but I'd like to enter it visually_. So the interpretation of `SPC` is like a placeholder for the count you'll enter later. You'll do `SPC dft` and look at which `t` is the one you want and teleport there (regardless of the number of `t`s between) – PythonNut Jun 25 '15 at 14:55
  • 1
    You define what you want, no need to feel constrained by "Vim-like" rules :). For me, it's not the same, *logically*, to do an operation **n** times on a motion/text-object, or to do a single operation on a range of **n** motions/text-objects (i.e. `3dw` may have the same effect as `d3w`, but nothing guarantees that, for custom operations/text-objects, `n operation text-object` == `operation n text-object`). For example, a "trim" operation could remove spaces for the beginning and end of a range: if I do "3 times trim a line", this is different (and it's ok) than "trim a range of 3 lines". – VanLaser Jun 25 '15 at 15:18
  • 1
    indeed. I just haven't thought of something clever to do with the alternate meaning. easymotions are super motions. What is a super operator? In the meantime, I'd rather have the prefix modifier as an option instead of leaving it unbound. My fingers find it slightly easier to type, and my mind seems to prefer declaring the use of the grenade launcher up-front. – PythonNut Jun 25 '15 at 16:28
  • Heh - It's high time for an *easyoperator* plugin then :) – VanLaser Jun 25 '15 at 16:39