Subject: Re: bug#6799: 24.0.50; Please add dired-details.el to Emacs [patch]

From: Christopher Schmidt <[email-masked]>
Date: Sun, 10 Feb 2013 15:02:21 +0000 (GMT)

Christopher Schmidt <[email-masked]> writes:
> Here is a preliminary patch for the trunk.

Here is the final patch.  Drew Adams and Michael Heerdegen tested it and
did not find any problems.
--- lisp/ChangeLog
+++ lisp/ChangeLog
@@ -1,5 +1,25 @@
 2013-02-10  Christopher Schmidt  <[email-masked]>
 
+	* locate.el (locate-mode-map): Disable dired-hide-details-mode.
+
+	* find-dired.el (find-dired): Call dired-insert-set-properties on
+	initial information line.  Set process mark on end of buffer.
+	(find-dired-sentinel): Call dired-insert-set-properties on
+	summary.
+
+	* dired.el (dired-hide-details-hide-symlink-targets)
+	(dired-hide-details-hide-information-lines): New options.
+	(dired-insert-directory): Set properties after final treatment of
+	output.
+	(dired-insert-set-properties): Set dired-hide-details-*
+	properties.
+	(dired-mode-map): Bind dired-hide-details-mode.
+	(dired-mode): Set buffer-invisibility-spec to a list.
+	(dired-next-line): Skip hidden lines.
+	(dired-previous-line): Use dired-next-line.
+	(dired-hide-details-mode): New minor mode.
+	(dired-hide-details-update-invisibility-spec): New function.
+
 	* minibuf-eldef.el (minibuffer-default--in-prompt-regexps): Handle
 	"foo (bar, default: xxx): " prompts.
 
--- lisp/dired.el
+++ lisp/dired.el
@@ -230,6 +230,18 @@
   :version "22.1"
   :group 'dired)
 
+(defcustom dired-hide-details-hide-symlink-targets t
+  "If non-nil, `dired-hide-details-mode' hides symbolic link targets."
+  :type 'boolean
+  :version "24.4"
+  :group 'dired)
+
+(defcustom dired-hide-details-hide-information-lines t
+  "Non-nil means hide lines other than header and file/dir lines."
+  :type 'boolean
+  :version "24.4"
+  :group 'dired)
+
 ;; Internal variables
 
 (defvar dired-marker-char ?*		; the answer is 42
@@ -1196,7 +1208,6 @@
       ;; Note: adjust dired-build-subdir-alist if you change this.
       (setq dir (replace-regexp-in-string "\\\\" "\\\\" dir nil t)
             dir (replace-regexp-in-string "\n" "\\n" dir nil t)))
-    (dired-insert-set-properties opoint (point))
     ;; If we used --dired and it worked, the lines are already indented.
     ;; Otherwise, indent them.
     (unless (save-excursion
@@ -1205,18 +1216,21 @@
       (let ((indent-tabs-mode nil))
 	(indent-rigidly opoint (point) 2)))
     ;; Insert text at the beginning to standardize things.
-    (save-excursion
-      (goto-char opoint)
-      (if (and (or hdr wildcard)
-               (not (and (looking-at "^  \\(.*\\):$")
-                         (file-name-absolute-p (match-string 1)))))
+    (let ((content-point opoint))
+      (save-excursion
+	(goto-char opoint)
+	(when (and (or hdr wildcard)
+		   (not (and (looking-at "^  \\(.*\\):$")
+			     (file-name-absolute-p (match-string 1)))))
 	  ;; Note that dired-build-subdir-alist will replace the name
 	  ;; by its expansion, so it does not matter whether what we insert
 	  ;; here is fully expanded, but it should be absolute.
-	  (insert "  " (directory-file-name (file-name-directory dir)) ":\n"))
-      (when wildcard
-	;; Insert "wildcard" line where "total" line would be for a full dir.
-	(insert "  wildcard " (file-name-nondirectory dir) "\n")))))
+	  (insert "  " (directory-file-name (file-name-directory dir)) ":\n")
+	  (setq content-point (point)))
+	(when wildcard
+	  ;; Insert "wildcard" line where "total" line would be for a full dir.
+	  (insert "  wildcard " (file-name-nondirectory dir) "\n")))
+      (dired-insert-set-properties content-point (point)))))
 
 (defun dired-insert-set-properties (beg end)
   "Add various text properties to the lines in the region."
@@ -1224,15 +1238,24 @@
     (goto-char beg)
     (while (< (point) end)
       (condition-case nil
-	  (if (dired-move-to-filename)
-	      (add-text-properties
-	       (point)
-	       (save-excursion
-		 (dired-move-to-end-of-filename)
-		 (point))
-	       '(mouse-face highlight
-		 dired-filename t
-		 help-echo "mouse-2: visit this file in other window")))
+	  (if (not (dired-move-to-filename))
+	      (put-text-property (line-beginning-position)
+				 (1+ (line-end-position))
+				 'invisible 'dired-hide-details-information)
+	    (put-text-property (+ (line-beginning-position) 1) (1- (point))
+			       'invisible 'dired-hide-details-detail)
+	    (add-text-properties
+	     (point)
+	     (progn
+	       (dired-move-to-end-of-filename)
+	       (point))
+	     '(mouse-face
+	       highlight
+	       dired-filename t
+	       help-echo "mouse-2: visit this file in other window"))
+	    (when (< (+ (point) 4) (line-end-position))
+	      (put-text-property (+ (point) 4) (line-end-position)
+				 'invisible 'dired-hide-details-link)))
 	(error nil))
       (forward-line 1))))
 
@@ -1496,6 +1519,7 @@
     ;; hiding
     (define-key map "$" 'dired-hide-subdir)
     (define-key map "\M-$" 'dired-hide-all)
+    (define-key map "(" 'dired-hide-details-mode)
     ;; isearch
     (define-key map (kbd "M-s a C-s")   'dired-do-isearch)
     (define-key map (kbd "M-s a M-C-s") 'dired-do-isearch-regexp)
@@ -1586,6 +1610,14 @@
       '(menu-item "Toggle Image Thumbnails in This Buffer" image-dired-dired-toggle-marked-thumbs
                   :help "Add or remove image thumbnails in front of marked file names"))
 
+    (define-key map [menu-bar immediate unhide-details]
+      '(menu-item "UnHide Details" dired-hide-details-mode
+		  :help "Unhide details in buffer"
+		  :visible dired-hide-details-mode))
+    (define-key map [menu-bar immediate hide-details]
+      '(menu-item "Hide Details" dired-hide-details-mode
+		  :help "Hide details in buffer"
+		  :visible (not dired-hide-details-mode)))
     (define-key map [menu-bar immediate revert-buffer]
       '(menu-item "Refresh" revert-buffer
 		  :help "Update contents of shown directories"))
@@ -1914,6 +1946,9 @@
 	selective-display t		; for subdirectory hiding
 	mode-line-buffer-identification
 	(propertized-buffer-identification "%17b"))
+  ;; ignore dired-hide-details-* value of invisible text property by default
+  (when (eq buffer-invisibility-spec t)
+    (setq buffer-invisibility-spec (list t)))
   (set (make-local-variable 'revert-buffer-function)
        (function dired-revert))
   (set (make-local-variable 'buffer-stale-function)
@@ -1978,15 +2013,32 @@
   "Move down lines then position at filename.
 Optional prefix ARG says how many lines to move; default is one line."
   (interactive "p")
+  (unless arg
+    (setq arg 1))
   (forward-line arg)
+  (while (and (progn
+		(while (and (< arg 0)
+			    (bolp)
+			    (/= (1+ (point)) (point-max))
+			    (eq (get-text-property (1+ (point)) 'invisible)
+				'dired-hide-details-information))
+		  (forward-char -1))
+		(invisible-p (point)))
+	      (let ((p (funcall (if (> arg 0)
+				    'next-single-property-change
+				  'previous-single-property-change)
+				(point)
+				'invisible)))
+		(when p
+		  (goto-char p)
+		  t))))
   (dired-move-to-filename))
 
-(defun dired-previous-line (arg)
+(defun dired-previous-linel (arg)
   "Move up lines then position at filename.
 Optional prefix ARG says how many lines to move; default is one line."
   (interactive "p")
-  (forward-line (- arg))
-  (dired-move-to-filename))
+  (dired-next-line (- (or arg 1))))
 
 (defun dired-next-dirline (arg &optional opoint)
   "Goto ARG'th next directory file line."
@@ -2230,6 +2282,42 @@
       (substring file (match-end 0))
     file))
 
+;;; Minor mode for hiding details
+;;;###autoload
+(define-minor-mode dired-hide-details-mode
+  "Hide details in `dired-mode'."
+  :group 'dired
+  (if (derived-mode-p 'locate-mode)
+      (setq dired-hide-details-mode nil)
+    (unless (derived-mode-p 'dired-mode)
+      (error "Not a Dired buffer"))
+    (dired-hide-details-update-invisibility-spec)
+    (if dired-hide-details-mode
+	(add-hook 'wdired-mode-hook
+		  'dired-hide-details-update-invisibility-spec
+		  nil
+		  t)
+      (remove-hook 'wdired-mode-hook
+		   'dired-hide-details-update-invisibility-spec
+		   t))))
+
+(defun dired-hide-details-update-invisibility-spec ()
+  (funcall (if dired-hide-details-mode
+	       'add-to-invisibility-spec
+	     'remove-from-invisibility-spec)
+	   'dired-hide-details-detail)
+  (funcall (if (and dired-hide-details-mode
+		    dired-hide-details-hide-information-lines)
+	       'add-to-invisibility-spec
+	     'remove-from-invisibility-spec)
+	   'dired-hide-details-information)
+  (funcall (if (and dired-hide-details-mode
+		    dired-hide-details-hide-symlink-targets
+		    (not (derived-mode-p 'wdired-mode)))
+	       'add-to-invisibility-spec
+	     'remove-from-invisibility-spec)
+	   'dired-hide-details-link))
+
 ;;; Functions for finding the file name in a dired buffer line.
 
 (defvar dired-permission-flags-regexp
--- lisp/find-dired.el
+++ lisp/find-dired.el
@@ -210,13 +210,15 @@
     (insert "  " dir ":\n")
     ;; Make second line a ``find'' line in analogy to the ``total'' or
     ;; ``wildcard'' line.
-    (insert "  " args "\n")
+    (let ((point (point)))
+      (insert "  " args "\n")
+      (dired-insert-set-properties point (point)))
     (setq buffer-read-only t)
     (let ((proc (get-buffer-process (current-buffer))))
       (set-process-filter proc (function find-dired-filter))
       (set-process-sentinel proc (function find-dired-sentinel))
       ;; Initialize the process marker; it is used by the filter.
-      (move-marker (process-mark proc) 1 (current-buffer)))
+      (move-marker (process-mark proc) (point) (current-buffer)))
     (setq mode-line-process '(":%s"))))
 
 (defun kill-find ()
@@ -337,10 +339,11 @@
 	  (let ((buffer-read-only nil))
 	    (save-excursion
 	      (goto-char (point-max))
-	      (insert "\n  find " state)
-	      (forward-char -1)		;Back up before \n at end of STATE.
-	      (insert " at " (substring (current-time-string) 0 19))
-	      (forward-char 1)
+	      (let ((point (point)))
+		(insert "\n  find " state)
+		(forward-char -1)		;Back up before \n at end of STATE.
+		(insert " at " (substring (current-time-string) 0 19))
+		(dired-insert-set-properties point (point)))
 	      (setq mode-line-process
 		    (concat ":"
 			    (symbol-name (process-status proc))))
--- lisp/locate.el
+++ lisp/locate.el
@@ -382,6 +382,7 @@
     (define-key map "l"       'locate-do-redisplay)
     (define-key map "U"       'dired-unmark-all-files)
     (define-key map "V"       'locate-find-directory)
+    (define-key map [remap dired-hide-details-mode] nil)
     map)
   "Local keymap for Locate mode buffers.")

Should the key bindings and definition of dired-hide-details-mode go
into dired-x.el?

        Christopher