]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/ztree/ztree-diff.el
Merge remote-tracking branch 'ztree/master'
[gnu-emacs-elpa] / packages / ztree / ztree-diff.el
index 6caa73eae1cf6a5a255d58d0778091ff917e2a96..ff9b3235f1207de464b1bb920410dba88107c230 100644 (file)
@@ -1,4 +1,4 @@
-;;; ztree-diff.el --- Text mode diff for directory trees
+;;; ztree-diff.el --- Text mode diff for directory trees -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2013-2015  Free Software Foundation, Inc.
 ;;
@@ -83,6 +83,9 @@ By default paths starting with dot (like .git) are ignored")
   "Show or not equal files/directories on both sides.")
 (make-variable-buffer-local 'ztree-diff-show-equal-files)
 
+(defvar ztree-diff-show-filtered-files nil
+  "Show or not files from the filtered list.")
+
 ;;;###autoload
 (define-minor-mode ztreediff-mode
   "A minor mode for displaying the difference of the directory trees in text mode."
@@ -94,6 +97,7 @@ By default paths starting with dot (like .git) are ignored")
   `(
     (,(kbd "C") . ztree-diff-copy)
     (,(kbd "h") . ztree-diff-toggle-show-equal-files)
+    (,(kbd "H") . ztree-diff-toggle-show-filtered-files)
     (,(kbd "D") . ztree-diff-delete-file)
     (,(kbd "v") . ztree-diff-view-file)
     (,(kbd "d") . ztree-diff-simple-diff-files)
@@ -110,28 +114,28 @@ By default paths starting with dot (like .git) are ignored")
 
 (defun ztree-diff-insert-buffer-header ()
   "Insert the header to the ztree buffer."
-  (insert-with-face "Differences tree" ztreep-diff-header-face)
-  (newline-and-begin)
+  (ztree-insert-with-face "Differences tree" ztreep-diff-header-face)
+  (insert "\n")
   (when ztree-diff-dirs-pair
-    (insert-with-face (concat "Left:  " (car ztree-diff-dirs-pair))
-                      ztreep-diff-header-small-face)
-    (newline-and-begin)
-    (insert-with-face (concat "Right: " (cdr ztree-diff-dirs-pair))
-                      ztreep-diff-header-small-face)
-    (newline-and-begin))
-  (insert-with-face "Legend:" ztreep-diff-header-small-face)
-  (newline-and-begin)
-  (insert-with-face " Normal file " ztreep-diff-model-normal-face)
-  (insert-with-face "- same on both sides" ztreep-diff-header-small-face)
-  (newline-and-begin)
-  (insert-with-face " Orphan file " ztreep-diff-model-add-face)
-  (insert-with-face "- does not exist on other side" ztreep-diff-header-small-face)
-  (newline-and-begin)
-  (insert-with-face " Mismatch file " ztreep-diff-model-diff-face)
-  (insert-with-face "- different from other side" ztreep-diff-header-small-face)
-  (newline-and-begin)
-  (insert-with-face "==============" ztreep-diff-header-face)
-  (newline-and-begin))
+    (ztree-insert-with-face (concat "Left:  " (car ztree-diff-dirs-pair))
+                            ztreep-diff-header-small-face)
+    (insert "\n")
+    (ztree-insert-with-face (concat "Right: " (cdr ztree-diff-dirs-pair))
+                            ztreep-diff-header-small-face)
+    (insert "\n"))
+  (ztree-insert-with-face "Legend:" ztreep-diff-header-small-face)
+  (insert "\n")
+  (ztree-insert-with-face " Normal file " ztreep-diff-model-normal-face)
+  (ztree-insert-with-face "- same on both sides" ztreep-diff-header-small-face)
+  (insert "\n")
+  (ztree-insert-with-face " Orphan file " ztreep-diff-model-add-face)
+  (ztree-insert-with-face "- does not exist on other side" ztreep-diff-header-small-face)
+  (insert "\n")
+  (ztree-insert-with-face " Mismatch file " ztreep-diff-model-diff-face)
+  (ztree-insert-with-face "- different from other side" ztreep-diff-header-small-face)
+  (insert "\n")
+  (ztree-insert-with-face "==============" ztreep-diff-header-face)
+  (insert "\n"))
 
 (defun ztree-diff-full-rescan ()
   "Force full rescan of the directory trees."
@@ -151,7 +155,7 @@ By default paths starting with dot (like .git) are ignored")
              (file-exists-p right))
         node
       nil)))
-      
+
 (defun ztree-diff-existing-common-parent (node)
   "Return the first node in up in hierarchy of the NODE which has both sides."
   (let ((common (ztree-diff-existing-common node)))
@@ -170,7 +174,7 @@ By default paths starting with dot (like .git) are ignored")
         (ztree-diff-model-partial-rescan common)
         (ztree-diff-node-update-all-parents-diff node)
         (ztree-refresh-buffer (line-number-at-pos))))))
-  
+
 
 (defun ztree-diff-partial-rescan ()
   "Perform partial rescan on the current node."
@@ -178,7 +182,7 @@ By default paths starting with dot (like .git) are ignored")
   (let ((found (ztree-find-node-at-point)))
     (when found
       (ztree-diff-do-partial-rescan (car found)))))
-  
+
 
 (defun ztree-diff-simple-diff (node)
   "Create a simple diff buffer for files from left and right panels.
@@ -213,7 +217,7 @@ Argument NODE node containing paths to files to call a diff on."
 2 if left or right present - view left or rigth"
   (let ((left (ztree-diff-node-left-path node))
         (right (ztree-diff-node-right-path node))
-        (open-f '(lambda (path) (if hard (find-file path)
+        (open-f #'(lambda (path) (if hard (find-file path)
                                   (let ((split-width-threshold nil))
                                     (view-file-other-window path))))))
     (cond ((and left right)
@@ -225,7 +229,7 @@ Argument NODE node containing paths to files to call a diff on."
           (left (funcall open-f left))
           (right (funcall open-f right))
           (t nil))))
-           
+
 
 
 (defun ztree-diff-copy-file (node source-path destination-path copy-to-right)
@@ -258,7 +262,7 @@ COPY-TO-RIGHT specifies which side of the NODE to update."
 
 
 (defun ztree-diff-copy-dir (node source-path destination-path copy-to-right)
-    "Update the NODE status and copy the directory.
+  "Update the NODE status and copy the directory.
 Directory copied from SOURCE-PATH to DESTINATION-PATH.
 COPY-TO-RIGHT specifies which side of the NODE to update."
   (let* ((src-path (file-name-as-directory source-path))
@@ -352,7 +356,7 @@ COPY-TO-RIGHT specifies which side of the NODE to update."
                 ((and (eq side 'right)
                       node-right)
                  (view-file node-right))))))))
-  
+
 
 (defun ztree-diff-delete-file ()
   "Delete the file under the cursor."
@@ -382,38 +386,61 @@ COPY-TO-RIGHT specifies which side of the NODE to update."
                                      remove-path))
             (let* ((delete-command
                     (if (file-directory-p remove-path)
-                        '(delete-directory remove-path t)
-                      '(delete-file remove-path t)))
+                        #'delete-directory
+                      #'delete-file))
                    (children (ztree-diff-node-children parent))
                    (err
                     (condition-case error-trap
                         (progn
-                          (eval delete-command)
+                          (funcall delete-command remove-path t)
                           nil)
                       (error error-trap))))
-              (if err (message (concat "Error: " (nth 2 err)))
+              (if err
+                  (progn
+                    (message (concat "Error: " (nth 2 err)))
+                    ;; when error happened while deleting the
+                    ;; directory, rescan the node
+                    ;; and update the parents with a new status
+                    ;; of this node
+                    (when (file-directory-p remove-path)
+                      (ztree-diff-model-partial-rescan node)
+                      (ztree-diff-node-update-all-parents-diff node)))
+                ;; if everything ok 
                 (progn
+                  ;; remove the node from children
                   (setq children (ztree-filter
                                   #'(lambda (x) (not (ztree-diff-node-equal x node)))
                                   children))
                   (ztree-diff-node-set-children parent children))
                 (ztree-diff-node-update-all-parents-diff node)
+                ;;(ztree-diff-model-partial-rescan node)
                 (ztree-refresh-buffer (line-number-at-pos))))))))))
 
 
 
-(defun ztree-node-is-in-filter-list (node)
+(defun ztree-diff-node-ignore-p (node)
   "Determine if the NODE is in filter list.
-If the node is in the filter list it shall not be visible"
-  (ztree-find ztree-diff-filter-list #'(lambda (rx) (string-match rx node))))
+If the node is in the filter list it shall not be visible,
+unless it is a parent node."
+  (let ((name (ztree-diff-node-short-name node)))
+    ;; ignore then
+    ;; not a root and is in filter list
+    (and (ztree-diff-node-parent node)
+         (ztree-find ztree-diff-filter-list #'(lambda (rx) (string-match rx name))))))
 
 
 (defun ztree-node-is-visible (node)
   "Determine if the NODE should be visible."
-  (and (ztree-diff-node-parent node)    ; parent is always visible
-       (not (ztree-node-is-in-filter-list (ztree-diff-node-short-name node)))
-       (or ztree-diff-show-equal-files
-           (ztree-diff-node-different node))))
+  ;; visible then
+  ;; 1) either it is a parent
+  (or (not (ztree-diff-node-parent node))    ; parent is always visible
+      (and
+       ;; 2.1) or it is not in ignore list and 
+       (or ztree-diff-show-filtered-files ; show filtered files regardless
+           (not (ztree-diff-node-ignore-p node)))
+       ;; 2.2) it has different status
+       (or ztree-diff-show-equal-files  ; show equal files regardless
+           (ztree-diff-node-different node)))))
 
 (defun ztree-diff-toggle-show-equal-files ()
   "Toggle visibility of the equal files."
@@ -421,13 +448,20 @@ If the node is in the filter list it shall not be visible"
   (setq ztree-diff-show-equal-files (not ztree-diff-show-equal-files))
   (ztree-refresh-buffer))
 
+(defun ztree-diff-toggle-show-filtered-files ()
+  "Toggle visibility of the filtered files."
+  (interactive)
+  (setq ztree-diff-show-filtered-files (not ztree-diff-show-filtered-files))
+  (ztree-refresh-buffer))
+
+
 ;;;###autoload
 (defun ztree-diff (dir1 dir2)
   "Create an interactive buffer with the directory tree of the path given.
 Argument DIR1 left directory.
 Argument DIR2 right directory."
   (interactive "DLeft directory \nDRight directory ")
-  (let* ((difference (ztree-diff-model-create dir1 dir2))
+  (let* ((difference (ztree-diff-model-create dir1 dir2 #'ztree-diff-node-ignore-p))
          (buf-name (concat "*"
                            (ztree-diff-node-short-name difference)
                            " <--> "
@@ -447,7 +481,7 @@ Argument DIR2 right directory."
     (ztreediff-mode)
     (setq ztree-diff-dirs-pair (cons dir1 dir2))
     (ztree-refresh-buffer)))
-          
+