/usr/share/emacs/site-lisp/emacs-goodies-el/dir-locals.el is in emacs-goodies-el 35.12.
This file is owned by root:root, with mode 0o655.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | ;;; dir-locals.el --- Local variables for a directory tree
;; Copyright (C) 2005, 2006 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: files
;; $Revision: 1.1 $
;; URL: http://www.loveshack.ukfsn.org/emacs
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; It can be useful to specify local variables directory-wide, e.g. to
;; define CC mode styles consistently. This library implements such a
;; scheme, controlled by the global minor mode `dir-locals-mode'.
;; Place a file named `.emacs-locals' (or the value of
;; `dir-locals-file-name') in the directory root. This should specify
;; local variables in the usual way. The values it sets are inherited
;; when a file in the directory tree is found. Local variables
;; specified in the found file override the directory-wide ones.
;; However, `eval' pseudo-variables specified in the file are
;; evaluated (assuming `enable-local-eval' is true) _before_ any
;; directory-wide processing, and they are evaluated in a scratch
;; buffer, so that they are only useful for side effects on local
;; variables. `mode' pseudo-variables which specify minor modes
;; toggle those modes for files within the directory. If
;; .emacs-locals specifies a major mode, it doesn't propagate, but any
;; local variables and minor modes its hook sets will; thus it should
;; normally not specify a major mode. The `coding' pseudo-variable
;; will not propagate from .emacs-locals.
;; For example, with dir-locals mode on, placing this in .emacs-locals
;; at the top-level of the Linux source tree would set the C
;; indentation style appropriately for files within the tree:
;;
;; Local variables:
;; c-file-style: "linux"
;; End:
;;
;; (and ignore the stupid remarks in Documentation/CodingStyle).
;; Another possible use is, say, setting change-log parameters in
;; different trees for which the Emacs 22 development source broke use
;; of change-log-mode-hook.
;; NB: This doesn't work with some versions of the Emacs 22 codebase
;; which changed the way hack-local-variables-hook is run, but the
;; change has been reverted.
;; Another, less clean, implementation of this sort of thing was
;; posted to gnu-emacs-sources as dirvals.el by Benjamin Rutt
;; <rutt.4@osu.edu>, June 2006, based on work by Matt Armstrong
;; <matt@lickey.com>. It uses a different format for the equivalent
;; of .emacs-locals.
;;; Code:
(defgroup dir-locals ()
"Directory-wide file-local variables"
:link '(emacs-commentary-link "dir-locals")
:group 'files)
(defcustom dir-locals-file-name ".emacs-locals"
"File name used by Dir-Locals mode to specify local variables.
This should specify local variables in the normal way. When Dir-Locals
minor mode is active, these will be inherited by files found in a
directory tree containing such a file at its root.
This may also be a function of no arguments which returns the name to
use, allowing arbitrary per-directory customization of the
per-directory customization file on the basis of `default-directory'."
:group 'dir-locals
:type '(choice file function))
;; Adapted from dirvals.el.
(defcustom dir-locals-chase-remote nil
"Non-nil means search upwards for `dir-locals-file-name' in remote filesystem."
:group 'dir-locals
:type 'boolean)
(define-minor-mode dir-locals-mode
"Toggle use of directory-wide file-local variables.
See `dir-locals-file-name'."
:global t
(if dir-locals-mode
(add-hook 'hack-local-variables-hook 'dir-locals-hack-local-variables)
(remove-hook 'hack-local-variables-hook
'dir-locals-hack-local-variables)))
;; Following find-change-log. Fixme: Should be abstracted from there.
(defun dir-locals-tree-find (file)
"Find FILE in the current directory or one of its parents.
If one is found, return its fully-qualified name, otherwise return
nil.
FILE may be a string or a nullary function returning one on the basis
of `default-directory'."
(unless (and (not dir-locals-chase-remote)
(fboundp 'file-remote-p) ; not in Emacs 21
(file-remote-p default-directory))
(let* ((dir-name
;; Chase links in the source file and start searching in
;; the dir where it resides.
(or (if buffer-file-name
(file-name-directory (file-chase-links buffer-file-name)))
default-directory))
(file (if (functionp file)
(funcall file)
file))
(file1 (if (file-directory-p dir-name)
(expand-file-name file dir-name))))
;; Chase links before visiting the file. This makes it easier
;; to use a file for several related directories.
(setq file1 (expand-file-name (file-chase-links file1)))
;; Move up in the dir hierarchy till we find a suitable file.
(while (and (not (file-exists-p file1))
(setq dir-name (file-name-directory
(directory-file-name
(file-name-directory file1))))
;; Give up if we are already at the root dir.
(not (string= (file-name-directory file1) dir-name)))
;; Move up to the parent dir and try again.
(setq file1 (expand-file-name (file-name-nondirectory file) dir-name)))
(if (file-exists-p file1)
file1))))
(defun dir-locals-hack-local-variables ()
"Set local variables from directory-wide values.
Inherit the local variables set in `dir-locals-file-name' if that is
found by `dir-locals-tree-find'. Ignore everything ignored by
`hack-local-variables'."
(let* ((file (dir-locals-tree-find dir-locals-file-name))
(hack-local-variables-hook nil)
(buffer-file
(if buffer-file-name
(expand-file-name (file-chase-links buffer-file-name))))
;; Fixme: Probably condition-case this and ensure any error
;; messages indicate the directory file.
(vars (when (and file
;; Don't do it twice, so as to avoid
;; repeating possible interactive queries.
(not (equal file buffer-file)))
(with-temp-buffer
;; Make queries from `hack-local-variables' clearer.
(rename-buffer (file-name-nondirectory file) t)
(insert-file-contents file)
(let* ((locals (buffer-local-variables))
(_ (hack-local-variables))
(new-locals (buffer-local-variables)))
;; Derive the list of new pairs.
(dolist (l locals)
(setq new-locals (delete l new-locals)))
;; And some internals which get updated.
(dolist (l '(buffer-display-time buffer-display-count))
(setq new-locals (assq-delete-all l new-locals)))
new-locals)))))
(dolist (v vars)
(let ((sym (car v)))
(unless (local-variable-p sym) ; file-locals take precedence
(if (and (string-match "-mode\\'" (symbol-name sym))
(fboundp sym))
(funcall sym)
(set (make-local-variable sym) (cdr v))))))))
(provide 'dir-locals)
;;; dir-locals.el ends here
|