Compare commits
7 Commits
production
...
developmen
Author | SHA1 | Date |
---|---|---|
contrapunctus | 9e73f1f6ed | |
contrapunctus | 6ddb39fe77 | |
contrapunctus | ba927feec1 | |
contrapunctus | 0c67ad4523 | |
contrapunctus | 2d22c2ecec | |
contrapunctus | ae97fa4032 | |
contrapunctus | a3125395d3 |
|
@ -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)).
|
||||
|
|
|
@ -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)
|
||||
|
|
Reference in New Issue