7

I found different solutions for keeping auto-save files out of the directory where the original file is located on the internet, including

(defconst emacs-tmp-dir (format "%s/%s%s/" "/t" "emacs" (user-uid)))
(setq backup-directory-alist
      `((".*" . ,emacs-tmp-dir)))
(setq auto-save-file-name-transforms
      `((".*" ,emacs-tmp-dir t)))
(setq auto-save-list-file-prefix
      emacs-tmp-dir)

which I currently use.

It works, but only for files on "shallow" levels of my deep directory tree. When editing files many directories down, I get an error message like this (which I partly censored because it got someone else's name in it):

Question

How do I get auto-save to work for these files?

Additional info

This page helped me solve the same problem for backup files ("How to set emacs so backups in one place with tree structure?") but I can't seem to figure out how to solve it for auto-save files. (Just leaving the link here in case the code has only be adapted slightly or someone who has the backup file problem stumbles across this question.)

UTF-8
  • 885
  • 6
  • 22
  • 1
    [This](https://github.com/zpinter/emacs.d/blob/master/pre-cask-config.el#L141-L150) looks promising. I am trying it now. – dmvianna Jan 11 '18 at 05:21
  • @dmvianna Why does the [configuration](https://github.com/zpinter/emacs.d/blob/master/pre-cask-config.el#L141-L150) `(setq auto-save-file-name-transforms \`((".*" ,emacs-tmp-dir t)))` look promising? The `UNIQUIFY` flag is set to t and therefore path is transformed into a long file name. That is exactly what you try to avoid. Isn't it? – Tobias Jan 12 '18 at 14:33

1 Answers1

3

You can avoid the removal of the directory component of auto-save files by setting the UNIQUIFY component in the entries of the variable auto-save-file-name-transforms to nil.

From the doc of auto-save-file-name-transforms:

Transforms to apply to buffer file name before making auto-save file name. Each transform is a list (REGEXP REPLACEMENT UNIQUIFY):

...

If the optional element UNIQUIFY is non-nil, the auto-save file name is constructed by taking the directory part of the replaced file-name, concatenated with the buffer file name with all directory separators changed to ‘!’ to prevent clashes.

In that case you have to make sure that the directory component of the buffer-auto-save-file-name refers to an existing directory. That is possible in auto-save-hook which is run just before saving the auto-save file.

If you want to try this strategy put the following stuff into your init file. But, make sure that there is no other part of your initialization fiddling with auto-save-file-name-transforms! Maybe the only entry in auto-save-file-name-transforms which you can keep is the one for tramp. That entry has a colon in its REGEXP.

Note that you should adapt the value of the option auto-save-dir-base to the needs of your operating system.

(defcustom auto-save-dir-base "/var/tmp/emacs-auto-save"
  "File name base for auto-save-dir.
The real auto save directory name is created by appending the UID of the user.
Restart of emacs required after changes."
  :group 'files
  :type 'directory)

(defun auto-save-ensure-dir ()
  "Ensure that the directory of `buffer-auto-save-file-name' exists.
Can be used in `auto-save-hook'."
  (cl-loop for buf in (buffer-list) do
       (with-current-buffer buf
         (when (and (buffer-file-name) ;; Is this buffer associated with a file?
            (stringp buffer-auto-save-file-name)) ;; Does it have an auto-save-file?
           (let ((dir (file-name-directory buffer-auto-save-file-name)))
         (unless (file-directory-p dir)
           (make-directory dir t)
           ))))))

(add-hook 'auto-save-hook #'auto-save-ensure-dir)

(defun auto-save-dir ()
  "Return the users auto save directory."
  (concat auto-save-dir-base (number-to-string (user-uid))))

(unless (file-directory-p (auto-save-dir))
  (make-directory (auto-save-dir)))

(add-to-list 'auto-save-file-name-transforms (list "\\`.*\\'" (concat (auto-save-dir) "\\&") nil) t)
Tobias
  • 32,569
  • 1
  • 34
  • 75
  • I need a solution that will work across operating systems. My difficulty might be different from the original poster. I either seem to get droppings within my projects or I get an error where the /tmp/emacs is set to a name that doesn’t exist. – dmvianna Jan 13 '18 at 00:54
  • @dmvianna You can set `auto-save-dir-base` depending on `system-type`. That should avoid the problem with the non-existent directory. – Tobias Jan 13 '18 at 00:57
  • How about `(defcustom auto-save-dir-base (format "%s/%s" temporary-file-directory "emacs-"))`? – dmvianna Jan 13 '18 at 09:38
  • Thanks, I was able to adapt your solution to my needs (different from the OP, as my problem was not having the `emacs-$UID` directory). – dmvianna Jan 13 '18 at 10:51