Compare commits

...
This repository has been archived on 2023-04-12. You can view files and clone it, but cannot push or open issues or pull requests.

7 Commits

Author SHA1 Message Date
contrapunctus 9e73f1f6ed Correct license statement 2023-04-12 20:09:16 +05:30
contrapunctus 6ddb39fe77 Add optional FILE parameter; fix handling of files without extensions 2022-01-31 20:08:02 +05:30
contrapunctus ba927feec1 Add autoload cookie 2021-11-28 21:33:03 +05:30
contrapunctus 0c67ad4523 Add MELPA shield 2021-11-27 09:50:31 +05:30
contrapunctus 2d22c2ecec Remove unnecessary concat (via riscy) 2021-11-26 13:42:46 +05:30
contrapunctus ae97fa4032 Handle compiler warning for string-remove-suffix 2021-11-24 08:46:30 +05:30
contrapunctus a3125395d3 Add :type for custom variable 2021-11-24 08:44:18 +05:30
2 changed files with 23 additions and 14 deletions

View File

@ -1,6 +1,8 @@
# async-backup
<a href="https://liberapay.com/contrapunctus/donate"><img alt="Donate using Liberapay" src="https://img.shields.io/liberapay/receives/contrapunctus.svg?logo=liberapay"></a>
[![MELPA](https://melpa.org/packages/async-backup-badge.svg)](https://melpa.org/#/async-backup)
Emacs has a built-in backup system, but it does not backup on each
save. It can be made to, but that makes saving really slow (and the
UI unresponsive), especially for large files.
@ -14,6 +16,6 @@ To enable for a specific file -
`M-x add-file-local-variable RET eval RET (add-hook 'after-save-hook #'async-backup nil t) RET`
# License
Chronometrist is released under your choice of [Unlicense](https://unlicense.org/) or the [WTFPL](http://www.wtfpl.net/).
`async-backup` is released under your choice of [Unlicense](https://unlicense.org/) or the [WTFPL](http://www.wtfpl.net/).
(See files [UNLICENSE](UNLICENSE) and [WTFPL](WTFPL)).

View File

@ -33,13 +33,15 @@
;;; Code:
(require 'cl-lib)
(eval-when-compile
(require 'subr-x))
(defgroup async-backup nil
"Backup on each save without freezing Emacs."
:group 'files)
(defcustom async-backup-location
(concat (locate-user-emacs-file "") "/async-backup")
(locate-user-emacs-file "async-backup")
"Path to save backups to."
:type 'directory)
@ -50,20 +52,25 @@
(defcustom async-backup-predicates '(identity)
"List of predicates which must all pass for a file to be backup up.
Each predicate must accept a single argemnt, which is the full
path of the file to be backed up.")
path of the file to be backed up."
:type '(repeat function))
(defun async-backup ()
"Backup file visited by current buffer."
(let* ((backup-root (string-remove-suffix "/" (expand-file-name async-backup-location)))
(input-file (buffer-file-name))
(file-name-base (file-name-base input-file))
(file-extension (file-name-extension input-file))
(file-directory (file-name-directory input-file))
;;;###autoload
(defun async-backup (&optional file)
"Backup FILE, or file visited by current buffer."
(let* ((backup-root (string-remove-suffix "/" (expand-file-name async-backup-location)))
(input-file (if file (expand-file-name file)
(buffer-file-name)))
(file-name-base (file-name-base input-file))
(file-extension (file-name-extension input-file))
(file-directory (file-name-directory input-file))
(output-directory (concat backup-root file-directory))
(output-file (concat output-directory
file-name-base
"-" (format-time-string async-backup-time-format)
"." file-extension)))
(output-file (concat output-directory
file-name-base
"-" (format-time-string async-backup-time-format)
(if file-extension
(concat "." file-extension)
""))))
(unless (file-exists-p output-directory)
(make-directory output-directory t))
(when (cl-every (lambda (predicate)