reddit / emacs

Emacs creates lock files despite being told not to

SnooPets20 · 2022-08-09 22:55
I absolutely hate when my projects leave traces of the tools I use. My projects should contain the source code of the program, and anything required for *it* to function, or directly related with it, nothing else. Emacs doesn't seem to think the same. It litters the directory you're editing with backup and lock files, and I don't understand why. While I seem to have been successful in stopping backup files from popping up, I can't do the same with lock files. Despite setting the variable `create-lockfiles` to nil, it still creates them. Ideally, I'd want these lock files to exist, just somewhere else. They shouldn't be where I'm editing. I don't really know how to control, this. There was a variable to change that but I always failed at setting it, complaining I was using the wrong type. Anyway, this code is what I have at the very top of my init file, this is all I need to keep my working directory (and my config folder) clean from Emacs' shenanigans. (setq user-emacs-directory (expand-file-name "~/.local/share/emacs")) (setq user-config-directory (expand-file-name "~/.config/emacs")) (setq native-comp-eln-load-path '((. "~/.local/share/emacs/eln-cache"))) (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) (setq package-user-dir (expand-file-name "elpa" user-emacs-directory)) (setq url-history-file (expand-file-name "url/history" user-emacs-directory)) (setq delete-old-versions t) (setq create-lockfiles nil) (setq auto-save-list-file-prefix (expand-file-name "auto-save-list/.saves-" user-emacs-directory)) (setq backup-directory-alist '(("." . "~/.local/share/emacs/backups"))) Does anybody know why Emacs STILL creates lock files where I'm editing? It's very annoying.
flexibeast · 2022-08-10 00:51
> There was a variable to change that but I always failed at setting it, complaining I was using the wrong type. i presume you're referring to the `lock-file-name-transforms` variable; could you share at least one of your attempts to set it?
SnooPets20 · 2022-08-10 01:59
Ah yes, I remember now. This is the variable which in its docs says that it behaves like another variable, whose value is an incomprehensible regex pattern. Sorry, I think I haven't actually attempted anything with this one, I simply don't understand it, I don't know where to start. I simply want these files to go to another directory, I don't care about how they're named (and that's what the variable name seems to imply).
flexibeast · 2022-08-10 02:54
Yeah, i find ELisp regex syntax Less Than Awesome to work with, particularly compared to e.g. PCREs. That said, there are various tools that can help with ELisp REs, such as `re-builder`, included in stock Emacs, and `xr`, available via GNU ELPA, which 'translates' ELisp REs to the 'rx' format, which many people find more understandable. Anyway, `lock-file-name-transforms` is a list of 'transforms', where each 'transform' is itself a list consisting of three items: a regex, the replacement text, and a boolean indicating whether to 'uniquify' the lock file name to try to prevent file name clashes. The regex specifies which buffer names this transform should be applied to. So say you want all buffers whose name ends in `.c` to have a lockfile in `/tmp`. The transform would be: ("^\\(.+\\.c\\)$" "/tmp/\\1" t) Breaking down the regex: ^ Matches the start of the buffer name. \\( Start a capture group. .+ One or more characters. \\. Literal '.' (because '.' usually means "any character"). c Literal character 'c'. \\) End the capture group. $ Matches the end of the buffer name. Whatever text is matched by this capture group is referenced by `\\1` ('1' meaning "the first capture group") in the replacement text. So if the buffer is called `file.c`, then the replacement text will end up being `/tmp/file.c`, 'uniquified' if necessary due to the presence of the `t` argument. Because the value of `lock-file-name-transforms` is a list of transforms, you need to put the transform into a list itself. So you'd end up with: (setq lock-file-name-transforms '(("^\\(.+\\.c\\)$" "/tmp/\\1" t))
mtert · 2022-08-10 03:18
Hey I'm just a bystander in this thread but I just gotta say that is some top-notch technical advice. Clear, thorough and helpful.
SnooPets20 · 2022-08-10 03:23
Ok thank you, this clears things up a ton. So if I want to apply this to all files, would this work? (setq lock-file-name-transforms '(("^(\\(.*\\)$") (concat user-emacs-directory \\1) t))
flexibeast · 2022-08-10 03:48
Not quite. Here's what you actually want: (setq lock-file-name-transforms `(("^\\(.*\\)$" ,(concat user-emacs-directory "\\1") t)) Explanation: The overall format of the variable can be described as: ( (REGEX-STRING REPLACEMENT-STRING UNIQUIFY) ADDITIONAL TRANSFORM LISTS ) where (REGEX-STRING REPLACEMENT-STRING UNIQUIFY) is a TRANSFORM LIST. However, * You had a stray `(` just after the `^`, which means that it will only match buffer names beginning with `(`. * You had a stray `)` after the close quote for the regex, which results in a list containing only the REGEX-STRING, not the other required components of a TRANSFORM LIST. * To use a function within a list, you need to use [backquoting](https://emacsdocs.org/docs/elisp/Backquote), which means using a backtick, \`, at the start of the list, and `,` before the form in the list that is to be evaluated. * The `\\1` needs to be a string for `concat`, so needs to be surrounded by double quotes. As a general note about regex syntax, `*` is often 'greedy', meaning it tries to match as much as possible, so should work here, but because it means "zero or more", in some use-cases it might match the empty string, which might not be what you want. EDIT: Gah, just noticed that the stray parentheses were in the code i provided at the end of my previous comment! Sorry about that. :-( Now fixed.
flexibeast · 2022-08-10 03:50
Thank you!
Faerryn · 2022-08-10 20:14
I do this: (let ((backups-dir (expand-file-name "backups/" user-emacs-directory)) (auto-saves-dir (expand-file-name "auto-saves/" user-emacs-directory)) (lockfiles-dir (expand-file-name "lockfiles/" user-emacs-directory)) (regexp (rx bos (* anychar) eos))) (mkdir backups-dir 'parents) (mkdir auto-saves-dir 'parents) (mkdir lockfiles-dir 'parents) (setf (alist-get regexp backup-directory-alist nil nil #'string-equal) backups-dir (alist-get regexp auto-save-file-name-transforms nil nil #'string-equal) (list auto-saves-dir t) (alist-get regexp lock-file-name-transforms nil nil #'string-equal) (list lockfiles-dir t)))