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.
(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)
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.
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
(setq auto-save-interval 1)
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)