24

Is it possible to configure Emacs, so that it saves all files when the emacs window loses focus?

viam0Zah
  • 25,949
  • 8
  • 77
  • 100
Rockiger
  • 422
  • 3
  • 11

5 Answers5

33

I added focus hooks to Gnu Emacs 24.4.

They are called focus-in-hook and focus-out-hook.

You can add

(defun save-all ()
  (interactive)
  (save-some-buffers t))

(add-hook 'focus-out-hook 'save-all)

to your .emacs file and it should save all files on loss of focus.

bonkydog
  • 2,012
  • 20
  • 11
  • 2
    One liner: `(add-hook 'focus-out-hook (lambda () (interactive) (save-some-buffers t)))` –  Mar 19 '16 at 15:32
  • The docs seem to imply that your first note no longer applies--is that right? After a quick test, it seems that `focus-out-hook` is not run when the window manager changes focus between emacs frames (that are from the same emacs instance). Maybe the addition of `handle-switch-frame` altered the behavior you described? – ohspite Jan 26 '17 at 16:35
  • @ohspite Looks like you're right. Thanks for the update. – bonkydog Jan 27 '17 at 21:12
  • Is is possible to disable this for specific modes? – alper Dec 08 '22 at 01:32
10

I use this, it will only work if emacs is running under X (like it probably would in something like ubuntu).

(when
   (and (featurep 'x) window-system)
 (defvar on-blur--saved-window-id 0 "Last known focused window.")
 (defvar on-blur--timer nil "Timer refreshing known focused window.")
 (defun on-blur--refresh ()
   "Runs on-blur-hook if emacs has lost focus."
   (let* ((active-window (x-window-property
                          "_NET_ACTIVE_WINDOW" nil "WINDOW" 0 nil t))
          (active-window-id (if (numberp active-window)
                                active-window
                              (string-to-number
                               (format "%x00%x"
                                       (car active-window)
                                       (cdr active-window)) 16)))
          (emacs-window-id (string-to-number
                            (frame-parameter nil 'outer-window-id))))
     (when (and
            (= emacs-window-id on-blur--saved-window-id)
            (not (= active-window-id on-blur--saved-window-id)))
       (run-hooks 'on-blur-hook))
     (setq on-blur--saved-window-id active-window-id)
     (run-with-timer 1 nil 'on-blur--refresh)))
 (add-hook 'on-blur-hook #'(lambda () (save-some-buffers t)))
 (on-blur--refresh))
  • Works on Ubuntu as advertised, and doesn't require making Emacs the center of one's workflow. – Ajit George Mar 19 '13 at 15:55
  • This is absolutly awesome, finally the solution to the problem and no workaround. – Rockiger Aug 20 '13 at 16:52
  • I believe the right format string should be "%x%04x" - for me (Ubuntu 12.04) the secondary Emacs frames have IDs that don't work with your hook. (Based on experiments only, could not find any documentation on this.) – volferine Nov 25 '13 at 12:56
2

Not sure if this is what you want.

(defun dld-deselect-frame-hook ()
  (save-some-buffers 1))

(add-hook 'deselect-frame-hook 'dld-deselect-frame-hook)

From: http://www.dribin.org/dave/blog/archives/2003/09/10/emacs/

EDIT: It only seems to work in XEmacs

2

[…] the feature I am talking about is from Scribes. It is very convient when editing html and the like, you don't have to press C-x C-s anymore, you just change the window and check your browser.

In that case, instead of switching to the browser application, order Emacs to load the browser application (C-c C-v or M-x browse-url-of-buffer). With this method, you can write your own function that saves the buffer and then brings the browser up, like:

(defun my-browse-url-of-buffer ()
  "Save current buffer and view its content in browser."
  (interactive)
  (save-buffer)
  (browse-url-of-buffer))

And hook it to a convenient binding.

Or you can still use the html-autoview-mode that each time you saves the buffer, automatically loads the file into your favorite browser.

viam0Zah
  • 25,949
  • 8
  • 77
  • 100
  • This sounds like an interesting solution. I will try this. But I am still a bit suprised, that Emacs can't react on somthing like changing focus. – Rockiger Aug 11 '09 at 19:44
  • @Rockiger it seems that Emacs doesn't provide a way to hook to the unfocus event. – viam0Zah Aug 12 '09 at 15:45
1

You can use `auto-save-interval' to save every n characters you type. Mine is set to 100. So about every 2-3 lines of code, maybe?

auto-save-interval is a variable defined in `C source code'. Its value is 100

Documentation: *Number of input events between auto-saves. Zero means disable autosaving due to number of characters typed.

You can customize this variable.

This doesn't answer your original question; it's just a way to achieve something similar.

EfForEffort
  • 55,816
  • 4
  • 36
  • 41
  • I know, the feature I am talking about is from Scribes. It is very convient when editing html and the like, you don't have to press C-x C-s anymore, you just change the window and check your browser. – Rockiger Aug 08 '09 at 08:53