2023-12-23 16:24:30 +08:00

127 lines
4.2 KiB
EmacsLisp

;; -*- coding: utf-8; -*-
;;; Require:
;;; Code:
(defgroup auto-save nil
"Auto save file when emacs idle."
:group 'auto-save)
(defcustom auto-save-idle 1
"The idle seconds to auto save file."
:type 'integer
:group 'auto-save)
(defcustom auto-save-silent nil
"Nothing to dirty minibuffer if this option is non-nil."
:type 'boolean
:group 'auto-save)
(defcustom auto-save-delete-trailing-whitespace nil
"Delete trailing whitespace when save if this option is non-nil.
Note, this option is non-nil, will delete all training whitespace execpet current line,
avoid delete current indent space when you programming."
:type 'boolean
:group 'auto-save)
(defvar auto-save-disable-predicates
nil "disable auto save in these case.")
;; Emacs' default auto-save is stupid to generate #foo# files!
(setq make-backup-files nil)
(setq auto-save-default nil)
(setq create-lockfiles nil)
(defun auto-save-buffers ()
(interactive)
(let ((autosave-buffer-list))
(ignore-errors
(save-current-buffer
(dolist (buf (buffer-list))
(set-buffer buf)
(when (and
;; Buffer associate with a filename?
(buffer-file-name)
;; Buffer is modifiable?
(buffer-modified-p)
;; Yassnippet is not active?
(or (not (boundp 'yas--active-snippets))
(not yas--active-snippets))
;; Company is not active?
(or (not (boundp 'company-candidates))
(not company-candidates))
;; Corfu is not active?
(or (not (boundp 'corfu--total))
(zerop corfu--total))
;; Org-capture is not active?
(not (eq (buffer-base-buffer (get-buffer (concat "CAPTURE-" (buffer-name))))
buf))
;; tell auto-save don't save
(not (seq-some (lambda (predicate)
(funcall predicate))
auto-save-disable-predicates)))
(push (buffer-name) autosave-buffer-list)
(if auto-save-silent
;; `inhibit-message' can shut up Emacs, but we want
;; it doesn't clean up echo area during saving
(with-temp-message ""
(let ((inhibit-message t))
(basic-save-buffer)))
(basic-save-buffer))
))
;; Tell user when auto save files.
(unless auto-save-silent
(cond
;; It's stupid tell user if nothing to save.
((= (length autosave-buffer-list) 1)
(message "# Saved %s" (car autosave-buffer-list)))
((> (length autosave-buffer-list) 1)
(message "# Saved %d files: %s"
(length autosave-buffer-list)
(mapconcat 'identity autosave-buffer-list ", ")))))
))))
(defun auto-save-delete-trailing-whitespace-except-current-line ()
(interactive)
(when auto-save-delete-trailing-whitespace
(let ((begin (line-beginning-position))
(end (point)))
(save-excursion
(when (< (point-min) begin)
(save-restriction
(narrow-to-region (point-min) (1- begin))
(delete-trailing-whitespace)))
(when (> (point-max) end)
(save-restriction
(narrow-to-region end (point-max))
(delete-trailing-whitespace)))))))
(defvar auto-save-timer nil)
(defun auto-save-set-timer ()
"Set the auto-save timer.
Cancel any previous timer."
(auto-save-cancel-timer)
(setq auto-save-timer
(run-with-idle-timer auto-save-idle t 'auto-save-buffers)))
(defun auto-save-cancel-timer ()
(when auto-save-timer
(cancel-timer auto-save-timer)
(setq auto-save-timer nil)))
(defun auto-save-enable ()
(interactive)
(auto-save-set-timer)
(add-hook 'before-save-hook 'auto-save-delete-trailing-whitespace-except-current-line)
)
(defun auto-save-disable ()
(interactive)
(auto-save-cancel-timer)
(remove-hook 'before-save-hook 'auto-save-delete-trailing-whitespace-except-current-line)
)
(provide 'auto-save)
;;; auto-save.el ends here