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.

nert
  • 213
  • 1
  • 6

1 Answers1

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))))
Jonathan Leech-Pepin
  • 4,307
  • 1
  • 19
  • 32
  • 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 '15 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 '15 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 ...) ...))` – Jonathan Leech-Pepin May 29 '15 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 '15 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. – Jonathan Leech-Pepin May 29 '15 at 14:40
  • Yes, that was it. I originally started with that sequence, but I changed it a lot in order to find the problem before asking here. – nert May 31 '15 at 15:54