I'm writing my first .dir-locals.el
, and I'm getting an error in *Messages*
.
Code:
(eval-after-load "grep"
'(add-to-list 'grep-find-ignored-directories "blur"))
Trace:
.dir-locals error: Wrong type argument: listp, eval-after-load
What am I doing wrong?
The general format for .dir-locals.el
is described here:
(emacs) Directory Variables
RETTo evaluate code, you must use the special pseudo variable name eval
, as described at:
(emacs) Specifying File Variables
RETe.g.:
((nil . ((indent-tabs-mode . t)
(eval . (eval-after-load "grep"
'(add-to-list 'grep-find-ignored-directories "blur")))
(fill-column . 80)))
(c-mode . ((c-file-style . "BSD")
(subdirs . nil))))
However, grep-find-ignored-directories
is not an automatic buffer-local variable, and we are not explicitly setting it as a directory local variable here (the 'local variable' in question here is eval
), so when grep-find-ignored-directories
gets set this way it is set globally, which is surely not what you intended1.
You might try something like this:
((nil . ((eval . (eval-after-load "grep"
'(add-to-list
(make-local-variable 'grep-find-ignored-directories)
"blur"))))))
but in fact that's still wrong, as once you have visited a file under this directory, that eval-after-load
(which is a global setting) will be triggered as soon as grep
is loaded, no matter which buffer you are in at the time, so you could easily add your "blur" value locally in some unwanted buffer from which you called grep, while also failing to add it for any of the previously-visited buffers in which you wanted it.
The simplest solution is probably to forcibly require grep before setting the variable:
((nil . ((eval . (progn
(require 'grep)
(add-to-list
(make-local-variable 'grep-find-ignored-directories)
"blur"))))))
That ensures that all files under the directory will get the local value (and that files elsewhere will not).
Now, that's one approach to the general problem, but taking a look at this specific case, and C-hv grep-find-ignored-directories
, this variable provide some functionality which can make the solution simpler, and not require grep to be loaded unnecessarily.
Your .dir-locals.el file can set a local variable thus:
((nil . ((my-ignore-blur-p . t))))
And in your .emacs you can do the following:
(defun my-ignore-blur-p (dir)
"Return non-nil when the `my-ignore-blur-p' local variable is set."
(local-variable-if-set-p 'my-ignore-blur-p))
(eval-after-load "grep"
'(add-to-list 'grep-find-ignored-directories
(cons 'my-ignore-blur-p "blur")))
Then when you execute rgrep
from any buffer in which this local variable is set, the custom function we have specified in the global grep-find-ignored-directories
variable will return a non-nil
value, which will cause "blur" to be included in the list of ignored directories.
(n.b. I used the same name for both the function and the variable because I can -- elisp has separate name spaces for variables and functions -- but that's not necessary. For clarity, I'm referring to the function in the eval-after-load
code, and the variable in the function code and the .dir-locals.el file).
Or you could just base the behaviour of the my-ignore-blur-p
function on the dir
argument (being the directory being searched), and ignore local variables altogether. That would make the decision to include or omit "blur" from the list completely independent of the buffer from which you initiated the rgrep command, which might be even more desirable.
1 If adding "blur" to grep-find-ignored-directories
globally is what you wanted, then don't use .dir-locals.el
at all -- just add your eval-after-load
call to your .emacs file.