evil icon indicating copy to clipboard operation
evil copied to clipboard

Guidance on creating wrapper functions for evil motions

Open JoshMcguigan opened this issue 3 years ago • 3 comments

Issue type

  • Question

Question

Hello! I'm looking for guidance regarding creating wrapper functions around evil motion commands. My use case here is to rebind a key to my own function which checks for some conditions and then dispatches to the appropriate function (one or more would be an evil motion).

Since evil uses 'pre-command-hook to detect motions being used, this detection is broken if I wrap the evil motion command in a function of my own. As a workaround I've copied applied the command properties from the evil motion to my own function:

      (apply #'evil-set-command-properties #'me/navigate-next
             (evil-get-command-properties #'evil-ex-search-next))

This workaround works, but I'm not sure it is ideal. For one thing, it seems very easy to forget to do this (or just not realize it was needed, as was the case for me). Secondly, not all the branches on my function lead to calling evil-ex-search-next.

It would also be reasonable I think, although I haven't yet had the need, to have a wrapper function which calls two different evil motions, each with their own sets of command properties. In this case it wouldn't be clear at "compile-time" which properties I should apply to my wrapper function.

I wonder if evil could hook each of the motion functions specifically, rather than using the pre/post command hooks? I think this would solve the concerns above.

In short, is there any specific guidance on how to create functions which are called interactively which themselves wrap one or more evil motion functions - where a given invocation of the wrapper function may or may not call an evil motion?

You can see the actual example of what I'm trying to accomplish in this section of my dotfiles .

Thanks!

JoshMcguigan avatar May 21 '22 19:05 JoshMcguigan

I'm not sure what you mean by "evil uses 'pre-command hook to detect motions being used" - can you point to some code? I'm also not sure what the problem is, but my gut reaction is that either using call-interactively rather than just calling the motions in simple parens, or making your functions advise the motions may be good things to try.

tomdl89 avatar May 25 '22 21:05 tomdl89

I'm not sure what you mean by "evil uses 'pre-command hook to detect motions being used" - can you point to some code?

Sure!

https://github.com/emacs-evil/evil/blob/157af04d2cf466e301e82b0e667c5e7203fd96a2/evil-core.el#L143

https://github.com/emacs-evil/evil/blob/157af04d2cf466e301e82b0e667c5e7203fd96a2/evil-repeat.el#L267

I'm also not sure what the problem is, but my gut reaction is that either using call-interactively rather than just calling the motions in simple parens, or making your functions advise the motions may be good things to try.

In my testing call-interactively still doesn't cause the pre-command-hook to fire, which was surprising to me.

Advising the functions is an interesting idea, I could try that out and see if it ends up being nicer than what I've got.

JoshMcguigan avatar May 26 '22 01:05 JoshMcguigan

You could also just put

(run-hooks 'pre-command-hook)

in your function, but I can see that feels a bit hacky too. To answer your initial question, no I don't think there's guidance on how to create wrapper functions for evil motions, and I think any approach will feel somewhat hacky. Let us know how you get on!

tomdl89 avatar May 26 '22 11:05 tomdl89