emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master a136ff8 36/36: Merged from upstream with StefanM's changes


From: Alexey Veretennikov
Subject: [elpa] master a136ff8 36/36: Merged from upstream with StefanM's changes
Date: Wed, 27 Jan 2016 23:51:00 +0000

branch: master
commit a136ff87271a7a4bf363a4d8bf07429db9bacaf4
Merge: e7f3aa4 a7c5489
Author: Alexey Veretennikov <address@hidden>
Commit: Alexey Veretennikov <address@hidden>

    Merged from upstream with StefanM's changes
---
 packages/ztree/README.md           |   21 ++-
 packages/ztree/ztree-diff-model.el |  386 +++++++++++++++++++-----------------
 packages/ztree/ztree-diff.el       |  274 ++++++++++++++++----------
 packages/ztree/ztree-dir.el        |   56 +++++-
 packages/ztree/ztree-util.el       |    6 +-
 packages/ztree/ztree-view.el       |  192 ++++++++++--------
 packages/ztree/ztree.el            |    4 +-
 7 files changed, 558 insertions(+), 381 deletions(-)

diff --git a/packages/ztree/README.md b/packages/ztree/README.md
index f96adb4..dc1907a 100644
--- a/packages/ztree/README.md
+++ b/packages/ztree/README.md
@@ -54,7 +54,9 @@ Then you need to specify the left and right directories to 
compare.
  * `F5` forces the full rescan.
 
 ### Customizations
-By default all files starting with dot (like `.gitignore`) are not shown and 
excluded from the difference status for directories. One can add an additional 
regexps to the list `ztree-diff-filter-list`. 
+By default all files starting with dot (like `.gitignore`) are not shown and 
excluded from the difference status for directories. One can add an additional 
regexps to the list `ztree-diff-filter-list`.
+
+One also could turn on unicode characters to draw the tree with instead of 
normal ASCII-characters. This is controlled by the `ztree-draw-unicode-lines` 
variable.
 
 ### Screenshots
 
@@ -87,3 +89,20 @@ Set the `ztree-dir-move-focus` variable to `t` in order to 
move focus to the oth
 
 ![ztree 
emacsx11](https://github.com/fourier/ztree/raw/screenshots/screenshots/emacs_xterm.png
 "Emacs in xterm with ztree-dir")
 
+
+## Contributions
+You can contribute to **ztree** in one of the following ways.
+- Submit a bug report
+- Submit a feature request
+- Submit a simple pull request (with changes < 15 lines)
+
+### Copyright issues
+Since **ztree** is a part of [GNU ELPA](https://elpa.gnu.org/), it is 
copyrighted by the [Free Software Foundation, Inc.](http://www.fsf.org/). 
Therefore in order to submit nontrivial changes (with total amount of lines > 
15), one needs to to grant the right to include your works in GNU Emacs to the 
FSF.
+
+For this you need to complete 
[this](https://raw.githubusercontent.com/fourier/ztree/contributions/request-assign.txt)
 form, and send it to address@hidden(mailto:address@hidden). The FSF will send 
you the assignment contract that both you and the FSF will sign.
+
+For more information one can read 
[here](http://www.gnu.org/licenses/why-assign.html) to understand why it is 
needed.
+
+As soon as the paperwork is done one can contribute to **ztree** with bigger 
pull requests.
+Note what pull requests without paperwork done will not be accepted, so please 
notify the [maintainer](mailto:address@hidden) if everything is in place.
+
diff --git a/packages/ztree/ztree-diff-model.el 
b/packages/ztree/ztree-diff-model.el
index f0b4e4a..b4ad75f 100644
--- a/packages/ztree/ztree-diff-model.el
+++ b/packages/ztree/ztree-diff-model.el
@@ -1,10 +1,10 @@
 ;;; ztree-diff-model.el --- diff model for directory trees -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2015  Free Software Foundation, Inc.
+;; Copyright (C) 2013-2016  Free Software Foundation, Inc.
 ;;
-;; Author: Alexey Veretennikov <alexey dot veretennikov at gmail dot com>
+;; Author: Alexey Veretennikov <address@hidden>
 ;; 
-;; Created: 2013-11-1l
+;; Created: 2013-11-11
 ;;
 ;; Keywords: files tools
 ;; URL: https://github.com/fourier/ztree
@@ -33,19 +33,17 @@
 (require 'ztree-util)
 (eval-when-compile (require 'cl-lib))
 
-(defvar ztree-diff-model-wait-message nil
-  "Message showing while constructing the diff tree.")
-(make-variable-buffer-local 'ztree-diff-model-wait-message)
-
-(defvar ztree-diff-model-ignore-fun nil
+(defvar-local 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."
-  (when ztree-diff-model-wait-message
-    (setq ztree-diff-model-wait-message (concat ztree-diff-model-wait-message 
"."))
-    (message ztree-diff-model-wait-message)))
+(defvar-local ztree-diff-model-progress-fun nil
+  "Function which should be called whenever the progress indications is 
updated.")
+
+
+(defun ztree-diff-model-update-progress ()
+  "Update the progress."
+  (when ztree-diff-model-progress-fun
+    (funcall ztree-diff-model-progress-fun)))
 
 ;; Create a record ztree-diff-node with defined fields and getters/setters
 ;; here:
@@ -54,16 +52,19 @@
 ;; right-path is the full path of the right side,
 ;; short-name - is the file or directory name
 ;; children - list of nodes - files or directories if the node is a directory
-;; different = {nil, 'new, 'diff} - means comparison status
+;; different = {nil, 'same, 'new, 'diff, 'ignore} - means comparison status
 (cl-defstruct (ztree-diff-node
                (:constructor)
                (:constructor ztree-diff-node-create
                 (parent left-path right-path
                         different
-                        &aux (short-name (ztree-file-short-name
-                                          (or left-path right-path)))
-                        (right-short-name (ztree-file-short-name
-                                           (or right-path left-path))))))
+                        &aux
+                        (short-name (ztree-file-short-name
+                                     (or left-path right-path)))
+                        (right-short-name
+                         (if (and left-path right-path)
+                             (ztree-file-short-name right-path)
+                           short-name)))))
   parent left-path right-path short-name right-short-name children different)
 
 (defun ztree-diff-model-ignore-p (node)
@@ -73,22 +74,26 @@
 
 (defun ztree-diff-node-to-string (node)
   "Construct the string with contents of the NODE given."
-  (let* ((string-or-nil #'(lambda (x) (if x
-                                          (cond ((stringp x) x)
-                                                ((eq x 'new) "new")
-                                                ((eq x 'diff) "different")
-                                                (t (ztree-diff-node-short-name 
x)))
-                                        "(empty)")))
-         (children (ztree-diff-node-children node))
-         (ch-str ""))
+  (let ((string-or-nil #'(lambda (x) (if x
+                                         (cond ((stringp x) x)
+                                               ((eq x 'new) "new")
+                                               ((eq x 'diff) "different")
+                                               ((eq x 'ignore) "ignored")
+                                               ((eq x 'same) "same")
+                                               (t (ztree-diff-node-short-name 
x)))
+                                       "(empty)")))
+        (children (ztree-diff-node-children node))
+        (ch-str ""))
     (dolist (x children)
-      (setq ch-str (concat ch-str "\n   * " (ztree-diff-node-short-name x))))
+      (setq ch-str (concat ch-str "\n   * " (ztree-diff-node-short-name x)
+                           ": "
+                           (funcall string-or-nil (ztree-diff-node-different 
x)))))
     (concat "Node: " (ztree-diff-node-short-name node)
             "\n"
-            ;; " * Parent: " (let ((parent (ztree-diff-node-parent node)))
-            ;;                 (if parent (ztree-diff-node-short-name parent) 
"nil"))
             " * Parent: " (funcall string-or-nil (ztree-diff-node-parent node))
             "\n"
+            " * Status: " (funcall string-or-nil (ztree-diff-node-different 
node))
+            "\n"
             " * Left path: " (funcall string-or-nil (ztree-diff-node-left-path 
node))
             "\n"
             " * Right path: " (funcall string-or-nil 
(ztree-diff-node-right-path node))
@@ -123,6 +128,7 @@ RIGHT if only on the right side."
     (if (and left right) 'both
       (if left 'left 'right))))
 
+
 (defun ztree-diff-node-equal (node1 node2)
   "Determines if NODE1 and NODE2 are equal."
   (and (string-equal (ztree-diff-node-short-name node1)
@@ -156,9 +162,9 @@ Returns t if equal."
   ;; file(1|2).
   (let* ((file1-untrampified (ztree-diff-untrampify-filename 
(ztree-diff-modef-quotify-string file1)))
          (file2-untrampified (ztree-diff-untrampify-filename 
(ztree-diff-modef-quotify-string file2)))
-         (diff-command (concat "diff -q" " " file1-untrampified " " 
file2-untrampified))
+         (diff-command (concat diff-command " -q" " " file1-untrampified " " 
file2-untrampified))
          (diff-output (shell-command-to-string diff-command)))
-    (not (> (length diff-output) 2))))
+    (if (<= (length diff-output) 2) 'same 'diff)))
 
 (defun ztree-directory-files (dir)
   "Return the list of full paths of files in a directory DIR.
@@ -169,32 +175,29 @@ Filters out . and .."
                 (directory-files dir 'full)))
 
 (defun ztree-diff-model-partial-rescan (node)
-  "Rescan the NODE."
-  ;; assuming what parent is always exists
-  ;; otherwise the UI shall force the full rescan
-  (let ((isdir (ztree-diff-node-is-directory node))
-        (left (ztree-diff-node-left-path node))
-        (right (ztree-diff-node-right-path node)))
-    ;; if node is a directory - traverse
-    (when (and left right
-               (file-exists-p left)
-               (file-exists-p right))
-      (if isdir
-        (let ((traverse (ztree-diff-node-traverse
-                         node
-                         left
-                         right)))
-          (setf (ztree-diff-node-different node) (car traverse))
-          (setf (ztree-diff-node-children node) (cdr traverse)))
-        ;; node is a file
-        (setf (ztree-diff-node-different node)
-              (if (ztree-diff-model-files-equal left right)
-                  nil
-                'diff))))))
-
-(defun ztree-diff-model-subtree (parent path side)
+  "Rescan the NODE.
+The node is a either a file or directory with both
+left and right parts existing."
+  ;; if a directory - recreate
+  (if (ztree-diff-node-is-directory node)
+      (ztree-diff-node-recreate node)
+    ;; if a file, change a status
+    (setf (ztree-diff-node-different node)
+          (if (or (ztree-diff-model-ignore-p node) ; if should be ignored
+                  (eql (ztree-diff-node-different node) 'ignore) ; was ignored
+                  (eql (ztree-diff-node-different ; or parent was ignored
+                        (ztree-diff-node-parent node))
+                       'ignore))
+              'ignore
+            (ztree-diff-model-files-equal (ztree-diff-node-left-path node)
+                                          (ztree-diff-node-right-path node)))))
+  ;; update all parents statuses
+  (ztree-diff-node-update-all-parents-diff node))
+
+(defun ztree-diff-model-subtree (parent path side diff)
   "Create a subtree with given PARENT for the given PATH.
-Argument SIDE either 'left or 'right side."
+Argument SIDE either 'left or 'right side.
+Argument DIFF different status to be assigned to all created nodes."
   (let ((files (ztree-directory-files path))
         (result nil))
     (dolist (file files)
@@ -203,29 +206,26 @@ Argument SIDE either 'left or 'right side."
                         parent
                         (when (eq side 'left) file)
                         (when (eq side 'right) file)
-                        'new))
-                 (children (ztree-diff-model-subtree node file side)))
+                        diff))
+                 (children (ztree-diff-model-subtree node file side diff)))
             (setf (ztree-diff-node-children node) children)
             (push node result))
         (push (ztree-diff-node-create
                parent
                (when (eq side 'left) file)
                (when (eq side 'right) file)
-               'new)
+               diff)
               result)))
     result))
 
 (defun ztree-diff-node-update-diff-from-children (node)
   "Set the diff status for the NODE based on its children."
-  (let ((children (ztree-diff-node-children node))
-        (diff nil))
-    (dolist (child children)
-      (unless (ztree-diff-model-ignore-p child)
-        (setq diff
-              (ztree-diff-model-update-diff
-               diff
-               (ztree-diff-node-different child)))))
-    (setf (ztree-diff-node-different node) diff)))
+  (unless (eql (ztree-diff-node-different node) 'ignore)
+    (let ((diff (cl-reduce #'ztree-diff-model-update-diff
+                           (ztree-diff-node-children node)
+                           :initial-value 'same
+                           :key 'ztree-diff-node-different)))
+      (setf (ztree-diff-node-different node) diff))))
 
 (defun ztree-diff-node-update-all-parents-diff (node)
   "Recursively update all parents diff status for the NODE."
@@ -235,135 +235,159 @@ Argument SIDE either 'left or 'right side."
 
 
 (defun ztree-diff-model-update-diff (old new)
-  "Get the diff status depending if OLD or NEW is not nil."
-  (if new
-      (if (or (not old)
-              (eq old 'new))
-          new
-        old)
-    old))
-
-(defun ztree-diff-node-traverse (parent path1 path2)
-  "Traverse 2 paths creating the list nodes with PARENT defined and diff 
status.
-Function traversing 2 paths PATH1 and PATH2 returning the list where the
-first element is the difference status (nil, 'diff, 'new') and
-the rest is the combined list of nodes."
-  (let ((list1 (ztree-directory-files path1))
-        (list2 (ztree-directory-files path2))
-        (different-dir nil)
-        (result nil))
-    (ztree-diff-model-update-wait-message)
+  "Get the diff status depending if OLD or NEW is not nil.
+If the OLD is 'ignore, do not change anything"
+  ;; if the old whole directory is ignored, ignore children's status
+  (cond ((eql old 'ignore) 'ignore)
+        ;; if the new status is ignored, use old
+        ((eql new 'ignore) old)
+        ;; if the old or new status is different, return different
+        ((or (eql old 'diff)
+             (eql new 'diff)) 'diff)
+        ;; if new is 'new, return new
+        ((eql new 'new) 'new)
+        ;; all other cases return old
+        (t old)))
+
+(defun ztree-diff-node-update-diff-from-parent (node)
+  "Recursively update diff status of all children of NODE.
+This function will traverse through all children recursively
+setting status from the NODE, unless they have an ignore status"
+  (let ((status (ztree-diff-node-different node))
+        (children (ztree-diff-node-children node)))
+    ;; if the parent has ignore status, force all kids this status
+    ;; otherwise only update status when the child status is not ignore
+    (mapc (lambda (child)
+            (when (or (eql status 'ignore)
+                      (not 
+                       (or (eql status 'ignore)
+                           (eql (ztree-diff-node-different child) 'ignore))))
+              (setf (ztree-diff-node-different child) status)
+              (ztree-diff-node-update-diff-from-parent child)))
+            children)))
+        
+    
+
+(defun ztree-diff-model-find-in-files (list shortname is-dir)
+  "Find in LIST of files the file with name SHORTNAME.
+If IS-DIR searching for directories; assume files otherwise"
+  (ztree-find list
+              (lambda (x) (and (string-equal (ztree-file-short-name x)
+                                             shortname)
+                               (eq is-dir (file-directory-p x))))))
+
+
+(defun ztree-diff-model-should-ignore (node)
+  "Determine if the NODE and its children should be ignored.
+If no parent - never ignore;
+if in ignore list - ignore
+if parent has ignored status - ignore"
+  (let ((parent (ztree-diff-node-parent node)))
+    (and parent
+         (or (eql (ztree-diff-node-different parent) 'ignore)
+             (ztree-diff-model-ignore-p node)))))
+
+
+(defun ztree-diff-node-recreate (node)
+  "Traverse 2 paths defined in the NODE updating its children and status."
+  (let* ((list1 (ztree-directory-files (ztree-diff-node-left-path node))) ;; 
left list of liles
+         (list2 (ztree-directory-files (ztree-diff-node-right-path node))) ;; 
right list of files
+         (should-ignore (ztree-diff-model-should-ignore node))
+         ;; status automatically assigned to children of the node
+         (children-status (if should-ignore 'ignore 'new))
+         (children nil))    ;; list of children
+    ;; update waiting status
+    (ztree-diff-model-update-progress)
+    ;; update node status ignore status either inhereted from the
+    ;; parent or the own
+    (when should-ignore
+      (setf (ztree-diff-node-different node) 'ignore))
     ;; first - adding all entries from left directory
     (dolist (file1 list1)
       ;; for every entry in the first directory
       ;; we are creating the node
       (let* ((simple-name (ztree-file-short-name file1))
              (isdir (file-directory-p file1))
-             (children nil)
-             (different nil)
-             ;; create the current node to be set as parent to
-             ;; subdirectories
-             (node (ztree-diff-node-create parent file1 nil nil))
-             ;; 1. find if the file is in the second directory and the type
-             ;;    is the same - i.e. both are directories or both are files
-             (file2 (ztree-find list2
-                                #'(lambda (x) (and (string-equal 
(ztree-file-short-name x)
-                                                                 simple-name)
-                                                   (eq isdir (file-directory-p 
x)))))))
-        ;; 2. if it is not in the second directory, add it as a node
-        (if (not file2)
-            (progn
-              ;; 2.1 if it is a directory, add the whole subtree
-              (when (file-directory-p file1)
-                (setq children (ztree-diff-model-subtree node file1 'left)))
-              ;; 2.2 update the difference status for this entry
-              (setq different 'new))
-          ;; 3. if it is found in second directory and of the same type
-          ;; 3.1 if it is a file
-          (if (not (file-directory-p file1))
-              ;; 3.1.1 set difference status to this entry
-              (setq different (if (ztree-diff-model-files-equal file1 file2) 
nil 'diff))
-            ;; 3.2 if it is the directory
-            ;; 3.2.1 get the result of the directories comparison together 
with status
-            (let ((traverse (ztree-diff-node-traverse node file1 file2)))
-              ;; 3.2.2 update the difference status for whole comparison from
-              ;;       difference result from the 2 subdirectories comparison
-              (setq different (car traverse))
-              ;; 3.2.3 set the children list from the 2 subdirectories 
comparison
-              (setq children (cdr traverse)))))
-        ;; update calculated parameters of the node
-        (setf (ztree-diff-node-right-path node) file2)
-        (setf (ztree-diff-node-children node) children)
-        (setf (ztree-diff-node-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)))
+             ;; find if the file is in the second directory and the type
+             ;; is the same - i.e. both are directories or both are files
+             (file2 (ztree-diff-model-find-in-files list2 simple-name isdir))
+             ;; create a child. The current node is a parent
+             ;; new by default - will be overriden below if necessary
+             (child
+              (ztree-diff-node-create node file1 file2 children-status)))
+        ;; update child own ignore status
+        (when (ztree-diff-model-should-ignore child)
+          (setf (ztree-diff-node-different child) 'ignore))
+        ;; if exists on a right side with the same type,
+        ;; remove from the list of files on the right side
+        (when file2
+          (setf list2 (cl-delete file2 list2 :test #'string-equal)))
+        (cond
+         ;; when exist just on a left side and is a directory, add all
+         ((and isdir (not file2))
+          (setf (ztree-diff-node-children child)
+                (ztree-diff-model-subtree child
+                                          file1
+                                          'left
+                                          (ztree-diff-node-different child))))
+         ;; if 1) exists on both sides and 2) it is a file
+         ;; and 3) not ignored file
+         ((and file2 (not isdir) (not (eql (ztree-diff-node-different child) 
'ignore)))
+          (setf (ztree-diff-node-different child)
+                (ztree-diff-model-files-equal file1 file2)))
+         ;; if exists on both sides and it is a directory, traverse further
+         ((and file2 isdir)
+          (ztree-diff-node-recreate child)))
+        ;; push the created node to the children list
+        (push child children)))
     ;; second - adding entries from the right directory which are not present
     ;; in the left directory
     (dolist (file2 list2)
       ;; for every entry in the second directory
       ;; we are creating the node
-      (let* ((simple-name (ztree-file-short-name file2))
-             (isdir (file-directory-p file2))
-             (children nil)
-             ;; create the node to be added to the results list
-             (node (ztree-diff-node-create parent nil file2 'new))
-             ;; 1. find if the file is in the first directory and the type
-             ;;    is the same - i.e. both are directories or both are files
-             (file1 (ztree-find list1
-                                #'(lambda (x) (and (string-equal 
(ztree-file-short-name x)
-                                                                 simple-name)
-                                                   (eq isdir (file-directory-p 
x)))))))
-        ;; if it is not in the first directory, add it as a node
-        (unless file1
+      (let* ((isdir (file-directory-p file2))
+             ;; create the child to be added to the results list
+             (child
+              (ztree-diff-node-create node nil file2 children-status)))
+        ;; update ignore status of the child
+        (when (ztree-diff-model-should-ignore child)
+          (setf (ztree-diff-node-different child) 'ignore))
           ;; 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)))
-          ;; set calculated children to the node
-          (setf (ztree-diff-node-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 &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))
-  (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 nil))
-         (traverse (ztree-diff-node-traverse model dir1 dir2)))
-    (setf (ztree-diff-node-children model) (cdr traverse))
-    (setf (ztree-diff-node-different model) (car traverse))
-    (message "Done.")
-    model))
+        (when isdir
+          (setf (ztree-diff-node-children child)
+                (ztree-diff-model-subtree child
+                                          file2
+                                          'right
+                                          (ztree-diff-node-different child))))
+        ;; push the created node to the result list
+        (push child children)))
+    ;; finally set different status based on all children
+    ;; depending if the node should participate in overall result
+    (unless should-ignore
+      (setf (ztree-diff-node-different node)
+            (cl-reduce #'ztree-diff-model-update-diff
+                       children
+                       :initial-value 'same
+                       :key 'ztree-diff-node-different)))
+    ;; and set children
+    (setf (ztree-diff-node-children node) children)))
+
 
 (defun ztree-diff-model-update-node (node)
   "Refresh the NODE."
-  (setq ztree-diff-model-wait-message
-        (concat "Updating " (ztree-diff-node-short-name node) " ..."))
-  (let ((traverse (ztree-diff-node-traverse node
-                                            (ztree-diff-node-left-path node)
-                                            (ztree-diff-node-right-path 
node))))
-    (setf (ztree-diff-node-children node) (cdr traverse))
-    (setf (ztree-diff-node-different node) (car traverse))
-    (message "Done.")))
+  (ztree-diff-node-recreate node))
+
+
 
+(defun ztree-diff-model-set-ignore-fun (ignore-p)
+  "Set the buffer-local ignore function to IGNORE-P.
+Ignore function is a function of one argument (ztree-diff-node)
+which returns t if the node should be ignored (like files starting
+with dot etc)."
+  (setf ztree-diff-model-ignore-fun ignore-p))
 
+(defun ztree-diff-model-set-progress-fun (progess-fun)
+  (setf ztree-diff-model-progress-fun progess-fun)) 
 
 (provide 'ztree-diff-model)
 
diff --git a/packages/ztree/ztree-diff.el b/packages/ztree/ztree-diff.el
index ea66a6e..ed3d5f9 100644
--- a/packages/ztree/ztree-diff.el
+++ b/packages/ztree/ztree-diff.el
@@ -1,10 +1,10 @@
 ;;; ztree-diff.el --- Text mode diff for directory trees -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2013-2015  Free Software Foundation, Inc.
+;; Copyright (C) 2013-2016  Free Software Foundation, Inc.
 ;;
-;; Author: Alexey Veretennikov <alexey dot veretennikov at gmail dot com>
+;; Author: Alexey Veretennikov <address@hidden>
 ;; 
-;; Created: 2013-11-1l
+;; Created: 2013-11-11
 ;;
 ;; Keywords: files tools
 ;; URL: https://github.com/fourier/ztree
@@ -63,29 +63,39 @@ By default all filest starting with dot '.', including . 
and ..")
   :group 'Ztree-diff :group 'font-lock-highlighting-faces)
 (defvar ztreep-diff-model-add-face 'ztreep-diff-model-add-face)
 
+(defface ztreep-diff-model-ignored-face
+  '((((type tty pc) (class color) (min-colors 256)) :foreground "#2f2f2f")
+    (((type tty pc) (class color) (min-colors 8))   :foreground "white")
+    (t                   (:foreground "#7f7f7f" :strike-through t)))
+  "*Face used for non-modified files in Ztree-diff."
+  :group 'Ztree-diff :group 'font-lock-highlighting-faces)
+(defvar ztreep-diff-model-ignored-face 'ztreep-diff-model-ignored-face)
+
 (defface ztreep-diff-model-normal-face
-  '((t                   (:foreground "#7f7f7f")))
+  '((((type tty pc) (class color) (min-colors 8)) :foreground "white")
+    (t                   (:foreground "#7f7f7f")))
   "*Face used for non-modified files in Ztree-diff."
   :group 'Ztree-diff :group 'font-lock-highlighting-faces)
 (defvar ztreep-diff-model-normal-face 'ztreep-diff-model-normal-face)
 
 
-(defvar ztree-diff-filter-list (list ztree-diff-hidden-files-regexp)
+(defvar-local ztree-diff-filter-list (list ztree-diff-hidden-files-regexp)
   "List of regexp file names to filter out.
 By default paths starting with dot (like .git) are ignored")
-(make-variable-buffer-local 'ztree-diff-filter-list)
 
-(defvar ztree-diff-dirs-pair nil
+(defvar-local ztree-diff-dirs-pair nil
   "Pair of the directories stored.  Used to perform the full rescan.")
-(make-variable-buffer-local 'ztree-diff-dirs-pair)
 
-(defvar ztree-diff-show-equal-files t
+(defvar-local ztree-diff-show-equal-files t
   "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
+(defvar-local ztree-diff-show-filtered-files nil
   "Show or not files from the filtered list.")
 
+(defvar-local ztree-diff-wait-message nil
+  "Message showing while constructing the diff tree.")
+
+
 ;;;###autoload
 (define-minor-mode ztreediff-mode
   "A minor mode for displaying the difference of the directory trees in text 
mode."
@@ -102,15 +112,17 @@ By default paths starting with dot (like .git) are 
ignored")
     (,(kbd "v") . ztree-diff-view-file)
     (,(kbd "d") . ztree-diff-simple-diff-files)
     (,(kbd "r") . ztree-diff-partial-rescan)
+    (,(kbd "R") . ztree-diff-full-rescan)
     ([f5] . ztree-diff-full-rescan)))
 
 
 (defun ztree-diff-node-face (node)
   "Return the face for the NODE depending on diff status."
   (let ((diff (ztree-diff-node-different node)))
-    (cond ((eq diff 'diff) ztreep-diff-model-diff-face)
+    (cond ((eq diff 'ignore) ztreep-diff-model-ignored-face)
+          ((eq diff 'diff) ztreep-diff-model-diff-face)
           ((eq diff 'new)  ztreep-diff-model-add-face)
-          (t ztreep-diff-model-normal-face))))
+          ((eq diff 'same) ztreep-diff-model-normal-face))))
 
 (defun ztree-diff-insert-buffer-header ()
   "Insert the header to the ztree buffer."
@@ -133,7 +145,11 @@ By default paths starting with dot (like .git) are 
ignored")
   (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 "Ignored file" ztreep-diff-model-ignored-face)
+  (ztree-insert-with-face " - ignored from comparison" 
ztreep-diff-header-small-face)
   (insert "\n")
+
   (ztree-insert-with-face "==============" ztreep-diff-header-face)
   (insert "\n"))
 
@@ -170,10 +186,11 @@ By default paths starting with dot (like .git) are 
ignored")
     (if (not parent)
         (when ztree-diff-dirs-pair
           (ztree-diff (car ztree-diff-dirs-pair) (cdr ztree-diff-dirs-pair)))
-      (progn
-        (ztree-diff-model-partial-rescan common)
-        (ztree-diff-node-update-all-parents-diff node)
-        (ztree-refresh-buffer (line-number-at-pos))))))
+      (ztree-diff-update-wait-message
+           (concat "Updating " (ztree-diff-node-short-name common) " ..."))
+      (ztree-diff-model-partial-rescan common)
+      (message "Done")
+      (ztree-refresh-buffer (line-number-at-pos)))))
 
 
 (defun ztree-diff-partial-rescan ()
@@ -220,10 +237,10 @@ Argument NODE node containing paths to files to call a 
diff on."
         ;; FIXME: The GNU convention is to only use "path" for lists of
         ;; directories as in load-path.
         (open-f #'(lambda (path) (if hard (find-file path)
-                              (let ((split-width-threshold nil))
-                                (view-file-other-window path))))))
+                                  (let ((split-width-threshold nil))
+                                    (view-file-other-window path))))))
     (cond ((and left right)
-           (if (not (ztree-diff-node-different node))
+           (if (eql (ztree-diff-node-different node) 'same)
                (funcall open-f left)
              (if hard
                  (ediff left right)
@@ -251,16 +268,17 @@ COPY-TO-RIGHT specifies which side of the NODE to update."
                  (error error-trap))))
       ;; error message if failed
       (if err (message (concat "Error: " (nth 2 err)))
-        (progn              ; otherwise:
-          ;; assuming all went ok when left and right nodes are the same
-          ;; set both as not different
-          (setf (ztree-diff-node-different node) nil)
-          ;; update left/right paths
-          (if copy-to-right
-              (setf (ztree-diff-node-right-path node) target-path)
-            (setf (ztree-diff-node-left-path node) target-path))
-          (ztree-diff-node-update-all-parents-diff node)
-          (ztree-refresh-buffer (line-number-at-pos)))))))
+        ;; otherwise:
+        ;; assuming all went ok when left and right nodes are the same
+        ;; set both as not different if they were not ignored
+        (unless (eq (ztree-diff-node-different node) 'ignore)
+          (setf (ztree-diff-node-different node) 'same))
+        ;; update left/right paths
+        (if copy-to-right
+            (setf (ztree-diff-node-right-path node) target-path)
+          (setf (ztree-diff-node-left-path node) target-path))
+        (ztree-diff-node-update-all-parents-diff node)
+        (ztree-refresh-buffer (line-number-at-pos))))))
 
 
 (defun ztree-diff-copy-dir (node source-path destination-path copy-to-right)
@@ -281,17 +299,23 @@ COPY-TO-RIGHT specifies which side of the NODE to update."
                      nil)
                  (error error-trap))))
       ;; error message if failed
-      (if err (message (concat "Error: " (nth 1 err)))
-        (progn
-          (message target-full-path)
-          (if copy-to-right
-              (setf (ztree-diff-node-right-path node)
-                    target-full-path)
-            (setf (ztree-diff-node-left-path node)
-                  target-full-path))
-          (ztree-diff-model-update-node node)
-          (ztree-diff-node-update-all-parents-diff node)
-          (ztree-refresh-buffer (line-number-at-pos)))))))
+      (if err
+          (progn
+            (message (concat "Error: " (nth 1 err)))
+            ;; and do rescan of the node
+            (ztree-diff-do-partial-rescan node))
+        ;; if everything is ok, update statuses
+        (message target-full-path)
+        (if copy-to-right
+            (setf (ztree-diff-node-right-path node) target-full-path)
+          (setf (ztree-diff-node-left-path node) target-full-path))
+        (ztree-diff-update-wait-message
+         (concat "Updating " (ztree-diff-node-short-name node) " ..."))
+        ;; TODO: do not rescan the node. Use some logic like in delete
+        (ztree-diff-model-update-node node)
+        (message "Done.")
+        (ztree-diff-node-update-all-parents-diff node)
+        (ztree-refresh-buffer (line-number-at-pos))))))
 
 
 (defun ztree-diff-copy ()
@@ -368,55 +392,67 @@ COPY-TO-RIGHT specifies which side of the NODE to update."
       (let* ((node (car found))
              (side (cdr found))
              (node-side (ztree-diff-node-side node))
-             (delete-from-left t)
-             (remove-path nil)
-             (parent (ztree-diff-node-parent node)))
-        (when parent                    ; do not delete the root node
-          ;; algorithm for determining what to delete similar to copy:
-          ;; 1. if the file is present on both sides, delete
-          ;;    from the side currently selected
-          (setq delete-from-left (if (eq node-side 'both)
-                                     (eq side 'left)
-                                   ;; 2) if one of sides is absent, delete
-                                   ;; from the side where the file is present
-                                   (eq node-side 'left)))
-          (setq remove-path (if delete-from-left
-                                (ztree-diff-node-left-path node)
-                              (ztree-diff-node-right-path node)))
-          (when (yes-or-no-p (format "Delete the file [%s]%s ?"
-                                     (if delete-from-left "LEFT" "RIGHT")
-                                     remove-path))
-            (let* ((delete-command
-                    (if (file-directory-p remove-path)
-                        #'delete-directory
-                      #'delete-file))
-                   (children (ztree-diff-node-children parent))
-                   (err
-                    (condition-case error-trap
-                        (progn
-                          (funcall delete-command remove-path t)
-                          nil)
-                      (error error-trap))))
-              (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 
+             (parent (ztree-diff-node-parent node))
+             ;; algorithm for determining what to delete similar to copy:
+             ;; 1. if the file is present on both sides, delete
+             ;;    from the side currently selected
+             ;; 2. if one of sides is absent, delete
+             ;;    from the side where the file is present
+             (delete-from-left
+              (or (eql node-side 'left)
+                  (and (eql node-side 'both)
+                       (eql side 'left))))
+             (remove-path (if delete-from-left
+                              (ztree-diff-node-left-path node)
+                            (ztree-diff-node-right-path node))))
+        (when (and parent                    ; do not delete the root node
+                   (yes-or-no-p (format "Delete the file [%s]%s ?"
+                                        (if delete-from-left "LEFT" "RIGHT")
+                                        remove-path)))
+          (let* ((delete-command
+                  (if (file-directory-p remove-path)
+                      #'delete-directory
+                    #'delete-file))
+                 (children (ztree-diff-node-children parent))
+                 (err
+                  (condition-case error-trap
+                      (progn
+                        (funcall delete-command remove-path t)
+                        nil)
+                    (error error-trap))))
+            (if err
                 (progn
-                  ;; remove the node from children
-                  (setq children (ztree-filter
-                                  #'(lambda (x) (not (ztree-diff-node-equal x 
node)))
-                                  children))
-                  (setf (ztree-diff-node-children parent) children))
-                (ztree-diff-node-update-all-parents-diff node)
-                ;;(ztree-diff-model-partial-rescan node)
-                (ztree-refresh-buffer (line-number-at-pos))))))))))
+                  (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)))
+              ;; if everything ok
+              ;; if was only on one side
+              ;; remove the node from children
+              (if (or (and (eql node-side 'left)
+                           delete-from-left)
+                      (and (eql node-side 'right)
+                           (not delete-from-left)))
+                  (setf (ztree-diff-node-children parent)
+                        (ztree-filter
+                         (lambda (x) (not (ztree-diff-node-equal x node)))
+                         children))
+                ;; otherwise update only one side
+                (mapc (if delete-from-left
+                          (lambda (x) (setf (ztree-diff-node-left-path x) nil))
+                        (lambda (x) (setf (ztree-diff-node-right-path x) nil)))
+                      (cons node (ztree-diff-node-children node)))
+                ;; and update diff status
+                ;; if was ignored keep the old status
+                (unless (eql (ztree-diff-node-different node) 'ignore)
+                  (setf (ztree-diff-node-different node) 'new))
+                ;; finally update all children statuses
+                (ztree-diff-node-update-diff-from-parent node)))
+            (ztree-diff-node-update-all-parents-diff node)
+            (ztree-refresh-buffer (line-number-at-pos))))))))
 
 
 
@@ -433,44 +469,68 @@ unless it is a parent node."
 
 (defun ztree-node-is-visible (node)
   "Determine if the NODE should be visible."
-  ;; 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)))))
+  (let ((diff (ztree-diff-node-different node)))
+    ;; visible then
+    ;; either it is a root. root have no parent
+    (or (not (ztree-diff-node-parent node))    ; parent is always visible
+        ;; or the files are different or orphan
+        (or (eql diff 'new)
+            (eql diff 'diff))
+        ;; or it is ignored but we show ignored for now
+        (and (eql diff 'ignore)
+             ztree-diff-show-filtered-files) 
+        ;; or they are same but we show same for now
+        (and (eql diff 'same)
+             ztree-diff-show-equal-files))))
 
 (defun ztree-diff-toggle-show-equal-files ()
   "Toggle visibility of the equal files."
   (interactive)
   (setq ztree-diff-show-equal-files (not ztree-diff-show-equal-files))
+  (message (concat (if ztree-diff-show-equal-files "Show" "Hide") " 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))
+  (message (concat (if ztree-diff-show-filtered-files "Show" "Hide") " 
filtered files"))
   (ztree-refresh-buffer))
 
 
+(defun ztree-diff-update-wait-message (&optional msg)
+  "Update the wait mesage with one more '.' progress indication."
+  (if msg
+      (setq ztree-diff-wait-message msg)
+    (when ztree-diff-wait-message
+      (setq ztree-diff-wait-message (concat ztree-diff-wait-message "."))))
+  (message ztree-diff-wait-message))
+
 ;;;###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 
#'ztree-diff-node-ignore-p))
+  (unless (and dir1 (file-directory-p dir1))
+    (error "Path %s is not a directory" dir1))
+  (unless (file-exists-p dir1)
+    (error "Path %s does not exist" dir1))
+  (unless (and dir2 (file-directory-p dir2))
+    (error "Path %s is not a directory" dir2))
+  (unless (file-exists-p dir2)
+    (error "Path %s does not exist" dir2))
+  (let* ((model
+          (ztree-diff-node-create nil dir1 dir2 nil))
          (buf-name (concat "*"
-                           (ztree-diff-node-short-name difference)
+                           (ztree-diff-node-short-name model)
                            " <--> "
-                           (ztree-diff-node-right-short-name difference)
+                           (ztree-diff-node-right-short-name model)
                            "*")))
+    ;; after this command we are in a new buffer,
+    ;; so all buffer-local vars are valid
     (ztree-view buf-name
-                difference
+                model
                 'ztree-node-is-visible
                 'ztree-diff-insert-buffer-header
                 'ztree-diff-node-short-name-wrapper
@@ -481,11 +541,19 @@ Argument DIR2 right directory."
                 'ztree-diff-node-action
                 'ztree-diff-node-side)
     (ztreediff-mode)
+    (ztree-diff-model-set-ignore-fun #'ztree-diff-node-ignore-p)
+    (ztree-diff-model-set-progress-fun #'ztree-diff-update-wait-message)
     (setq ztree-diff-dirs-pair (cons dir1 dir2))
+    (ztree-diff-update-wait-message (concat "Comparing " dir1 " and " dir2 " 
..."))
+    (ztree-diff-node-recreate model)
+    (message "Done.")
+    
     (ztree-refresh-buffer)))
 
 
 
 
+
+
 (provide 'ztree-diff)
 ;;; ztree-diff.el ends here
diff --git a/packages/ztree/ztree-dir.el b/packages/ztree/ztree-dir.el
index 08f4041..d3d3b25 100644
--- a/packages/ztree/ztree-dir.el
+++ b/packages/ztree/ztree-dir.el
@@ -1,10 +1,10 @@
 ;;; ztree-dir.el --- Text mode directory tree -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2015  Free Software Foundation, Inc.
+;; Copyright (C) 2013-2016  Free Software Foundation, Inc.
 ;;
-;; Author: Alexey Veretennikov <alexey dot veretennikov at gmail dot com>
+;; Author: Alexey Veretennikov <address@hidden>
 ;; 
-;; Created: 2013-11-1l
+;; Created: 2013-11-11
 ;;
 ;; Keywords: files tools
 ;; URL: https://github.com/fourier/ztree
@@ -45,6 +45,7 @@
 
 (require 'ztree-util)
 (require 'ztree-view)
+(eval-when-compile (require 'cl-lib))
 
 ;;
 ;; Constants
@@ -60,7 +61,18 @@ By default all filest starting with dot '.', including . and 
..")
 
 (defvar ztree-dir-move-focus nil
   "If set to true moves the focus to opened window when the
-user press RETURN on file ")t
+user press RETURN on file ")
+
+(defvar-local ztree-dir-filter-list (list ztree-hidden-files-regexp)
+  "List of regexp file names to filter out.
+By default paths starting with dot (like .git) are ignored.
+One could add own filters in the following way:
+
+(setq-default ztree-dir-filter-list (cons \"^.*\\.pyc\" ztree-dir-filter-list))
+")
+
+(defvar-local ztree-dir-show-filtered-files nil
+  "Show or not files from the filtered list.")
 
 
 ;;
@@ -76,6 +88,19 @@ user press RETURN on file ")t
 (defvar ztreep-header-face 'ztreep-header-face)
 
 
+(define-minor-mode ztreedir-mode
+  "A minor mode for displaying the directory trees in text mode."
+  ;; initial value
+  nil
+  ;; modeline name
+  " Dir"
+  ;; The minor mode keymap
+  `(
+    (,(kbd "H") . ztree-dir-toggle-show-filtered-files)))
+
+
+
+
 ;;
 ;; File bindings to the directory tree control
 ;;
@@ -91,8 +116,12 @@ user press RETURN on file ")t
 
 (defun ztree-file-not-hidden (filename)
   "Determines if the file with FILENAME should be visible."
-  (not (string-match ztree-hidden-files-regexp
-                     (ztree-file-short-name filename))))
+  (let ((name (ztree-file-short-name filename)))
+    (and (not (or (string= name ".") (string= name "..")))
+         (or 
+          ztree-dir-show-filtered-files 
+          (not (cl-find-if (lambda (rx) (string-match rx name)) 
ztree-dir-filter-list))))))
+
 
 (defun ztree-find-file (node hard)
   "Find the file at NODE.
@@ -107,6 +136,17 @@ Otherwise, the ztree window is used to find the file."
           (t 
            (find-file node)))))
 
+
+(defun ztree-dir-toggle-show-filtered-files ()
+  "Toggle visibility of the filtered files."
+  (interactive)
+  (setq ztree-dir-show-filtered-files (not ztree-dir-show-filtered-files))
+  (message (concat (if ztree-dir-show-filtered-files "Show" "Hide") " filtered 
files"))
+  (ztree-refresh-buffer))
+
+
+
+
 ;;;###autoload
 (defun ztree-dir (path)
   "Create an interactive buffer with the directory tree of the PATH given."
@@ -122,7 +162,9 @@ Otherwise, the ztree window is used to find the file."
                   #'string-equal
                   (lambda (x) (directory-files x 'full))
                   nil                   ; face
-                  #'ztree-find-file)))) ; action
+                  #'ztree-find-file)    ; action
+      (ztreedir-mode))))
+
 
 
 (provide 'ztree-dir)
diff --git a/packages/ztree/ztree-util.el b/packages/ztree/ztree-util.el
index 40fe12e..ec49457 100644
--- a/packages/ztree/ztree-util.el
+++ b/packages/ztree/ztree-util.el
@@ -1,10 +1,10 @@
 ;;; ztree-util.el --- Auxiliary utilities for the ztree package -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2015  Free Software Foundation, Inc.
+;; Copyright (C) 2013-2016  Free Software Foundation, Inc.
 ;;
-;; Author: Alexey Veretennikov <alexey dot veretennikov at gmail dot com>
+;; Author: Alexey Veretennikov <address@hidden>
 ;; 
-;; Created: 2013-11-1l
+;; Created: 2013-11-11
 ;;
 ;; Keywords: files tools
 ;; URL: https://github.com/fourier/ztree
diff --git a/packages/ztree/ztree-view.el b/packages/ztree/ztree-view.el
index 4a5a766..3244ccc 100644
--- a/packages/ztree/ztree-view.el
+++ b/packages/ztree/ztree-view.el
@@ -1,10 +1,10 @@
 ;;; ztree-view.el --- Text mode tree view (buffer) -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2015  Free Software Foundation, Inc.
+;; Copyright (C) 2013-2016  Free Software Foundation, Inc.
 ;;
-;; Author: Alexey Veretennikov <alexey dot veretennikov at gmail dot com>
+;; Author: Alexey Veretennikov <address@hidden>
 ;; 
-;; Created: 2013-11-1l
+;; Created: 2013-11-11
 ;;
 ;; Keywords: files tools
 ;; URL: https://github.com/fourier/ztree
@@ -48,78 +48,65 @@
 ;; Globals
 ;;
 
-(defvar ztree-expanded-nodes-list nil
+(defvar ztree-draw-unicode-lines nil
+  "If set forces ztree to draw lines with unicode characters.")
+
+(defvar-local ztree-expanded-nodes-list nil
   "A list of Expanded nodes (i.e. directories) entries.")
-(make-variable-buffer-local 'ztree-expanded-nodes-list)
 
-(defvar ztree-start-node nil
+(defvar-local ztree-start-node nil
   "Start node(i.e. directory) for the window.")
-(make-variable-buffer-local 'ztree-start-node)
 
-(defvar ztree-line-to-node-table nil
+(defvar-local ztree-line-to-node-table nil
   "List of tuples with full node(i.e. file/directory name and the line.")
-(make-variable-buffer-local 'ztree-line-to-node-table)
 
-(defvar ztree-start-line nil
+(defvar-local ztree-start-line nil
   "Index of the start line - the root.")
-(make-variable-buffer-local 'ztree-start-line)
 
-(defvar ztree-parent-lines-array nil
+(defvar-local ztree-parent-lines-array nil
   "Array of parent lines.
 The ith value of the array is the parent line for line i.
 If ith value is i - it is the root line")
-(make-variable-buffer-local 'ztree-parent-lines-array)
 
-(defvar ztree-count-subsequent-bs nil
+(defvar-local ztree-count-subsequent-bs nil
   "Counter for the subsequest BS keys (to identify double BS).
 Used in order to not to use cl package and `lexical-let'")
-(make-variable-buffer-local 'ztree-count-subsequent-bs)
 
-(defvar ztree-line-tree-properties nil
+(defvar-local ztree-line-tree-properties nil
   "Hash with key - line number, value - property ('left, 'right, 'both).
 Used for 2-side trees, to determine if the node exists on left or right
 or both sides")
-(make-variable-buffer-local 'ztree-line-tree-properties)
 
-(defvar ztree-tree-header-fun nil
+(defvar-local ztree-tree-header-fun nil
   "Function inserting the header into the tree buffer.
 MUST inster newline at the end!")
-(make-variable-buffer-local 'ztree-tree-header-fun)
 
-(defvar ztree-node-short-name-fun nil
+(defvar-local ztree-node-short-name-fun nil
   "Function which creates a pretty-printable short string from the node.")
-(make-variable-buffer-local 'ztree-node-short-name-fun)
 
-(defvar ztree-node-is-expandable-fun nil
+(defvar-local ztree-node-is-expandable-fun nil
   "Function which determines if the node is expandable.
 For example if the node is a directory")
-(make-variable-buffer-local 'ztree-node-is-expandable-fun)
 
-(defvar ztree-node-equal-fun nil
+(defvar-local ztree-node-equal-fun nil
   "Function which determines if the 2 nodes are equal.")
-(make-variable-buffer-local 'ztree-node-equal-fun)
 
-(defvar ztree-node-contents-fun nil
+(defvar-local ztree-node-contents-fun nil
   "Function returning list of node contents.")
-(make-variable-buffer-local 'ztree-node-contents-fun)
 
-(defvar ztree-node-side-fun nil
+(defvar-local ztree-node-side-fun nil
   "Function returning position of the node: 'left, 'right or 'both.
 If not defined(by default) - using single screen tree, otherwise
 the buffer is split to 2 trees")
-(make-variable-buffer-local 'ztree-node-side-fun)
 
-(defvar ztree-node-face-fun nil
+(defvar-local ztree-node-face-fun nil
   "Function returning face for the node.")
-(make-variable-buffer-local 'ztree-node-face-fun)
 
-(defvar ztree-node-action-fun nil
+(defvar-local ztree-node-action-fun nil
   "Function called when Enter/Space pressed on the node.")
-(make-variable-buffer-local 'ztree-node-action-fun)
 
-(defvar ztree-node-showp-fun nil
+(defvar-local ztree-node-showp-fun nil
   "Function called to decide if the node should be visible.")
-(make-variable-buffer-local 'ztree-node-showp-fun)
 
 
 ;;
@@ -176,7 +163,9 @@ the buffer is split to 2 trees")
 (define-derived-mode ztree-mode special-mode "Ztree"
   "A major mode for displaying the directory tree in text mode."
   ;; only spaces
-  (setq indent-tabs-mode nil))
+  (setq indent-tabs-mode nil)
+  (setq        buffer-read-only t))
+
 
 (defun ztree-find-node-in-line (line)
   "Return the node for the LINE specified.
@@ -343,45 +332,66 @@ Optional argument FACE face to use to draw a character."
     (goto-char (+ x (-(point) 1)))
     (delete-char 1)
     (insert-char c 1)
-    (put-text-property (1- (point)) (point) 'face (if face face 
'ztreep-arrow-face))))
+    (put-text-property (1- (point)) (point) 'font-lock-face (if face face 
'ztreep-arrow-face))))
+
+(defun ztree-vertical-line-char ()
+  "Return the character used to draw vertical line"
+  (if ztree-draw-unicode-lines #x2502 ?\|))
+
+(defun ztree-horizontal-line-char ()
+  "Return the character used to draw vertical line"
+  (if ztree-draw-unicode-lines #x2500 ?\-))
+
+(defun ztree-left-bottom-corner-char ()
+  "Return the character used to draw vertical line"
+  (if ztree-draw-unicode-lines #x2514 ?\`))
+
+(defun ztree-left-intersection-char ()
+  "Return left intersection character.
+It is just vertical bar when unicode disabled"
+  (if ztree-draw-unicode-lines #x251C ?\|))
 
 (defun ztree-draw-vertical-line (y1 y2 x &optional face)
   "Draw a vertical line of '|' characters from Y1 row to Y2 in X column.
 Optional argument FACE face to draw line with."
-  (let ((count (abs (- y1 y2))))
+  (let ((ver-line-char (ztree-vertical-line-char))
+        (count (abs (- y1 y2))))
     (if (> y1 y2)
         (progn
           (dotimes (y count)
-            (ztree-draw-char ?\| x (+ y2 y) face))
-          (ztree-draw-char ?\| x (+ y2 count) face))
+            (ztree-draw-char ver-line-char x (+ y2 y) face))
+          (ztree-draw-char ver-line-char x (+ y2 count) face))
       (progn
         (dotimes (y count)
-          (ztree-draw-char ?\| x (+ y1 y) face))
-        (ztree-draw-char ?\| x (+ y1 count) face)))))
+          (ztree-draw-char ver-line-char x (+ y1 y) face))
+        (ztree-draw-char ver-line-char x (+ y1 count) face)))))
 
 (defun ztree-draw-vertical-rounded-line (y1 y2 x &optional face)
   "Draw a vertical line of '|' characters finishing with '`' character.
 Draws the line from Y1 row to Y2 in X column.
 Optional argument FACE facet to draw the line with."
-  (let ((count (abs (- y1 y2))))
+  (let ((ver-line-char (ztree-vertical-line-char))
+        (corner-char (ztree-left-bottom-corner-char))
+        (count (abs (- y1 y2))))
     (if (> y1 y2)
         (progn
           (dotimes (y count)
-            (ztree-draw-char ?\| x (+ y2 y) face))
-          (ztree-draw-char ?\` x (+ y2 count) face))
+            (ztree-draw-char ver-line-char x (+ y2 y) face))
+          (ztree-draw-char corner-char x (+ y2 count) face))
       (progn
         (dotimes (y count)
-          (ztree-draw-char ?\| x (+ y1 y) face))
-        (ztree-draw-char ?\` x (+ y1 count) face)))))
+          (ztree-draw-char ver-line-char x (+ y1 y) face))
+        (ztree-draw-char corner-char x (+ y1 count) face)))))
 
 
 (defun ztree-draw-horizontal-line (x1 x2 y)
   "Draw the horizontal line from column X1 to X2 in the row Y."
-  (if (> x1 x2)
-      (dotimes (x (1+ (- x1 x2)))
-        (ztree-draw-char ?\- (+ x2 x) y))
-    (dotimes (x (1+ (- x2 x1)))
-      (ztree-draw-char ?\- (+ x1 x) y))))
+  (let ((hor-line-char (ztree-horizontal-line-char)))
+    (if (> x1 x2)
+        (dotimes (x (1+ (- x1 x2)))
+          (ztree-draw-char hor-line-char (+ x2 x) y))
+      (dotimes (x (1+ (- x2 x1)))
+        (ztree-draw-char hor-line-char (+ x1 x) y)))))
 
 
 (defun ztree-draw-tree (tree depth start-offset)
@@ -396,6 +406,8 @@ Argument START-OFFSET column to start drawing from."
            (line-start (+ 3 offset))
            (line-end-leaf (+ 7 offset))
            (line-end-node (+ 4 offset))
+           (corner-char (ztree-left-bottom-corner-char))
+           (intersection-char (ztree-left-intersection-char))
            ;; determine if the line is visible. It is always the case
            ;; for 1-sided trees; however for 2 sided trees
            ;; it depends on which side is the actual element
@@ -417,17 +429,24 @@ Argument START-OFFSET column to start drawing from."
                                           (funcall visible (ztree-car-atom 
x)))))
               (x-offset (+ 2 offset)))
           (when last-child
-            (ztree-draw-vertical-rounded-line (1+ root)
-                                              (ztree-car-atom last-child)
-                                              x-offset)))
-        ;; draw recursively
-        (dolist (child children)
-          (ztree-draw-tree child (1+ depth) start-offset)
-          (let ((end (if (listp child) line-end-node line-end-leaf)))
-            (when (funcall visible (ztree-car-atom child))
-              (ztree-draw-horizontal-line line-start
-                                          end
-                                          (ztree-car-atom child)))))))))
+            (ztree-draw-vertical-line (1+ root)
+                                      (ztree-car-atom last-child)
+                                      x-offset))
+          ;; draw recursively
+          (dolist (child children)
+            (ztree-draw-tree child (1+ depth) start-offset)
+            (let ((end (if (listp child) line-end-node line-end-leaf))
+                  (row (ztree-car-atom child)))
+              (when (funcall visible (ztree-car-atom child))
+                (ztree-draw-char intersection-char (1- line-start) row)
+                (ztree-draw-horizontal-line line-start
+                                            end
+                                            row))))
+          ;; finally draw the corner at the end of vertical line
+          (when last-child
+            (ztree-draw-char corner-char
+                             x-offset
+                             (ztree-car-atom last-child))))))))
 
 (defun ztree-fill-parent-array (tree)
   "Set the root lines array.
@@ -538,29 +557,33 @@ Writes a string with given DEPTH, prefixed with [ ] if 
EXPANDABLE
 and [-] or [+] depending on if it is EXPANDED from the specified OFFSET.
 Optional argument FACE face to write text with."
   (let ((node-sign #'(lambda (exp)
-                       (insert "[" (if exp "-" "+") "]")
-                       (set-text-properties (- (point) 3)
-                                            (point)
-                                            '(face ztreep-expand-sign-face)))))
-    (move-to-column offset t)
+                       (let ((sign (concat "[" (if exp "-" "+") "]")))
+                         (insert (propertize sign 
+                                             'font-lock-face
+                                             ztreep-expand-sign-face)))))
+        ;; face to use. if FACE is not null, use it, otherwise
+        ;; deside from the node type
+        (entry-face (cond (face face)
+                          (expandable 'ztreep-node-face)
+                          (t ztreep-leaf-face))))
+    ;; move-to-column in contrast to insert reuses the last property
+    ;; so need to clear it
+    (let ((start-pos (point)))
+      (move-to-column offset t)
+      (remove-text-properties start-pos (point) '(font-lock-face nil)))
     (delete-region (point) (line-end-position))
+    ;; every indentation level is 4 characters
     (when (> depth 0)
-      (dotimes (_ depth)
-        (insert " ")
-        (insert-char ?\s 3)))           ; insert 3 spaces
+      (insert-char ?\s (* 4 depth)))           ; insert 4 spaces
     (when (> (length short-name) 0)
-      (if expandable
-          (progn
-            (funcall node-sign expanded)   ; for expandable nodes insert 
"[+/-]"
-            (insert " ")
-            (put-text-property 0 (length short-name)
-                               'face (if face face 'ztreep-node-face) 
short-name)
-            (insert short-name))
-        (progn
-          (insert "    ")
-          (put-text-property 0 (length short-name)
-                             'face (if face face 'ztreep-leaf-face) short-name)
-          (insert short-name))))))
+      (let ((start-pos (point)))
+        (if expandable
+            (funcall node-sign expanded))   ; for expandable nodes insert 
"[+/-]"
+        ;; indentation for leafs 4 spaces from the node name
+        (insert-char ?\s (- 4 (- (point) start-pos))))
+      (insert (propertize short-name 'font-lock-face entry-face)))))
+
+
 
 (defun ztree-jump-side ()
   "Jump to another side for 2-sided trees."
@@ -605,7 +628,8 @@ Optional argument LINE scroll to the line given."
                    children-fun
                    face-fun
                    action-fun
-                   &optional node-side-fun
+                   &optional
+                   node-side-fun
                    )
   "Create a ztree view buffer configured with parameters given.
 Argument BUFFER-NAME Name of the buffer created.
diff --git a/packages/ztree/ztree.el b/packages/ztree/ztree.el
index b591756..300ed85 100644
--- a/packages/ztree/ztree.el
+++ b/packages/ztree/ztree.el
@@ -3,8 +3,8 @@
 ;; Copyright (C) 2013-2016  Free Software Foundation, Inc.
 ;;
 ;; Author: Alexey Veretennikov <address@hidden>
-;; Created: 2013-11-1l
-;; Version: 1.0.2
+;; Created: 2013-11-11
+;; Version: 1.0.3
 ;; Package-Requires: ((cl-lib "0"))
 ;; Keywords: files tools
 ;; URL: https://github.com/fourier/ztree



reply via email to

[Prev in Thread] Current Thread [Next in Thread]