Browse files

Updated Copyright

Reworked mechanisms:
- Clicking onto nodes in the methods-buffer
- working with indirect buffers
- History-display
Some small fixes (e.g. ecb-merge-face-into-text now checks if the face is
already there)
  • Loading branch information...
1 parent e4d7c5e commit aa7071f974112f8ef495ea2e163f720e61371f5f berndl committed Apr 15, 2009
Showing with 2,280 additions and 974 deletions.
  1. +75 −1 NEWS
  2. +88 −92 ecb-analyse.el
  3. +0 −1 ecb-autogen.el
  4. +295 −63 ecb-common-browser.el
  5. +0 −1 ecb-compatibility.el
  6. +0 −1 ecb-compilation.el
  7. +5 −7 ecb-create-layout.el
  8. +1 −3 ecb-cycle.el
  9. +1 −3 ecb-eshell.el
  10. +2 −1 ecb-examples.el
  11. +72 −18 ecb-face.el
  12. +852 −285 ecb-file-browser.el
  13. +1 −3 ecb-help.el
  14. +5 −6 ecb-jde.el
  15. +1 −4 ecb-layout-defs.el
  16. +1 −2 ecb-layout.el
  17. +569 −318 ecb-method-browser.el
  18. +25 −24 ecb-mode-line.el
  19. +54 −17 ecb-navigate.el
  20. +25 −28 ecb-semantic-wrapper.el
  21. +2 −4 ecb-speedbar.el
  22. +1 −4 ecb-tod.el
  23. +1 −4 ecb-upgrade.el
  24. +91 −21 ecb-util.el
  25. +20 −15 ecb.el
  26. +93 −48 tree-buffer.el
View
76 NEWS
@@ -41,13 +41,67 @@
immediatelly and not interruptable (as with the idle-scheduler of
semantic), which can be quite annoying with big source-files.
+** ECB is able to work with indirect buffers it the base-buffer is filebased
+
+ Now you can work with indirect-buffers as well as with normal file-buffers,
+ i.e. indirect buffers are shown in the history��, their contents are
+ displayed in the methods-buffer, the ECB-analyse-buffer works with them,
+ autom. synchronizing the ECB-tree-buffers works for them etc...
+
+** Complete reworked history-buffer
+
+*** The history is able to deal with indirect-buffer entries.
+ See new option `ecb-history-stick-indirect-buffers-to-basebuffer'.
+
+*** The history can now be bucketized, see new `ecb-history-make-buckets'.
+ This option allows to define several criterias for building buckets in the
+ history-buffer all the history entries are sorted in (e.g. by major-mode,
+ directory, file-extension or regular expressions).
+
+ The latter one allows in combination with the indirect-buffer ability to
+ work with something like "virtual folders" (well, "virtual folders"
+ light).
+
+ For example, there is a large project with a huge number of files, and
+ there are various tasks in this project. So it could be convenient to
+ group buffers according to various tasks. It could be fulfiled through
+ using indirect buffers, for example like this
+
+ task_1-aaa.pl
+ task_1-bbb.c
+ task_1-ccc.sh
+ ...
+ task_N-xxx.java
+ task_N-ccc.sh
+
+ This means create indirect buffers with a name-part which can be used for
+ grouping together buffers with same name-part (here e.g. task_1- ...
+ task_N-). In the example above you would create two indirect buffers for
+ the filebuffer ccc.sh, one named task_1-ccc.sh, the other named
+ task_N-ccc.sh).
+
+ Then use the new option `ecb-history-make-buckets' to define regexps for
+ bucketizing all (indirect) buffers according their task-part in the
+ buffer-name.
+
+*** There are now new faces for the history entries.
+ See new options `ecb-history-bucket-node-face',
+ `ecb-history-dead-buffer-face' and `ecb-history-indirect-buffer-face' and
+ equaly named new faces.
+
** Much saver advice-backbone for all advices needed by ECB
This is not a user-visible change but enhances the stability of ECB by
using now a new advice-backbone which guarantes that all ecb-advices are
enabled rsp. disabled correctly depending on the surrounding context.
Introducing three new macros `defecb-advice-set', `defecb-advice' and
`ecb-with-original-adviced-function-set'.
+
+** New support for Git and Monotone as version-control systems
+
+ If Git rsp. Monotone are supported by VC (means vc-git.el rsp. vc-mtn.el
+ are distributed with Emacs) then ECB supports now both of them out of the
+ box.
** New features rsp. commands
@@ -90,7 +144,16 @@
In Emacs 22 this command ignores the settings in `same-window-*'. Now ECB
adopts this behavior also for its adviced version so the command works
in a smart manner optimized for ECB.
-
+
+** Better compatibility with CEDET 1.0preX and semantic 2.0preX
+
+*** The ECB-analyse-interactor now works very well with current semantic analyzer
+
+*** Fix compatibility about some changes of semantic concerning adopting
+ external member-functions (as in C++ or eieio).
+
+*** ECB now works very well with semantic-idle-scheduler-mode (s.a.)
+
** Fixed Bugs
*** Fixed a bug which prevented `ecb-rebuild-methods-buffer' to work correctly
@@ -106,8 +169,19 @@
Downloading does not work with the former one and getting a packagelist is
not possible with the latter one. Therefore ECB now uses both URLs.
+ REMARK: Theres no guarantee that this feature works correctly! It is
+ deprecated and will not be supported anymore.
+
*** Fixed context-menu for VC-operations in the sources- and history-window
Now all vc-commands are called interactively by ECB.
+
+*** Fixed a bug with the ECB-navigation feature (C-c . p and C-c . n)
+ Now the commands `ecb-nav-goto-next' and `ecb-nav-goto-previous' work
+ saver and also for indirect buffers.
+
+*** Fixed small bugs with synchronizing current tag with highlighted tag
+ in the methods buffer. This was when the buffer was reparsed with
+ `semantic-idle-scheduler-mode' or after saving the buffer.
View
180 ecb-analyse.el
@@ -299,51 +299,61 @@ This means in fact display the current analysis for current point."
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: make interruptable. Necessary
;; e.g. when typing: "(e" then scanning all elisp stuff beginning with e is
;; really annoying....
- (let* ((mode-local-active-mode major-mode)
- (scope (semantic-calculate-scope (point)))
- (ctxt (ecb--semantic-analyze-current-context (point)))
- (cnt (ecb--semantic-find-tag-by-overlay))
- (completions (when ctxt
- (ecb--semantic-analyze-possible-completions ctxt))))
+ (let ((analysis nil)
+ (scope nil)
+ (completions nil)
+ (cnt nil)
+ (mode-local-active-mode nil)
+ )
;; Try and get some sort of analysis
+ (condition-case nil
+ (progn
+ (setq mode-local-active-mode major-mode)
+ (save-excursion
+ ;; Get the current scope
+ (setq scope (semantic-calculate-scope (point)))
+ ;; Get the analysis
+ (setq analysis (ecb--semantic-analyze-current-context (point)))
+ (setq cnt (ecb--semantic-find-tag-by-overlay))
+ (when analysis
+ (setq completions (ecb--semantic-analyze-possible-completions analysis)))))
+ (error nil))
(ecb-exec-in-window ecb-analyse-buffer-name
;; we must remove the old nodes
(tree-buffer-set-root (tree-node-new-root))
- (when ctxt
- ;; Now insert information about the context
- (when cnt
- (ecb-analyse-add-nodes "Context" "Context"
- cnt ecb-analyse-nodetype-context))
- ;; Let different classes draw more nodes.
- (ecb-analyse-more-nodes ctxt)
+ (when cnt
+ (ecb-analyse-add-nodes "Context" "Context"
+ cnt ecb-analyse-nodetype-context))
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: maybe we should adopt this
+ ;; for ecb-analyse..
+ ;; (when analysis
+ ;; ;; If this analyzer happens to point at a complete symbol, then
+ ;; ;; see if we can dig up some documentation for it.
+ ;; (semantic-ia-sb-show-doc analysis))
+
+ ;; Show local variables
+ (when scope
+ (ecb-analyse-show-scope scope))
+
+ (when analysis
+ ;; Let different classes draw more buttons.
+ (ecb-analyse-more-nodes analysis)
(when completions
(ecb-analyse-add-nodes "Completions" "Completions" completions
ecb-analyse-nodetype-completions)))
(tree-buffer-update)))
(run-hooks 'ecb-analyse-buffer-sync-hook))
-
-;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: why does this not work?!
-
-;; (defmethod ecb-analyse-more-nodes ((context semantic-analyze-context))
-;; "Show a set of ecb-nodes specific to CONTEXT."
-;; (let* ((scope (or (oref context scope)
-;; (semantic-calculate-scope (point))))
-;; (localvars (or (when scope (oref scope localvar))
-;; (semantic-get-all-local-variables))))
-;; (when localvars
-;; (ecb-analyse-add-nodes "Local Variables" "Local Variables" localvars
-;; ecb-analyse-nodetype-localvars)))
-;; (let ((prefix (oref context prefix)))
-;; (when prefix
-;; (ecb-analyse-add-nodes "Prefix" "Prefix" prefix ecb-analyse-nodetype-prefix))))
+
+(defun ecb-analyse-show-scope (scope)
+ "Show SCOPE information."
+ (let ((localvars (when scope
+ (oref scope localvar))))
+ (when localvars
+ (ecb-analyse-add-nodes "Local Variables" "Local Variables" localvars
+ ecb-analyse-nodetype-localvars))))
(defmethod ecb-analyse-more-nodes ((context semantic-analyze-context))
"Show a set of ecb-nodes specific to CONTEXT."
- (let* ((scope (oref context scope))
- (localvars (when scope (oref scope localvar))))
- (when localvars
- (ecb-analyse-add-nodes "Local Variables" "Local Variables" localvars
- ecb-analyse-nodetype-localvars)))
(let ((prefix (oref context prefix)))
(when prefix
(ecb-analyse-add-nodes "Prefix" "Prefix" prefix ecb-analyse-nodetype-prefix))))
@@ -385,8 +395,9 @@ of LIST."
(when list
(save-excursion
(set-buffer ecb-analyse-buffer-name)
- (let* ((bucket-name-formatted (ecb-merge-face-into-text bucket-name
- ecb-analyse-bucket-node-face))
+ (let* ((bucket-name-formatted
+ (ecb-merge-face-into-text (ecb-format-bucket-name bucket-name)
+ ecb-analyse-bucket-node-face))
(bucket-node (tree-node-new bucket-name-formatted
ecb-analyse-nodetype-bucket
(list 'ecb-bucket-node
@@ -411,7 +422,7 @@ of LIST."
(ecb-merge-face-into-text string ecb-analyse-bucket-element-face))
(if (ecb--semantic-tag-p elem)
(tree-node-new string nodetype
- (list elem
+ (list elem
(if (ecb--semantic-tag-with-position-p elem)
ecb-analyse-nodedata-tag-with-pos
ecb-analyse-nodedata-tag-without-pos)
@@ -438,79 +449,62 @@ used as window."
;; if we have a positioned tag we jump to it
(when (and tag (= (nth 1 data) ecb-analyse-nodedata-tag-with-pos))
;; We must highlight the tag
- (tree-buffer-highlight-node-by-data/type data)
- (ecb-jump-to-tag (or (and (ecb--semantic-tag-buffer tag)
- (buffer-file-name (ecb--semantic-tag-buffer tag)))
- ;; then we have a tag with no buffer but only
- ;; buffer-start- and buffer-end-pos
- ecb-path-selected-source)
+ (tree-buffer-highlight-node-by-data/name data)
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: what about tags without
+ ;; buffer but onlxy with start- and end-pos?!
+ (ecb-display-tag (ecb-source-make (ecb-buffer-file-name
+ (ecb--semantic-tag-buffer tag))
+ (ecb--semantic-tag-buffer tag))
tag
- (or window ecb-last-edit-window-with-point)
+ (or window (ecb-get-edit-window nil))
t nil))))))
-(tree-buffer-defpopup-command ecb-analyse-complete
- "Complete at current point of the edit-window the selected completion-tag."
- ;; We must highlight the tag
- (let* ((data (tree-node->data node))
- (tag (nth 0 data))
- (type (tree-node->type node)))
- (when (= type ecb-analyse-nodetype-completions)
- (tree-buffer-highlight-node-by-data/type data)
- (ecb-find-file-and-display ecb-path-selected-source nil)
- (let* ((a (ecb--semantic-analyze-current-context (point)))
- (bounds (oref a bounds))
- (movepoint nil))
- (save-excursion
- (if (and (<= (point) (cdr bounds)) (>= (point) (car bounds)))
- (setq movepoint t))
- (goto-char (car bounds))
- (delete-region (car bounds) (cdr bounds))
- (insert (ecb--semantic-tag-name tag))
- (if movepoint (setq movepoint (point))))
- (if movepoint
- (goto-char movepoint))))))
-
-(tree-buffer-defpopup-command ecb-analyse-insert
- "Insert at current point of the edit-window the selected Local-var-tag."
+(tree-buffer-defpopup-command ecb-analyse-complete/insert
+ "Complete/insert at current point the selected completion/localvar."
;; We must highlight the tag
(let* ((data (tree-node->data node))
(tag (nth 0 data))
(type (tree-node->type node)))
- (when (= type ecb-analyse-nodetype-completions)
- (tree-buffer-highlight-node-by-data/type data)
- (ecb-find-file-and-display ecb-path-selected-source nil)
+ (when (or (= type ecb-analyse-nodetype-completions)
+ (= type ecb-analyse-nodetype-localvars))
+ (tree-buffer-highlight-node-by-data/name data)
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: here we must handle
+ ;; indirect buffers - probbaly with a smart new function
+ ;; ecb-display-source which decides smartly if to switch to a buffer or
+ ;; if to find-file....
+ (ecb-display-source ecb-path-selected-source nil)
(let* ((a (ecb--semantic-analyze-current-context (point)))
- (bounds (oref a bounds))
+ (bounds (if a (oref a bounds)))
(movepoint nil))
- (save-excursion
- (if (and (<= (point) (cdr bounds)) (>= (point) (car bounds)))
- (setq movepoint t))
- (goto-char (car bounds))
- (delete-region (car bounds) (cdr bounds))
- (insert (ecb--semantic-tag-name tag))
- (if movepoint (setq movepoint (point))))
- (if movepoint
- (goto-char movepoint))))))
-
-(defun ecb-analyse-node-clicked (node ecb-button edit-window-nr
- shift-mode meta-mode)
- "Handle clicking onto NODE in the analyse-buffer. ECB-BUTTON can be 1, 2 or
-3. If 3 then EDIT-WINDOW-NR contains the number of the edit-window the NODE
-should be displayed or whatever should be done with NODE. For 1 and 2 the
-value of EDIT-WINDOW-NR is ignored."
+ (if (null bounds)
+ (insert (ecb--semantic-tag-name tag))
+ (save-excursion
+ (if (and (<= (point) (cdr bounds)) (>= (point) (car bounds)))
+ (setq movepoint t))
+ (goto-char (car bounds))
+ (delete-region (car bounds) (cdr bounds))
+ (insert (ecb--semantic-tag-name tag))
+ (if movepoint (setq movepoint (point))))
+ (if movepoint
+ (goto-char movepoint)))))))
+
+(defecb-tree-buffer-callback ecb-analyse-node-clicked ecb-analyse-buffer-name select nil
+ "Handles clicking onto any of the nodes in the analyse-buffer of ECB."
(if shift-mode
(ecb-mouse-over-analyse-node node nil nil 'force))
(let* ((data (tree-node->data node))
(tag (nth 0 data))
(type (tree-node->type node)))
+ ;; we handle hiding the ecb-windows for ourself
+ (setq no-meta-hiding t)
(cond
((= type ecb-analyse-nodetype-bucket)
(tree-node-toggle-expanded node)
(tree-buffer-update node))
((= type ecb-analyse-nodetype-completions)
- (ecb-analyse-complete node))
+ (ecb-analyse-complete/insert node))
((= type ecb-analyse-nodetype-localvars)
- (ecb-analyse-insert node))
+ (ecb-analyse-complete/insert node))
(t
(ecb-analyse-jump-to-tag node (ecb-get-edit-window
;; `ecb-analyse-jump-to-tag' expects all
@@ -628,9 +622,11 @@ moved over it."
(tag-p (not (equal (nth 1 data) ecb-analyse-nodedata-no-tag)))
(tag-with-pos-p (equal (nth 1 data) ecb-analyse-nodedata-tag-with-pos))
(nodetype (nth 2 data)))
- (delq nil (list (if (equal nodetype ecb-analyse-nodetype-completions)
- '(ecb-analyse-complete "Complete"))
- (if tag-p
+ (delq nil (list (if (member nodetype (list
+ ecb-analyse-nodetype-completions
+ ecb-analyse-nodetype-localvars))
+ '(ecb-analyse-complete/insert "Complete/insert"))
+ (if tag-p
'(ecb-analyse-show-tag-info "Show tag info"))
(if tag-with-pos-p
'(ecb-analyse-jump-to-tag "Jump to tag"))))))
View
1 ecb-autogen.el
@@ -9,7 +9,6 @@
;; Klaus Berndl <klaus.berndl@sdm.de>
;; Kevin A. Burton <burton@openprivacy.org>
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
;; Keywords: browser, code, programming, tools
;; Created: 2003
View
358 ecb-common-browser.el
@@ -44,6 +44,7 @@
(require 'tree-buffer)
;; (require 'ecb-layout) ;; causes cyclic dependencies!
(require 'ecb-mode-line)
+(require 'ecb-navigate)
;; various loads
(require 'assoc)
@@ -605,6 +606,148 @@ examples how to use this macro!"
;; Internals
;;====================================================
+(defun ecb-combine-ecb-button/edit-win-nr (ecb-button edit-window-nr)
+ "Depending on ECB-BUTTON and EDIT-WINDOW-NR return one value:
+- nil if ECB-BUTTON is 1.
+- t if ECB-BUTTON is 2 and the edit-area of ECB is splitted.
+- EDIT-WINDOW-NR if ECB-BUTTON is 3."
+ (case ecb-button
+ (1 nil)
+ (2 (ecb-edit-window-splitted))
+ (3 edit-window-nr)))
+
+(defun ecb-get-edit-window (other-edit-window)
+ "Get the correct edit-window. Which one is the correct one depends on the
+value of OTHER-EDIT-WINDOW \(which is a value returned by
+`ecb-combine-ecb-button/edit-win-nr') and `ecb-mouse-click-destination'.
+- OTHER-EDIT-WINDOW is nil: Get the edit-window according to the option
+ `ecb-mouse-click-destination'.
+- OTHER-EDIT-WINDOW is t: Get the next edit-window in the cyclic list of
+ current edit-windows starting either from the left-top-most one or from the
+ last edit-window with point (depends on
+ `ecb-mouse-click-destination').
+- OTHER-EDIT-WINDOW is an integer: Get exactly the edit-window with that
+ number > 0."
+ (let ((edit-win-list (ecb-canonical-edit-windows-list)))
+ (typecase other-edit-window
+ (null
+ (if (eq ecb-mouse-click-destination 'left-top)
+ (car edit-win-list)
+ ecb-last-edit-window-with-point))
+ (integer
+ (ecb-get-edit-window-by-number other-edit-window edit-win-list))
+ (otherwise
+ (ecb-next-listelem edit-win-list
+ (if (eq ecb-mouse-click-destination 'left-top)
+ (car edit-win-list)
+ ecb-last-edit-window-with-point))))))
+
+(defun ecb-source-make (filename &optional buffer)
+ "Build a source-object from FILENAME and BUFFER.
+If optional arg BUFFER is nil then the just FILENAME is returned.
+If BUFFER is not nil then it can be either a buffer-object or a buffer-name.
+A cons is returned where car is FILENAME and cdr is the buffername of BUFFER."
+ (let ((buffername (when buffer
+ (if (bufferp buffer)
+ (buffer-name buffer)
+ buffer))))
+ (if buffername
+ (cons filename buffername)
+ filename)))
+
+(defun ecb-source-get-filename (source)
+ "SOURCE is either a string, then it is a filename or a cons, then the car is
+the filename and the cdr is the buffer-name, whereas the latter one can be the
+name of an indirect-buffer."
+ (if (consp source)
+ (car source)
+ source))
+
+(defun ecb-source-get-buffername (source)
+ "SOURCE is either a string, then it is a filename or a cons, then the car is
+the filename and the cdr is the buffer-name, whereas the latter one can be the
+name of an indirect-buffer."
+ (if (consp source)
+ (cdr source)))
+
+(defun ecb-source-get-buffer (source)
+ "Return a living buffer-object for SOURCE.
+SOURCE is either a string, then it is a filename or a cons, then the car is
+the filename and the cdr is the buffer-name, whereas the latter one can be the
+name of an indirect-buffer.
+
+If SOURCE contains a living buffer then this buffer is returned. Otherwise a
+buffer for the filename-part of SOURCE is created and returned. For an
+existing ans readable file this means the file is loaded into a buffer.
+
+Note: The buffer is just returned but not displayed."
+ (let* ((my-source (if (consp source) source (cons source nil)))
+ (filename (car my-source))
+ (buffer (and (cdr my-source)
+ (get-buffer (cdr my-source)))))
+ (or buffer
+ (find-file-noselect filename))))
+
+(defun ecb-display-source (source other-edit-window)
+ "Display SOURCE in the correct edit-window.
+What the correct window is depends on the setting in
+`ecb-mouse-click-destination' and the value of OTHER-EDIT-WINDOW
+\(for this see `ecb-combine-ecb-button/edit-win-nr').
+
+SOURCE is either a string, then it is a filename or a cons, then the car is
+the filename and the cdr is the buffer-name, whereas the latter one can be the
+name of an indirect-buffer."
+ (select-window (ecb-get-edit-window other-edit-window))
+ (ecb-nav-save-current)
+ (switch-to-buffer (ecb-source-get-buffer source))
+ (ecb-nav-add-item (ecb-nav-file-history-item-new)))
+
+(defvar ecb-path-selected-directory nil
+ "Path to currently selected directory.")
+
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>:
+;; XXXX here we have to check all usages of this var and check if this works
+;; also for indirect buffers
+(defvar ecb-path-selected-source nil
+ "Path to currently selected source.
+
+It is a cons where the cdr is a buffer-object of the current selected source
+The name of this file is the car of the cons:
+\(<filename> . <indirect-buffer-object>).
+
+This variable is only set by `ecb-path-selected-source-set' and evaluated by
+the function `ecb-path-selected-source'.
+
+Do not use it directly! Use always one of the mentioned functions!")
+
+(defun ecb-path-selected-source-set (filename buffer)
+ "Set `ecb-path-selected-source' to FILENAME and BUFFER.
+Returns in the new value. FILENAME and BUFFER must not be nil.
+For a description of FILENAME and BUFFER see `ecb-source-make'."
+ (unless (and filename buffer)
+ (error "ECB %s: Invalid setting of `ecb-path-selected-source with file %s, buffer %s"
+ ecb-version filename buffer))
+ (setq ecb-path-selected-source (ecb-source-make filename buffer)))
+
+(defun ecb-path-selected-source (&optional type)
+ "Get the value of the internal variable `ecb-path-selected-source'.
+If optional arg TYPE is the symbol 'file then the filename-part
+is returned as string, if it is the symbol 'buffername then the
+stored buffername is returned if there is any and and if it is the
+symbol 'buffer then the buffer-object of the stored buffername is
+returned if there is any or nil.
+
+In all other cases of TYPE always that value is returned
+`ecb-path-selected-source' has been set by most recent
+`ecb-path-selected-source-set'."
+ (case type
+ (file (ecb-source-get-filename ecb-path-selected-source))
+ (buffername (ecb-source-get-buffername ecb-path-selected-source))
+ (buffer (ecb-source-get-buffer ecb-path-selected-source))
+ (otherwise ecb-path-selected-source)))
+
+
+
(defvar ecb-basic-buffer-sync-old '(Info-mode dired-mode))
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: rename this in the info-file
;; was ecb-window-sync
@@ -715,8 +858,126 @@ associated symbol which contains this name.")
(defsubst ecb-tree-buffers-get-symbol (name)
(ecb-find-assoc-value name ecb-tree-buffers))
+(defvar ecb-tree-buffer-callbacks '((expand . nil) (select . nil))
+ "All callback-functions for the tree-buffers of ECB.
+This list contains two items of the form:
+\(<callback-type> .\(<buffer-callback-alist>))
+where <callback-type> is 'select and 'expand and
+<buffer-callback-alist> is an alist where each item is a cons
+like \(<buffer-name-symbol> . <callback-symbol>)."
+ )
+
+
+(defun ecb-tree-buffer-callbacks-add (type buffer-name-symbol callback)
+ (unless (member type '(select expand))
+ (error "ECB %s tries to add tree-buffer-callback of unknown type %s"
+ ecb-version type))
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: maybe we should add a check if
+ ;; the buffer-name-symbol is already registered with defecb-tree-buffer-creator
+ (let ((type-elem (ecb-find-assoc type ecb-tree-buffer-callbacks)))
+ (unless (ecb-find-assoc buffer-name-symbol type-elem)
+ (setcdr type-elem (cons (cons buffer-name-symbol callback)
+ (cdr type-elem))))))
+
+
+(defun ecb-tree-buffer-callbacks-alist-of-type (type)
+ (unless (member type '(select expand))
+ (error "ECB %s tries to get tree-buffer-callback of unknown type %s"
+ ecb-version type))
+ (cdr (assoc type ecb-tree-buffer-callbacks)))
+
+
+(defmacro defecb-tree-buffer-callback (callback
+ tree-buffer-name-symbol
+ callback-type
+ optional-arg-list
+ docstring &rest body)
+ "Define a callback-function CALLBACK for a tree-buffer which name is hold in
+the symbol TREE-BUFFER-NAME-SYMBOL. Do not quote CALLBACK and
+TREE-BUFFER-NAME-SYMBOL and CALLBACK-TYPE. DOCSTRING is the
+docstring for CALLBACK. BODY is all the program-code of CALLBACK.
+
+CALLBACK-TYPE must be either 'expand or 'select, whereas the
+former one defines a callback for handling expanding a node and
+the latter one for clicking onto a node.
+
+CALLBACK is defined as a function with at least five arguments:
+NODE, ECB-BUTTON, EDIT-WINDOW-NR, SHIFT-MODE and META-MODE.
+CALLBACK must handle clicking onto NODE in the tree-buffer for
+which the callback is defined. ECB-BUTTON can be 1, 2 or 3 \(=
+mouse-buttons). If 3 then EDIT-WINDOW-NR contains the number of
+the edit-window the NODE should be displayed or whatever should
+be done with NODE. For 1 and 2 the value of EDIT-WINDOW-NR is
+ignored. SHIFT-MODE and META-MODE are not nil if the user has
+pressed the shift- rsp. the meta-button during his click. Note:
+using the keyboard in the tree-buffer instead the mouse is
+already handled by the caller of CALLBACK, so CALLBACK has no
+need to bother with keyboard or mouse specific stuff!
+
+If OPTIONAL-ARG-LIST is not nil then it must be a list with all
+optional or rest arguments. You have to include the keywords
+&optional or/and &rest! The first item of this list must be
+either the keyword &optional or &rest! The defined CALLBACK gets
+exactly these additional arguments after the reqired 5 arguments
+described above. Do not quote OPTIONAL-ARG-LIST!
+
+The defined CALLBACK automatically hides the ecb-windows after
+selecting a node in case META-MODE is not nil and if the CALLBACK
+is of type 'select; this is a must for every tree-buffer. Do not
+do this within BODY! But: During the evaluation of BODY the local
+variable no-meta-hiding is bound and set to nil per default. If
+BODY sets it to not nil then the hiding of the ecb-windows is
+prevented even if META-MODE is not nil.
+
+The value of the last expression of BODY is returned.
+
+This macro automatically adds the appropriate description of the
+5 arguments of the defined CALLBACK to DOCSTRING. So just
+describe what the CALLBACK does!
+
+It is strongly recommended defining a callback-function for a
+tree-buffer of ECB with this macro and not with plain `defun',
+because then a lot of stuff needed to be done by every
+tree-buffer is automatically performed."
+ `(eval-and-compile
+ (ecb-tree-buffer-callbacks-add (quote ,callback-type)
+ (quote ,tree-buffer-name-symbol)
+ (quote ,callback))
+ (defun ,callback ,(append '(node ecb-button edit-window-nr shift-mode meta-mode)
+ optional-arg-list)
+ ,(concat (if (equal callback-type 'select)
+ (concat
+ "Handle clicking onto NODE in the current tree-buffer.\n"
+ "ECB-BUTTON can be 1, 2 or 3. If 3 then EDIT-WINDOW-NR contains the number\n"
+ "of the edit-window the NODE should be displayed or whatever should be done\n"
+ "with NODE. For 1 and 2 the value of EDIT-WINDOW-NR is ignored.\n"
+ "SHIFT-MODE and META-MODE are self-explanatory.")
+ (concat
+ "Handle expanding NODE in the current tree-buffer.\n"
+ "ECB-BUTTON can be 1, 2 or 3. If 3 then EDIT-WINDOW-NR contains the number\n"
+ "of the edit-window the NODE should be displayed or whatever should be done\n"
+ "with NODE. For 1 and 2 the value of EDIT-WINDOW-NR is ignored.\n"
+ "SHIFT-MODE and META-MODE are self-explanatory."))
+ "\n\n"
+ docstring)
+ (let ((no-meta-hiding nil))
+ (prog1
+ (progn
+ ,@body)
+ ,(if (equal callback-type 'select)
+ `(when (and (not no-meta-hiding) meta-mode)
+ (ecb-run-with-idle-timer 0.001 nil 'ecb-hide-ecb-windows))))))))
+
+;; (insert (pp (macroexpand
+;; '(defecb-tree-buffer-callback kausi-callback ecb-history-buffer
+;; expand (&optional a b)
+;; "das ist ein Docstring"
+;; (message "")
+;; (if nil t nil)))))
+
+
+(put 'defecb-tree-buffer-callback 'lisp-indent-function 4)
-
;; the filename/path cache
(defecb-multicache ecb-filename-cache 500 nil '(FILES-AND-SUBDIRS
@@ -1209,12 +1470,17 @@ not nil then in both PATH and FILENAME env-var substitution is done. If the
;; -- end of canonical filenames
-(defun ecb-format-bucket-name (name)
- "Format NAME as a bucket-name according to `ecb-bucket-node-display'."
- (let ((formatted-name (concat (nth 0 ecb-bucket-node-display)
- name
- (nth 1 ecb-bucket-node-display))))
- (ecb-merge-face-into-text formatted-name (nth 2 ecb-bucket-node-display))
+(defun ecb-format-bucket-name (name &optional ignore-prefix-suffix ignore-bucket-face)
+ "Format NAME as a bucket-name according to `ecb-bucket-node-display'.
+If optional arg IGNORE-PREFIX-SUFFIX rsp. IGNORE-BUCKET-FACE is not nil then
+these settings of `ecb-bucket-node-display' are ignored."
+ (let ((formatted-name (if ignore-prefix-suffix
+ name
+ (concat (nth 0 ecb-bucket-node-display)
+ name
+ (nth 1 ecb-bucket-node-display)))))
+ (unless ignore-bucket-face
+ (ecb-merge-face-into-text formatted-name (nth 2 ecb-bucket-node-display)))
formatted-name))
(defun ecb-toggle-do-not-leave-window-after-select ()
@@ -1262,41 +1528,7 @@ The tree-buffer is the current buffer."
'ecb-toggle-maximize-ecb-window-with-mouse)))
-(defun ecb-combine-ecb-button/edit-win-nr (ecb-button edit-window-nr)
- "Depending on ECB-BUTTON and EDIT-WINDOW-NR return one value:
-- nil if ECB-BUTTON is 1.
-- t if ECB-BUTTON is 2 and the edit-area of ECB is splitted.
-- EDIT-WINDOW-NR if ECB-BUTTON is 3."
- (case ecb-button
- (1 nil)
- (2 (ecb-edit-window-splitted))
- (3 edit-window-nr)))
-(defun ecb-get-edit-window (other-edit-window)
- "Get the correct edit-window. Which one is the correct one depends on the
-value of OTHER-EDIT-WINDOW \(which is a value returned by
-`ecb-combine-ecb-button/edit-win-nr') and `ecb-mouse-click-destination'.
-- OTHER-EDIT-WINDOW is nil: Get the edit-window according to the option
- `ecb-mouse-click-destination'.
-- OTHER-EDIT-WINDOW is t: Get the next edit-window in the cyclic list of
- current edit-windows starting either from the left-top-most one or from the
- last edit-window with point (depends on
- `ecb-mouse-click-destination').
-- OTHER-EDIT-WINDOW is an integer: Get exactly the edit-window with that
- number > 0."
- (let ((edit-win-list (ecb-canonical-edit-windows-list)))
- (typecase other-edit-window
- (null
- (if (eq ecb-mouse-click-destination 'left-top)
- (car edit-win-list)
- ecb-last-edit-window-with-point))
- (integer
- (ecb-get-edit-window-by-number other-edit-window edit-win-list))
- (otherwise
- (ecb-next-listelem edit-win-list
- (if (eq ecb-mouse-click-destination 'left-top)
- (car edit-win-list)
- ecb-last-edit-window-with-point))))))
;;====================================================
;; Mouse callbacks
@@ -1320,25 +1552,24 @@ combination is invalid \(see `ecb-interpret-mouse-click'."
(shift-mode (nth 1 ecb-button-list))
(meta-mode (nth 2 ecb-button-list))
(keyboard-p (equal (nth 3 ecb-button-list) 'keyboard))
- (maximized-p (ecb-buffer-is-maximized-p tree-buffer-name)))
+ (maximized-p (ecb-buffer-is-maximized-p tree-buffer-name))
+ (select-callbacks (ecb-tree-buffer-callbacks-alist-of-type 'select))
+ (callback-fcn nil))
;; we need maybe later that something has clicked in a tree-buffer, e.g.
;; in `ecb-handle-major-mode-visibilty'.
(setq ecb-item-in-tree-buffer-selected t)
(if (not keyboard-p)
(setq ecb-layout-prevent-handle-ecb-window-selection t))
+
;; first we dispatch to the right action
(when ecb-button-list
- (cond ((ecb-string= tree-buffer-name ecb-directories-buffer-name)
- (ecb-directory-clicked node ecb-button nil shift-mode meta-mode))
- ((ecb-string= tree-buffer-name ecb-sources-buffer-name)
- (ecb-source-clicked node ecb-button nil shift-mode meta-mode))
- ((ecb-string= tree-buffer-name ecb-history-buffer-name)
- (ecb-history-clicked node ecb-button nil shift-mode meta-mode))
- ((ecb-string= tree-buffer-name ecb-methods-buffer-name)
- (ecb-method-clicked node ecb-button nil shift-mode meta-mode))
- ((ecb-string= tree-buffer-name ecb-analyse-buffer-name)
- (ecb-analyse-node-clicked node ecb-button nil shift-mode meta-mode))
- (t nil)))
+ (setq callback-fcn
+ (ecb-member-of-symbol/value-list tree-buffer-name
+ select-callbacks
+ 'car
+ 'cdr))
+ (when (functionp callback-fcn)
+ (funcall callback-fcn node ecb-button nil shift-mode meta-mode)))
;; now we go back to the tree-buffer but only if all of the following
;; conditions are true:
@@ -1401,19 +1632,20 @@ combination is invalid \(see `ecb-interpret-mouse-click')."
(ecb-button (nth 0 ecb-button-list))
(shift-mode (nth 1 ecb-button-list))
(meta-mode (nth 2 ecb-button-list))
- (keyboard-p (equal (nth 3 ecb-button-list) 'keyboard)))
+ (keyboard-p (equal (nth 3 ecb-button-list) 'keyboard))
+ (expand-callbacks (ecb-tree-buffer-callbacks-alist-of-type 'expand))
+ (callback-fcn nil))
(if (not keyboard-p)
(setq ecb-layout-prevent-handle-ecb-window-selection t))
+ ;; we just dispatch to the right action
(when ecb-button-list
- (cond ((ecb-string= tree-buffer-name ecb-directories-buffer-name)
- (ecb-update-directory-node node))
- ((ecb-string= tree-buffer-name ecb-sources-buffer-name)
- (ecb-source-clicked node ecb-button nil shift-mode meta-mode))
- ((ecb-string= tree-buffer-name ecb-history-buffer-name)
- (ecb-history-clicked node ecb-button nil shift-mode meta-mode))
- ((ecb-string= tree-buffer-name ecb-methods-buffer-name)
- nil)
- (t nil)))))
+ (setq callback-fcn
+ (ecb-member-of-symbol/value-list tree-buffer-name
+ expand-callbacks
+ 'car
+ 'cdr))
+ (when (functionp callback-fcn)
+ (funcall callback-fcn node ecb-button nil shift-mode meta-mode)))))
(defun ecb-interpret-mouse-click (mouse-button
shift-pressed
View
1 ecb-compatibility.el
@@ -7,7 +7,6 @@
;; Author: Klaus Berndl <klaus.berndl@sdm.de>
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
;; Keywords: browser, code, programming, tools
;; Created: 2004
View
1 ecb-compilation.el
@@ -9,7 +9,6 @@
;; Klaus Berndl <klaus.berndl@sdm.de>
;; Kevin A. Burton <burton@openprivacy.org>
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
;; Keywords: browser, code, programming, tools
;; Created: 2001
View
12 ecb-create-layout.el
@@ -5,11 +5,8 @@
;; Kevin A. Burton,
;; Free Software Foundation, Inc.
-;; Author: Jesper Nordenberg <mayhem@home.se>
-;; Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
+;; Author: Klaus Berndl <klaus.berndl@sdm.de>
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
;; Keywords: browser, code, programming, tools
;; Created: 2002
@@ -817,9 +814,10 @@ unbound."
(ecb-load-layouts)
(let ((new-layout-list
(sort (ecb-set-difference (ecb-available-layouts-of-type nil)
- (mapcar (function (lambda (elem)
- (car elem)))
- ecb-buildin-layouts))
+ (mapcar (function (lambda (elem)
+ (car elem)))
+ ecb-buildin-layouts)
+ 'member)
'ecb-string<))
(layout-name nil))
(if (= (length new-layout-list) 0)
View
4 ecb-cycle.el
@@ -5,11 +5,9 @@
;; Kevin A. Burton,
;; Free Software Foundation, Inc.
-;; Author: Jesper Nordenberg <mayhem@home.se>
-;; Klaus Berndl <klaus.berndl@sdm.de>
+;; Author: Klaus Berndl <klaus.berndl@sdm.de>
;; Kevin A. Burton <burton@openprivacy.org>
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
;; Keywords: browser, code, programming, tools
;; Created: 2002
View
4 ecb-eshell.el
@@ -5,11 +5,9 @@
;; Kevin A. Burton,
;; Free Software Foundation, Inc.
-;; Author: Jesper Nordenberg <mayhem@home.se>
-;; Klaus Berndl <klaus.berndl@sdm.de>
+;; Author: Klaus Berndl <klaus.berndl@sdm.de>
;; Kevin A. Burton <burton@openprivacy.org>
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
;; Keywords: browser, code, programming, tools
;; Created: 2001
View
3 ecb-examples.el
@@ -9,7 +9,6 @@
;; Klaus Berndl <klaus.berndl@sdm.de>
;; Kevin A. Burton <burton@openprivacy.org>
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
;; Keywords: browser, code, programming, tools
;; Created: 2002
@@ -234,6 +233,8 @@ it will be called autom. by the internal synchronizing mechanism of ECB."
;; For details please read the documentation of
;; `defecb-autocontrol/sync-function'!
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: currently not working for
+ ;; indirect buffers...
(let ((filename (buffer-file-name (current-buffer))))
(if (and filename (file-readable-p filename))
View
90 ecb-face.el
@@ -5,11 +5,9 @@
;; Kevin A. Burton,
;; Free Software Foundation, Inc.
-;; Author: Jesper Nordenberg <mayhem@home.se>
-;; Klaus Berndl <klaus.berndl@sdm.de>
+;; Author: Klaus Berndl <klaus.berndl@sdm.de>
;; Kevin A. Burton <burton@openprivacy.org>
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
-;; Kevin A. Burton <burton@openprivacy.org>
;; Keywords: browser, code, programming, tools
;; Created: 2001
@@ -223,6 +221,66 @@ Changes take first effect after finishing and reactivating ECB!"
(face :tag "Special face"
:value ecb-history-general-face)))
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: add the following three faces
+;; incl. their options to the texi
+(defface ecb-history-bucket-node-face (ecb-face-default nil nil nil
+ 'ecb-bucket-node-face)
+ "*Face used for displaying a bucket-node in the ECB-history-buffer.
+
+In GNU Emacs 21.X this face inherits from the face 'ecb-default-general-face'.
+
+With XEmacs and GNU Emacs 20.X there is no inheritance-feature so if the
+buckets in the ECB-history-buffer should be displayed with the same basic
+attributes set by 'ecb-default-general-face' this set of basic attributes have
+to be set in 'ecb-history-bucket-node-face' too!"
+ :group 'ecb-faces)
+
+(defcustom ecb-history-bucket-node-face 'ecb-history-bucket-node-face
+ "*Basic face for displaying a bucket-node in the ECB-history-buffer.
+This defines the basic face for the bucket-nodes used to bucketize the
+history-entries as defined with the option `ecb-history-make-buckets'.
+
+Changes take first effect after finishing and reactivating ECB!"
+ :group 'ecb-face-options
+ :group 'ecb-history
+ :type '(radio (const :tag "Use ecb-bucket-node-face"
+ :value ecb-bucket-node-face)
+ (face :tag "Special face"
+ :value ecb-history-bucket-node-face)))
+
+(defface ecb-history-indirect-buffer-face (ecb-face-default nil nil t
+ 'ecb-history-general-face)
+ "*Define a face for displaying indirect buffers in the history buffer."
+ :group 'ecb-faces)
+
+(defcustom ecb-history-indirect-buffer-face 'ecb-history-indirect-buffer-face
+ "*Face for indirect buffers in the history buffer."
+ :group 'ecb-history
+ :group 'ecb-face-options
+ :type '(radio (const :tag "Use ecb-history-general-face"
+ :value ecb-history-general-face)
+ (face :tag "Special face"
+ :value ecb-history-indirect-buffer-face)))
+
+(defface ecb-history-dead-buffer-face (ecb-face-default nil nil nil
+ 'ecb-history-general-face
+ "gray60"
+ "gray60"
+ nil nil
+ nil "gray60")
+ "*Define a face for history entries pointing to dead buffers"
+ :group 'ecb-faces)
+
+(defcustom ecb-history-dead-buffer-face 'ecb-history-dead-buffer-face
+ "*Face for history entries pointing to dead buffers."
+ :group 'ecb-history
+ :group 'ecb-face-options
+ :type '(radio (const :tag "Use ecb-history-general-face"
+ :value ecb-history-general-face)
+ (face :tag "Special face"
+ :value ecb-history-dead-buffer-face)))
+
+
(defface ecb-default-highlight-face (ecb-face-default nil nil nil
nil ;'ecb-default-general-face
"yellow" nil
@@ -393,7 +451,7 @@ Changes take first effect after finishing and reactivating ECB!"
:value ecb-analyse-general-face)))
(defface ecb-analyse-bucket-element-face (ecb-face-default nil nil nil
- 'ecb-default-general-face
+ 'ecb-analyse-general-face
"brown")
"*Face used for displaying elements of buckets in the ECB-analyse-buffer.
@@ -419,7 +477,7 @@ Changes take first effect after finishing and reactivating ECB!"
:value ecb-analyse-bucket-element-face)))
(defface ecb-analyse-bucket-node-face (ecb-face-default nil t nil
- 'ecb-default-general-face)
+ 'ecb-bucket-node-face)
"*Face used for displaying a bucket-node in the ECB-analyse-buffer.
In GNU Emacs 21.X this face inherits from the face 'ecb-default-general-face'.
@@ -438,8 +496,8 @@ Completions etc. in the ECB-analyse-buffer.
Changes take first effect after finishing and reactivating ECB!"
:group 'ecb-face-options
:group 'ecb-analyse
- :type '(radio (const :tag "Use ecb-default-general-face"
- :value ecb-default-general-face)
+ :type '(radio (const :tag "Use ecb-bucket-node-face"
+ :value ecb-bucket-node-face)
(face :tag "Special face"
:value ecb-analyse-bucket-node-face)))
@@ -460,44 +518,42 @@ jumping to it by clicking onto a node in the methods buffer."
:type 'face)
(defface ecb-source-in-directories-buffer-face (ecb-face-default nil nil nil
- 'ecb-default-general-face
+ 'ecb-directories-general-face
"medium blue"
"LightBlue1"
nil nil
nil "gray")
"*Define a face for displaying sources in the directories buffer."
:group 'ecb-faces)
-(defcustom ecb-source-in-directories-buffer-face
- 'ecb-source-in-directories-buffer-face
+(defcustom ecb-source-in-directories-buffer-face 'ecb-source-in-directories-buffer-face
"*Face for source files in the directories buffer."
:group 'ecb-directories
:group 'ecb-face-options
:type 'face)
-(defface ecb-source-read-only-face (ecb-face-default nil nil t)
+(defface ecb-source-read-only-face (ecb-face-default nil nil t
+ 'ecb-default-general-face)
"*Define a face for displaying read-only sources."
:group 'ecb-faces)
-(defcustom ecb-source-read-only-face
- 'ecb-source-read-only-face
+(defcustom ecb-source-read-only-face 'ecb-source-read-only-face
"*Face for read-only sources."
:group 'ecb-sources
:group 'ecb-directories
:group 'ecb-face-options
:type 'face)
(defface ecb-directory-not-accessible-face (ecb-face-default nil nil nil
- 'ecb-default-general-face
+ 'ecb-directories-general-face
"gray60"
"gray60"
nil nil
nil "gray60")
"*Define a face for displaying not accessible dirs in the directories buffer."
:group 'ecb-faces)
-(defcustom ecb-directory-not-accessible-face
- 'ecb-directory-not-accessible-face
+(defcustom ecb-directory-not-accessible-face 'ecb-directory-not-accessible-face
"*Face for not accessible dirs in the directories buffer."
:group 'ecb-directories
:group 'ecb-face-options
@@ -613,8 +669,6 @@ See `ecb-mode-line-data'. For XEmacs the face should inherit from the face
:group 'ecb-face-options
:type 'face)
-
-
(silentcomp-provide 'ecb-face)
;;; ecb-face.el ends here
View
1,137 ecb-file-browser.el
@@ -176,10 +176,12 @@ layouts sources should be displayed in the directories window."
(string :tag "Layout name"))))
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: replace in texi
(defcustom ecb-directories-show-node-info '(if-too-long . path)
"*When to display which node-info in the directories-buffer.
-Define which node info should displayed after moving the mouse over a node
-\(or after a shift click onto the node) in the directories-buffer.
+Define which node info should be displayed after moving the mouse
+over a node \(or after a shift click onto the node) in the
+directories-buffer.
You can define \"when\" a node-info should be displayed:
- always: Node info is displayed by moving with the mouse over a node.
@@ -191,7 +193,7 @@ You can define \"when\" a node-info should be displayed:
primary mouse button onto the node.
- never: Node info is never displayed.
-You can define what info should be displayed:
+You can define \"which\" info should be displayed:
- name: Only the full node-name is displayed.
- path: The full-path of the node is displayed.
@@ -598,15 +600,17 @@ then activating ECB again!"
:group 'ecb-sources
:type 'string)
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: replace in texi
(defcustom ecb-sources-show-node-info '(if-too-long . name)
"*When to display which node-info in the sources-buffer.
-Define which node info should displayed after moving the mouse over a node
-\(or after a shift click onto the node) in the sources-buffer.
+Define which node info should be displayed after moving the mouse
+over a node \(or after a shift click onto the node) in the
+sources-buffer.
You can define \"when\" a node-info should be displayed:
See `ecb-directories-show-node-info' for the possible choices.
-You can define what info should be displayed:
+You can define \"which\" info should be displayed:
- name: Only the full node-name is displayed.
- file-info: File infos for this file are displayed.
- file-info-full: Fill infos incl. full path for this file are displayed.
@@ -745,16 +749,20 @@ these regexps! Therefore be carefore with regexps beginning with ^!"
(defsubst ecb-check-filename-for-history-exclude (filename)
(ecb-match-regexp-list filename ecb-history-exclude-file-regexps))
-(defcustom ecb-history-show-node-info '(always . path)
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: replace in texi
+(defcustom ecb-history-show-node-info '(always . name-path)
"*When to display which node-info in the history-buffer.
-Define which node info should displayed after moving the mouse over a node
-\(or after a shift click onto the node) in the history-buffer.
+Define which node info should be displayed after moving the mouse
+over a node \(or after a shift click onto the node) in the
+history-buffer.
You can define \"when\" a node-info should be displayed:
See `ecb-directories-show-node-info' for the possible choices.
-You can define what info should be displayed:
-See `ecb-directories-show-node-info' for the possible choices.
+You can define \"which\" info should be displayed:
+- name: Only the full node-name is displayed.
+- path: The full-path of the node is displayed.
+- name-path: The full node-name and the full-path is displayed.
Do NOT set this option directly via setq but use always customize!"
:group 'ecb-history
@@ -765,7 +773,55 @@ Do NOT set this option directly via setq but use always customize!"
(const :tag "Never" :value never))
(choice :tag "What"
(const :tag "Node-name" :value name)
- (const :tag "Full path" :value path))))
+ (const :tag "Full path" :value path)
+ (const :tag "Node-name \(Full path)" :value name-path))))
+
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: maybe we need a
+;; tree-buffer-command which allows changing on the fly...
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: add this to texi
+(defcustom ecb-history-make-buckets 'directory
+ "*Bucketize the entries of the history-buffer.
+
+There are several options how the bucketizing should be done:
+- 'never: No bucketizing at all, ie. all entries of the history-buffer we be
+ displayed flat.
+- 'directory: All entries with related filesources residing in the same
+ directory will be contained in a bucket named with that directory.
+- 'mode: All entries with related buffers have the same
+ major-mode will be contained in a bucket named with that major-mode
+- 'extension: All entries with related filesources having the
+ same extension will be contained in a bucket named with that extension
+
+If the value is a list of regular expressions then all entries where the
+buffername matches the same regular expression will be contained in one
+bucket. If the value is nil then this is interpreted as an empty list of
+regular expressions!
+
+The default value is 'directory."
+ :group 'ecb-history
+ :initialize 'custom-initialize-default
+ :set (function (lambda (symbol value)
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: maybe we must
+ ;; update the history when ecb is active and the
+ ;; history-window is visible
+ (set symbol value)))
+ :type '(radio (const :tag "Never" :value never)
+ (const :tag "By directory" :value directory)
+ (const :tag "By major-mode" :value mode)
+ (const :tag "By file-extension" :value extension)
+ (repeat :tag "By regexps"
+ (regexp :tag "A bucket regexp"))))
+
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: add the new face to the texi,
+;; also this option
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: we need a set-function for all
+;; options changing the history-display, so we can call within this
+;; set-function the new history-build-function - s.b.
+(defcustom ecb-history-stick-indirect-buffers-to-basebuffer t
+ ""
+ :group 'ecb-history
+ :type 'boolean
+ )
(defcustom ecb-history-sort-method 'name
"*Defines how the entries in the history-buffer are sorted.
@@ -803,14 +859,14 @@ There are three options:
(const :tag "Do not clear the history"
:value nil)))
-
-(defcustom ecb-history-item-name 'buffer-name
- "*The name to use for items in the history buffer."
- :group 'ecb-history
- :type '(radio (const :tag "Buffer name"
- :value buffer-name)
- (const :tag "File name"
- :value file-name)))
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: remove this also from the texi
+;; (defcustom ecb-history-item-name 'buffer-name
+;; "*The name to use for items in the history buffer."
+;; :group 'ecb-history
+;; :type '(radio (const :tag "Buffer name"
+;; :value buffer-name)
+;; (const :tag "File name"
+;; :value file-name)))
(defcustom ecb-directories-menu-user-extension
'(("Version Control"
@@ -873,6 +929,7 @@ re-arranged with `ecb-directories-menu-sorter'."
:group 'ecb-directories
:type 'function)
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: update in texi
(defcustom ecb-sources-menu-user-extension
'(("Version control"
(ecb-file-popup-ediff-revision "Ediff against revision")
@@ -887,8 +944,11 @@ re-arranged with `ecb-directories-menu-sorter'."
"*Static user extensions for the popup-menu of the sources buffer.
For further explanations see `ecb-directories-menu-user-extension'.
-The node-argument of a menu-function contains as data the filename of the
-source for which the popup-menu has been opened.
+The node-argument of a menu-function contains as data the source
+for which the popup-menu has been opened. Use always
+`ecb-source-get-*' to extract whatever you need from the
+node-data. E.g. use `ecb-source-get-filename' to get the full
+filename of the source of the node.
Per default the static user-extensions are added at the beginning of the
built-in menu-entries of `ecb-sources-menu' but the whole menu can be
@@ -912,6 +972,7 @@ re-arranged with `ecb-sources-menu-sorter'."
:group 'ecb-sources
:type 'function)
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: adjust this also in the texi
(defcustom ecb-history-menu-user-extension
'(("Version control"
(ecb-file-popup-ediff-revision "Ediff against revision")
@@ -926,8 +987,16 @@ re-arranged with `ecb-sources-menu-sorter'."
"*Static user extensions for the popup-menu of the history buffer.
For further explanations see `ecb-directories-menu-user-extension'.
-The node-argument of a menu-function contains as data the filename of the
-source for which the popup-menu has been opened.
+The node-argument of a menu-function contains as data a cons:
+
+car is the filename of the source for which the popup-menu has
+been opened. cdr is the related buffer-name; but be careful,
+because the node can point to a dead buffer (see
+`ecb-kill-buffer-clears-history'). Use always `ecb-source-get-*'
+to extract whatever you need from the node-data. E.g. use
+`ecb-source-get-filename' to get the full filename of the source
+of the node and use `ecb-source-get-buffername' or `ecb-source-get-buffer' to
+get the buffername rsp. the buffer-object.
Per default the static user-extensions are added at the beginning of the
built-in menu-entries of `ecb-history-menu' but the whole menu can be
@@ -1180,13 +1249,26 @@ Emacs) and `vc-cvs-status' \(Xemacs) to the ECB-VC-state-values."
(const :tag "ignored" :value ignored)
(const :tag "unknown" :value unknown)))))
+;; Remark why we need for ECB the information if a *directory* isa managed by
+;; a version-control system and why we can not use the file-based machanism
+;; offered by vc*.el:
+;; With only a file-based check we would need to check each file in each directory
+;; when displaying the contents of a directory either in the sources-buffer or
+;; in the directories buffer (when ecb-show-sources-in-directories-buffer is
+;; not nil). With our directory-based machanism we check only if the directory
+;; is in general managed by a version-control system and then we perform the
+;; check for each file of a directory only in this case --> this is much
+;; faster.
+;; Therefore we can not use functions like `vc-backend' or `vc-registered'.
(defcustom ecb-vc-supported-backends
(delq nil (if ecb-running-xemacs
`((ecb-vc-dir-managed-by-CVS . vc-cvs-status))
`((ecb-vc-dir-managed-by-CVS . ecb-vc-state)
(ecb-vc-dir-managed-by-RCS . ecb-vc-state)
(ecb-vc-dir-managed-by-SCCS . ecb-vc-state)
- (ecb-vc-dir-managed-by-SVN . ecb-vc-state))))
+ (ecb-vc-dir-managed-by-SVN . ecb-vc-state)
+ (ecb-vc-dir-managed-by-GIT . ecb-vc-state)
+ (ecb-vc-dir-managed-by-MTN . ecb-vc-state))))
"*Define how to to identify the VC-backend and how to check the state.
The value of this option is a list containing cons-cells where the car is a
function which is called to identify the VC-backend for a DIRECTORY and the
@@ -1260,19 +1342,15 @@ beginning of this option."
;;====================================================
-;; constants for the node-types
-(defconst ecb-directories-nodetype-directory 0)
-(defconst ecb-directories-nodetype-sourcefile 1)
-(defconst ecb-directories-nodetype-sourcepath 2)
-(defconst ecb-sources-nodetype-sourcefile 0)
-(defconst ecb-history-nodetype-sourcefile 0)
-
-
-(defvar ecb-path-selected-directory nil
- "Path to currently selected directory.")
+;; constants for the node-types - they should be all different!
+(defconst ecb-directories-nodetype-directory 100)
+(defconst ecb-directories-nodetype-sourcefile 200)
+(defconst ecb-directories-nodetype-sourcepath 300)
+(defconst ecb-sources-nodetype-sourcefile 400)
+(defconst ecb-history-nodetype-bucket 500)
+(defconst ecb-history-nodetype-filebuffer 600)
+(defconst ecb-history-nodetype-indirect-filebuffer 700)
-(defvar ecb-path-selected-source nil
- "Path to currently selected source.")
;; accessors for the FILES-AND-SUBDIRS-cache
@@ -1615,7 +1693,6 @@ ECB-history-window is not visible in current layout."
(ignore-errors (ecb-speedbar-deactivate)))
(switch-to-buffer ecb-sources-buffer-name))))
-
(defecb-window-dedicator ecb-set-history-buffer ecb-history-buffer-name
"Display the History-buffer in current window and make window dedicated."
(switch-to-buffer ecb-history-buffer-name))
@@ -1643,23 +1720,15 @@ At the end the hooks in `ecb-basic-buffer-sync-hook' run."
(when (and ecb-minor-mode
(not ecb-windows-hidden)
(ecb-point-in-edit-window-number))
- (let ((filename (buffer-file-name (current-buffer))))
- ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: how to deal here with
- ;; indirect buffers??indirect-buffers should be added as childs in to
- ;; the related file-history-node. but here we have to find a condition
- ;; when we want to sync for indirect buffers!!
- ;; maybe we should sync when current buffer-name in the edit-area
- ;; changes...
- ;; so we do not compare with ecb-path-selected-source but with
- ;; ecb-last-source-buffer
- (cond ( ;; synchronizing for real filesource-buffers
+ ;; XXXX (changed for indirect-buffers)
+ (let* ((filename (ecb-buffer-file-name (current-buffer))))
+ (cond ( ;; synchronizing for real filesource-buffers and indirect
+ ;; buffers which have a filesource-buffer as base-buffer
(and filename
- (ecb-buffer-or-file-readable-p)
+ (ecb-buffer-or-file-readable-p filename)
(or force
- ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: test this
- ;; very intensive!!!!!!!!!!!!!!!!!!!!!!!!!!
- (not (equal (current-buffer) ecb-last-source-buffer))))
-;; (not (ecb-string= filename ecb-path-selected-source))))
+ (not (equal (ecb-source-make filename (buffer-name))
+ (ecb-path-selected-source)))))
;; * KB: Problem: seems this little sleep is necessary because
;; otherwise jumping to certain markers in new opened files (e.g.
@@ -1708,11 +1777,10 @@ At the end the hooks in `ecb-basic-buffer-sync-hook' run."
;; Klaus: The explicit update of the directories buffer is not
;; necessary because the sync with the current source is done by
- ;; `ecb-select-source-file'!
+ ;; `ecb-select-source'!
;; (ecb-update-directories-buffer)
- ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: maybe we must here
- ;; add the buffer-name in case of an indirect buffer
- (ecb-select-source-file filename force)
+ (ecb-path-selected-source-set filename (buffer-name))
+ (ecb-select-source force)
(ecb-update-methods-buffer--internal 'scroll-to-begin)
(setq ecb-major-mode-selected-source major-mode)
@@ -2008,7 +2076,7 @@ nil. Returns 'window-not-visible if the ECB-sources-buffer is not visible."
;; update the sources buffer - because the filtered cache is nil
;; the full sources are displayed.
(ecb-update-sources-buffer ecb-path-selected-directory)
- (tree-buffer-highlight-node-by-data/type ecb-path-selected-source)
+ (tree-buffer-highlight-node-by-data/name (ecb-path-selected-source 'file))
nil)
;; apply the filter-regexp
(let ((new-tree (tree-node-new-root))
@@ -2036,7 +2104,7 @@ nil. Returns 'window-not-visible if the ECB-sources-buffer is not visible."
(tree-buffer-set-root new-tree)
(tree-buffer-update)
(ecb-scroll-window (point-min) (point-min))
- (tree-buffer-highlight-node-by-data/type ecb-path-selected-source)
+ (tree-buffer-highlight-node-by-data/name (ecb-path-selected-source 'file))
;; add the new filter to the cache, so the next call to
;; `ecb-update-sources-buffer' displays the filtered sources.
@@ -2148,7 +2216,7 @@ then nothing is done unless first optional argument FORCE is not nil."
;; (tree-buffer-get-root)))
;; (tree-buffer-update))
(when (not (ecb-show-sources-in-directories-buffer-p))
- (tree-buffer-highlight-node-by-data/type ecb-path-selected-directory
+ (tree-buffer-highlight-node-by-data/name ecb-path-selected-directory
nil start)))))
;; now we update the sources buffer for `ecb-path-selected-directory'
(ecb-update-sources-buffer last-dir)
@@ -2181,59 +2249,421 @@ then nothing is done unless first optional argument FORCE is not nil."
f
(ecb-file-name-sans-extension f))))
-;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: maybe we must add an optional
-;; argument for indirect-buffers
-(defun ecb-select-source-file (filename &optional force)
+;; XXXX changed for indirect buffers.
+(defun ecb-select-source (&optional force)
"Updates the directories, sources and history buffers to match the filename
given. If FORCE is not nil then the update of the directories buffer is done
even if current directory is equal to `ecb-path-selected-directory'."
- (ecb-set-selected-directory (ecb-file-name-directory filename) force)
- (setq ecb-path-selected-source filename)
-
+ (ecb-set-selected-directory (ecb-file-name-directory
+ (ecb-path-selected-source 'file)) force)
+
;; Update directory buffer
(when (ecb-show-sources-in-directories-buffer-p)
(ecb-exec-in-window ecb-directories-buffer-name
- (tree-buffer-highlight-node-by-data/type ecb-path-selected-source)))
-
+ (tree-buffer-highlight-node-by-data/name (ecb-path-selected-source 'file))))
+
;; Update source buffer
(ecb-exec-in-window ecb-sources-buffer-name
- (tree-buffer-highlight-node-by-data/type ecb-path-selected-source))
-
- ;; Update history buffer always regardless of visibility of history window
- ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: pass indirect-buffers
- (ecb-add-item-to-history-buffer ecb-path-selected-source)
- (ecb-sort-history-buffer)
- ;; Update the history window only if it is visible
- ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: here we must take care of
- ;; indirect buffers
- (ecb-update-history-window ecb-path-selected-source))
+ (tree-buffer-highlight-node-by-data/name (ecb-path-selected-source 'file)))
+
+ (ecb-add-buffers-to-history-new)
+
+;; ;; Update history buffer always regardless of visibility of history window
+;; ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: pass indirect-buffers
+;; (ecb-add-item-to-history-buffer (ecb-path-selected-source 'file))
+;; (ecb-sort-history-buffer)
+;; ;; Update the history window only if it is visible
+;; ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: here we must take care of
+;; ;; indirect buffers
+;; (ecb-update-history-window (ecb-path-selected-source 'file))
+ )
(defvar ecb-history-filter nil
"A cons-cell where car is the filter-function and the cdr is a string how
-the current active filter should be displayed in the modeline of the
-History-buffer. The filter-function gets the filename of an existing
-file-buffer and has to return not nil if for this filename a history-entry
-should be added.")
+the current active filter should be displayed in the modeline of
+the History-buffer. The filter-function gets as arguments the
+buffername and the filename of an existing file-buffer and has to
+return not nil if for these data a history-entry should be
+added.")
(defun ecb-reset-history-filter ()
"Reset the `ecb-history-filter' so all file-buffers are displayed."
- (setq ecb-history-filter '(identity . nil)))
+ (setq ecb-history-filter (cons (function
+ (lambda (buf file)
+ t))
+ nil)))
(defun ecb-history-filter-reset-p ()
(null (cdr ecb-history-filter)))
(ecb-reset-history-filter)
+(defvar ecb-history-content nil
+ "An alist with items like \(<buffer-name> . \(<file-name> . <dead-p>))
+For each node in the history-buffer an item exists with <dead-p> is nil.
+If killing a buffer does not clear out this item from the history \(see option
+`ecb-kill-buffer-clears-history') then the item is not removed from this alist
+but <dead-p> is set to t. Otherwise the item is removed from the alist.
+
+So this alist can contain more items than the history-buffer contains nodes!"
+ )
+
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: add this to ecb-activate
+(defun ecb-history-content-init ()
+ (setq ecb-history-content nil))
+
+(defun ecb-history-content-buffer-elem (buffer-name)
+ (assoc buffer-name ecb-history-content))
+
+(defun ecb-history-content-remove-buffer (buffer-name)
+ (setq ecb-history-content
+ (delq (ecb-history-content-buffer-elem buffer-name)
+ ecb-history-content)))
+
+(defun ecb-history-content-set-buffer-dead (buffer-name)
+ (let ((elem (ecb-history-content-buffer-elem buffer-name)))
+ (when elem
+ (setcdr (cdr elem) 'dead))))
+
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: with the old-history-mechanism
+;; mysteriously the * ECB History* buffer is added with a file clicked in the
+;; source-buffer (e.e. ecb-upgrade.el). Lets see if this behavior is still
+;; there after switching to the new mechanism - for now it should be not
+;; dangerous. Maybe have to check within this function is buffer-name is a
+;; file-buffer?!
+(defun ecb-history-content-add-buffer (buffer-name file-name)
+ (ecb-history-content-remove-buffer buffer-name)
+ (push (cons buffer-name (cons file-name 'alive)) ecb-history-content))
+
+(defun ecb-history-kill-buffer-clear (curr-buf)
+ "Does all necessary clearence when CURR-BUF is killed."
+ (let* ((buffer-file (ecb-fix-filename (ecb-buffer-file-name curr-buf)))
+ (node (if buffer-file
+ (ecb-exec-in-window ecb-history-buffer-name
+ (tree-buffer-find-displayed-node-by-data/name
+ (ecb-source-make buffer-file curr-buf))))))
+ (when node
+ (if (or (buffer-base-buffer curr-buf) ; indirect-buffers always!
+ (equal ecb-kill-buffer-clears-history 'auto)
+ (and (equal ecb-kill-buffer-clears-history 'ask)
+ (y-or-n-p "Remove history entry for this buffer?")))
+ (progn
+ ;; we must do this even when the history is not visible!!
+ ;; the history should be always up-to-date
+ (save-excursion
+ (set-buffer ecb-history-buffer-name)
+ (tree-buffer-remove-node node))
+;; (ecb-history-content-remove-buffer (buffer-name curr-buf))
+ )
+;; (ecb-history-content-set-buffer-dead (buffer-name curr-buf))
+ )
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: later we completely rebuild
+ ;; here the history to reface not cleared items
+ (ecb-add-buffers-to-history-new)
+;; (ecb-update-history-window)
+ )))
+
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: update the texi for this command
(defun ecb-add-all-buffers-to-history ()
"Add all current file-buffers to the history-buffer of ECB.
-Dependend on the value of `ecb-history-sort-method' afterwards the history is
-sorted either by name or by extension. If `ecb-history-sort-method' is nil the
-most recently used buffers are on the top of the history and the seldom used
-buffers at the bottom."
+Dependend on the values of `ecb-history-make-buckets' and
+`ecb-history-sort-method' afterwards the history is bucketized or
+not and sorted either by name or by extension \(if bucketized
+then the sorting is only within each bucket). If
+`ecb-history-sort-method' is nil the most recently used buffers
+are on the top of the history and the seldom used buffers at the
+bottom \(again: when bucketized then this holds only within each
+bucket)."
(interactive)
(ecb-reset-history-filter)
- (ecb-add-buffers-to-history))
+ (ecb-add-buffers-to-history-new 'no-dead-buffers))
+
+(defun ecb-history-content-all-dead-buffers-alist ()
+ "Return alist with items \(<buffer-name> . <file-name>) for dead buffers
+entries of the history-buffer."
+ (save-excursion
+ (set-buffer ecb-history-buffer-name)
+ (delq nil (tree-node-map-subtree
+ (tree-buffer-get-root)
+ (function
+ (lambda (node)
+ (let ((data (tree-node->data node)))
+ (unless (or (= (tree-node->type node) ecb-history-nodetype-bucket)
+ (get-buffer (ecb-source-get-buffername data)))
+ (cons (ecb-source-get-buffername data)
+ (ecb-source-get-filename data))))))))))
+
+(defun ecb-add-buffers-to-history-new (&optional no-dead-buffers)
+ "Update contents of the history-buffer.
+This means a history-item is added to the history-buffer if an existing buffer:
+- is a file-buffer or is based on a file-buffer \(e.g. indirect-file-buffers)
+- is not excluded by `ecb-check-filename-for-history-exclude'
+- is not filtered out by the current history-filter
+In addition dead-buffer items of the history-content before are added again
+unless optional argument NO-DEAD-BUFFERS is not nil.
+
+It takes into account the values of the options `ecb-history-make-buckets' and
+`ecb-history-stick-indirect-buffers-to-basebuffer'.
+
+It calls at the end `ecb-mode-line-format'.
+
+If the current history-filter leads to an empty history-buffer it will not be
+applied but an unfiltered history will be build.
+
+Returns t if the current history filter has been applied otherwise nil."
+ (let* ((never-bucket-string "No_hist_bucketizing")
+ (aggr-sort-fcn (function
+ (lambda (l r)
+ ;; l and r are conses like:
+ ;; (<bucket-string> . (<buffername> . <filename>))
+ (if (ecb-string= (car l) (car r) ecb-history-sort-ignore-case)
+ (case ecb-history-sort-method
+ (extension
+ (let ((ext-l (file-name-extension (cdr (cdr l)) t))
+ (ext-r (file-name-extension (cdr (cdr r)) t)))
+ (if (ecb-string= ext-l ext-r ecb-history-sort-ignore-case)
+ (ecb-string< (car (cdr l)) (car (cdr r))
+ ecb-history-sort-ignore-case)
+ (ecb-string< ext-l ext-r ecb-history-sort-ignore-case))))
+ (name
+ (ecb-string< (car (cdr l)) (car (cdr r))
+ ecb-history-sort-ignore-case))
+ (otherwise nil))
+ (ecb-string< (car l) (car r) ecb-history-sort-ignore-case)))))
+ (aggr-same-fcn (function
+ (lambda (l r)
+ ;; l and r are strings (= the car of an item of base-alist)
+ (ecb-string= l r ecb-history-sort-ignore-case))))
+ (indirect-buffer-base nil)
+ ;; lets build an alist where each item is a cons like
+ ;; (<buffer-name> . <filename>) and only items are contained which are:
+ ;; - based on file-buffers (indirect-file-buffers too)
+ ;; - not excluded by `ecb-check-filename-for-history-exclude'
+ ;; - not filtered out by the current history-filter
+ ;; if indirect-buffers should be sticked to the base-buffer then we
+ ;; are sorting out them here and add them all to indirect-buffer-base
+ (buf-file-alist
+ (delq nil
+ (mapcar (function
+ (lambda (buf)
+ (let ((file-name (ecb-fix-filename
+ (ecb-buffer-file-name buf)))
+ (base-buf (buffer-base-buffer buf)))
+ (if (and file-name
+ (not (ecb-check-filename-for-history-exclude file-name))
+ (funcall (car ecb-history-filter)
+ (buffer-name buf)
+ file-name))
+ (if (and ecb-history-stick-indirect-buffers-to-basebuffer
+ base-buf)
+ ;; if indirect-buffers should be sticked
+ ;; to the base-buffer then we are sorting
+ ;; out them here and add them all to
+ ;; indirect-buffer-base
+ (progn
+ (push (cons (buffer-name base-buf)
+ (cons (buffer-name buf) file-name))
+ indirect-buffer-base)
+ nil)
+ (cons (buffer-name buf) file-name))))))
+ ;; we call reverse to get the most recently used
+ ;; buffers first; usefull when no sorting takes place
+ (reverse (buffer-list)))))
+ (additonal-dead-history-buffer-alist
+ (if no-dead-buffers
+ nil
+ ;; we need these entries of the history-buffer which are marked as
+ ;; dead in the ecb-history-content. If all is working fine the
+ ;; set-difference would not be necessary because dead-items are
+ ;; dead because no buffer exists for them - so both lists should
+ ;; be disjunct - but who knows, to get sure we make the difference
+ ;; so we have no duplicates.
+ (ecb-set-difference (ecb-history-content-all-dead-buffers-alist)
+ buf-file-alist
+ 'member)))
+ (base-alist (mapcar (function
+ (lambda (elem)
+ ;; an elem is a cons (<buffername> . <filename>)
+ (cons (case ecb-history-make-buckets
+ (never never-bucket-string)
+ (directory (substring-no-properties
+ (ecb-fix-filename
+ (file-name-directory (cdr elem)))))
+ (mode (symbol-name
+ (if (get-buffer (car elem))
+ (save-excursion
+ (set-buffer (get-buffer (car elem)))
+ major-mode)
+ ;; for dead buffers of the
+ ;; history we use auto-mode-alist
+ (or (ecb-match-regexp-list (car elem)
+ auto-mode-alist
+ 'car 'cdr)
+ 'no-major-mode-avail))))
+ (extension (file-name-extension (cdr elem) t))
+ (otherwise (or (ecb-match-regexp-list
+ (car elem)
+ ecb-history-make-buckets)
+ "No matchings")))
+ elem)))
+ (append buf-file-alist
+ additonal-dead-history-buffer-alist)))
+ (aggregated-alist-with-buckets (ecb-aggregate-alist base-alist
+ aggr-same-fcn
+ aggr-sort-fcn))
+ (aggregated-indirect-buffers-alist (ecb-aggregate-alist indirect-buffer-base
+ 'string=
+ (function
+ (lambda (l r)
+ (string< (car l)
+ (car r))))))
+ ;; an alist with items like (<bucket-name> . <expand-state>) for each
+ ;; toplevel bucket of the history-buffer. This is the state before
+ ;; rebuilding the history!
+ (curr-bucket-expand-status-alist
+ (save-excursion
+ (set-buffer ecb-history-buffer-name)
+ (delq nil (mapcar (function
+ (lambda (node)
+ (when (= (tree-node->type node)
+ ecb-history-nodetype-bucket)
+ (cons (tree-node->name node)
+ (and (tree-node->expandable node)
+ (tree-node->expanded node))))))
+ (tree-node->children (tree-buffer-get-root))))))
+ )
+;; just for debugging:
+;; (list buf-file-alist
+;; aggregated-alist-with-buckets
+;; additonal-dead-history-buffer-alist
+;; indirect-buffer-base
+;; aggregated-indirect-buffers-alist)
+ (save-excursion
+ (set-buffer ecb-history-buffer-name)
+ (tree-buffer-clear-tree)
+ (dolist (bucket-elem aggregated-alist-with-buckets)
+ (let* ((bucket-name (car bucket-elem))
+ (bucket-name-formatted (ecb-merge-face-into-text (ecb-format-bucket-name bucket-name)
+ ecb-history-bucket-node-face))
+ (bucket-node (if (string= never-bucket-string bucket-name)
+ (tree-buffer-get-root)
+ (tree-node-new bucket-name-formatted
+ ecb-history-nodetype-bucket
+ 'ecb-bucket-node
+ nil
+ (tree-buffer-get-root)
+ 'beginning))))
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: if bucket only contains
+ ;; one elem, we should maybe not make a bucket but insert this node
+ ;; flat
+ (unless (string= never-bucket-string bucket-name)
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: maybe we can make
+ ;; this even smarter...depending if now a bucket contains more
+ ;; items than before - for this we have to store not onlxy the
+ ;; expand-state but also the number of children of a bucket
+ (setf (tree-node->expanded bucket-node)
+ (if (assoc bucket-name-formatted
+ curr-bucket-expand-status-alist)
+ (cdr (assoc bucket-name-formatted
+ curr-bucket-expand-status-alist))
+ t)))
+ (dolist (elem (cdr bucket-elem))
+ (let* ((buf-name (car elem))
+ ;; can only be not nil if the option
+ ;; `ecb-history-stick-indirect-buffers-to-basebuffer' is not
+ ;; nil --> see above the mechanism how indirect-buffer-base
+ ;; is build
+ (indirect-buffer-p (buffer-base-buffer (get-buffer buf-name)))
+ ;; Note: indirect-buffer elems can not be dead-buffer
+ ;; elems, because indirect-buffer-items are *always*
+ ;; removed immediately from the history-buffer when such a
+ ;; buffer is killed!
+ (buf-name-formatted (cond (indirect-buffer-p
+ (ecb-merge-face-into-text
+ buf-name
+ ecb-history-indirect-buffer-face))
+ ((member elem
+ additonal-dead-history-buffer-alist)
+ (ecb-merge-face-into-text
+ buf-name
+ ecb-history-dead-buffer-face))
+ (t buf-name)))
+ (file-name (cdr elem))
+ (dir (ecb-file-name-directory file-name))
+ (vc-p (and (ecb-vc-directory-should-be-checked-p dir)
+ (ecb-vc-managed-dir-p dir)))
+ (node-name (if vc-p
+ (ecb-vc-generate-node-name buf-name-formatted
+ (nth 0 (ecb-vc-cache-get file-name)))
+ (ecb-generate-node-name buf-name-formatted -1 "leaf"
+ ;; here ecb-sources-buffer-name is
+ ;; also correct for history
+ ;; because we want the same
+ ;; icon-stuff as in the sources buffer
+ ecb-sources-buffer-name)))
+ (node (tree-node-new
+ node-name
+ (if indirect-buffer-p
+ ecb-history-nodetype-indirect-filebuffer
+ ecb-history-nodetype-filebuffer)
+ (ecb-source-make file-name buf-name)
+ t
+ bucket-node)))
+ ;; if `ecb-history-stick-indirect-buffers-to-basebuffer' is nil
+ ;; then this dolist does nothing because then the list is always
+ ;; nil, because aggregated-indirect-buffers-alist is nil in this
+ ;; case
+ (dolist (indirect-elem (ecb-find-assoc-value buf-name
+ aggregated-indirect-buffers-alist))
+ (let* ((ind-buf-name (car indirect-elem))
+ ;; here we have no need to deal with dead-buffers
+ ;; because indirect-buffers can not dead-buffer-items -
+ ;; s.a.
+ (ind-buf-name-formatted (ecb-merge-face-into-text
+ ind-buf-name
+ ecb-history-indirect-buffer-face))
+ (ind-node-name (if vc-p
+ (ecb-vc-generate-node-name ind-buf-name-formatted
+ (nth 0 (ecb-vc-cache-get file-name)))
+ (ecb-generate-node-name ind-buf-name-formatted -1 "leaf"
+ ;; here ecb-sources-buffer-name is
+ ;; also correct for history
+ ;; because we want the same
+ ;; icon-stuff as in the sources buffer
+ ecb-sources-buffer-name))))
+ (setf (tree-node->expandable node) t)
+ (setf (tree-node->expanded node) t)
+ (tree-node-new
+ ;; indirect buffers have the same vc-state as the file
+ ;; associated with the base-buffer ==> we use the same
+ ind-node-name
+ ecb-history-nodetype-indirect-filebuffer
+ (ecb-source-make file-name ind-buf-name)
+ t
+ node)))
+ )))))
+ (ecb-exec-in-window ecb-history-buffer-name
+ (tree-buffer-update)
+ (tree-buffer-highlight-node-by-data/name (ecb-path-selected-source)))
+ (prog1
+ (if (and (save-excursion
+ (set-buffer ecb-history-buffer-name)
+ (tree-buffer-empty-p))
+ (not (ecb-history-filter-reset-p)))
+ (progn
+ (ecb-add-all-buffers-to-history)
+ (message "ECB has not applied this filter because it would filter out all entries!")
+ nil)
+ t)
+ ;; now the modeline has to display the current filter
+ (ecb-mode-line-format))
+ ))
+
+;;(insert (pp (ecb-klaus-add-buffers-to-history)))
+
+;;(ecb-add-buffers-to-history-new)
+
(defun ecb-add-buffers-to-history ()
"Add exactly these currently existing file-buffers to the history-buffer
@@ -2271,34 +2701,41 @@ by the option `ecb-mode-line-prefixes'."
(and (cdr ecb-history-filter)
(format "[Filter: %s]" (cdr ecb-history-filter))))
-;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: maybe we need here an optional
-;; argument indirect-buffer
+
(defun ecb-add-item-to-history-buffer (filename)
"Add a new item for FILENAME to the history buffer if the current filter of
`ecb-history-filter' does not filter out this file."
(save-excursion
(set-buffer ecb-history-buffer-name)
- (tree-node-remove-child-by-data (tree-buffer-get-root) filename)
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: handle indirect buffers
+ (tree-node-remove-child-by-data/name (tree-buffer-get-root)
+ (ecb-source-make filename
+ (get-file-buffer filename)))
(when (and (not (ecb-check-filename-for-history-exclude filename))
- (funcall (car ecb-history-filter) filename))
+ (funcall (car ecb-history-filter)
+ (buffer-name (get-file-buffer filename))
+ filename))
+ (ecb-history-content-add-buffer (buffer-name (get-file-buffer filename))
+ filename)
(tree-node-add-children
(tree-buffer-get-root)
(tree-node-new
- (let ((file-1 (if (eq ecb-history-item-name 'buffer-name)
- (let ((b (get-file-buffer filename)))
- (if b
- (buffer-name b)
- (ecb-get-source-name filename)))
- (ecb-get-source-name filename)))
+ (let ((file-1 (let ((b (get-file-buffer filename)))
+ (if b
+ (buffer-name b)
+ (ecb-get-source-name filename))))
(dir (ecb-file-name-directory filename)))
(if (and (ecb-vc-directory-should-be-checked-p dir)
(ecb-vc-managed-dir-p dir))
(ecb-vc-generate-node-name file-1
(nth 0 (ecb-vc-cache-get filename)))
(ecb-generate-node-name file-1 -1 "leaf"
ecb-sources-buffer-name)))
- ecb-history-nodetype-sourcefile
- filename t)
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: give indirect buffers an
+ ;; own type
+ ecb-history-nodetype-filebuffer
+ (ecb-source-make filename (get-file-buffer filename))
+ t)
'at-beginning))))
@@ -2312,58 +2749,14 @@ by the option `ecb-mode-line-prefixes'."
(case ecb-history-sort-method
(name
(function (lambda (l r)
- (let* ((l0 (tree-node->name l))
- (r0 (tree-node->name r))
- (vc-ascii-icon-length-l (get-text-property
- 0
- 'ecb-vc-ascii-icon-length
- l0))
- (vc-ascii-icon-length-r (get-text-property
- 0
- 'ecb-vc-ascii-icon-length
- r0))
- (prefix-length-l (or vc-ascii-icon-length-l
- (or (get-text-property
- 0
- 'tree-buffer-image-length
- l0)
- 0)))
- (prefix-length-r (or vc-ascii-icon-length-r
- (or (get-text-property
- 0
- 'tree-buffer-image-length
- r0)
- 0)))
- (l1 (substring l0 prefix-length-l))
- (r1 (substring r0 prefix-length-r)))
+ (let* ((l1 (ecb-get-sourcename-of-nodename (tree-node->name l)))
+ (r1 (ecb-get-sourcename-of-nodename (tree-node->name r))))
(ecb-string< l1 r1 ecb-history-sort-ignore-case)))))
(extension
(function
(lambda (l r)
- (let* ((l0 (tree-node->name l))
- (r0 (tree-node->name r))
- (vc-ascii-icon-length-l (get-text-property
- 0
- 'ecb-vc-ascii-icon-length
- l0))
- (vc-ascii-icon-length-r (get-text-property
- 0
- 'ecb-vc-ascii-icon-length
- r0))
- (prefix-length-l (or vc-ascii-icon-length-l
- (or (get-text-property
- 0
- 'tree-buffer-image-length
- l0)
- 0)))
- (prefix-length-r (or vc-ascii-icon-length-r
- (or (get-text-property
- 0
- 'tree-buffer-image-length
- r0)
- 0)))
- (l1 (substring l0 prefix-length-l))
- (r1 (substring r0 prefix-length-r))
+ (let* ((l1 (ecb-get-sourcename-of-nodename (tree-node->name l)))
+ (r1 (ecb-get-sourcename-of-nodename (tree-node->name r)))
(ext-l (ecb-file-name-extension l1 t))
(ext-r (ecb-file-name-extension r1 t)))
(if (ecb-string= ext-l ext-r ecb-history-sort-ignore-case)
@@ -2373,48 +2766,122 @@ by the option `ecb-mode-line-prefixes'."
(function (lambda (l r)
nil))))))))
-
+;; (defun ecb-sort-history-buffer ()
+;; "Sort the history buffer according to `ecb-history-sort-method'."
+;; (when ecb-history-sort-method
+;; (save-excursion
+;; (set-buffer ecb-history-buffer-name)
+;; (tree-node-sort-children
+;; (tree-buffer-get-root)
+;; (case ecb-history-sort-method
+;; (name
+;; (function (lambda (l r)
+;; (let* ((l0 (tree-node->name l))
+;; (r0 (tree-node->name r))
+;; (vc-ascii-icon-length-l (get-text-property
+;; 0
+;; 'ecb-vc-ascii-icon-length
+;; l0))
+;; (vc-ascii-icon-length-r (get-text-property
+;; 0
+;; 'ecb-vc-ascii-icon-length
+;; r0))
+;; (prefix-length-l (or vc-ascii-icon-length-l
+;; (or (get-text-property
+;; 0
+;; 'tree-buffer-image-length
+;; l0)
+;; 0)))
+;; (prefix-length-r (or vc-ascii-icon-length-r
+;; (or (get-text-property
+;; 0
+;; 'tree-buffer-image-length
+;; r0)
+;; 0)))
+;; (l1 (substring l0 prefix-length-l))
+;; (r1 (substring r0 prefix-length-r)))
+;; (ecb-string< l1 r1 ecb-history-sort-ignore-case)))))
+;; (extension
+;; (function
+;; (lambda (l r)
+;; (let* ((l0 (tree-node->name l))
+;; (r0 (tree-node->name r))
+;; (vc-ascii-icon-length-l (get-text-property
+;; 0
+;; 'ecb-vc-ascii-icon-length
+;; l0))
+;; (vc-ascii-icon-length-r (get-text-property
+;; 0
+;; 'ecb-vc-ascii-icon-length
+;; r0))
+;; (prefix-length-l (or vc-ascii-icon-length-l
+;; (or (get-text-property
+;; 0
+;; 'tree-buffer-image-length
+;; l0)
+;; 0)))
+;; (prefix-length-r (or vc-ascii-icon-length-r
+;; (or (get-text-property
+;; 0
+;; 'tree-buffer-image-length
+;; r0)
+;; 0)))
+;; (l1 (substring l0 prefix-length-l))
+;; (r1 (substring r0 prefix-length-r))
+;; (ext-l (ecb-file-name-extension l1 t))
+;; (ext-r (ecb-file-name-extension r1 t)))
+;; (if (ecb-string= ext-l ext-r ecb-history-sort-ignore-case)
+;; (ecb-string< l1 r1 ecb-history-sort-ignore-case)
+;; (ecb-string< ext-l ext-r ecb-history-sort-ignore-case))))))
+;; (otherwise
+;; (function (lambda (l r)
+;; nil))))))))
+
+;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: remove this later and all
+;; references because this is included in the new mechanism
+;; `ecb-add-buffers-to-history-new'!
(defun ecb-update-history-window (&optional filename)
"Updates the history window and highlights the item for FILENAME if given."
(ecb-exec-in-window ecb-history-buffer-name
(tree-buffer-update)
- (tree-buffer-highlight-node-by-data/type filename)))
+ (tree-buffer-highlight-node-by-data/name
+ (if filename
+ (ecb-source-make filename (get-file-buffer filename))))))
+
-;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: do we need here an argument for
-;; indirect buffers
-(defun ecb-set-selected-source (filename other-edit-window
- no-edit-buffer-selection hide)
- "Updates all the ECB buffers and loads the file. The file is also
+;; XXXX (changed for indirect-buffers)
+(defun ecb-set-selected-source (source other-edit-window
+ no-edit-buffer-selection)
+ "Updates all the ECB buffers and loads the SOURCE. The source is also
displayed unless NO-EDIT-BUFFER-SELECTION is set to non nil. In such case the
-file is only loaded invisible in the background, all semantic-parsing and
+source is only loaded invisible in the background, all semantic-parsing and
ECB-Buffer-updating is done but the content of the main-edit window is not
changed. For the allowed values of OTHER-EDIT-WINDOW see
-`ecb-combine-ecb-button/edit-win-nr'. If HIDE is not nil then ECB hides the
-ecb-windows after displaying the file in an edit-window."
- (ecb-select-source-file filename)
+`ecb-combine-ecb-button/edit-win-nr'.
+
+SOURCE is either a string, then it is a filename or a cons, then the car is
+the filename and the cdr is the buffer-name, whereas the latter one can be an
+indirect-buffer."
(if no-edit-buffer-selection
;; load the selected source in an invisible buffer, do all the
;; updating and parsing stuff with this buffer in the background and
;; display the methods in the METHOD-buffer. We can not go back to
;; the edit-window because then the METHODS buffer would be
;; immediately updated with the methods of the edit-window.
(save-excursion
- (set-buffer (find-file-noselect filename))
- (ecb-update-methods-buffer--internal 'scroll-to-begin))
- ;; open the selected source in the edit-window and do all the update and
- ;; parsing stuff with this buffer
- ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: here we must take care of
- ;; indirect buffers and use switch-to-buffer instead of
- ;; find-file-and-display... but maybe we must write an own switch-function
- ;; which takes care of ecb-navigate-stuff.
- (ecb-find-file-and-display ecb-path-selected-source
- other-edit-window)
+ (set-buffer (ecb-source-get-buffer source))
+ (ecb-path-selected-source-set (ecb-source-get-filename source)
+ (buffer-name))
+ (ecb-update-methods-buffer--internal 'scroll-to-begin nil t t))
+ ;; open the selected source in the correct edit-window and do all the
+ ;; update and parsing stuff with this buffer
+ (ecb-display-source source other-edit-window)
+ (ecb-path-selected-source-set (ecb-source-get-filename source)
+ (buffer-name))
(ecb-update-methods-buffer--internal 'scroll-to-begin)
(setq ecb-major-mode-selected-source major-mode)
- (ecb-tag-sync 'force)
- (if hide
- (ecb-hide-ecb-windows))))
-
+ (ecb-tag-sync 'force))
+ (ecb-select-source t))
(defun ecb-clear-history ()
"Clears the ECB history-buffer."
@@ -2424,7 +2891,9 @@ ecb-windows after displaying the file in an edit-window."
(ecb-exec-in-window ecb-history-buffer-name
(tree-buffer-clear-tree)
(tree-buffer-update)
- (tree-buffer-highlight-node-by-data/type ecb-path-selected-source))))
+ ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: fix this - i can't work -
+ ;; just call synchronize
+ (tree-buffer-highlight-node-by-data/name (ecb-path-selected-source 'file)))))
@@ -2451,14 +2920,18 @@ ecb-windows after displaying the file in an edit-window."
nil
(tree-node->expanded node)))))))
+(defecb-tree-buffer-callback ecb-directory-expand ecb-directories-buffer-name expand nil
+ "Expand the clickes directory and add all subnodes if any.
+Subnodes can be directories or sources."
+ (ecb-update-directory-node node))
(defun ecb-get-source-paths-from-functions ()
"Return a list of paths found by querying `ecb-source-path-functions'."
(let ((func ecb-source-path-functions)
(paths nil)
(rpaths nil))
(while func
- (setq paths (append paths (funcall (car ecb-source-path-functions)))
+ (setq paths (append paths (funcall (car func)))
func (cdr func)))
(while paths
(setq rpaths (cons (ecb-fix-filename (car paths)) rpaths)
@@ -2648,7 +3121,9 @@ directory. This function is only for use by `ecb-stealthy-updates'!"
(ecb-throw-on-input 'lines-of-buffer-loop)
(goto-line state)
(setq curr-node (tree-buffer-get-node-at-point))
- (when (and (ecb-directory-should-prescanned-p
+ (when (and ;;(not (= ecb-directories-nodetype-sourcefile
+ ;; (tree-node->type curr-node)))
+ (ecb-directory-should-prescanned-p
(tree-node->data curr-node))
(ecb-file-exists-p
(tree-node->data curr-node)))
@@ -2697,17 +3172,15 @@ when called. Return the new state-value."
(curr-node nil)
(new-name nil)
(read-only-p nil)
- (node-type-to-check (if (string= (buffer-name (current-buffer))
- ecb-sources-buffer-name)
- ecb-sources-nodetype-sourcefile
- ecb-directories-nodetype-sourcefile)))
+ (node-types-to-check (list ecb-sources-nodetype-sourcefile
+ ecb-directories-nodetype-sourcefile)))
(ecb-exit-on-input 'read-only-stealthy
(save-excursion
(while (<= state lines-of-buffer)
(ecb-throw-on-input 'lines-of-buffer-loop)
(goto-line state)
(setq curr-node (tree-buffer-get-node-at-point))
- (when (and (= (tree-node->type curr-node) node-type-to-check)
+ (when (and (member (tree-node->type curr-node) node-types-to-check)
(ecb-sources-read-only-check-p
(ecb-file-name-directory (tree-node->data curr-node))))
(setq new-name (tree-node->name curr-node))
@@ -3027,8 +3500,14 @@ if ECB treats such a directory as managed by CVS or not!"
(defun ecb-vc-dir-managed-by-SVN (directory)
"Return 'SVN if DIRECTORY is managed by SVN. nil if not."
- (and (ecb-file-exists-p (concat directory "/.svn/"))
- (locate-library "vc-svn")
+ (and (locate-library "vc-svn")
+ (let ((admin-dir (if (boundp 'vc-svn-admin-directory)
+ vc-svn-admin-directory
+ (cond ((and (memq system-type '(cygwin windows-nt ms-dos))
+ (getenv "SVN_ASP_DOT_NET_HACK"))
+ "_svn")
+ (t ".svn")))))
+ (ecb-file-exists-p (concat directory "/" admin-dir "/")))
'SVN))
(defun ecb-vc-dir-managed-by-SCCS (directory)
@@ -3040,10 +3519,48 @@ if ECB treats such a directory as managed by CVS or not!"
(and (ecb-file-exists-p (concat proj-dir "/SCCS")) 'SCCS)
nil))))
+;; Git support
+
+(defun ecb-vc-dir-managed-by-GIT (directory)
+ "Return 'GIT if DIRECTORY is managed by Git. nil if not.
+Because with Git only the top-most directory of a source-tree has a subdir
+.git this function tries recursively upwards if there is a .git-subdir."
+ (and (locate-library "vc-git")
+ (fboundp 'vc-git-root)
+ (vc-git-root directory)
+ 'GIT))
+
+;; an own implementation for Git...
+;; (defun ecb-vc-dir-managed-by-GIT (directory)
+;; (let* ((sourcedir (ecb-fix-filename (file-truename directory)))