10

I like the idea of .dir-locals.el. I have my own .dir-locals.el file in my home directory that should set all the variables for directories/files that I open unless there is .dir-locals.el closer to the directory I open the file in. However, even though the file is recognized, directory variables for subdirectories are not applied to opened files.

This is my ~/.dir-locals.el:

(("dev/school" .
  ((indent-tabs-mode . nil)
   (c-basic-offset . 4)))
 ("dev/test" .
  ((indent-tabs-mode . nil)
   (c-basic-offset . 4)))
 (c-mode .
  ((c-file-style . "linux")
   (c-basic-offset . 8))))

When I open file ~/dev/test/test.c the variable indent-tabs-mode is set to t and c-basic-offset is 8.

(describe-variable 'c-basic-offset) in that file tells me it is set to 8 from ~/.dir-locals.el.

(describe-variable 'indent-tabs-mode) in that file says it's value (t) is just in its default state.

Can I somehow achieve the desired behaviour? What am I doing wrong? How are file paths mapped to subdirectories in ~/.dir-locals.el?

Edit:

As Jonathan suggested, I also tried:

(;; dev/school subdir
 ("dev/school" .
  ;; dev/school specification for all modes
  (nil . ((indent-tabs-mode . nil)
          (c-basic-offset . 4)))))

and even what add-dir-local-variable added:

(("dev/school"
  (indent-tabs-mode)
  (c-basic-offset . 4)))

Unfortunately, none of those work either.

1 Answer 1

7

Based on the documentation in the manual, you are missing a portion of the subdir specification.

Sample .dir-locals.el

From the manual with comments for emphasis/clarification

(;; Dir settings
 (nil . ((indent-tabs-mode . t)
         (fill-column . 80)))
 (c-mode . ((c-file-style . "BSD")
            (subdirs . nil)))
 ;; Subdir specification
 ("src/imported" .
  ;; Subdir settings
  ((nil . ((change-log-default-name
            . "ChangeLog.local"))))))

Corrected .dir-locals.el

This is based on the assumption that you want the subdir specifications to apply to all modes. If you only want them to apply to c-mode replace nil with c-mode in the mode-specification.

(;; dev/school subdir
 ("dev/school" .
  ;; dev/school specification for all modes
  ((nil . ((indent-tabs-mode . nil)
           (c-basic-offset . 4)))))
 ;; dev/test subdir
 ("dev/test" .
  ;; dev/test specification for all modes
  ((nil . ((indent-tabs-mode . nil)
           (c-basic-offset . 4)))))
 ;; c-mode specification for dir + subdirs
 (c-mode .
  ((c-file-style . "linux")
   (c-basic-offset . 8))))
6
  • I misunderstood that example in the documentaiton, thank you for clarifying that. However, I tried your version (copy-paste) and it still behaves the same way. Even with 'emacs -Q'. Suggestions for debugging are welcomed, too.
    – nert
    May 28, 2015 at 20:22
  • I also tried using add-dir-local-variable and it was added to ~/.dir-locals.el with even shorter syntax than I used in the question: ("dev/test" (indent-tabs-mode)). Still doesn't work, though.
    – nert
    May 28, 2015 at 20:36
  • I think my version was missing some parens, I've added them in (looking it over compared to the sample and there should have been extra ones around the subdir specs ("dev/test" . ((spec1 ...) (spec2 ...) ...)) May 29, 2015 at 13:33
  • Yes, that works! The only problem now is that the mode variables take precedence over the directory ones, but since they are only related to c-mode I can set them with setq-default during init. Thank you very much.
    – nert
    May 29, 2015 at 14:24
  • 1
    That's strange. I did a test today using ((org-mode . ((org-indent-mode . t))) ("subdir" . ((nil . ((org-indent-mode . nil)))) and it worked properly (prompted to set local var to nil). Maybe try putting the root ones above the sub-dir specifications within the list, it's possible it sets it to the last value found. May 29, 2015 at 14:40

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.