• 作成:

Emacsの標準バックアップ機能で初回保存時に限らず常にバックアップするようにする

Emacsには標準でファイルバックアップ機能があります.

(custom-set-variables
 '(backup-directory-alist `(("" . ,(concat user-emacs-directory "file-backup/"))))
 '(delete-old-versions t)            ;askだと削除時に一々聞いてくる
 '(kept-new-versions 50)             ;backupに新しいものをいくつ残すか
 '(kept-old-versions 0)              ;backupに古いものをいくつ残すか
 '(make-backup-files t)              ;バックアップファイルを作成する。
 '(vc-make-backup-files t)           ;VCS以下のファイルもバックアップを作成する
 '(version-control t)                ;複数バックアップ
 )

の様に設定することで, ~/.emacs.d/file-backup/に複数のバージョンのバックアップを保存することができます.

しかし, この標準のバックアップシステムには問題があります.

save-bufferは、バックアップの作成に責任がある。通常、backup-optionはnilであり、save-bufferは、ファイルを訪問してから最初に保存するときにのみバックアップファイルを作成する。 backup-optionが別の値であると、別の場面でもバックアップファイルを作成することを指示する。

GNU Emacs Lispリファレンスマニュアル: Saving Buffers

このように, save-buffer時によるファイルバックアップはそのEmacsセッションの最初の保存時にしかバックアップを保存してくれないのです.

Emacsが書かれた時代にはディスク容量は貴重だったので, それで良かったのかもしれませんが, 今はそんなところでケチられても全く嬉しくないですね.

backup-each-save.el : Emacs式大富豪的バックアップ!保存する度に日時付きファイルでバックアップ

のような拡張機能を使っても良いのですが, せっかく標準にバックアップ機能があるのですから標準のものを使いたいですよね.

ファイルを保存するたびに標準バックアップが走るようにしたい.

Emacsで保存する度に、保存時刻付きのバックアップファイルを1つのディレクトリに作る - 理系的芋のチラ裏の様にC-x C-ssave-bufferにオプションを付けても良いのですが, これはC-x sで走るsave-some-buffersに効果が無さそうですね.

save-some-bufferssave-bufferを呼び出しているので, save-bufferを弄って毎回保存されるようにすれば, 解決できそうです.

save-bufferの中身を見ると, 引数が指定された場合はbuffer-backed-upnilにしているようです. きっとこれがバッファが既にバックアップされてるかを示す変数ですね.

というわけで,

(defun setq-buffer-backed-up-nil (&rest _) (interactive) (setq buffer-backed-up nil))
(advice-add 'save-buffer :before 'setq-buffer-backed-up-nil)

このようにhookをかけてやることで初回保存時に限らず毎回バックアップファイルを保存するようになります.

version-controlを設定して複数バックアップを有効にして, kept-new-versionsを増やしていないと, あっという間に古いバックアップファイルが消えてしまうので注意してください.

しかし, 改善はしましたが正直言ってEmacsの標準バックアップ機能は微妙ですね… ファイルごとに最大件数を指定するという思想が微妙です. 時刻を保存して, 最大バックアップ使用量を超えたら古いバックアップから消していくなどの対応が欲しいです. もっと言えば前回との差分をガンガン保存していってその時点のファイルを抽出する簡易CVSのような機能が欲しいですね. まあ, バックアップなんてそんなに真面目に使った記憶が無いので簡易なものでも困らないのですが.