2

New to Emacs and Lisp. I'm trying to replicate BBEdit's automatic backups, that is:

  • create a subfolder for each day (2022-11-02)
  • include the date and time in the backup's filename (2022-11-02 21-45-07-123)

Managed to create one backup file by changing this code:

(defun my-make-backup-file-name (FILE)
    (let ((dirname (concat "~/Documents/Emacs/Emacs Backups/" (format-time-string "%Y-%m-%d/"))))
        (if (not (file-exists-p dirname)) (make-directory dirname t))
        
        (setq filenameWithExtension (file-name-nondirectory FILE))
        (setq filenameWithoutExtension (file-name-sans-extension filenameWithExtension))
        (setq filenameExtension (file-name-extension filenameWithExtension))
        (concat dirname filenameWithoutExtension " (" (format-time-string "%Y-%m-%d %H-%M-%S-%3N") ")." filenameExtension)   
    )
)

(setq make-backup-file-name-function #'my-make-backup-file-name)

But I'd also like to create a backup on every save. This code does it:

(setq vc-make-backup-files t)

(setq version-control t 
    kept-new-versions 10 
    kept-old-versions 0 
    delete-old-versions t 
    backup-by-copying t) 

;; Default and per-save backups go here:
(setq backup-directory-alist '(("" . "~/.emacs.d/backup/per-save")))
(defun force-backup-of-buffer ()
;; Make a special "per session" backup at the first save of each
;; emacs session.
(when (not buffer-backed-up)
  ;; Override the default parameters for per-session backups.
  (let ((backup-directory-alist '(("" . "~/.emacs.d/backup/per-session")))
        (kept-new-versions 3))
    (backup-buffer)))
;; Make a "per save" backup on each save.  The first save results in
;; both a per-session and a per-save backup, to keep the numbering
;; of per-save backups consistent.
(let ((buffer-backed-up nil))
  (backup-buffer)))
(add-hook 'before-save-hook  'force-backup-of-buffer)

But how can I make both codes work together?

(I'm not interested in the split into two folders (in the code example ~/.emacs.d/backup/per-save and ~/.emacs.d/backup/per-session), just trying to get Emacs to make a backup on every save with a custom filename into ~/Documents/Emacs/Emacs Backups/[YYYY-MM-DD].)

1 Answer 1

2

Got it. This code creates a backup file on each save. File path example: ~/Documents/Emacs/Emacs Backups/2022-11-04/todo (2022-11-04 00-28-00-674).org.

;;;; Create versioned backup file on every save into date hierachy  

;;;; Create YYYY-MM-DD subfolder and backup filename    
;;;; Based on: https://emacs.stackexchange.com/questions/28124/change-naming-scheme-for-backup-files/28145#28145    
(defun my-make-backup-file-name (FILE)  
    (let ((dirname (concat "~/Documents/Emacs/Emacs Backups/" (format-time-string "%Y-%m-%d/"))))   
    (setq backup-directory-alist '(("" . dirname))) 

    (if (not (file-exists-p dirname)) (make-directory dirname t))   

    (setq filenameWithExtension (file-name-nondirectory FILE))  
    (setq filenameWithoutExtension (file-name-sans-extension filenameWithExtension))    
    (setq filenameExtension (file-name-extension filenameWithExtension))    
    (concat dirname filenameWithoutExtension " (" (format-time-string "%Y-%m-%d %H-%M-%S-%3N") ")." filenameExtension)      
))  

(setq make-backup-file-name-function #'my-make-backup-file-name)    

;;;; Create versioned backup file on every save 
;;;; Based on: https://www.emacswiki.org/emacs/ForceBackups 
(setq version-control 'never    
    vc-make-backup-files t  
    backup-by-copying t)    

(defun force-backup-of-buffer ()    
    (when (not buffer-backed-up)    
        (setq buffer-backed-up t))  
    (let ((buffer-backed-up nil))   
        (backup-buffer))    
)   

(add-hook 'before-save-hook  'force-backup-of-buffer)   

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.