14

I would like to set the major mode for a file as you would using file-local variables

Local Variables:
mode: text
End:

but in .dir-locals.el in order not to “pollute” the file in question. Is this possible?

3
  • Is this purely for personal use, or something you want to be shareable? There are several ways you can tackle this in elisp, rather than resorting to directory-local variables.
    – phils
    Nov 14, 2015 at 5:12
  • @phils It would be nice to have a shareable solution, which is why I thought about dir-locals. But practically, it is more or less personal. (Unlikely to be shared with many people, and who knows if they use emacs and/or care).
    – xebtl
    Nov 15, 2015 at 20:20
  • Ok. I think utilising the eval pseudo-variable is the only way to handle it in a .dir-locals.el file. For custom elisp, you might just look at using auto-mode-alist to match the filename regexp (you can use regexp-quote to create patterns for verbatim string values, if necessary).
    – phils
    Nov 15, 2015 at 20:52

3 Answers 3

6

It's possible to specify a string instead of a mode, but this only works for subdirectories. So I'll use nil instead to match all modes, then the eval key to change the major mode conditionally:

((nil
  (eval
   (lambda ()
     (when (string= (file-name-nondirectory buffer-file-name)
                    "file-name.extension")
       (my-mode))))))

A downside of this approach is that the eval key is unsafe, so you'll need to confirm the variable permanently for this to have an effect.

2
  • Thanks, this works. Could someone explain the difference with the following form? ``` ((nil . ((eval . (lambda () (when (string= (file-name-nondirectory (buffer-name)) "filename") (my-mode))))))) ``` May 15, 2020 at 4:32
  • When I try to apply the mode using this I've got (error "Lisp nesting exceeds ‘max-lisp-eval-depth’") because it keeps trying to apply the mode in a loop.
    – jcubic
    Sep 24, 2021 at 18:03
5

The following .dir-locals.el works just fine for me to set the major mode of all files in a directory to shell-script-mode:

((nil . ((mode . shell-script))))

The obvious downside is that you can't specify the major mode for only a given subset of files in the directory.

Addendum: Amusingly, it also has the side effect of setting the major mode of .dir-locals.el itself to shell-script-mode.

Addendum 2: Rather more amusingly, it also has the side effect of setting the major mode of Dired buffers to shell-script-mode, making it impossible to open any (as an error is thrown during the initialization).

0
0

For me accepted answer give error:

(error "Lisp nesting exceeds ‘max-lisp-eval-depth’")

Because it tried to apply the mode recursively, when it open a file it executed a mode and if the mode was changed it executed the eval again recursively:

For me this works:

((nil (eval
       (lambda ()
         (when (and (string-match-p "\\.js\\'" buffer-file-name)
                    (not (string= (major-mode) "rjsx-mode")))
           (rjsx-mode))))))

For rjsx-mode that I wanted to apply for all js file in project directory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.