例えば「昨日まで書いてあったんだけど、もうあの内容は消しちゃったな
あ」ということは良くあると思います。
ずいぶん前から「現在の日時付きの名前で ~/.trash にバックアップして
から、セーブする関数」を使っています。結構便利です。ファイルは無限
に増えるので、cron 等で削除して下さい。
(defvar renban-copy-directory "~/.trash" "The directory for renban-copy.")
(defvar renban-copy-upper-limit-size (* 512 1024) "The upper limit of the file size for renban-copy.")
(defun renban-copy ()
"現在のバッファに対応するファイルを filename.year-date-time という
書式で `renban-copy-directory' にコピーします。
`renban-copy-upper-limit-size' より大きなサイズのファイルはコピー
しません。"
(unless renban-copy-directory
(error "%s is nil." (symbol-name 'renban-copy-directory)))
(let ((srcname buffer-file-name)
(dir (expand-file-name renban-copy-directory))
(dir-mode #o2700)
dstname)
(when (and srcname
(file-exists-p srcname)
(buffer-modified-p)
(<= (nth 7 (file-attributes srcname))
renban-copy-upper-limit-size))
(unless (file-exists-p dir)
(make-directory dir t))
(unless (eq dir-mode (file-modes dir))
(set-file-modes dir dir-mode))
(setq dstname
(expand-file-name
(concat
(file-name-nondirectory srcname)
"."
(format-time-string "%y-%m%d-%H%M%S"))
dir))
(message "Copying...")
(copy-file srcname dstname t nil)
(message "Copying...done."))))
renban-copy() は advice や関数と組み合わせて使います。
例1: save-buffer() に advice します。他の elisp プログラムから呼ば
れた場合も、バックアップされます。
(defadvice save-buffer
(before
save-buffer-before-advice
activate)
"save-buffer() の前に renban-copy() します。"
(renban-copy))
例2: 例1 とほぼ同じですが、バックアップする/しないを Ctrl-u で制御
できます。引数の意味が save-buffer() と逆になってしまう
ので、気にな
る人は気になるかもしれません。
(defadvice save-buffer
(before
save-buffer-before-advice
activate)
"save-buffer() の前に renban-copy() します。
ただし、引数が与えられたら renban-copy しません。"
(let ((arg (ad-get-arg 0)))
(if (or (null arg) (= arg 1))
(renban-copy))))
例3: Ctrl-x Ctrl-s した時だけバックアップします。例えば Mew のドラ
フトはバックアップされないので、残念な気持ちになることもあるかもし
れません。
(defun renban-copy-and-save (&optional arg)
"renban-copy() してから save-buffer() します。
ただし、引数が与えられたら renban-copy() しません。"
(interactive "P")
(unless arg (renban-copy))
(save-buffer))
(define-key ctl-x-map (kbd "C-s") 'renban-copy-and-save)
元ネタは blankspace -> tips
の my-backup-save() ですが、原型がほと
んどなくなってしまいました。こちらは現在のバッファをバックアップす
るので、微妙に動きが違います。
P.S.
ちょっとブログにアップするだけの予定だったのに、気がついたら関数を
だいぶ書き換えていました。アップ前は renban-copy() の中でセーブまで
していましたが、アップ後の方が汎用的で良いと思います。
追記(2010-03-14):
新規にファイルを作成し、セーブする場合に問題があったので、
renban-copy() を置き換えました。さらに 例2 も Mew のドラフトを作る
ときに問題があったので差し替えました…。