summaryrefslogtreecommitdiff
path: root/lisp/files.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/files.el')
-rw-r--r--lisp/files.el47
1 files changed, 47 insertions, 0 deletions
diff --git a/lisp/files.el b/lisp/files.el
index 8477c227bcc..8fa7f16de01 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -4110,6 +4110,52 @@ This function returns either:
(declare-function map-merge-with "map" (type function &rest maps))
(declare-function map-merge "map" (type &rest maps))
+(defun dir-locals--get-sort-score (node)
+ "Return a number used for sorting the definitions of dir locals.
+NODE is assumed to be a cons cell where the car is either a
+string or a symbol representing a mode name.
+
+If it is a mode then the the depth of the mode (ie, how many
+parents that mode has) will be returned.
+
+If it is a string then the length of the string plus 1000 will be
+returned.
+
+Otherwise it returns -1.
+
+That way the value can be used to sort the list such that deeper
+modes will be after the other modes. This will be followed by
+directory entries in order of length. If the entries are all
+applied in order then that means the more specific modes will
+ override the values specified by the earlier modes and directory
+variables will override modes."
+ (let ((key (car node)))
+ (cond ((null key) -1)
+ ((symbolp key)
+ (let ((mode key)
+ (depth 0))
+ (while (setq mode (get mode 'derived-mode-parent))
+ (setq depth (1+ depth)))
+ depth))
+ ((stringp key)
+ (+ 1000 (length key)))
+ (t -2))))
+
+(defun dir-locals--sort-variables (variables)
+ "Sorts VARIABLES so that applying them in order has the right effect.
+The variables are compared by dir-locals--get-sort-score.
+Directory entries are then recursively sorted using the same
+criteria."
+ (setq variables (sort variables
+ (lambda (a b)
+ (< (dir-locals--get-sort-score a)
+ (dir-locals--get-sort-score b)))))
+ (dolist (n variables)
+ (when (stringp (car n))
+ (setcdr n (dir-locals--sort-variables (cdr n)))))
+
+ variables)
+
(defun dir-locals-read-from-dir (dir)
"Load all variables files in DIR and register a new class and instance.
DIR is the absolute name of a directory which must contain at
@@ -4147,6 +4193,7 @@ Return the new class name, which is a symbol named DIR."
variables
newvars))))))
(setq success latest))
+ (setq variables (dir-locals--sort-variables variables))
(dir-locals-set-class-variables class-name variables)
(dir-locals-set-directory-class dir class-name success)
class-name))