3

What I want to do: have the function evil-delete do one more task after its usual code. (I'm presuming that evil-delete is the underlying workhorse that is called by evil-delete-line and about five other functions.) evil-delete takes optional parameters.

In a scheme, I'd write:

(define  original-evil-delete  evil-delete) ; capture the original binding

(define (evil-delete-then-gui-set-selection . args)
    "Delete, and copy deleted-text into the OS clipboard."
    (prog1 (apply original-evil-delete args)
           (gui-set-selection 'CLIPBOARD (current-kill 0))))

(set!  evil-delete  evil-delete-then-gui-set-selection)
; I want this "new" binding to be used in other functions that call `evil-delete`.

But between lisp's defvar-vs-defun distinction, possibly-dynamic scoping, and forwarding optional-args, I'm having a bit of trouble translating this scheme to elisp. Any help appreciated. (I don't think I need to worry about "interactive", at least?)

Also, if there is a better way of doing this -- e.g. some hook available -- then I'd appreciate hearing that too. Finally, it's not out-of-question that I instead make new versions of the ~dozen "wrapper" functions and re-bind all the keys to use these new versions, thereby avoiding most issues except forwarding-default-args.

2
  • 3
    Look at advising the function with after advice.
    – Dan
    Commented Dec 21, 2019 at 1:04
  • 3
    Advising functions
    – NickD
    Commented Dec 21, 2019 at 2:19

1 Answer 1

4

TL;DR: As mentioned by the comments on your initial question, you are looking for Advising Functions.


Even though this question has been idle for a while at the time of my writing this, I wanted to provide a formal answer, because the way in which you have phrased the (very valid) question is how someone unfamiliar with Emacs might phrase it — and helping the uninitiated is what StackExchange is all about, right?

Really, you just needed a different term, and you'd have your answer. With "Advice," you can "extend" functions' behavior before, during, and after their normal execution. You can re-write your original Scheme example pretty quickly like this:

(defun evil-delete-then-gui-set-selection (orig-fun &rest args)
  "Delete, and copy deleted-text into the OS clipboard."
  (let ((res (apply orig-fun args)))
    (gui-set-selection 'CLIPBOARD (current-kill 0))))

(advice-add 'evil-delete :around #'evil-delete-then-gui-set-selection)

Great! But we can even make this easier. Instead of wrapping the function, making sure to apply the parameters properly, and to capture the return value, you just want to add a little extra to the end. Do this:

(advice-add 'evil-delete :after
            #'(lambda () (gui-set-selection 'CLIPBOARD (current-kill 0))))

Just note that if you wish to remove the advice, a named function is easier. You also asked about adding it to multiple functions, so you could certainly do something like this:

(defun clear-gui-selection ()
  (gui-set-selection 'CLIPBOARD (current-kill 0)))

(mapc #'(lambda (advised-func) (advice-add advised-func #'clear-gui-selection))
      '(evil-delete other-func third-func))

We totally could get into the details of defun and how you might find an existing function definition and muck with it, but that's almost certainly not what you're looking for. What you're looking for is some good Emacs "advice."

(Note: I haven't run this on your evil-mode things; I just took what you had and translated it for simplicity. YMMV.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.