Emacs でバックアップを有効にすると ~ で始まるバックアップファイルが大量にできて見苦しく,以前はバックアップをオフにして使っていた.ところが最近,ESS を使ってトライアンドエラーでスクリプトを書くことが多くなり,git コミットよりも短いスパンで変更を戻したい場合が多くなった.そこで,Emacs 標準のバージョン管理ツールを,自分の使いやすいようにカスタマイズすることにした.
書いた emacs lisp はこんなところ.バックアップファイルは Emacs の version-control に従ってナンバリングされ,ファイルを閉じたときに同時に削除.保存場所は ls にひっかからないよう,ディレクトリごとに .bak サブディレクトリを作成し,その下に保存することにした.
;;; Use emacs version-control, saving in .bak directory (setq make-backup-files t) (setq version-control t) (defun backup-dir (fpath) (expand-file-name ".bak/" (file-name-directory fpath))) (defun make-backup-file-name (fpath) (let ((backup-dir (backup-dir fpath))) (if (not (file-exists-p backup-dir)) (make-directory backup-dir)) (concat backup-dir (file-name-nondirectory fpath) "~"))) (defun find-backup-file-name (fpath) (cons (let ((backup-dir (backup-dir fpath)) (fname (file-name-nondirectory fpath)) (version 1)) (defun vfpath (v) (concat backup-dir fname ".~" (number-to-string v) "~")) (if (not (file-exists-p backup-dir)) (make-directory backup-dir)) (while (file-exists-p (vfpath version)) (setq version (1+ version))) (vfpath version)) nil)) ;;; Delete backup files when the buffer is killed (defun delete-backup-files (fpath) (if fpath (let ((backup-dir (backup-dir fpath)) (fname (file-name-nondirectory fpath))) (dolist (vfpath (file-expand-wildcards (concat backup-dir fname "*~"))) (delete-file vfpath))))) (add-hook 'kill-buffer-hook (lambda () (delete-backup-files buffer-file-name))) (add-hook 'kill-emacs-hook (lambda () (dolist (buffer (buffer-list)) (if (buffer-file-name buffer) (delete-backup-files (buffer-file-name buffer)))))) ;;; Make a copy of the newest version (defun make-dup-file (fpath) (if fpath (let ((backup-dir (backup-dir fpath)) (fname (file-name-nondirectory fpath))) (if (not (file-exists-p backup-dir)) (make-directory backup-dir)) (write-region nil nil (concat backup-dir fname) nil 1)))) (add-hook 'after-save-hook (lambda () (make-dup-file buffer-file-name)))