views:

340

answers:

3

Call me lame, but I'm tired of my subconscious C-x C-s nervous twitch. I am switching buffers often enough and I think I would like to save a certain buffer as soon as I switch to another. I have not had the time yet to learn Emacs-Lisp basics.

Any hints on how to do this, or better solutions?

(On a related note, I found an autosave workaround that can save the current buffer as soon as you are idle for a given amount of time.)

+4  A: 

I'm kind of new to emacs lisp myself but this works in my testing:

(defadvice switch-to-buffer (before save-buffer-now)
  (save-buffer))

(ad-activate 'switch-to-buffer)

It's kind of annoying though because it's called after EVERY buffer (like scratch). So, consider this answer a hint.

When you want to disable it, you'll need to call:

(ad-disable-advice 'switch-to-buffer 'before 'save-buffer-now)
(ad-activate 'switch-to-buffer)
seth
+1  A: 

A couple of ideas.

First, if you find yourself invoking a command like save with a sufficiently high frequency, you might consider a shorter key binding for the command. For example, I also found myself having the same "twitch," so now I use f2 instead of C-x C-s for saving edits.

The function that I bind to f2 saves every unsaved buffer unconditionally. You might find it useful:

(defun force-save-all ()
    "Unconditionally saves all unsaved buffers."
    (interactive)
    (save-some-buffers t))

(global-set-key [f2] 'force-save-all)

Now, on to the main issue. You could try something like this (notice that force-save-all is called):

(defun my-switch-to-buffer (buffer)
    (interactive (list (read-buffer "Switch to buffer: " (cadr buffer-name-history) nil)))
    (force-save-all)
    (switch-to-buffer buffer))

(global-set-key "\C-xb" 'my-switch-to-buffer)

Of course, you could also bind the switch buffer functionality to another key, like a function key, so that it's a one press operation.

I thought that @seth had a great idea about using advice, but I noticed that the ELisp manual suggests that advice not be used for key bindings. I'm not quite sure why this is the case, but that's what the manual suggests FYI.

Greg Mattes
Interesting. Didn't see that part about keybindings when I was reading the manual. Thanks.
seth
The only problem with this solution is when you e.g. start using `ido-switch-buffer`, you have to track down the changes in your function, too.
Török Gábor
That's true, I suppose you could rebind the switch-to-buffer symbol to this new function (saving the original in another symbol, e.g. orig-save-to-buffer)
Greg Mattes
+9  A: 

To expand on Seth's answer, I'd do this:

(defadvice switch-to-buffer (before save-buffer-now activate)
  (when buffer-file-name (save-buffer)))
(defadvice other-window (before other-window-now activate)
  (when buffer-file-name (save-buffer)))
(defadvice other-frame (before other-frame-now activate)
  (when buffer-file-name (save-buffer)))

The check for 'buffer-file-name avoids saving buffers w/out files. You need to figure out all the entry points you use for switching buffers that you care about (I'd also advise other-window).

Trey Jackson
+1 from me...forgot about buffer-file-name
seth