Function: hack-dir-local-variables

hack-dir-local-variables is a byte-compiled function defined in files.el.gz.

Signature

(hack-dir-local-variables)

Documentation

Read per-directory local variables for the current buffer.

Store the directory-local variables in dir-local-variables-alist and file-local-variables-alist, without applying them.

This does nothing if either enable-local-variables or enable-dir-local-variables are nil.

View in manual

Source Code

;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun hack-dir-local-variables ()
  "Read per-directory local variables for the current buffer.
Store the directory-local variables in `dir-local-variables-alist'
and `file-local-variables-alist', without applying them.

This does nothing if either `enable-local-variables' or
`enable-dir-local-variables' are nil."
  (let (items)
    (when (and enable-local-variables
	       enable-dir-local-variables
	       (or enable-remote-dir-locals
		   (not (file-remote-p (or (buffer-file-name)
					   default-directory)))))
      (run-hook-wrapped 'hack-dir-local-get-variables-functions
                        (lambda (fun)
                          (let ((res (funcall fun)))
                            (cond
                             ((null res))
                             ((consp (car-safe res))
                              (setq items (append res items)))
                             (t (push res items))))
			  nil)))
    ;; Sort the entries from nearest dir to furthest dir.
    (setq items (sort (nreverse items)
                      :key (lambda (x) (length (car-safe x))) :reverse t))
    ;; Filter out duplicates, preferring the settings from the nearest dir
    ;; and from the first hook function.
    (let ((seen nil))
      (dolist (item items)
        (when seen ;; Special case seen=nil since it's the most common case.
          (setcdr item (seq-filter (lambda (vv) (not (memq (car-safe vv) seen)))
                                   (cdr item))))
        (setq seen (nconc (seq-difference (mapcar #'car (cdr item))
                                          '(eval mode))
                          seen))))
    ;; Rather than a loop, maybe we should handle all the dirs
    ;; "together", e.g.  prompting the user only once.  But if so, we'd
    ;; probably want to also merge the prompt for file-local vars,
    ;; which comes from the call to `hack-local-variables-filter' in
    ;; `hack-local-variables'.
    (dolist (item items)
      (let ((dir-name (car item))
            (variables (cdr item)))
        (when variables
          (dolist (elt variables)
            (if (eq (car elt) 'coding)
                (unless hack-dir-local-variables--warned-coding
                  (setq hack-dir-local-variables--warned-coding t)
                  (display-warning 'files
                                   "Coding cannot be specified by dir-locals"))
              (unless (memq (car elt) '(eval mode))
                (setq dir-local-variables-alist
                      (assq-delete-all (car elt) dir-local-variables-alist)))
              (push elt dir-local-variables-alist)))
          (hack-local-variables-filter variables dir-name))))))