[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
- [elpa] master b5b2d02 32/36: removed test files, (continued)
- [elpa] master b5b2d02 32/36: removed test files, Alexey Veretennikov, 2016/01/27
- [elpa] master 74899aa 30/36: Merge branch 'master' of github.com:fourier/ztree, Alexey Veretennikov, 2016/01/27
- [elpa] master 6d7ce1f 28/36: Fixed Delete method, Alexey Veretennikov, 2016/01/27
- [elpa] master 3d70aef 25/36: Merge pull request #30 from tarsius/fix-typo, Alexey Veretennikov, 2016/01/27
- [elpa] master 159ddbd 26/36: Fixed partial update, Alexey Veretennikov, 2016/01/27
- [elpa] master a7c5489 35/36: Upgraded version number, Alexey Veretennikov, 2016/01/27
- [elpa] master 7b5dfce 23/36: Use defvar-local instead of combo defvar && make-variable-buffer-local, Alexey Veretennikov, 2016/01/27
- [elpa] master e143f66 27/36: Fixed copy of the files; added 'R' for full rescan, Alexey Veretennikov, 2016/01/27
- [elpa] master dbf9539 31/36: Fixed issue #27, Alexey Veretennikov, 2016/01/27
- [elpa] master 597b005 34/36: 2016-01-26 Stefan Monnier <address@hidden>, Alexey Veretennikov, 2016/01/27
- [elpa] master a136ff8 36/36: Merged from upstream with StefanM's changes,
Alexey Veretennikov <=