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.

Name
  • 7,689
  • 4
  • 38
  • 84
  • 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](http://emacs.stackexchange.com/q/519/115). – Kaushal Modi Aug 04 '15 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 04 '15 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 04 '15 at 21:57
  • @kaushalmodi thanks for your alternative solution which bypasses `after-save-hook`. – Name Aug 04 '15 at 22:03

2 Answers2

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)
phils
  • 48,657
  • 3
  • 76
  • 115
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.

Nordlöw
  • 487
  • 3
  • 12
  • 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 '16 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. – Gilles 'SO- stop being evil' May 12 '16 at 08: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 '21 at 00:52