7

This question is inspired by https://emacs.stackexchange.com/a/5947/.

Assume that I have a function like

(defun do-some-actions () ()
(..put a copy of the current file in a specific folder...)
  )

And I would like that the above function to be run after saving files. The following hook can do the job:

(add-hook 'after-save-hook 'do-some-actions)

But in this way Emacs runs the function do-some-action even for the files which have not been manually saved. For instance when I install the packages via Melpa, Emacs itself saves some files with the name package_name-autoloads.el in the directory ~/.emacs.d/elpa/package_name/ and even though these files have not been saved manually, the function do-some-actions is executed.

My question is about the possibility to prevent Emacs to this after-save-hook when the file has not been saved manually.

4
  • 3
    You can probably create a my-save-buffer wrapper function that first calls (save-buffer) and then does do-some-actions and bind that to C-x C-s in a specific mode map or as a buffer-local binding. Aug 4, 2015 at 21:24
  • 4
    Alternatively, define what "saved manually" actually means (it could cover multiple commands, to my mind; M-x apropos-command RET save\|write RET may help), and then test those conditions in your hook function (e.g. by checking whether the this-command value is a member of your list of "saved manually" commands).
    – phils
    Aug 4, 2015 at 21:34
  • @phils Thank you for mentioning this-command, indeed very useful command. What I had in mind by manually saving was saving via save-buffer (C-x C-s). I think your comment to test if this-command has been save-buffer is the answer of my question. If you are comfortable please feel free to convert your comment to an answer.
    – Name
    Aug 4, 2015 at 21:57
  • @kaushalmodi thanks for your alternative solution which bypasses after-save-hook.
    – Name
    Aug 4, 2015 at 22:03

2 Answers 2

8

Firstly you need to define what "saved manually" actually means. It could cover multiple commands, to my mind. M-x apropos-command RET save\|write RET probably includes all the typical cases.

Once you know which commands you're interested in, you could simply test the this-command variable in your hook function, to see whether its value is a member of your list of "saved manually" commands.

e.g.:

(defun my-after-save-actions ()
  "Used in `after-save-hook'."
  (when (memq this-command '(save-buffer save-some-buffers))
    ;; put a copy of the current file in a specific folder...
    ))

(add-hook 'after-save-hook 'my-after-save-actions)
4
  • Isn't called-interactively-p what were looking for?
    – Nordlöw
    May 11, 2016 at 22:53
  • Nordlöw: How would that help?
    – phils
    May 11, 2016 at 23:11
  • See answer below.
    – Nordlöw
    May 11, 2016 at 23:21
  • That's fine, but is a completely different approach with a very specific definition of "saved manually". called-interactively-p just isn't relevant to my answer.
    – phils
    May 11, 2016 at 23:56
3

Here's an alternative solution:

(defcustom after-save-interactively-hook nil
  "Normal hook that is run after a buffer is saved interactively to its file.
  See `run-hooks'."
  :group 'files
  :type 'hook)

(defun save-buffer-and-call-interactive-hooks (&optional arg)
  (interactive "p")
  (save-buffer arg)
  (when (called-interactively-p 'all)  ;; run post-hooks only if called interactively
    (run-hooks 'after-save-interactively-hook)))

(global-set-key [(control x) (control s)] 'save-buffer-and-call-interactive-hooks)

(defun run-mode-specific-after-save-interactively-buffer-hooks ())

(add-hook 'after-save-interactively-hook 'run-mode-specific-after-save-interactively-buffer-hooks t)

that I use.

3
  • 1
    I'd suggest that if you've bound C-x C-s to a command you've written yourself, you could be reasonably sure that nothing is going to call that function non-interactively, unless you've written such code yourself (which would be pointless for this particular instance, of course).
    – phils
    May 11, 2016 at 23:57
  • That won't trigger in cases where saving is invoked by another command, such as C-x # in a server buffer, which is probably not what was desired. May 12, 2016 at 8:06
  • @Nordlöw I have need to use the filepath of the buffer I am saving. It seems I need to switch from a -hook to a abnormal -function to pass the buffer being saved The call to add-function fails however (add-function :after 'after-save-interactively-function 'run-mode-specific-after-save-interactively-buffer-hooks)
    – MMM
    Apr 15, 2021 at 0:52

Your Answer

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

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