aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Malabarba2015-11-07 13:54:56 +0000
committerArtur Malabarba2015-11-07 13:55:16 +0000
commit3d4fdb9f59731113f467b3705c8346b1ee8d2d81 (patch)
tree0a4b971094880b5ea3f48fb275537851b9f9edf6
parent8af7598d9851c067176ced829d8a5902f3afcbc1 (diff)
downloademacs-scratch/dir-local-wildcard.tar.gz
emacs-scratch/dir-local-wildcard.zip
* lisp/files.el (dir-locals-file): Allow wildcardsscratch/dir-local-wildcard
(dir-locals-find-file, dir-locals-collect-variables) (dir-locals-read-from-file): Update accordingly. (hack-dir-local-variables): Rename a local variable.
-rw-r--r--lisp/files-x.el27
-rw-r--r--lisp/files.el141
-rw-r--r--lisp/help-fns.el43
3 files changed, 123 insertions, 88 deletions
diff --git a/lisp/files-x.el b/lisp/files-x.el
index a130ffcf928..dcd495db15a 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -429,18 +429,23 @@ from the MODE alist ignoring the input argument VALUE."
429 (catch 'exit 429 (catch 'exit
430 (unless enable-local-variables 430 (unless enable-local-variables
431 (throw 'exit (message "Directory-local variables are disabled"))) 431 (throw 'exit (message "Directory-local variables are disabled")))
432 (let ((variables-file (or (and (buffer-file-name) 432 (let ((variables-file (and (buffer-file-name)
433 (not (file-remote-p (buffer-file-name))) 433 (not (file-remote-p (buffer-file-name)))
434 (dir-locals-find-file (buffer-file-name))) 434 (dir-locals-find-file (buffer-file-name))))
435 dir-locals-file))
436 variables) 435 variables)
437 (if (consp variables-file) ; result from cache 436 (setq variables-file
438 ;; If cache element has an mtime, assume it came from a file. 437 ;; If there are several .dir-locals, the user probably
439 ;; Otherwise, assume it was set directly. 438 ;; wants to edit the last one (the highest priority).
440 (setq variables-file (if (nth 2 variables-file) 439 (cond ((stringp variables-file)
441 (expand-file-name dir-locals-file 440 (car (last (file-expand-wildcards variables-file))))
442 (car variables-file)) 441 ((consp variables-file) ; result from cache
443 (cadr variables-file)))) 442 ;; If cache element has an mtime, assume it came from a file.
443 ;; Otherwise, assume it was set directly.
444 (if (nth 2 variables-file)
445 (let ((default-directory (car variables-file)))
446 (car (last (file-expand-wildcards dir-locals-file 'full))))
447 (cadr variables-file)))
448 (t dir-locals-file)))
444 ;; I can't be bothered to handle this case right now. 449 ;; I can't be bothered to handle this case right now.
445 ;; Dir locals were set directly from a class. You need to 450 ;; Dir locals were set directly from a class. You need to
446 ;; directly modify the class in dir-locals-class-alist. 451 ;; directly modify the class in dir-locals-class-alist.
diff --git a/lisp/files.el b/lisp/files.el
index 9de9ac09f48..3d6495f30d2 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -28,6 +28,8 @@
28 28
29;;; Code: 29;;; Code:
30 30
31(require 'map)
32(require 'seq)
31(defvar font-lock-keywords) 33(defvar font-lock-keywords)
32 34
33(defgroup backup nil 35(defgroup backup nil
@@ -3648,7 +3650,7 @@ Return the new variables list."
3648 (error 3650 (error
3649 ;; The file's content might be invalid (e.g. have a merge conflict), but 3651 ;; The file's content might be invalid (e.g. have a merge conflict), but
3650 ;; that shouldn't prevent the user from opening the file. 3652 ;; that shouldn't prevent the user from opening the file.
3651 (message ".dir-locals error: %s" (error-message-string err)) 3653 (message "%s error: %s" dir-locals-file (error-message-string err))
3652 nil)))) 3654 nil))))
3653 3655
3654(defun dir-locals-set-directory-class (directory class &optional mtime) 3656(defun dir-locals-set-directory-class (directory class &optional mtime)
@@ -3698,7 +3700,7 @@ VARIABLES list of the class. The list is processed in order.
3698 applied by recursively following these rules." 3700 applied by recursively following these rules."
3699 (setf (alist-get class dir-locals-class-alist) variables)) 3701 (setf (alist-get class dir-locals-class-alist) variables))
3700 3702
3701(defconst dir-locals-file ".dir-locals.el" 3703(defconst dir-locals-file ".dir-locals*.el"
3702 "File that contains directory-local variables. 3704 "File that contains directory-local variables.
3703It has to be constant to enforce uniform values 3705It has to be constant to enforce uniform values
3704across different environments and users.") 3706across different environments and users.")
@@ -3719,17 +3721,23 @@ If not, the cache entry is cleared so that the file will be re-read.
3719This function returns either nil (no directory local variables found), 3721This function returns either nil (no directory local variables found),
3720or the matching entry from `dir-locals-directory-cache' (a list), 3722or the matching entry from `dir-locals-directory-cache' (a list),
3721or the full path to the `dir-locals-file' (a string) in the case 3723or the full path to the `dir-locals-file' (a string) in the case
3722of no valid cache entry." 3724of no valid cache entry. If `dir-locals-file' contains
3723 (setq file (expand-file-name file)) 3725wildcards, then the return value is not a proper filename, it is
3724 (let* ((dir-locals-file-name 3726an absolute version of `dir-locals-file' which is guaranteed to
3725 (if (eq system-type 'ms-dos) 3727expand to at least one file."
3726 (dosified-file-name dir-locals-file) 3728 (setq file (file-name-directory (expand-file-name file)))
3727 dir-locals-file)) 3729 (let* ((dir-locals-file-name (if (eq system-type 'ms-dos)
3728 (locals-file (locate-dominating-file file dir-locals-file-name)) 3730 (dosified-file-name dir-locals-file)
3729 (dir-elt nil)) 3731 dir-locals-file))
3732 (locals-dir (locate-dominating-file
3733 file (lambda (dir)
3734 (let ((default-directory dir))
3735 (file-expand-wildcards dir-locals-file-name 'full)))))
3736 locals-file dir-elt)
3730 ;; `locate-dominating-file' may have abbreviated the name. 3737 ;; `locate-dominating-file' may have abbreviated the name.
3731 (and locals-file 3738 (when locals-dir
3732 (setq locals-file (expand-file-name dir-locals-file-name locals-file))) 3739 (setq locals-dir (expand-file-name locals-dir))
3740 (setq locals-file (expand-file-name dir-locals-file-name locals-dir)))
3733 ;; Let dir-locals-read-from-file inform us via demoted-errors 3741 ;; Let dir-locals-read-from-file inform us via demoted-errors
3734 ;; about unreadable files, etc. 3742 ;; about unreadable files, etc.
3735 ;; Maybe we'd want to keep searching though - that is 3743 ;; Maybe we'd want to keep searching though - that is
@@ -3740,54 +3748,69 @@ of no valid cache entry."
3740 ;; Find the best cached value in `dir-locals-directory-cache'. 3748 ;; Find the best cached value in `dir-locals-directory-cache'.
3741 (dolist (elt dir-locals-directory-cache) 3749 (dolist (elt dir-locals-directory-cache)
3742 (when (and (string-prefix-p (car elt) file 3750 (when (and (string-prefix-p (car elt) file
3743 (memq system-type 3751 (memq system-type
3744 '(windows-nt cygwin ms-dos))) 3752 '(windows-nt cygwin ms-dos)))
3745 (> (length (car elt)) (length (car dir-elt)))) 3753 (> (length (car elt)) (length (car dir-elt))))
3746 (setq dir-elt elt))) 3754 (setq dir-elt elt)))
3747 (if (and dir-elt 3755 (if (and dir-elt
3748 (or (null locals-file) 3756 (or (null locals-dir)
3749 (<= (length (file-name-directory locals-file)) 3757 (<= (length locals-dir)
3750 (length (car dir-elt))))) 3758 (length (car dir-elt)))))
3751 ;; Found a potential cache entry. Check validity. 3759 ;; Found a potential cache entry. Check validity.
3752 ;; A cache entry with no MTIME is assumed to always be valid 3760 ;; A cache entry with no MTIME is assumed to always be valid
3753 ;; (ie, set directly, not from a dir-locals file). 3761 ;; (ie, set directly, not from a dir-locals file).
3754 ;; Note, we don't bother to check that there is a matching class 3762 ;; Note, we don't bother to check that there is a matching class
3755 ;; element in dir-locals-class-alist, since that's done by 3763 ;; element in dir-locals-class-alist, since that's done by
3756 ;; dir-locals-set-directory-class. 3764 ;; dir-locals-set-directory-class.
3757 (if (or (null (nth 2 dir-elt)) 3765 (if (or (null (nth 2 dir-elt))
3758 (let ((cached-file (expand-file-name dir-locals-file-name 3766 (let* ((default-directory (car dir-elt))
3759 (car dir-elt)))) 3767 (cached-files (seq-filter #'file-readable-p
3760 (and (file-readable-p cached-file) 3768 (file-expand-wildcards dir-locals-file))))
3761 (equal (nth 2 dir-elt) 3769 ;; The entry MTIME should match the most recent
3762 (nth 5 (file-attributes cached-file)))))) 3770 ;; MTIME among matching files.
3763 ;; This cache entry is OK. 3771 (and cached-files
3764 dir-elt 3772 (= (time-to-seconds (nth 2 dir-elt))
3765 ;; This cache entry is invalid; clear it. 3773 (apply #'max (mapcar (lambda (f) (time-to-seconds (nth 5 (file-attributes f))))
3766 (setq dir-locals-directory-cache 3774 cached-files))))))
3767 (delq dir-elt dir-locals-directory-cache)) 3775 ;; This cache entry is OK.
3768 ;; Return the first existing dir-locals file. Might be the same 3776 dir-elt
3769 ;; as dir-elt's, might not (eg latter might have been deleted). 3777 ;; This cache entry is invalid; clear it.
3770 locals-file) 3778 (setq dir-locals-directory-cache
3779 (delq dir-elt dir-locals-directory-cache))
3780 ;; Return the first existing dir-locals file. Might be the same
3781 ;; as dir-elt's, might not (eg latter might have been deleted).
3782 locals-file)
3771 ;; No cache entry. 3783 ;; No cache entry.
3772 locals-file))) 3784 locals-file)))
3773 3785
3774(defun dir-locals-read-from-file (file) 3786(defun dir-locals-read-from-file (file)
3775 "Load a variables FILE and register a new class and instance. 3787 "Load a variables FILE and register a new class and instance.
3776FILE is the name of the file holding the variables to apply. 3788FILE is the absolute name of the file holding the variables to
3789apply. It may contain wildcards.
3777The new class name is the same as the directory in which FILE 3790The new class name is the same as the directory in which FILE
3778is found. Returns the new class name." 3791is found. Returns the new class name."
3779 (with-temp-buffer 3792 (let* ((dir-name (file-name-directory file))
3793 (class-name (intern dir-name))
3794 (files (sort (file-expand-wildcards "/home/artur/Git/emacs/.dir-locals*.el") #'string<))
3795 (read-circle nil)
3796 (variables))
3780 (with-demoted-errors "Error reading dir-locals: %S" 3797 (with-demoted-errors "Error reading dir-locals: %S"
3781 (insert-file-contents file) 3798 (dolist (file files)
3782 (unless (zerop (buffer-size)) 3799 (with-temp-buffer
3783 (let* ((dir-name (file-name-directory file)) 3800 (insert-file-contents file)
3784 (class-name (intern dir-name)) 3801 (condition-case-unless-debug nil
3785 (variables (let ((read-circle nil)) 3802 (setq variables
3786 (read (current-buffer))))) 3803 (map-merge-with 'list (lambda (a b) (map-merge 'list a b))
3787 (dir-locals-set-class-variables class-name variables) 3804 variables
3788 (dir-locals-set-directory-class dir-name class-name 3805 (read (current-buffer))))
3789 (nth 5 (file-attributes file))) 3806 (end-of-file nil)))))
3790 class-name))))) 3807 (dir-locals-set-class-variables class-name variables)
3808 (dir-locals-set-directory-class
3809 dir-name class-name
3810 (seconds-to-time (apply #'max (mapcar (lambda (file)
3811 (time-to-seconds (nth 5 (file-attributes file))))
3812 files))))
3813 class-name))
3791 3814
3792(defcustom enable-remote-dir-locals nil 3815(defcustom enable-remote-dir-locals nil
3793 "Non-nil means dir-local variables will be applied to remote files." 3816 "Non-nil means dir-local variables will be applied to remote files."
@@ -3810,17 +3833,17 @@ This does nothing if either `enable-local-variables' or
3810 (not (file-remote-p (or (buffer-file-name) 3833 (not (file-remote-p (or (buffer-file-name)
3811 default-directory))))) 3834 default-directory)))))
3812 ;; Find the variables file. 3835 ;; Find the variables file.
3813 (let ((variables-file (dir-locals-find-file 3836 (let ((file-pattern-or-cache (dir-locals-find-file
3814 (or (buffer-file-name) default-directory))) 3837 (or (buffer-file-name) default-directory)))
3815 (class nil) 3838 (class nil)
3816 (dir-name nil)) 3839 (dir-name nil))
3817 (cond 3840 (cond
3818 ((stringp variables-file) 3841 ((stringp file-pattern-or-cache)
3819 (setq dir-name (file-name-directory variables-file) 3842 (setq dir-name (file-name-directory file-pattern-or-cache)
3820 class (dir-locals-read-from-file variables-file))) 3843 class (dir-locals-read-from-file file-pattern-or-cache)))
3821 ((consp variables-file) 3844 ((consp file-pattern-or-cache)
3822 (setq dir-name (nth 0 variables-file)) 3845 (setq dir-name (nth 0 file-pattern-or-cache))
3823 (setq class (nth 1 variables-file)))) 3846 (setq class (nth 1 file-pattern-or-cache))))
3824 (when class 3847 (when class
3825 (let ((variables 3848 (let ((variables
3826 (dir-locals-collect-variables 3849 (dir-locals-collect-variables
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 958a0754946..4e0bfee5bf7 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -907,29 +907,36 @@ if it is given a local binding.\n"))))
907 (buffer-file-name buffer))) 907 (buffer-file-name buffer)))
908 (dir-locals-find-file 908 (dir-locals-find-file
909 (buffer-file-name buffer)))) 909 (buffer-file-name buffer))))
910 (dir-file t)) 910 (is-directory nil))
911 (princ (substitute-command-keys 911 (princ (substitute-command-keys
912 " This variable's value is directory-local")) 912 " This variable's value is directory-local"))
913 (if (null file) 913 (when (consp file) ; result from cache
914 (princ ".\n") 914 ;; If the cache element has an mtime, we
915 (princ ", set ") 915 ;; assume it came from a file.
916 (if (consp file) ; result from cache 916 (if (nth 2 file)
917 ;; If the cache element has an mtime, we 917 (setq file (expand-file-name
918 ;; assume it came from a file. 918 dir-locals-file (car file)))
919 (if (nth 2 file) 919 ;; Otherwise, assume it was set directly.
920 (setq file (expand-file-name 920 (setq file (car file)
921 dir-locals-file (car file))) 921 is-directory t)))
922 ;; Otherwise, assume it was set directly. 922 (if (null file)
923 (setq file (car file) 923 (princ ".\n")
924 dir-file nil))) 924 (princ ", set ")
925 (princ (substitute-command-keys 925 (let ((files (file-expand-wildcards file)))
926 (if dir-file 926 (princ (substitute-command-keys
927 "by the file\n `" 927 (cond
928 "for the directory\n `"))) 928 (is-directory "for the directory\n `")
929 ;; Many files matched.
930 ((cdr files)
931 (setq file (file-name-directory (car files)))
932 (format "by a file\n matching `%s' in the directory\n `"
933 dir-locals-file))
934 (t (setq file (car files))
935 "by the file\n `"))))
929 (with-current-buffer standard-output 936 (with-current-buffer standard-output
930 (insert-text-button 937 (insert-text-button
931 file 'type 'help-dir-local-var-def 938 file 'type 'help-dir-local-var-def
932 'help-args (list variable file))) 939 'help-args (list variable file))))
933 (princ (substitute-command-keys "'.\n")))) 940 (princ (substitute-command-keys "'.\n"))))
934 (princ (substitute-command-keys 941 (princ (substitute-command-keys
935 " This variable's value is file-local.\n")))) 942 " This variable's value is file-local.\n"))))