aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/files.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/files.el')
-rw-r--r--lisp/files.el76
1 files changed, 60 insertions, 16 deletions
diff --git a/lisp/files.el b/lisp/files.el
index 210cd0fa7ad..a36ac6b1318 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -3494,6 +3494,8 @@ we don't actually set it to the same mode the buffer already has."
3494 ;; Check for auto-mode-alist entry in dir-locals. 3494 ;; Check for auto-mode-alist entry in dir-locals.
3495 (with-demoted-errors "Directory-local variables error: %s" 3495 (with-demoted-errors "Directory-local variables error: %s"
3496 ;; Note this is a no-op if enable-local-variables is nil. 3496 ;; Note this is a no-op if enable-local-variables is nil.
3497 ;; We don't use `hack-dir-local-get-variables-functions' here, because
3498 ;; modes are specific to Emacs.
3497 (let* ((mode-alist (cdr (hack-dir-local--get-variables 3499 (let* ((mode-alist (cdr (hack-dir-local--get-variables
3498 (lambda (key) (eq key 'auto-mode-alist)))))) 3500 (lambda (key) (eq key 'auto-mode-alist))))))
3499 (set-auto-mode--apply-alist mode-alist keep-mode-if-same t))) 3501 (set-auto-mode--apply-alist mode-alist keep-mode-if-same t)))
@@ -4769,7 +4771,7 @@ Return the new class name, which is a symbol named DIR."
4769 4771
4770(defvar hack-dir-local-variables--warned-coding nil) 4772(defvar hack-dir-local-variables--warned-coding nil)
4771 4773
4772(defun hack-dir-local--get-variables (predicate) 4774(defun hack-dir-local--get-variables (&optional predicate)
4773 "Read per-directory local variables for the current buffer. 4775 "Read per-directory local variables for the current buffer.
4774Return a cons of the form (DIR . ALIST), where DIR is the 4776Return a cons of the form (DIR . ALIST), where DIR is the
4775directory name (maybe nil) and ALIST is an alist of all variables 4777directory name (maybe nil) and ALIST is an alist of all variables
@@ -4799,6 +4801,16 @@ PREDICATE is passed to `dir-locals-collect-variables'."
4799 (dir-locals-get-class-variables class) 4801 (dir-locals-get-class-variables class)
4800 dir-name nil predicate)))))) 4802 dir-name nil predicate))))))
4801 4803
4804(defvar hack-dir-local-get-variables-functions
4805 (list #'hack-dir-local--get-variables)
4806 "Special hook to compute the set of dir-local variables.
4807Every function is called without arguments and should return either
4808a cons of the form (DIR . ALIST) or a (possibly empty) list of such conses,
4809where ALIST is an alist of (VAR . VAL) settings.
4810DIR should be a string (a directory name) and is used to obey
4811`safe-local-variable-directories'.
4812This hook is run after the major mode has been setup.")
4813
4802(defun hack-dir-local-variables () 4814(defun hack-dir-local-variables ()
4803 "Read per-directory local variables for the current buffer. 4815 "Read per-directory local variables for the current buffer.
4804Store the directory-local variables in `dir-local-variables-alist' 4816Store the directory-local variables in `dir-local-variables-alist'
@@ -4806,21 +4818,53 @@ and `file-local-variables-alist', without applying them.
4806 4818
4807This does nothing if either `enable-local-variables' or 4819This does nothing if either `enable-local-variables' or
4808`enable-dir-local-variables' are nil." 4820`enable-dir-local-variables' are nil."
4809 (let* ((items (hack-dir-local--get-variables nil)) 4821 (let (items)
4810 (dir-name (car items)) 4822 (when (and enable-local-variables
4811 (variables (cdr items))) 4823 enable-dir-local-variables
4812 (when variables 4824 (or enable-remote-dir-locals
4813 (dolist (elt variables) 4825 (not (file-remote-p (or (buffer-file-name)
4814 (if (eq (car elt) 'coding) 4826 default-directory)))))
4815 (unless hack-dir-local-variables--warned-coding 4827 (run-hook-wrapped 'hack-dir-local-get-variables-functions
4816 (setq hack-dir-local-variables--warned-coding t) 4828 (lambda (fun)
4817 (display-warning 'files 4829 (let ((res (funcall fun)))
4818 "Coding cannot be specified by dir-locals")) 4830 (cond
4819 (unless (memq (car elt) '(eval mode)) 4831 ((null res))
4820 (setq dir-local-variables-alist 4832 ((consp (car-safe res))
4821 (assq-delete-all (car elt) dir-local-variables-alist))) 4833 (setq items (append res items)))
4822 (push elt dir-local-variables-alist))) 4834 (t (push res items)))))))
4823 (hack-local-variables-filter variables dir-name)))) 4835 ;; Sort the entries from nearest dir to furthest dir.
4836 (setq items (sort (nreverse items)
4837 :key (lambda (x) (length (car-safe x))) :reverse t))
4838 ;; Filter out duplicates, preferring the settings from the nearest dir
4839 ;; and from the first hook function.
4840 (let ((seen nil))
4841 (dolist (item items)
4842 (when seen ;; Special case seen=nil since it's the most common case.
4843 (setcdr item (seq-filter (lambda (vv) (not (memq (car-safe vv) seen)))
4844 (cdr item))))
4845 (setq seen (nconc (seq-difference (mapcar #'car (cdr item))
4846 '(eval mode))
4847 seen))))
4848 ;; Rather than a loop, maybe we should handle all the dirs
4849 ;; "together", e.g. prompting the user only once. But if so, we'd
4850 ;; probably want to also merge the prompt for file-local vars,
4851 ;; which comes from the call to `hack-local-variables-filter' in
4852 ;; `hack-local-variables'.
4853 (dolist (item items)
4854 (let ((dir-name (car items))
4855 (variables (cdr items)))
4856 (when variables
4857 (dolist (elt variables)
4858 (if (eq (car elt) 'coding)
4859 (unless hack-dir-local-variables--warned-coding
4860 (setq hack-dir-local-variables--warned-coding t)
4861 (display-warning 'files
4862 "Coding cannot be specified by dir-locals"))
4863 (unless (memq (car elt) '(eval mode))
4864 (setq dir-local-variables-alist
4865 (assq-delete-all (car elt) dir-local-variables-alist)))
4866 (push elt dir-local-variables-alist)))
4867 (hack-local-variables-filter variables dir-name))))))
4824 4868
4825(defun hack-dir-local-variables-non-file-buffer () 4869(defun hack-dir-local-variables-non-file-buffer ()
4826 "Apply directory-local variables to a non-file buffer. 4870 "Apply directory-local variables to a non-file buffer.