branch: master commit 82ec15f415307c718a9b02e2fb239db10fd324ac Author: Alexey Veretennikov <txm.four...@gmail.com> Commit: Alexey Veretennikov <txm.four...@gmail.com>
Fixed issue #15; added hotkey 'H' to show/hide filtered files; fixed bug with removing files/directories --- ztree-diff-model.el | 45 ++++++++++++++++++++++++++------------- ztree-diff.el | 58 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 27 deletions(-) diff --git a/ztree-diff-model.el b/ztree-diff-model.el index b68631e..7bec461 100644 --- a/ztree-diff-model.el +++ b/ztree-diff-model.el @@ -36,6 +36,9 @@ "Message showing while constructing the diff tree.") (make-variable-buffer-local 'ztree-diff-model-wait-message) +(defvar ztree-diff-model-ignore-fun nil + "Function which determines if the node should be excluded from comparison.") +(make-variable-buffer-local 'ztree-diff-model-ignore-fun) (defun ztree-diff-model-update-wait-message () "Update the wait mesage with one more '.' progress indication." @@ -43,8 +46,6 @@ (setq ztree-diff-model-wait-message (concat ztree-diff-model-wait-message ".")) (message ztree-diff-model-wait-message))) - - ;; Create a record ztree-diff-node with defined fields and getters/setters ;; here: ;; parent - parent node @@ -55,6 +56,11 @@ ;; different = {nil, 'new, 'diff} - means comparison status (ztree-defrecord ztree-diff-node (parent left-path right-path short-name right-short-name children different)) +(defun ztree-diff-model-ignore-p (node) + "Determine if the NODE should be excluded from comparison results." + (when ztree-diff-model-ignore-fun + (funcall ztree-diff-model-ignore-fun node))) + (defun ztree-diff-node-to-string (node) "Construct the string with contents of the NODE given." (let* ((string-or-nil #'(lambda (x) (if x @@ -204,10 +210,11 @@ Argument SIDE either 'left or 'right side." (let ((children (ztree-diff-node-children node)) (diff nil)) (dolist (child children) - (setq diff - (ztree-diff-model-update-diff - diff - (ztree-diff-node-different child)))) + (unless (ztree-diff-model-ignore-p child) + (setq diff + (ztree-diff-model-update-diff + diff + (ztree-diff-node-different child))))) (ztree-diff-node-set-different node diff))) (defun ztree-diff-node-update-all-parents-diff (node) @@ -274,12 +281,14 @@ the rest is the combined list of nodes." (setq different (car traverse)) ;; 3.2.3 set the children list from the 2 subdirectories comparison (setq children (cdr traverse))))) - ;; 2.3 update difference status for the whole comparison - (setq different-dir (ztree-diff-model-update-diff different-dir different)) ;; update calculated parameters of the node (ztree-diff-node-set-right-path node file2) (ztree-diff-node-set-children node children) (ztree-diff-node-set-different node different) + ;; 2.3 update difference status for the whole comparison + ;; depending if the node should participate in overall result + (unless (ztree-diff-model-ignore-p node) + (setq different-dir (ztree-diff-model-update-diff different-dir different))) ;; push the created node to the result list (push node result))) ;; second - adding entries from the right directory which are not present @@ -299,25 +308,31 @@ the rest is the combined list of nodes." simple-name) (eq isdir (file-directory-p x))))))) ;; if it is not in the first directory, add it as a node - (when (not file1) + (unless file1 ;; if it is a directory, set the whole subtree to children (when (file-directory-p file2) (setq children (ztree-diff-model-subtree node file2 'right))) - ;; update the different status for the whole comparison - (setq different-dir (ztree-diff-model-update-diff different-dir 'new)) ;; set calculated children to the node (ztree-diff-node-set-children node children) + ;; update the different status for the whole comparison + ;; depending if the node should participate in overall result + (unless (ztree-diff-model-ignore-p node) + (setq different-dir (ztree-diff-model-update-diff different-dir 'new))) ;; push the created node to the result list (push node result)))) ;; result is a pair: difference status and nodes list (cons different-dir result))) -(defun ztree-diff-model-create (dir1 dir2) - "Create a node based on DIR1 and DIR2." - (when (not (file-directory-p dir1)) +(defun ztree-diff-model-create (dir1 dir2 &optional ignore-p) + "Create a node based on DIR1 and DIR2. +IGNORE-P is the optional filtering function, taking node as +an argument, which determines if the node should be excluded +from comparison." + (unless (file-directory-p dir1) (error "Path %s is not a directory" dir1)) - (when (not (file-directory-p dir2)) + (unless (file-directory-p dir2) (error "Path %s is not a directory" dir2)) + (setf ztree-diff-model-ignore-fun ignore-p) (setq ztree-diff-model-wait-message (concat "Comparing " dir1 " and " dir2 " ...")) (let* ((model (ztree-diff-node-create nil dir1 dir2 diff --git a/ztree-diff.el b/ztree-diff.el index 6fd3644..ff9b323 100644 --- a/ztree-diff.el +++ b/ztree-diff.el @@ -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) @@ -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) " <--> "