9

I'd like to know if it is possible the buffer is saved at the exact moment of modification; at the instant of the key up event.

  • 1
    You will receive other answers, but you may be interested in the auto-save-buffers-enhanced: https://github.com/kentaro/auto-save-buffers-enhanced/blob/master/auto-save-buffers-enhanced.el – lawlist May 17 '15 at 03:37
  • 1
    Do you have a specific reason for wanting this? This would be pretty insane. I don't type fast, but I know even a fast SSD couldn't keep up with my typing. (At least not in emacs) – PythonNut May 17 '15 at 21:45

4 Answers4

11
(defun my-instant-save-buffer (eins zwei drei)
  "To be hooked into list `after-change-functions' 

`after-change-functions' expects functions receiving three arguments. 
Arguments are ignored here, but slots needed by add-hook"
  (save-buffer))

(add-hook 'after-change-functions 'my-instant-save-buffer)
Jordon Biondo
  • 12,332
  • 2
  • 41
  • 62
Andreas Röhler
  • 1,894
  • 10
  • 10
  • This should come with a warning: just because you *can* do it does not mean that you *should*. I haven't tested but I think that this is likely to impact performance substantially. – NickD Dec 17 '19 at 16:51
  • @NickD Agreed. However, just answered the question, not giving as hint of good practice. – Andreas Röhler Dec 19 '19 at 11:47
7

I had the same requirement and auto-save feature of emacs hasn't worked well for me because it can't addadvice to c functions. So, I wrote a package real-auto-save for that. It is available on melpa.

You can install it by

M-x package-install RET real-auto-save 

and in your config you can add

(require 'real-auto-save)
(add-hook 'prog-mode-hook 'real-auto-save-mode)
(setq real-auto-save-interval 1) ;; in seconds

After every second, if your buffer is modified, it will be saved automatically.

If you specifically want to save after key up event, you can write a lisp function for that.

Jordon Biondo
  • 12,332
  • 2
  • 41
  • 62
Chillar Anand
  • 4,042
  • 1
  • 23
  • 52
3

You can enable auto-save-mode, so Emacs automatically saves your current buffer in a different file. Then, add this function to auto-save-hook to also write it directly on the actual file you are editing:

(defun save-buffer-if-visiting-file (&optional args)
   "Save the current buffer only if it is visiting a file"
   (interactive)
   (if (and (buffer-file-name) (buffer-modified-p))
       (save-buffer args)))

(add-hook 'auto-save-hook 'save-buffer-if-visiting-file)

According to the Emacs manual on auto-save control:

The variable auto-save-interval specifies how many characters there are between auto-saves. By default, it is 300. Emacs doesn’t accept values that are too small: if you customize auto-save-interval to a value less than 20, Emacs will behave as if the value is 20.

So, if you want Emacs to save for every key press, change auto-save-interval to 1:

(setq auto-save-interval 1)
Jordon Biondo
  • 12,332
  • 2
  • 41
  • 62
Tu Do
  • 6,772
  • 20
  • 39
  • 3
    The manual you quoted says anything less than 20 will make Emacs behave as if the value is 20. How does it work with 1 then? – Hakan Serce Oct 28 '17 at 17:01
0

It's a little bit elaborated version of @andreas-röhler's answer somewhat adressing @NickD comment.

Saves after 50 milliseconds of inactivity and rapid buffer changes would not cause tons of savings.

(let ((timeout 0.05)
      (timers-alist nil))
  (cl-flet* ((get-timer (key)
                        (cdr (assoc key timers-alist)))
              (set-timer (key timer)
                        (push (cons key timer) timers-alist))
              (drop-timer (key)
                          (setq timers-alist (assoc-delete-all key timers-alist)))
              (save-buffer-and-drop-timer (buffer)
                                          (with-current-buffer buffer
                                            (progn
                                              (save-buffer)
                                              (drop-timer buffer))))
              (save-buffer-deffered (buffer)
                                    (unless (get-timer buffer)
                                      (set-timer buffer
                                                (run-with-idle-timer timeout
                                                                      nil
                                                                      #'save-buffer-and-drop-timer
                                                                      buffer)))))
    (defun save-file-buffer-deffered (&rest args)
      (if (buffer-file-name)
          (save-buffer-deffered (current-buffer))))))

(add-hook 'after-change-functions 'save-file-buffer-deffered)
Astery
  • 101
  • 3
  • It's doesn't addressing exact question, but where is nothing similar to this topic came up for me in search. – Astery Feb 28 '21 at 10:28