Search code examples
elisp

What is the correct way to edit an in-built function?


Say I want to add a hook to an in-built function, for example dired-find-file.

So I declare and add my hook as follow:

(defvar my/dired-find-file-hook nil)
(add-hook 'my/dired-find-file-hook 'my-find-file-function)

I now need to run (run-hooks 'my/dired-find-file-hook) at the end of dired-find-file, what is the best way to do this?

What I have been doing is just declaring the entire function again, as per the following, but this feels like a messy way to achieve this.

  (defun dired-find-file ()
    "In Dired, visit the file or directory named on this line."
    (interactive)
    ;; Bind `find-file-run-dired' so that the command works on directories
    ;; too, independent of the user's setting.
    (let ((find-file-run-dired t)
          ;; This binding prevents problems with preserving point in
          ;; windows displaying Dired buffers, because reverting a Dired
          ;; buffer empties it, which changes the places where the
          ;; markers used by switch-to-buffer-preserve-window-point
          ;; point.
          (switch-to-buffer-preserve-window-point
           (if dired-auto-revert-buffer
               nil
             switch-to-buffer-preserve-window-point)))
      (find-file (dired-get-file-for-visit)))
    (run-hooks 'my/dired-find-file-hook))

Is there a better way I should achieve this?


Solution

  • I think you're actually looking for "advice". Your example could be this:

    (define-advice dired-find-file (:after () my-find-file)
      "Display a message whenever `dired-find-file' is called."
      (message "I'm running after `dired-find-file'."))
    

    You could run a hook in that custom code, but I expect you'd just put all the code from my-find-file-function in here directly, in place of that message.

    See C-hig (elisp)Advice Combinators for the different ways in which your custom code can be executed relative to the original function.

    There are two different implementations of advice in Emacs. This example (and everything in the manual) is using nadvice.el which is the newer approach, but if you look around you may also find examples using advice.el which has lots of differences. defadvice is old-style advice.el, whereas define-advice and advice-add are new-style nadvice.el