GNU bug report logs - #12357
24.2; list-load-path-shadow should ignore .dir-locals.el

Previous Next

Package: emacs;

Reported by: Johan Claesson <johanclaesson <at> bredband.net>

Date: Wed, 5 Sep 2012 15:54:02 UTC

Severity: minor

Tags: patch

Found in version 24.2

Fixed in version 24.4

Done: Glenn Morris <rgm <at> gnu.org>

Bug is archived. No further changes may be made.

Full log


Message #23 received at 12357 <at> debbugs.gnu.org (full text, mbox):

From: Johan Claesson <johanclaesson <at> bredband.net>
To: Xue Fuqiao <xfq <at> gnu.org>
Cc: Glenn Morris <rgm <at> gnu.org>, 12357 <at> debbugs.gnu.org
Subject: Re: bug#12357: 24.2;
 list-load-path-shadow should ignore .dir-locals.el
Date: Sun, 02 Mar 2014 23:14:30 +0100
[Message part 1 (text/plain, inline)]

Great.  Attached is a loading.texi patch that just add to the
description of list-load-path-shadows that it will not report
.dir-locals.el files.  Do you think there should be a @deffn entry for 
list-load-path-dir-locals-shadows as well?

Also attached is a shadow.el patch with the following changes: 

1. Some more doc string text. 
2. list-load-path-dir-locals-shadows uses the same button making code as
list-load-path-shadows. 
3. Inherit the major mode from special-mode instead of fundamental-mode
to get quit on ?q etc. 
4. Also bind forward-button to tab in this mode.  And backward-button to
backtab. 
5. It will not bail out on an invalid directory in load-path any more (i
happened to have some invalid directories in load-path while testing
this :) ). 

Regards,

/Johan

[loading.texi.diff (text/x-diff, inline)]
=== modified file 'doc/lispref/loading.texi'
--- old/doc/lispref/loading.texi	2014-01-01 07:43:34 +0000
+++ new/doc/lispref/loading.texi	2014-03-02 21:39:14 +0000
@@ -411,12 +411,19 @@
 directory.  Such a situation might indicate a problem in the way Emacs
 was installed.
 
+Files named @file{.dir-locals.el} are not reported by this command.
+These files specify directory local variables, see @ref{Directory
+Local Variables}.  It is normal that it exists multiple files with
+this name.
+
 When called from Lisp, this function prints a message listing the
 shadowed files, instead of displaying them in a buffer.  If the
 optional argument @code{stringp} is non-@code{nil}, it instead returns
 the shadowed files as a string.
 @end deffn
 
+
+
 @node Loading Non-ASCII
 @section Loading Non-@acronym{ASCII} Characters
 

[shadow.el.diff (text/x-diff, inline)]
=== modified file 'lisp/emacs-lisp/shadow.el'
--- old/lisp/emacs-lisp/shadow.el	2014-01-01 07:43:34 +0000
+++ new/lisp/emacs-lisp/shadow.el	2014-03-02 22:06:37 +0000
@@ -115,7 +115,8 @@
 	  ;; FILE now contains the current file name, with no suffix.
 	  (unless (or (member file files-seen-this-dir)
 		      ;; Ignore these files.
-		      (member file '("subdirs" "leim-list")))
+		      (member file '("subdirs" "leim-list"))
+                      (string= file (file-name-sans-extension dir-locals-file)))
 	    ;; File has not been seen yet in this directory.
 	    ;; This test prevents us declaring that XXX.el shadows
 	    ;; XXX.elc (or vice-versa) when they are in the same directory.
@@ -169,20 +170,27 @@
      . (1 font-lock-warning-face)))
   "Keywords to highlight in `load-path-shadows-mode'.")
 
-(define-derived-mode load-path-shadows-mode fundamental-mode "LP-Shadows"
+(define-derived-mode load-path-shadows-mode special-mode "LP-Shadows"
   "Major mode for load-path shadows buffer."
   (set (make-local-variable 'font-lock-defaults)
        '((load-path-shadows-font-lock-keywords)))
   (setq buffer-undo-list t
 	buffer-read-only t))
 
+(let ((map (make-sparse-keymap)))
+  (define-key map [tab] 'forward-button)
+  (define-key map [backtab] 'backward-button)
+  (setq load-path-shadows-mode-map map))
+
 ;; TODO use text-properties instead, a la dired.
 (require 'button)
 (define-button-type 'load-path-shadows-find-file
   'follow-link t
-;;  'face 'default
   'action (lambda (button)
-	    (let ((file (concat (button-get button 'shadow-file) ".el")))
+	    (let* ((shadow-file (button-get button 'shadow-file))
+                   (file (if (equal (file-name-extension shadow-file) "el")
+                             shadow-file
+                           (concat shadow-file ".el"))))
 	      (or (file-exists-p file)
 		  (setq file (concat file ".gz")))
 	      (if (file-readable-p file)
@@ -190,6 +198,20 @@
 		(error "Cannot read file"))))
   'help-echo "mouse-2, RET: find this file")
 
+(defun load-path-shadows-make-buttons ()
+  "Create buttons for `load-path-shadows-mode'."
+  (let ((inhibit-read-only t))
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward "\\(^.*\\) hides \\(.*$\\)"
+                                nil t)
+        (dotimes (i 2)
+          (make-button (match-beginning (1+ i))
+                       (match-end (1+ i))
+                       'type 'load-path-shadows-find-file
+                       'shadow-file
+                       (match-string (1+ i))))))))
+
 
 ;;;###autoload
 (defun list-load-path-shadows (&optional stringp)
@@ -231,6 +253,11 @@
 XXX.elc in an early directory (that does not contain XXX.el) is
 considered to shadow a later file XXX.el, and vice-versa.
 
+Files named .dir-locals.el are not reported by this command.
+These files specify directory local variables.  It is normal that
+it exists multiple files with this name.  But see the command
+`list-load-path-dir-locals-shadows'.
+
 Shadowings are located by calling the (non-interactive) companion
 function, `load-path-shadows-find'."
   (interactive)
@@ -257,14 +284,7 @@
 		  (erase-buffer)
 		  (insert string)
 		  (insert msg "\n")
-		  (while (re-search-backward "\\(^.*\\) hides \\(.*$\\)"
-					     nil t)
-		    (dotimes (i 2)
-		      (make-button (match-beginning (1+ i))
-				   (match-end (1+ i))
-				   'type 'load-path-shadows-find-file
-				   'shadow-file
-				   (match-string (1+ i)))))
+                  (load-path-shadows-make-buttons)
 		  (goto-char (point-max)))))
 	  ;; We are non-interactive, print shadows via message.
 	  (unless (zerop n)
@@ -281,6 +301,64 @@
 	      (forward-line 1))
 	    (message "%s" msg)))))))
 
+
+
+
+
+(defun list-load-path-dir-locals-shadows ()
+  "Display a list of dir-local files that shadow other such files.
+
+A .dir-locals.el file will shadow any other such file higher up
+in the directory tree.  Sometimes this is what you want,
+sometimes it is not.  This command will show all such shadowing
+in the current `load-path'.
+
+This command complements the command `list-load-path-shadows'.
+"
+  (interactive)
+  (dir-locals-shadows load-path))
+
+(defun dir-locals-shadows (path)
+  "Display a list of dir-local files that shadow other files under PATH."
+  (when (stringp path)
+    (setq path (list path)))
+  (with-current-buffer (get-buffer-create "*Dir-Locals-Shadows*")
+    (let ((inhibit-read-only t))
+      (erase-buffer)
+      (dolist (dir path)
+        (if (file-directory-p dir)
+            (dir-locals-shadows-1 dir (dir-locals-find-file (file-name-as-directory dir)))
+          (insert (format "invalid dir %s\n" dir)))))
+    (load-path-shadows-mode)
+    (load-path-shadows-make-buttons)
+    (if (> (point-max) (point-min))
+        (display-buffer (current-buffer))
+      (kill-buffer (current-buffer))
+      (message "No dir-local shadows found."))))
+
+(defun dir-locals-class-name (class)
+  (if (stringp class)
+      class
+    (if (file-name-directory (symbol-name (cadr class)))
+        (concat (car class) dir-locals-file)
+      (format "%s%s (class %s)" (car class) dir-locals-file (cadr class)))))
+
+(defun dir-locals-shadows-1 (dir locals)
+  "Auxiliary function for `dir-locals-shadows'."
+  (dolist (file (directory-files dir nil nil 'no-sort))
+    (let ((subdir (expand-file-name file dir)))
+      (when (and (file-directory-p subdir)
+                 (not (or (string-equal file ".")
+                          (string-equal file "..")
+                          (file-symlink-p subdir))))
+        (let ((subdir-locals (dir-locals-find-file (file-name-as-directory subdir))))
+          (and locals
+               (not (equal locals subdir-locals))
+               (insert (format "%s hides %s\n"
+                               (dir-locals-class-name subdir-locals)
+                               (dir-locals-class-name locals))))
+          (dir-locals-shadows-1 subdir subdir-locals))))))
+
 (provide 'shadow)
 
 ;;; shadow.el ends here

[Message part 4 (text/plain, inline)]




Xue Fuqiao <xfq <at> gnu.org> writes:

> Johan Claesson <johanclaesson <at> bredband.net> writes:
>
>> A command to search for .dir-local.el shadows could look something like
>> below.
>
> Looks fine to me.  I made a patch (and tested it).  Any comments?
>
> (I haven't written the documentation/ChangeLog/NEWS yet.)
>
> === modified file 'lisp/emacs-lisp/shadow.el'
> --- lisp/emacs-lisp/shadow.el	2014-01-01 07:43:34 +0000
> +++ lisp/emacs-lisp/shadow.el	2014-02-26 08:38:54 +0000
> @@ -115,7 +115,8 @@
>  	  ;; FILE now contains the current file name, with no suffix.
>  	  (unless (or (member file files-seen-this-dir)
>  		      ;; Ignore these files.
> -		      (member file '("subdirs" "leim-list")))
> +		      (member file '("subdirs" "leim-list"))
> +		      (string= file (file-name-sans-extension dir-locals-file)))
>  	    ;; File has not been seen yet in this directory.
>  	    ;; This test prevents us declaring that XXX.el shadows
>  	    ;; XXX.elc (or vice-versa) when they are in the same directory.
> @@ -281,6 +282,49 @@
>  	      (forward-line 1))
>  	    (message "%s" msg)))))))
>  
> +
> +
> +(defun list-load-path-dir-locals-shadows ()
> +  "Display a list of dir-local files that shadow other files."
> +  (interactive)
> +  (dir-locals-shadows load-path))
> +
> +(defun dir-locals-shadows (path)
> +  "Display a list of dir-local files that shadow other files under PATH."
> +  (when (stringp path)
> +    (setq path (list path)))
> +  (with-current-buffer (get-buffer-create "*Dir-Locals-Shadows*")
> +    (erase-buffer)
> +    (dolist (dir path)
> +      (dir-locals-shadows-1 dir (dir-locals-find-file (file-name-as-directory dir))))
> +    (if (> (point-max) (point-min))
> +        (display-buffer (current-buffer))
> +      (kill-buffer (current-buffer))
> +      (message "No dir-local shadows found."))))
> +
> +(defun dir-locals-class-name (class)
> +  (if (stringp class)
> +      class
> +    (if (file-name-directory (symbol-name (cadr class)))
> +        (concat (car class) dir-locals-file)
> +      (format "%s%s (class %s)" (car class) dir-locals-file (cadr class)))))
> +
> +(defun dir-locals-shadows-1 (dir locals)
> +  "Auxiliary function for `dir-locals-shadows'."
> +  (dolist (file (directory-files dir nil nil 'no-sort))
> +    (let ((subdir (expand-file-name file dir)))
> +      (when (and (file-directory-p subdir)
> +                 (not (or (string-equal file ".")
> +                          (string-equal file "..")
> +                          (file-symlink-p subdir))))
> +        (let ((subdir-locals (dir-locals-find-file (file-name-as-directory subdir))))
> +          (and locals
> +               (not (equal locals subdir-locals))
> +               (insert (format "%s shadows %s\n"
> +                               (dir-locals-class-name subdir-locals)
> +                               (dir-locals-class-name locals))))
> +          (dir-locals-shadows-1 subdir subdir-locals))))))
> +
>  (provide 'shadow)
>  
>  ;;; shadow.el ends here

This bug report was last modified 11 years and 84 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.