DirectoryVariables

See also: LocalVariables, FileLocalVariables

From the manual, Directory Variables

If you put a file with a special name .dir-locals.el in a directory, Emacs will read it when it visits any file in that directory or any of its subdirectories, and apply the settings it specifies to the file’s buffer. Emacs searches for `.dir-locals.el’ starting in the directory of the visited file, and moving up the directory tree.

The `.dir-locals.el’ file should hold a specially-constructed list. This list maps Emacs mode names (symbols) to alists; each alist specifies values for variables to use when the respective mode is turned on. The special mode name ‘nil’ means that its alist applies to any mode. Instead of a mode name, you can specify a string that is a name of a subdirectory of the project’s directory; then the corresponding alist applies to all the files in that subdirectory.

Here’s an example of a `.dir-locals.el’ file:

     ((nil . ((indent-tabs-mode . t)
              (tab-width . 4)
              (fill-column . 80)))
      ;; Warn about spaces used for indentation:
      (haskell-mode . ((eval . (highlight-regexp "^ *"))))
      (c-mode . ((c-file-style . "BSD")))
      (java-mode . ((c-file-style . "BSD")))
      ("src/imported"
       . ((nil . ((change-log-default-name . "ChangeLog.local"))))))

Note that values are not evaluated. However, as in the haskell-mode instance above, you can use the special eval pseudo-variable to evaluate arbitrary code. Remember that when you do this you are no longer dealing with buffer-local variables, but simply evaluating elisp in the current context! e.g.: (eval . (setq foo "bar")) would only set a buffer-local value for foo if that variable was automatically buffer-local.

Notation

Sometimes you’ll see examples of .dir-locals.el files using fewer dots and parentheses, and the difference (or indeed equivalence) between the different ways of formatting them might be confusing, so you may wish to read the Dotted Pair Notation page of the manual:

    (info "(elisp) Dotted Pair Notation")

Note that the ‘add-dir-local-variable’ command updates the file using non-dotted notation.

Without a .dir-locals.el file

You can also configure directory local variables purely in elisp (i.e. without using a .dir-local.el file). The following example uses TrampMode paths, and therefore requires directory variable support for remote files to have been enabled (see below).

    (dir-locals-set-class-variables
     'plone-core
     '((nil . ((buffer-read-only . t)))))
    
    (dir-locals-set-class-variables
     'plone-instance
     '((nil . ((indent-tabs-mode . nil)
               (fill-column . 80)))
       ;; (python-mode . (()))
       ))
    
    (dir-locals-set-directory-class
     "/scpc:(user)@(host):/home/(user)/Plone/" 'plone-core)
    
    (dir-locals-set-directory-class
     "/scpc:(user)@(host):/home/(user)/Plone/zinstance/" 'plone-instance)

Change log

As of Emacs 24:

As of Emacs 24.3:

Remote files (via Tramp)

(See TrampMode.)

For performance reasons, Emacs will not attempt to apply directory local variables to buffers visiting remote files (via tramp); however it can be configured to do so, if you are willing to incur the associated performance cost (which can be relatively minimal in some situations).

In Emacs 24.3+, see the ‘enable-remote-dir-locals’ variable.

For earlier versions we can advise ‘hack-dir-local-variables’ to work around the default behaviour:

    ;; Enable directory local variables with remote files. This facilitates both
    ;; the (dir-locals-set-class-variables ...)(dir-locals-set-directory-class ...)
    ;; and the .dir-locals.el approaches.
    (defadvice hack-dir-local-variables (around my-remote-dir-local-variables)
      "Allow directory local variables with remote files, by temporarily redefining
    `file-remote-p' to return nil unconditionally."
      (flet ((file-remote-p (&rest) nil))
        ad-do-it))
    (ad-activate 'hack-dir-local-variables)