Page 1 of 1

Auto backup hook

PostPosted: Sat Aug 10, 2013 10:11 pm
by sollidsnake
Hi all!
I'm a Vim user trying to migrate to Emacs. When using Vim I wrote a simple code (in vimscript) where it saves me a copy of my working file (with the file name plus date and time) everytime I open or save it.
I tried doing it with Emacs but ended up in a loophole. Here's what I wrote so far:

Code: Select all
(defvar autobk-default-dir "~/.emacsbk/")

(defun autobk-save ()
  "func description"
  (interactive)
  (defvar autobk-orignal-file-name buffer-file-name)
  (write-file (concat
          autobk-default-dir
          (buffer-name)
          "_"
          (shell-command-to-string "echo -n $(date +%Y-%m-%d)")
          ".bak"))
  (write-file autobk-orignal-file-name)
  (message buffer-file-name))

(add-hook 'before-save-hook 'autobk-save)

The loophole happens because I add the function autobk-save to the before-save-hook and inside autobk-save I try to save the file, which calls the hook which calls the function again and again. So I think I need a way to tell the write-file function inside autobk-save to not use the hook, right? I tried sniffing around the file.el code but haven't found a clue the could help me. I know this is probably a bad code and maybe also a bad question, but I'm still a beginner with lisp and I'm open to any suggestions.

Thank you in advance :)

Re: Auto backup hook

PostPosted: Tue Aug 13, 2013 6:03 pm
by nuntius
sollidsnake wrote:The loophole happens because I add the function autobk-save to the before-save-hook and inside autobk-save I try to save the file, which calls the hook which calls the function again and again. So I think I need a way to tell the write-file function inside autobk-save to not use the hook, right?)


Maybe you could use a dynamic variable to detect and break out of the recursion?

http://www.gnu.org/software/emacs/manua ... nding.html

Re: Auto backup hook

PostPosted: Thu Aug 15, 2013 8:36 am
by edgar-rft
If I use the internal C function `write-region' instead of `write-file' from "files.el", then the following code works with my Emacs23, because `write-region' doesn't call the Emacs file-hooks:

Code: Select all
(defvar autobk-default-dir (expand-file-name "~/.emacsbk/"))

(defun autobk-save ()
  "Write the entire buffer contents as text to a backup file."
  (interactive)
  (write-region nil nil (format "%s%s_%s.bak" autobk-default-dir (buffer-name)
                          (format-time-string "%Y-%m-%d" (current-time)))))
 
(add-hook 'before-save-hook 'autobk-save)

Note that in contrast to the `write-file' function, `write-region' is a plain and stupid "write buffer contents to destination" function that doesn't check if the "~/.emacsbk/" directory exists or is writable at all. But it writes an error message to the *Messages* buffer if something goes wrong. The first two nil arguments mean "write the entire buffer contents as text, don't care about anything else".

The `autobk-save' function could be improved by adding Elisp code to check if the directory exists and is writable, or automatically creates the directory if it doesn't exist. See the Elisp manual, chapter "Files" that also describes the functions for directories which on Unix and Linux are files as well.

Another alternative would be to use Elisp functions like `copy-file' for simple harddisk "copy and rename" operations *before* opening and *after* saving a file.

- edgar