1
;;; ecb-file-browser.el --- the file-browser of Emacs
3
;; Copyright (C) 2000 - 2003 Jesper Nordenberg,
5
;; Free Software Foundation, Inc.
7
;; Author: Jesper Nordenberg <mayhem@home.se>
8
;; Klaus Berndl <klaus.berndl@sdm.de>
9
;; Maintainer: Klaus Berndl <klaus.berndl@sdm.de>
10
;; Keywords: browser, code, programming, tools
13
;; This program is free software; you can redistribute it and/or modify it under
14
;; the terms of the GNU General Public License as published by the Free Software
15
;; Foundation; either version 2, or (at your option) any later version.
17
;; This program is distributed in the hope that it will be useful, but WITHOUT
18
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
22
;; You should have received a copy of the GNU General Public License along with
23
;; GNU Emacs; see the file COPYING. If not, write to the Free Software
24
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
;; $Id: ecb-file-browser.el,v 1.10 2004/02/16 08:56:41 berndl Exp $
30
;; This file contains the code of the file-browser of ECB
33
(require 'tree-buffer)
34
(require 'ecb-mode-line)
35
(require 'ecb-navigate)
37
(require 'ecb-speedbar)
44
;; to avoid compiler grips
48
(require 'silentcomp))
50
(silentcomp-defun ecb-speedbar-update-contents)
52
(defvar ecb-path-selected-directory nil
53
"Path to currently selected directory.")
55
(defvar ecb-path-selected-source nil
56
"Path to currently selected source.")
58
(defun ecb-file-browser-initialize ()
59
(setq ecb-path-selected-directory nil
60
ecb-path-selected-source nil))
62
;;====================================================
64
;;====================================================
67
(defgroup ecb-directories nil
68
"Settings for the directories-buffer in the Emacs code browser."
72
(defgroup ecb-sources nil
73
"Settings for the sources-buffers in the Emacs code browser."
77
(defgroup ecb-history nil
78
"Settings for the history-buffer in the Emacs code browser."
82
(defcustom ecb-source-path nil
83
"*Paths where to find code sources.
84
Each path can have an optional alias that is used as it's display name. If no
85
alias is set, the path is used as display name."
86
:group 'ecb-directories
87
:group 'ecb-most-important
88
:initialize 'custom-initialize-default
89
:set (function (lambda (symbol value)
91
(if (and ecb-minor-mode
92
(functionp 'ecb-update-directories-buffer))
93
(ecb-update-directories-buffer))))
94
:type '(repeat (choice :tag "Display type"
95
:menu-tag "Display type"
96
(directory :tag "Path")
97
(list :tag "Path with alias"
98
(directory :tag "Path")
99
(string :tag "Alias")))))
102
(defcustom ecb-add-path-for-not-matching-files '(t . nil)
103
"*Add path of a file to `ecb-source-path' if not already contained.
104
This is done during the auto. windows synchronization which happens if a file
105
is opened not via the file/directory-browser of ECB. In such a situation ECB
106
adds the path of the new file auto. to `ecb-source-path' at least temporally
107
for the current Emacs session. This option defines two things:
108
1. Should only the root-part \(which means for Unix-like systems always '/'
109
and for windows-like systems the drive) of the new file be added as
110
source-path to `ecb-source-path' or the whole directory-part?
111
2. Should this path be added for future sessions too?
113
The value of this option is a cons-cell where the car is a boolean for 1. and
114
the cdr is a boolean for 2.
116
A value of not nil for the car \(1.) is reasonably if a user often opens files
117
not via the ECB-browser which are not located in any of the paths of
118
`ecb-source-path' because then only one path for each drive \(windows) or the
119
root-path \(unix) is added to the directory buffer of ECB."
120
:group 'ecb-directories
121
:type '(cons (boolean :tag "Add only root path")
122
(boolean :tag "Ask for saving for future sessions")))
125
(defvar ecb-source-path-functions nil
126
"List of functions to call for finding sources.
127
Each time the function `ecb-update-directories-buffer' is called, the
128
functions in this variable will be evaluated. Such a function must return
129
either nil or a list of strings where each string is a path.")
132
(defcustom ecb-display-default-dir-after-start t
133
"*Automatically display current default-directory after activating ECB.
134
If a file-buffer is displayed in the edit-window then ECB synchronizes its
135
tree-buffers to this file-buffer - at least if the option `ecb-window-sync' it
136
not nil. So for this situation `ecb-display-default-dir-after-start' takes no
137
effect but this option is for the case if no file-buffer is displayed in the
138
edit-window after startup:
140
If true then ECB selects autom. the current default-directory after activation
141
even if no file-buffer is displayed in the edit-window. This is useful if ECB
142
is autom. activated after startup of Emacs and Emacs is started without a
143
file-argument. So the directory from which the startup has performed is auto.
144
selected in the ECB-directories buffer and the ECB-sources buffer displays the
145
contents of this directory."
146
:group 'ecb-directories
150
(defcustom ecb-show-sources-in-directories-buffer '("left7" "left13"
152
"*Show source files in directories buffer.
153
The value is either 'always or 'never or a list of layout-names for which
154
layouts sources should be displayed in the directories window."
155
:group 'ecb-directories
156
:initialize 'custom-initialize-default
157
:set (function (lambda (symbol value)
159
(if (and ecb-minor-mode
160
(functionp 'ecb-set-selected-directory)
161
ecb-path-selected-directory)
162
(ecb-set-selected-directory ecb-path-selected-directory t))))
163
:type '(radio (const :tag "Always" :value always)
164
(const :tag "Never" :value never)
165
(repeat :tag "With these layouts"
166
(string :tag "Layout name"))))
169
(defcustom ecb-directories-update-speedbar 'auto
170
"*Update an integrated speedbar after selecting a directory.
171
If not nil then an integrated speedbar will be updated after selecting a
172
directory in the ECB-directories-buffer so the speedbar displays the contents
175
Of course this option makes only sense if the integrated speedbar is displayed
176
in addition to the ECB-directories-buffer.
178
This option can have the following values:
179
- t: Always update speedbar.
180
- nil: Never update speedbar.
181
- auto: Update when senseful \(see scenarios below)
182
- <function>: A user-defined function. The function is called after a
183
directory is selected, gets the selected directory as argument and has to
184
return nil if the the integrated speedbar should NOT be updated.
186
Two example-scenarios where different values for this option can be senseful:
188
If `ecb-show-sources-in-directories-buffer' is not nil or you have a layout
189
where an ECB-sources-buffer is visible then you probably want to use the
190
ECB-directories-buffer \(and/or the ECB-sources-buffer) for directory- and
191
file-browsing. If you have in addition an integrated speedbar running then you
192
probably want to use speedbar instead of the ECB-methods-buffer for
193
source-content-browsing. In this case you probably want the speedbar not be
194
updated because you do not need speedbar reflecting the current-directory
195
contents but only the contents of the currently selected source-file and the
196
integrated speedbar updates itself autom. for the latter one!
198
If `ecb-show-sources-in-directories-buffer' is nil and there is also no
199
ECB-sources-buffer visible in the current layout then you probably want to use
200
an integrated speedbar for browsing directory-contents \(i.e. the files) and
201
file-contents \(instead of the ECB-methods-buffer for example). In this case
202
you probably want the speedbar updated because you need speedbar reflecting
203
the current-directory contents so you can select files.
205
The value 'auto \(see above) takes exactly these two scenarios into account."
206
:group 'ecb-directories
207
:type '(radio (const :tag "Always" :value t)
208
(const :tag "Never" :value nil)
209
(const :tag "Automatic" :value auto)
210
(function :tag "Custom function")))
213
(defun ecb-show-sources-in-directories-buffer-p ()
214
(cond ((equal ecb-show-sources-in-directories-buffer 'never)
216
((equal ecb-show-sources-in-directories-buffer 'always)
219
(and (listp ecb-show-sources-in-directories-buffer)
220
(member ecb-layout-name
221
ecb-show-sources-in-directories-buffer)))))
223
(defcustom ecb-cache-directory-contents '((".*" . 50))
224
"*Cache contents of certain directories.
225
This can be useful if `ecb-source-path' contains directories with many files
226
and subdirs, especially if these directories are mounted net-drives \(\"many\"
227
means here something > 1000, dependent of the speed of the net-connection and
228
the machine). For these directories actualizing the sources- and/or directories-
229
buffer of ECB \(if displayed in current layout!) can slow down dramatically so
230
a caching increases speed a lot.
232
The value of this option is a list where the each element is a cons-cell and
234
\(<dir-regexp> . <filenumber threshold>)
235
<dir-regexp>: Regular expression a directory must match to be cached.
236
<filenumber threshold>: Number of directory contents must exceed this number.
238
A directory will only be cached if and only if the directory-name matches
239
one regexp of this option and its content-number exceeds the related
240
threshold AND the directory-name does not match and regexp of
241
`ecb-cache-directory-contents-not'!
243
The cache entry for a certain directory will be refreshed and actualized only
244
by using the POWER-click \(see `ecb-primary-secondary-mouse-buttons') in the
245
directories-buffer of ECB.
249
A value of \(\(\"/usr/home/john_smith/bigdir*\" . 1000)) means the contents of
250
every subdirectory of the home-directory of John Smith will be cached if the
251
directory contains more than 1000 entries and its name begins with \"bigdir\".
253
A value of \(\(\".*\" . 1000)) caches every directory which has more than 1000
256
A value of \(\(\".*\" . 0)) caches every directory regardless of the number of
259
Please note: If you want your home-dir being cached then you MUST NOT use
260
\"~\" because ECB tries always to match full path-names!"
261
:group 'ecb-directories
262
:group 'ecb-most-important
263
:type `(repeat (cons (regexp :tag "Directory-regexp")
264
(integer :tag "Filenumber threshold" :value 1000))))
267
(defcustom ecb-cache-directory-contents-not nil
268
"*Do not cache the contents of certain directories.
269
The value of this option is a list where the each element is a regular
270
expression a directory must match if it should not being cached.
272
If a directory-name matches at least one of the regexps of this option the
273
directory-contents will never being cached. See `ecb-cache-directory-contents'
274
to see when a directory will be cached.
276
This option can be useful when normally all directories with a certain amount
277
of content \(files and subdirs) should be cached but some special directories
278
not. This can be achieved by:
279
- setting `ecb-cache-directory-contents' to \(\".*\" . 500): Caches all
280
directories with more then 500 entries
281
- setting `ecb-cache-directory-contents-not' to a value which matches these
282
directories which should not being cached \(e.g. \(\"/usr/home/john_smith\")
283
excludes the HOME-directory of John Smith from being cached).
285
Please note: If you want your home-dir exclude from being cached then you MUST
286
NOT use \"~\" because ECB tries always to match full path-names!"
287
:group 'ecb-directories
288
:type `(repeat (regexp :tag "Directory-regexp")))
291
(defcustom ecb-directories-buffer-name " *ECB Directories*"
292
"*Name of the ECB directory buffer.
293
Because it is not a normal buffer for editing you should enclose the name with
294
stars, e.g. \"*ECB Directories*\".
296
If it is necessary for you you can get emacs-lisp access to the buffer-object of
297
the ECB-directory-buffer by this name, e.g. by a call of `set-buffer'.
299
Changes for this option at runtime will take affect only after deactivating and
300
then activating ECB again!"
301
:group 'ecb-directories
305
(defcustom ecb-excluded-directories-regexp "^\\(CVS\\|\\.[^xX]*\\)$"
306
"*Directories that should not be included in the directories list.
307
The value of this variable should be a regular expression."
308
:group 'ecb-directories
312
(defcustom ecb-auto-expand-directory-tree 'best
313
"*Automatically expand the directory tree to the current source file.
314
There are three options:
315
- best: Expand the best-matching source-path
316
- first: Expand the first matching source-path
317
- nil: Do not automatically expand the directory tree."
318
:group 'ecb-directories
319
:type '(radio (const :tag "Best matching"
321
(const :tag "First matching"
323
(const :tag "No auto. expand"
327
(defcustom ecb-sources-buffer-name " *ECB Sources*"
328
"*Name of the ECB sources buffer.
329
Because it is not a normal buffer for editing you should enclose the name with
330
stars, e.g. \"*ECB Sources*\".
332
If it is necessary for you you can get emacs-lisp access to the buffer-object of
333
the ECB-sources-buffer by this name, e.g. by a call of `set-buffer'.
335
Changes for this option at runtime will take affect only after deactivating and
336
then activating ECB again!"
341
(defcustom ecb-sources-exclude-cvsignore nil
342
"*Specify if files contained in a .cvsignore should be excluded.
343
Value is a list of regular expressions or nil. If you want to exclude files
344
listed in a .cvsignore-file from being displayed in the ecb-sources-buffer
345
then specify a regexp for such a directory.
347
If you want to exclude the contents of .cvsignore-files for every directory
348
then you should add one regexp \".*\" which matches every directory.
350
If you never want to exclude the contents of .cvsignore-files then set this
351
option to nil. This is the default."
353
:group 'ecb-directories
354
:type '(repeat (regexp :tag "Directory-regexp")))
357
(defcustom ecb-source-file-regexps
358
'((".*" . ("\\(^\\(\\.\\|#\\)\\|\\(~$\\|\\.\\(elc\\|obj\\|o\\|class\\|lib\\|dll\\|a\\|so\\|cache\\)$\\)\\)"
359
"^\\.\\(emacs\\|gnus\\)$")))
360
"*Specifies which files are shown as source files.
361
This is done on directory-base, which means for each directory-regexp the
362
files to display can be specified. If more than one directory-regexp matches
363
the current selected directory then always the first one \(and its related
364
file-exclude/include-regexps) is used! If no directory-regexp matches then all
365
files are displayed for the currently selected directory.
367
Important note: It is recommended that the *LAST* element of this list should
368
contain an always matching directory-regexp \(\".*\")!
370
So the value of this option is a list of cons-cells where the car is a
371
directory regexp and the cdr is a 2 element list where the first element is a
372
exclude regexp and the second element is a include regexp. A file is displayed
373
in the sources-buffer of ECB iff: The file does not match the exclude regexp
374
OR the file matches the include regexp.
376
But regardless of the value of this option a file F is never displayed in the
377
sources-buffer if the directory matches `ecb-sources-exclude-cvsignore'
378
and the directory contains a file .cvsignore which contains F as an entry!
380
There are three predefined and useful combinations of an exclude and include
383
- All, but no backup, object, lib or ini-files \(except .emacs and .gnus). This
384
means all files except those starting with \".\", \"#\" or ending with
385
\"~\", \".elc\", \".obj\", \".o\", \".lib\", \".dll\", \".a\", \".so\".
386
(but including .emacs and .gnus)
387
- Common source file types (.c, .java etc.)
388
In addition to these predefined values a custom exclude and include
389
combination can be defined.
391
Tips for the directory- and file-regexps: \"$^\" matches no files/directories,
392
\".*\" matches all files/directories."
394
:group 'ecb-most-important
395
:type '(repeat (cons :tag "Directory file-spec"
396
(regexp :tag "Directory regexp")
397
(choice :tag "Files to display"
398
:menu-tag "Files to display"
399
(const :tag "All files"
401
(const :tag "All, but no backups, objects, etc..."
402
:value ("\\(^\\(\\.\\|#\\)\\|\\(~$\\|\\.\\(elc\\|obj\\|o\\|class\\|lib\\|dll\\|a\\|so\\|cache\\)$\\)\\)" "^\\.\\(x?emacs\\|gnus\\)$"))
403
(const :tag "Common source file types"
404
:value ("" "\\(\\(M\\|m\\)akefile\\|.*\\.\\(java\\|el\\|c\\|cc\\|h\\|hh\\|txt\\|html\\|texi\\|info\\|bnf\\)\\)$"))
406
(regexp :tag "Exclude regexp"
408
(regexp :tag "Include regexp"
412
(defcustom ecb-show-source-file-extension t
413
"*Show the file extension of source files."
418
(defcustom ecb-sources-sort-method 'name
419
"*Defines how the source files are sorted.
420
- 'name: Sorting by name.
421
- 'extension: Sorting first by name and then by extension.
422
- nil: No sorting, means source files are displayed in the sequence returned by
423
`directory-files' \(called without sorting)."
425
:type '(radio (const :tag "By name"
427
(const :tag "By extension"
429
(const :tag "No sorting"
433
(defcustom ecb-history-buffer-name " *ECB History*"
434
"*Name of the ECB history buffer.
435
Because it is not a normal buffer for editing you should enclose the name with
436
stars, e.g. \"*ECB History*\".
438
If it is necessary for you you can get emacs-lisp access to the buffer-object of
439
the ECB-history-buffer by this name, e.g. by a call of `set-buffer'.
441
Changes for this option at runtime will take affect only after deactivating and
442
then activating ECB again!"
447
(defcustom ecb-sort-history-items nil
448
"*Sorts the items in the history buffer."
452
(defcustom ecb-kill-buffer-clears-history nil
453
"*Define if `kill-buffer' should also clear the history.
454
There are three options:
455
- auto: Removes automatically the corresponding history-entry after the buffer
457
- ask: Asks, if the history-entry should be removed after the kill.
458
- nil: `kill-buffer' does not affect the history \(this is the default)."
460
:type '(radio (const :tag "Remove history entry automatically"
462
(const :tag "Ask if history entry should be removed"
464
(const :tag "Do not clear the history"
468
(defcustom ecb-history-item-name 'buffer-name
469
"*The name to use for items in the history buffer."
471
:type '(radio (const :tag "Buffer name"
473
(const :tag "File name"
476
(defcustom ecb-directories-menu-user-extension
478
(ecb-dir-popup-cvs-status "CVS Status" )
479
(ecb-dir-popup-cvs-examine "CVS Examine")
480
(ecb-dir-popup-cvs-update "CVS Update")))
481
"*Static user extensions for the popup-menu of the directories buffer.
482
Value is a list of elements of the following type: Each element defines a new
483
menu-entry and is either:
485
a) Menu-command: A list containing two sub-elements, whereas the first is the
486
function \(a function symbol) being called if the menu-entry is selected
487
and the second is the name of the menu-entry.
488
b) Separator: A one-element-list and the element is the string \"---\": Then a
489
non-selectable menu-separator is displayed.
490
c) Submenu: A list where the first element is the title of the submenu
491
displayed in the main-menu and all other elements are either menu-commands
492
\(see a) or separators \(see b).
494
The function of a menu-command must follow the following guidelines: Such a
495
function must be defined with the macro `tree-buffer-defpopup-command! This
496
macro defines a new popup-command whereas the newly defined command gets one
497
argument NODE. See the docstring of `tree-buffer-defpopup-command' for further
500
Example for the definition of such a popupmenu-command:
502
\(tree-buffer-defpopup-command ecb-my-special-dir-popup-function
503
\"Prints the name of the directory of the node under point.\"
504
\(let \(\(node-data=dir \(tree-node-get-data node)))
505
\(message \"Dir under node: %s\" node-data=dir)))
507
Per default the static user-extensions are added at the beginning of the
508
built-in menu-entries of `ecb-directories-menu' but the whole menu can be
509
re-arranged with `ecb-directories-menu-sorter'.
511
These menu-extensions are static. A dynamic menu-extension can be achieved via
512
`ecb-directories-menu-user-extension-function'."
513
:group 'ecb-directories
514
:type '(repeat (choice :tag "Menu-entry" :menu-tag "Menu-entry"
516
(const :tag "Separator" :value ("---"))
517
(list :tag "Menu-command"
518
(function :tag "Function" :value ignore)
519
(string :tag "Entry-name"))
521
(string :tag "Submenu-title")
522
(repeat (choice :tag "Submenu-entry" :menu-tag "Submenu-entry"
524
(const :tag "Separator" :value ("---"))
525
(list :tag "Submenu-command"
526
(function :tag "Function"
528
(string :tag "Entry-name"))))))))
530
(defcustom ecb-directories-menu-user-extension-function nil
531
"*Dynamic user extensions for the popup-menu of the directories buffer.
532
A function which has to return a list in the same format like the option
533
`ecb-directories-menu-user-extension'. This function is called when the user
534
opens the popup-menu for the directories buffer.
536
Per default the dynamic user-extensions are added in front of the static
537
extensions of `ecb-directories-menu-user-extension' but the whole menu can be
538
re-arranged with `ecb-directories-menu-sorter'."
539
:group 'ecb-directories
542
(defcustom ecb-sources-menu-user-extension
544
(ecb-file-popup-ediff-revision "Ediff against revision")
546
(ecb-file-popup-vc-next-action "Check In/Out")
547
(ecb-file-popup-vc-log "Revision history")
548
(ecb-file-popup-vc-annotate "Annotate")
549
(ecb-file-popup-vc-diff "Diff against last version")))
550
"*Static user extensions for the popup-menu of the sources buffer.
551
For further explanations see `ecb-directories-menu-user-extension'.
553
The node-argument of a menu-function contains as data the filename of the
554
source for which the popup-menu has been opened.
556
Per default the static user-extensions are added at the beginning of the
557
built-in menu-entries of `ecb-sources-menu' but the whole menu can be
558
re-arranged with `ecb-sources-menu-sorter'."
560
:type '(repeat (choice :tag "Menu-entry" :menu-tag "Menu-entry"
562
(const :tag "Separator" :value ("---"))
563
(list :tag "Menu-command"
564
(function :tag "Function" :value ignore)
565
(string :tag "Entry-name"))
567
(string :tag "Submenu-title")
568
(repeat (choice :tag "Submenu-entry" :menu-tag "Submenu-entry"
570
(const :tag "Separator" :value ("---"))
571
(list :tag "Submenu-command"
572
(function :tag "Function"
574
(string :tag "Entry-name"))))))))
576
(defcustom ecb-sources-menu-user-extension-function nil
577
"*Dynamic user extensions for the popup-menu of the sources buffer.
578
A function which has to return a list in the same format like the option
579
`ecb-sources-menu-user-extension'. This function is called when the user
580
opens the popup-menu for the sources buffer.
582
Per default the dynamic user-extensions are added in front of the static
583
extensions of `ecb-sources-menu-user-extension' but the whole menu can be
584
re-arranged with `ecb-sources-menu-sorter'."
588
(defcustom ecb-history-menu-user-extension
590
(ecb-file-popup-ediff-revision "Ediff against revision")
592
(ecb-file-popup-vc-next-action "Check In/Out")
593
(ecb-file-popup-vc-log "Revision history")
594
(ecb-file-popup-vc-annotate "Annotate")
595
(ecb-file-popup-vc-diff "Diff against last version")))
596
"*Static user extensions for the popup-menu of the history buffer.
597
For further explanations see `ecb-directories-menu-user-extension'.
599
The node-argument of a menu-function contains as data the filename of the
600
source for which the popup-menu has been opened.
602
Per default the static user-extensions are added at the beginning of the
603
built-in menu-entries of `ecb-history-menu' but the whole menu can be
604
re-arranged with `ecb-history-menu-sorter'."
606
:type '(repeat (choice :tag "Menu-entry" :menu-tag "Menu-entry"
608
(const :tag "Separator" :value ("---"))
609
(list :tag "Menu-command"
610
(function :tag "Function" :value ignore)
611
(string :tag "Entry-name"))
613
(string :tag "Submenu-title")
614
(repeat (choice :tag "Submenu-entry" :menu-tag "Submenu-entry"
616
(const :tag "Separator" :value ("---"))
617
(list :tag "Submenu-command"
618
(function :tag "Function"
620
(string :tag "Entry-name"))))))))
623
(defcustom ecb-history-menu-user-extension-function nil
624
"*Dynamic user extensions for the popup-menu of the history buffer.
625
A function which has to return a list in the same format like the option
626
`ecb-history-menu-user-extension'. This function is called when the user
627
opens the popup-menu for the history buffer.
629
Per default the dynamic user-extensions are added in front of the static
630
extensions of `ecb-history-menu-user-extension' but the whole menu can be
631
re-arranged with `ecb-history-menu-sorter'."
635
(defcustom ecb-directories-menu-sorter nil
636
"*Function which re-sorts the menu-entries of the directories buffer.
637
If a function then this function is called to re-arrange the menu-entries of
638
the combined menu-entries of the user-menu-extensions of
639
`ecb-directories-menu-user-extension' and the built-in-menu
640
`ecb-directories-menu'. If nil then no special sorting will be done and the
641
user-extensions are placed in front of the built-in-entries.
643
The function get one argument, a list of menu-entries. For the format of this
644
argument see `ecb-directories-menu-user-extension'. The function must return a
645
new list in the same format. Of course this function can not only re-arrange
646
the entries but also delete entries or add new entries."
647
:group 'ecb-directories
648
:type '(choice :tag "Menu-sorter" :menu-tag "Menu-sorter"
649
(const :tag "No special sorting" :value nil)
650
(function :tag "Sort-function" :value identity)))
653
(defcustom ecb-sources-menu-sorter nil
654
"*Function which re-sorts the menu-entries of the directories buffer.
655
If a function then this function is called to sort the menu-entries of the
656
combined menu-entries of the user-menu-extensions of
657
`ecb-sources-menu-user-extension' and the built-in-menu
658
`ecb-sources-menu'. If nil then no special sorting will be done and the
659
user-extensions are placed in front of the built-in-entries.
661
For the guidelines for such a sorter-function see
662
`ecb-directories-menu-sorter'."
664
:type '(choice :tag "Menu-sorter" :menu-tag "Menu-sorter"
665
(const :tag "No special sorting" :value nil)
666
(function :tag "Sort-function" :value identity)))
669
(defcustom ecb-history-menu-sorter nil
670
"*Function which re-sorts the menu-entries of the directories buffer.
671
If a function then this function is called to sort the menu-entries of the
672
combined menu-entries of the user-menu-extensions of
673
`ecb-history-menu-user-extension' and the built-in-menu
674
`ecb-history-menu'. If nil then no special sorting will be done and the
675
user-extensions are placed in front of the built-in-entries.
677
For the guidelines for such a sorter-function see
678
`ecb-directories-menu-sorter'."
680
:type '(choice :tag "Menu-sorter" :menu-tag "Menu-sorter"
681
(const :tag "No special sorting" :value nil)
682
(function :tag "Sort-function" :value identity)))
685
(defcustom ecb-directories-buffer-after-create-hook nil
686
"*Local hook running after the creation of the directories-buffer.
687
Every function of this hook is called once without arguments direct after
688
creating the directories-buffer of ECB and it's local key-map. So for example a
689
function could be added which performs calls of `local-set-key' to define new
690
key-bindings only for the directories-buffer of ECB.
692
The following keys must not be rebind in the directories-buffer:
694
:group 'ecb-directories
698
(defcustom ecb-sources-buffer-after-create-hook nil
699
"*Local hook running after the creation of the sources-buffer.
700
Every function of this hook is called once without arguments direct after
701
creating the sources-buffer of ECB and it's local key-map. So for example a
702
function could be added which performs calls of `local-set-key' to define new
703
key-bindings only for the sources-buffer of ECB."
708
(defcustom ecb-history-buffer-after-create-hook nil
709
"*Local hook running after the creation of the history-buffer.
710
Every function of this hook is called once without arguments direct after
711
creating the history-buffer of ECB and it's local key-map. So for example a
712
function could be added which performs calls of `local-set-key' to define new
713
key-bindings only for the history-buffer of ECB."
718
;;====================================================
720
;;====================================================
722
(defmacro ecb-exec-in-directories-window (&rest body)
724
(when (ecb-window-select ecb-directories-buffer-name)
729
(defmacro ecb-exec-in-sources-window (&rest body)
731
(when (ecb-window-select ecb-sources-buffer-name)
736
(defmacro ecb-exec-in-history-window (&rest body)
738
(when (ecb-window-select ecb-history-buffer-name)
744
(defun ecb-expand-directory-tree (path node)
746
(dolist (child (tree-node-get-children node))
747
(let ((data (tree-node-get-data child)))
748
(when (and (>= (length path) (length data))
749
(string= (substring path 0 (length data)) data)
750
(or (= (length path) (length data))
751
(eq (elt path (length data)) ecb-directory-sep-char)))
752
(let ((was-expanded (tree-node-is-expanded child)))
753
(tree-node-set-expanded child t)
754
(ecb-update-directory-node child)
756
(or (when (> (length path) (length data))
757
(ecb-expand-directory-tree path child))
758
(not was-expanded)))))))))
761
(defvar ecb-files-and-subdirs-cache nil
762
"Cache for every directory all subdirs and files. This is an alist where an
764
\(<directory> . \(<file-list> . <subdirs-list>))")
767
(defun ecb-files-and-subdirs-cache-add (cache-elem)
768
(if (not (ecb-files-and-subdirs-cache-get (car cache-elem)))
769
(setq ecb-files-and-subdirs-cache
770
(cons cache-elem ecb-files-and-subdirs-cache))))
773
(defun ecb-files-and-subdirs-cache-get (dir)
774
(cdr (assoc dir ecb-files-and-subdirs-cache)))
777
(defun ecb-files-and-subdirs-cache-remove (dir)
778
(let ((elem (assoc dir ecb-files-and-subdirs-cache)))
780
(setq ecb-files-and-subdirs-cache
781
(delete elem ecb-files-and-subdirs-cache)))))
784
(defun ecb-clear-files-and-subdirs-cache ()
785
(setq ecb-files-and-subdirs-cache nil))
788
(defun ecb-check-directory-for-caching (dir number-of-contents)
789
"Return not nil if DIR matches not any regexp of the option
790
`ecb-cache-directory-contents-not' but matches at least one regexp in
791
`ecb-cache-directory-contents' and NUMBER-OF-CONTENTS is greater then the
793
(and (not (catch 'exit
794
(dolist (elem ecb-cache-directory-contents-not)
795
(let ((case-fold-search t))
797
(if (string-match (car elem) dir)
798
(throw 'exit (car elem))))
801
(dolist (elem ecb-cache-directory-contents)
802
(let ((case-fold-search t))
804
(if (and (string-match (car elem) dir)
805
(> number-of-contents (cdr elem)))
806
(throw 'exit (car elem))))
810
(defun ecb-check-directory-for-source-regexps (dir)
811
"Return the related source-exclude-include-regexps of
812
`ecb-source-file-regexps' if DIR matches any directory-regexp in
813
`ecb-source-file-regexps'."
815
(dolist (elem ecb-source-file-regexps)
816
(let ((case-fold-search t))
818
(if (string-match (car elem) dir)
819
(throw 'exit (cdr elem))))
823
(defun ecb-files-from-cvsignore (dir)
824
"Return an expanded list of filenames which are excluded by the .cvsignore
825
file in current directory."
826
(let ((cvsignore-content (ecb-file-content-as-string
827
(expand-file-name ".cvsignore" dir)))
829
(when cvsignore-content
830
(dolist (f (split-string cvsignore-content))
831
(setq files (append (directory-files dir nil (wildcard-to-regexp f) t)
836
(defun ecb-check-directory-for-cvsignore-exclude (dir)
837
"Return not nil if DIR matches a regexp in `ecb-sources-exclude-cvsignore'."
839
(dolist (elem ecb-sources-exclude-cvsignore)
840
(let ((case-fold-search t))
842
(if (string-match elem dir)
847
(defun ecb-get-files-and-subdirs (dir)
848
"Return a cons cell where car is a list of all files to display in DIR and
849
cdr is a list of all subdirs to display in DIR. Both lists are sorted
850
according to `ecb-sources-sort-method'."
851
(or (ecb-files-and-subdirs-cache-get dir)
853
(let ((files (directory-files dir nil nil t))
854
(source-regexps (or (ecb-check-directory-for-source-regexps
855
(ecb-fix-filename dir))
857
(cvsignore-files (if (ecb-check-directory-for-cvsignore-exclude dir)
858
(ecb-files-from-cvsignore dir)))
859
sorted-files source-files subdirs cache-elem)
860
;; if necessary sort FILES
862
(cond ((equal ecb-sources-sort-method 'name)
863
(sort files 'string<))
864
((equal ecb-sources-sort-method 'extension)
865
(sort files (function
867
(let ((ext-a (file-name-extension a t))
868
(ext-b (file-name-extension b t)))
869
(if (string= ext-a ext-b)
871
(string< ext-a ext-b)))))))
873
;; divide real files and subdirs. For really large directories (~ >=
874
;; 2000 entries) this is the performance-bottleneck in the
875
;; file-browser of ECB.
876
(dolist (file sorted-files)
877
(if (file-directory-p (ecb-fix-filename dir file))
878
(if (not (string-match ecb-excluded-directories-regexp file))
879
(setq subdirs (append subdirs (list file))))
880
(if (and (not (member file cvsignore-files))
881
(or (string-match (cadr source-regexps) file)
882
(not (string-match (car source-regexps) file))))
883
(setq source-files (append source-files (list file))))))
885
(setq cache-elem (cons dir (cons source-files subdirs)))
886
;; check if this directory must be cached
887
(if (ecb-check-directory-for-caching dir (length sorted-files))
888
(ecb-files-and-subdirs-cache-add cache-elem))
893
(defvar ecb-sources-cache nil
894
"Cache for the contents of the buffer `ecb-sources-buffer-name'. This is an
895
alist where every element is a cons cell which looks like:
896
\(<directory> . <cache-entry>) whereas <cache-entry> is a cons-cell too which
897
contains as car a 3-elem list \(tree-buffer-root <copy of tree-buffer-nodes>
898
buffer-string) for a full \(i.e. all files) cache and as cdr a 4-elem list
899
\(tree-buffer-root, tree-buffer-nodes, sources-buffer-string, <filter>) for a
900
filtered cache where <filter> is another cons-cell \(<filter-regexp> .
904
(defun ecb-sources-cache-remove (dir)
905
"Remove the cache-entry for DIR in `ecb-sources-cache'."
906
(let ((cache-elem (assoc dir ecb-sources-cache)))
908
(setq ecb-sources-cache (delq cache-elem ecb-sources-cache)))))
911
(defun ecb-sources-cache-add-full (dir cache-elem-full)
912
"Add the full sources-cache CACHE-ELEM-FULL for DIR to
913
`ecb-sources-cache'. If there is already a full cache-entry then replace it."
914
(let ((elem (assoc dir ecb-sources-cache)))
916
(setq ecb-sources-cache
917
(cons (cons dir (cons cache-elem-full nil))
919
(setcdr elem (cons cache-elem-full
920
(cdr (cdr elem)))))))
922
(defun ecb-sources-cache-add-filtered (dir cache-elem-filtered)
923
"Add the filtered sources-cache CACHE-ELEM-FILTERED for DIR to
924
`ecb-sources-cache'. If there is already a filtered cache-entry then replace
926
(let ((elem (assoc dir ecb-sources-cache)))
928
(setq ecb-sources-cache
929
(cons (cons dir (cons nil cache-elem-filtered))
931
(setcdr elem (cons (car (cdr elem))
932
cache-elem-filtered)))))
934
(defun ecb-sources-cache-get-full (dir)
935
"Return the full value of a cached-directory DIR, means the 3-element-list
936
\(tree-buffer-root, tree-buffer-nodes, sources-buffer-string). If no
937
cache-entry for DIR is available then nil is returned."
938
(car (cdr (assoc dir ecb-sources-cache))))
940
(defun ecb-sources-cache-get-filtered (dir)
941
"Return the filtered value of a cached-directory DIR, means the
942
4-element-list \(tree-buffer-root, tree-buffer-nodes, sources-buffer-string,
943
filter-regexp). If no cache-entry for DIR is available then nil is returned."
944
(cdr (cdr (assoc dir ecb-sources-cache))))
946
(defun ecb-sources-cache-clear ()
947
"Clear the whole cache of `ecb-sources-cache'."
948
(setq ecb-sources-cache nil))
951
(defun ecb-update-sources-buffer (dir-before-update)
952
"Updates the sources-buffer with all sources contained in
953
`ecb-path-selected-directory' - the contents are either newly computed or come
954
from the `ecb-sources-cache'. DIR-BEFORE-UPDATE is the directory which was
955
selected before this update."
957
;; Here we add a cache-mechanism which caches for each path the node-tree
958
;; and the whole buffer-string of the sources-buffer. A cache-elem would be
959
;; removed from the cache if a directory is POWER-clicked in the directories
960
;; buffer because this is the only way to synchronize the sources-buffer
961
;; with the disk-contents of the clicked directory. This works because the
962
;; tree of the sources-buffer contains only not expandable nodes (see the
963
;; comment in `ecb-rebuild-methods-buffer-with-tagcache'). If we would
964
;; make the nodes in the Sources-buffer "expandable" this caching would not
967
(ecb-exec-in-sources-window
968
;; if we have a filtered cache we must display it - otherwise we use the
969
;; full cache if there is any
970
(let ((cache-elem (or (ecb-sources-cache-get-filtered ecb-path-selected-directory)
971
(ecb-sources-cache-get-full ecb-path-selected-directory))))
974
(tree-buffer-set-root (nth 0 cache-elem))
975
(tree-buffer-update nil (cons (nth 2 cache-elem)
976
(nth 1 cache-elem))))
977
(let ((new-tree (tree-node-new-root))
978
(old-children (tree-node-get-children (tree-buffer-get-root)))
979
(new-cache-elem nil))
980
;; building up the new files-tree
981
(ecb-tree-node-add-files
983
ecb-path-selected-directory
984
(car (ecb-get-files-and-subdirs ecb-path-selected-directory))
985
0 ecb-show-source-file-extension old-children t)
987
;; updating the buffer itself
988
(tree-buffer-set-root new-tree)
991
;; check if the sources buffer for this directory must be
992
;; cached: If yes update the cache
993
(when (ecb-check-directory-for-caching
994
ecb-path-selected-directory
995
(length tree-buffer-nodes))
996
(setq new-cache-elem (list (tree-buffer-get-root)
997
(ecb-copy-list tree-buffer-nodes)
998
(buffer-substring (point-min)
1000
(ecb-sources-cache-add-full ecb-path-selected-directory
1003
(when (not (string= dir-before-update ecb-path-selected-directory))
1004
(tree-buffer-scroll (point-min) (point-min))))))
1006
(defun ecb-sources-filter-by-ext (ext-str)
1007
"Filter the sources by extension EXT-STR."
1008
(if (= (length ext-str) 0)
1009
(ecb-apply-filter-to-sources-buffer
1010
"^[^.]+$" ;; matches only filenames with no extension
1012
(ecb-apply-filter-to-sources-buffer
1013
(format "\\.%s\\'" ext-str)
1014
(format "*.%s" ext-str))))
1016
(tree-buffer-defpopup-command ecb-popup-sources-filter-by-ext
1017
"Filter the sources by extension by popup."
1018
(ecb-sources-filter-by-ext
1019
(read-string "Insert the filter-extension without leading dot: "
1021
(file-name-extension (tree-node-get-data node))))))
1023
(defun ecb-sources-filter-by-regexp ()
1024
"Filter the sources by a regexp. Ask for the regexp."
1025
(let ((regexp-str (read-string "Insert the filter-regexp: ")))
1026
(if (> (length regexp-str) 0)
1027
(ecb-apply-filter-to-sources-buffer regexp-str))))
1029
(tree-buffer-defpopup-command ecb-popup-sources-filter-by-regexp
1030
"Filter the sources by regexp by popup."
1031
(ecb-sources-filter-by-regexp))
1033
(tree-buffer-defpopup-command ecb-popup-sources-filter-none
1034
"Remove any filter from the sources by popup."
1035
(ecb-apply-filter-to-sources-buffer nil))
1038
(defun ecb-sources-filter ()
1039
"Apply a filter to the sources-buffer to reduce the number of entries.
1040
So you get a better overlooking. There are three choices:
1041
- Filter by extension: Just insert the extension you want the Sources-buffer
1042
being filtered. Insert the extension without leading dot!
1043
- Filter by regexp: Insert the filter as regular expression.
1044
- No filter: This means to display an entry for every file in the current
1045
selected directory \(all except these filter already filtered out by
1046
`ecb-source-file-regexps' and `ecb-sources-exclude-cvsignore').
1047
Such a filter is only applied to the current selected directory, i.e. each
1048
directory has its own filtered sources-buffer."
1050
(let ((choice (ecb-query-string "Filter sources by:"
1051
'("extension" "regexp" "nothing"))))
1052
(cond ((string= choice "extension")
1053
(ecb-sources-filter-by-ext
1054
(read-string "Insert the filter-extension without leading dot: ")))
1055
((string= choice "regexp")
1056
(ecb-sources-filter-by-regexp))
1057
(t (ecb-apply-filter-to-sources-buffer nil)))))
1059
(defun ecb-sources-filter-modeline-prefix (buffer-name sel-dir sel-source)
1060
"Compute a mode-line prefix for the Sources-buffer so the current filter
1061
applied to the sources is displayed. This function is only for using by
1062
the option `ecb-mode-line-prefixes'."
1063
(let ((filtered-cache-elem (ecb-sources-cache-get-filtered sel-dir)))
1064
(if (null filtered-cache-elem)
1065
nil ;; no prefix if no filter
1066
(format "[Filter: %s]" (cdr (nth 3 filtered-cache-elem))))))
1068
(defun ecb-apply-filter-to-sources-buffer (filter-regexp &optional filter-display)
1069
"Apply the regular expression FILTER-REGEXP to the files of
1070
`ecb-path-selected-directory' and display only the filtered files in the
1071
Sources-buffer. If FILTER-REGEXP is nil then any applied filter is removed and
1072
all files are displayed."
1073
(save-selected-window
1074
(ecb-exec-in-sources-window
1075
(if (null filter-regexp)
1078
;; remove the filtered cache by setting it to nil
1079
(ecb-sources-cache-add-filtered ecb-path-selected-directory nil)
1080
;; update the sources buffer - because the filtered cache is nil
1081
;; the full sources are displayed.
1082
(ecb-update-sources-buffer ecb-path-selected-directory)
1083
(tree-buffer-highlight-node-data ecb-path-selected-source))
1084
;; apply the filter-regexp
1085
(let ((new-tree (tree-node-new-root))
1086
(old-children (tree-node-get-children (tree-buffer-get-root)))
1087
(all-files (car (ecb-get-files-and-subdirs ecb-path-selected-directory)))
1088
(filtered-files nil))
1089
(dolist (file all-files)
1090
(if (string-match filter-regexp file)
1091
(setq filtered-files
1092
(cons file filtered-files))))
1093
;; building up the new files-tree
1094
(ecb-tree-node-add-files
1096
ecb-path-selected-directory
1097
(nreverse filtered-files)
1098
0 ecb-show-source-file-extension old-children t)
1100
;; updating the buffer itself
1101
(tree-buffer-set-root new-tree)
1102
(tree-buffer-update)
1103
(tree-buffer-scroll (point-min) (point-min))
1104
(tree-buffer-highlight-node-data ecb-path-selected-source)
1106
;; add the new filter to the cache, so the next call to
1107
;; `ecb-update-sources-buffer' displays the filtered sources.
1108
(ecb-sources-cache-add-filtered ecb-path-selected-directory
1109
(list (tree-buffer-get-root)
1110
(ecb-copy-list tree-buffer-nodes)
1114
filter-regexp))))))))
1115
;; now we update the mode-lines so the current filter (can be no filter) is
1116
;; displayed in the mode-line. See `ecb-sources-filter-modeline-prefix'.
1117
(ecb-mode-line-format))
1120
(defun ecb-set-selected-directory (path &optional force)
1121
"Set the contents of the ECB-directories and -sources buffer correct for the
1122
value of PATH. If PATH is equal to the value of `ecb-path-selected-directory'
1123
then nothing is done unless first optional argument FORCE is not nil."
1124
(let ((last-dir ecb-path-selected-directory))
1125
(save-selected-window
1126
(setq ecb-path-selected-directory (ecb-fix-filename path))
1127
;; if ecb-path-selected-directory has not changed then there is no need
1128
;; to do anything here because neither the content of directory buffer
1129
;; nor the content of the sources buffer can have been changed!
1130
(when (or force (not (string= last-dir ecb-path-selected-directory)))
1131
(when (or (not (ecb-show-sources-in-directories-buffer-p))
1132
ecb-auto-expand-directory-tree)
1133
(ecb-exec-in-directories-window
1135
(when ecb-auto-expand-directory-tree
1136
;; Expand tree to show selected directory
1138
(if (equal ecb-auto-expand-directory-tree 'best)
1139
;; If none of the source-paths in the buffer
1140
;; `ecb-directories-buffer-name' matches then nil
1141
;; otherwise the node of the best matching source-path
1142
(cdar (sort (delete nil
1143
(mapcar (lambda (elem)
1144
(let ((data (tree-node-get-data elem)))
1148
(regexp-quote data))
1149
ecb-path-selected-directory)
1152
(tree-node-get-children (tree-buffer-get-root))))
1154
(> (length (car lhs)) (length (car rhs))))))
1155
;; we start at the root node
1156
(tree-buffer-get-root)))
1157
(when (and (equal ecb-auto-expand-directory-tree 'best)
1159
;; expand the best-match node itself
1160
(tree-node-set-expanded start t)
1161
;; This functions ensures a correct expandable-state of
1163
(ecb-update-directory-node start))
1164
;; start recursive expanding of either the best-matching node or
1165
;; the root-node itself.
1166
(ecb-expand-directory-tree ecb-path-selected-directory
1168
(tree-buffer-get-root)))
1169
(tree-buffer-update))
1170
(when (not (ecb-show-sources-in-directories-buffer-p))
1171
(tree-buffer-highlight-node-data ecb-path-selected-directory
1173
;; now we update the sources buffer for `ecb-path-selected-directory'
1174
(ecb-update-sources-buffer last-dir))))
1176
;; set the default-directory of each tree-buffer to current selected
1177
;; directory so we can open files via find-file from each tree-buffer.
1178
;; is this necessary if neither dir.- nor sources-buffer-contents have been
1179
;; changed? I think not but anyway, doesn't matter, costs are very low.
1181
(dolist (buf ecb-tree-buffers)
1183
(setq default-directory
1184
(concat ecb-path-selected-directory
1185
(and (not (= (aref ecb-path-selected-directory
1186
(1- (length ecb-path-selected-directory)))
1187
ecb-directory-sep-char))
1188
ecb-directory-sep-string)))))
1189
;; set the modelines of all visible tree-buffers new
1190
(ecb-mode-line-format))
1193
(defun ecb-get-source-name (filename)
1194
"Returns the source name of a file."
1195
(let ((f (file-name-nondirectory filename)))
1196
(if ecb-show-source-file-extension
1198
(file-name-sans-extension f))))
1201
(defun ecb-select-source-file (filename &optional force)
1202
"Updates the directories, sources and history buffers to match the filename
1203
given. If FORCE is not nil then the update of the directories buffer is done
1204
even if current directory is equal to `ecb-path-selected-directory'."
1205
(save-selected-window
1206
(ecb-set-selected-directory (file-name-directory filename) force)
1207
(setq ecb-path-selected-source filename)
1209
;; Update directory buffer
1210
(when (ecb-show-sources-in-directories-buffer-p)
1211
(ecb-exec-in-directories-window
1212
(tree-buffer-highlight-node-data ecb-path-selected-source)))
1214
;; Update source buffer
1215
(ecb-exec-in-sources-window
1216
(tree-buffer-highlight-node-data ecb-path-selected-source))
1218
;; Update history buffer always regardless of visibility of history window
1219
(ecb-add-item-to-history-buffer ecb-path-selected-source)
1220
(ecb-sort-history-buffer)
1221
;; Update the history window only if it is visible
1222
(ecb-update-history-window ecb-path-selected-source)))
1225
(defvar ecb-history-filter nil
1226
"A cons-cell where car is the filter-function and the cdr is a string how
1227
the current active filter should be displayed in the modeline of the
1228
History-buffer. The filter-function gets the filename of an existing
1229
file-buffer and has to return not nil if for this filename a history-entry
1232
(defun ecb-reset-history-filter ()
1233
"Reset the `ecb-history-filter' so all file-buffers are displayed."
1234
(setq ecb-history-filter '(identity . nil)))
1236
(ecb-reset-history-filter)
1238
(defun ecb-add-all-buffers-to-history ()
1239
"Add all current file-buffers to the history-buffer of ECB.
1240
If `ecb-sort-history-items' is not nil then afterwards the history is sorted
1241
alphabetically. Otherwise the most recently used buffers are on the top of the
1242
history and the seldom used buffers at the bottom."
1244
(ecb-reset-history-filter)
1245
(ecb-add-buffers-to-history))
1247
(defun ecb-add-buffers-to-history ()
1248
"Add exactly these currently existing file-buffers to the history-buffer
1249
which are not filtered out by current value of `ecb-history-filter'."
1250
;; first we clear out the history buffer
1252
(set-buffer ecb-history-buffer-name)
1253
(tree-buffer-clear))
1254
(mapc (function (lambda (buf)
1255
(when (buffer-file-name buf)
1256
(ecb-add-item-to-history-buffer
1257
(buffer-file-name buf)))))
1258
(reverse (buffer-list)))
1259
(ecb-sort-history-buffer)
1260
(ecb-update-history-window (buffer-file-name ecb-last-source-buffer))
1261
;; now the modeline has to display the current filter
1262
(ecb-mode-line-format))
1265
(defun ecb-history-filter-modeline-prefix (buffer-name sel-dir sel-source)
1266
"Compute a mode-line prefix for the History-buffer so the current filter
1267
applied to the history-entries is displayed. This function is only for using
1268
by the option `ecb-mode-line-prefixes'."
1269
(and (cdr ecb-history-filter)
1270
(format "[Filter: %s]" (cdr ecb-history-filter))))
1273
(defun ecb-add-item-to-history-buffer (filename)
1274
"Add a new item for FILENAME to the history buffer if the current filter of
1275
`ecb-history-filter' does not filter out this file."
1277
(ecb-buffer-select ecb-history-buffer-name)
1278
(tree-node-remove-child-data (tree-buffer-get-root) filename)
1279
(when (funcall (car ecb-history-filter)
1281
(tree-node-add-child-first
1282
(tree-buffer-get-root)
1284
(if (eq ecb-history-item-name 'buffer-name)
1285
(let ((b (get-file-buffer filename)))
1288
(ecb-get-source-name filename)))
1289
(ecb-get-source-name filename))
1294
(defun ecb-sort-history-buffer ()
1295
"Sort the history buffer according to `ecb-sort-history-items'."
1296
(when ecb-sort-history-items
1298
(ecb-buffer-select ecb-history-buffer-name)
1299
(tree-node-sort-children
1300
(tree-buffer-get-root)
1301
(function (lambda (l r) (string< (tree-node-get-name l)
1302
(tree-node-get-name r))))))))
1305
(defun ecb-update-history-window (&optional filename)
1306
"Updates the history window and highlights the item for FILENAME if given."
1307
(save-selected-window
1308
(ecb-exec-in-history-window
1309
(tree-buffer-update)
1310
(tree-buffer-highlight-node-data filename))))
1312
(defun ecb-set-selected-source (filename other-edit-window
1313
no-edit-buffer-selection)
1314
"Updates all the ECB buffers and loads the file. The file is also
1315
displayed unless NO-EDIT-BUFFER-SELECTION is set to non nil. In such case
1316
the file is only loaded invisible in the background, all semantic-parsing
1317
and ECB-Buffer-updating is done but the content of the main-edit window
1318
is not changed. For the allowed values of OTHER-EDIT-WINDOW see
1319
`ecb-combine-ecb-button/edit-win-nr'."
1320
(ecb-select-source-file filename)
1321
(if no-edit-buffer-selection
1322
;; load the selected source in an invisible buffer, do all the
1323
;; updating and parsing stuff with this buffer in the background and
1324
;; display the methods in the METHOD-buffer. We can not go back to
1325
;; the edit-window because then the METHODS buffer would be
1326
;; immediately updated with the methods of the edit-window.
1328
(set-buffer (find-file-noselect filename))
1329
(ecb-update-methods-buffer--internal 'scroll-to-begin))
1330
;; open the selected source in the edit-window and do all the update and
1331
;; parsing stuff with this buffer
1332
(ecb-find-file-and-display ecb-path-selected-source
1334
(ecb-update-methods-buffer--internal 'scroll-to-begin)
1335
(setq ecb-major-mode-selected-source major-mode)
1336
(ecb-tag-sync 'force)))
1338
(defun ecb-clear-history ()
1339
"Clears the ECB history-buffer."
1341
(unless (or (not ecb-minor-mode)
1342
(not (equal (selected-frame) ecb-frame)))
1343
(save-selected-window
1344
(ecb-exec-in-history-window
1346
(tree-buffer-update)
1347
(tree-buffer-highlight-node-data ecb-path-selected-source)))))
1350
(defun ecb-tree-node-add-files
1351
(node path files type include-extension old-children
1352
&optional not-expandable)
1353
"For every file in FILES add a child-node to NODE."
1354
(dolist (file files)
1355
(let* ((filename (ecb-fix-filename path file))
1356
(file-1 (if include-extension
1358
(file-name-sans-extension file)))
1359
(displayed-file file-1))
1360
(tree-node-add-child
1366
(or not-expandable (= type 1))
1367
(if ecb-truncate-long-names 'end))))))
1370
(defun ecb-update-directory-node (node)
1371
"Updates the directory node NODE and add all subnodes if any."
1372
(let ((old-children (tree-node-get-children node))
1373
(path (tree-node-get-data node)))
1374
(tree-node-set-children node nil)
1375
(if (file-accessible-directory-p path)
1376
(let ((files-and-dirs (ecb-get-files-and-subdirs path)))
1377
(ecb-tree-node-add-files node path (cdr files-and-dirs)
1379
(if (ecb-show-sources-in-directories-buffer-p)
1380
(ecb-tree-node-add-files node path (car files-and-dirs) 1
1381
ecb-show-source-file-extension
1383
(tree-node-set-expandable node (or (tree-node-get-children node)))
1384
;; if node is not expandable we set its expanded state to nil
1385
(tree-node-set-expanded node (if (not (tree-node-is-expandable node))
1387
(tree-node-is-expanded node)))))))
1390
(defun ecb-get-source-paths-from-functions ()
1391
"Return a list of paths found by querying `ecb-source-path-functions'."
1392
(let ((func ecb-source-path-functions)
1396
(setq paths (append paths (funcall (car ecb-source-path-functions)))
1399
(setq rpaths (cons (expand-file-name (car paths)) rpaths)
1404
(defun ecb-path-matching-any-source-path-p (path)
1405
(let ((source-paths (append (ecb-get-source-paths-from-functions)
1408
(dolist (dir source-paths)
1409
(let ((norm-dir (ecb-fix-filename (if (listp dir) (car dir) dir) nil t)))
1411
(if (string-match (regexp-quote norm-dir)
1412
(ecb-fix-filename (file-name-directory path)))
1413
(throw 'exit norm-dir)))
1417
(defun ecb-update-directories-buffer ()
1418
"Updates the ECB directories buffer."
1420
(unless (or (not ecb-minor-mode)
1421
(not (equal (selected-frame) ecb-frame)))
1422
(save-selected-window
1423
(ecb-exec-in-directories-window
1424
;; (setq tree-buffer-type-faces
1425
;; (list (cons 1 ecb-source-in-directories-buffer-face)))
1426
(let* ((node (tree-buffer-get-root))
1427
(old-children (tree-node-get-children node))
1428
(paths (append (ecb-get-source-paths-from-functions)
1430
(tree-node-set-children node nil)
1432
(let* ((path (if (listp dir) (car dir) dir))
1433
(norm-dir (ecb-fix-filename path nil t))
1434
(name (if (listp dir) (cadr dir) norm-dir)))
1435
(tree-node-add-child
1437
(ecb-new-child old-children name 2 norm-dir nil
1438
(if ecb-truncate-long-names 'beginning)))))
1439
;; (when (not paths)
1440
;; (tree-node-add-child node (tree-node-new "Welcome to ECB! Please select:"
1441
;; 3 '(lambda()) t))
1442
;; (tree-node-add-child node (tree-node-new "" 3 '(lambda()) t))
1443
;; (tree-node-add-child node (tree-node-new "[F2] Customize ECB" 3
1444
;; 'ecb-customize t))
1445
;; (tree-node-add-child node (tree-node-new "[F3] ECB Help" 3
1446
;; 'ecb-show-help t))
1447
;; (tree-node-add-child
1448
;; node (tree-node-new
1449
;; "[F4] Add Source Path" 3
1450
;; '(lambda () (call-interactively 'ecb-add-source-path)) t)))
1451
(tree-buffer-update))))))
1454
(defun ecb-new-child (old-children name type data &optional not-expandable shorten-name)
1455
"Return a node with type = TYPE, data = DATA and name = NAME. Tries to find
1456
a node with matching TYPE and DATA in OLD-CHILDREN. If found no new node is
1457
created but only the fields of this node will be updated. Otherwise a new node
1460
(dolist (child old-children)
1461
(when (and (equal (tree-node-get-data child) data)
1462
(= (tree-node-get-type child) type))
1463
(tree-node-set-name child name)
1465
(tree-node-set-expandable child nil))
1466
(throw 'exit child)))
1467
(let ((node (tree-node-new name type data not-expandable nil
1468
(if ecb-truncate-long-names 'end))))
1469
(tree-node-set-shorten-name node shorten-name)
1473
(defun ecb-add-source-path (&optional dir alias no-prompt-for-future-session)
1474
"Add a directory to the `ecb-source-path'."
1476
;; we must manually cut a filename because we must not add filenames to
1477
;; `ecb-source-path'!
1478
(let* ((use-dialog-box nil)
1479
(my-dir (ecb-fix-filename
1481
(file-name-directory (read-file-name "Add source path: ")))
1484
(read-string (format "Alias for \"%s\" (empty = no alias): "
1486
(setq ecb-source-path (append ecb-source-path
1487
(list (if (> (length my-alias) 0)
1488
(list my-dir my-alias) my-dir))))
1489
(ecb-update-directories-buffer)
1490
(if (and (not no-prompt-for-future-session)
1491
(y-or-n-p "Add the new source-path also for future-sessions? "))
1492
(customize-save-variable 'ecb-source-path ecb-source-path)
1493
(customize-set-variable 'ecb-source-path ecb-source-path))))
1495
(tree-buffer-defpopup-command ecb-add-source-path-node
1496
"Runs `ecb-add-source-path' from popup."
1497
(call-interactively 'ecb-add-source-path))
1500
(tree-buffer-defpopup-command ecb-node-to-source-path
1501
"Add this node to the source-path."
1502
(ecb-add-source-path (tree-node-get-data node)))
1505
(defun ecb-delete-s (child children sources)
1507
(if (eq child (car children))
1509
(cons (car sources) (ecb-delete-s child (cdr children) (cdr sources))))))
1512
(tree-buffer-defpopup-command ecb-delete-source-path
1513
"Delete this source-path via popup."
1514
(let ((path (tree-node-get-data node)))
1515
(when (ecb-confirm (concat "Really delete source-path " path "?"))
1516
(setq ecb-source-path (ecb-delete-s
1517
node (tree-node-get-children (tree-node-get-parent node))
1519
(ecb-update-directories-buffer)
1520
(if (y-or-n-p "Delete source-path also for future-sessions? ")
1521
(customize-save-variable 'ecb-source-path ecb-source-path)
1522
(customize-set-variable 'ecb-source-path ecb-source-path)))))
1525
(defun ecb-remove-dir-from-caches (dir)
1526
(ecb-files-and-subdirs-cache-remove dir)
1527
(ecb-sources-cache-remove dir))
1529
(defun ecb-directory-update-speedbar (dir)
1530
"Update the integrated speedbar if necessary."
1531
(and (ecb-speedbar-active-p)
1532
;; depending on the value of `ecb-directory-update-speedbar' we have to
1533
;; check if it is senseful to update the speedbar.
1534
(or (equal ecb-directories-update-speedbar t)
1535
(and (equal ecb-directories-update-speedbar 'auto)
1536
(not (or (get-buffer-window ecb-sources-buffer-name ecb-frame)
1537
(member ecb-layout-name
1538
ecb-show-sources-in-directories-buffer))))
1539
(and (not (equal ecb-directories-update-speedbar 'auto))
1540
(functionp ecb-directories-update-speedbar)
1541
(funcall ecb-directories-update-speedbar dir)))
1542
(ecb-speedbar-update-contents)))
1545
(defun ecb-directory-clicked (node ecb-button edit-window-nr shift-mode)
1546
"Handle clicking onto NODE in the directories-buffer. ECB-BUTTON can be 1, 2
1547
or 3. If 3 then EDIT-WINDOW-NR contains the number of the edit-window the NODE
1548
should be displayed. For 1 and 2 the value of EDIT-WINDOW-NR is ignored."
1549
(if (= 3 (tree-node-get-type node))
1550
(funcall (tree-node-get-data node))
1551
(ecb-update-directory-node node)
1553
(ecb-mouse-over-directory-node node nil nil 'force))
1554
(if (or (= 0 (tree-node-get-type node)) (= 2 (tree-node-get-type node)))
1556
(if (= 2 ecb-button)
1557
(when (tree-node-is-expandable node)
1558
(tree-node-toggle-expanded node))
1560
;; Removing the element from the sources-cache and the
1561
;; files-and-subdirs-cache
1563
(ecb-remove-dir-from-caches (tree-node-get-data node)))
1565
(ecb-set-selected-directory (tree-node-get-data node) shift-mode)
1566
;; if we have running an integrated speedbar we must update the
1568
(ecb-directory-update-speedbar (tree-node-get-data node)))
1570
(ecb-exec-in-directories-window
1571
;; Update the tree-buffer with optimized display of NODE
1572
(tree-buffer-update node)))
1573
(ecb-set-selected-source (tree-node-get-data node)
1574
(ecb-combine-ecb-button/edit-win-nr ecb-button edit-window-nr)
1578
(defun ecb-source-clicked (node ecb-button edit-window-nr shift-mode)
1579
"Handle clicking onto NODE in the sources-buffer. ECB-BUTTON can be 1, 2 or
1580
3. If 3 then EDIT-WINDOW-NR contains the number of the edit-window the NODE
1581
should be displayed. For 1 and 2 the value of EDIT-WINDOW-NR is ignored."
1583
(ecb-mouse-over-source-node node nil nil 'force))
1584
(ecb-set-selected-source (tree-node-get-data node)
1585
(ecb-combine-ecb-button/edit-win-nr ecb-button edit-window-nr)
1589
(defun ecb-history-clicked (node ecb-button edit-window-nr shift-mode)
1590
"Handle clicking onto NODE in the history-buffer. ECB-BUTTON can be 1, 2 or
1591
3. If 3 then EDIT-WINDOW-NR contains the number of the edit-window the NODE
1592
should be displayed. For 1 and 2 the value of EDIT-WINDOW-NR is ignored."
1594
(ecb-mouse-over-history-node node nil nil 'force))
1595
(ecb-set-selected-source (tree-node-get-data node)
1596
(ecb-combine-ecb-button/edit-win-nr ecb-button edit-window-nr)
1599
(defun ecb-expand-directory-nodes (level)
1600
"Set the expand level of the nodes in the ECB-directories-buffer.
1601
For argument LEVEL see `ecb-expand-methods-nodes'.
1603
Be aware that for deep structured paths and a lot of source-paths this command
1604
can last a long time - depending of machine- and disk-performance."
1605
(interactive "nLevel: ")
1606
(save-selected-window
1607
(ecb-exec-in-directories-window
1608
(tree-buffer-expand-nodes level)))
1609
(ecb-current-buffer-sync 'force))
1612
(defun ecb-get-file-info-text (file)
1613
"Return a file-info string for a file in the ECB sources buffer"
1614
(let ((attrs (file-attributes file)))
1615
(format "%s %8s %4d %10d %s %s"
1617
(user-login-name (nth 2 attrs))
1620
(format-time-string "%Y/%m/%d %H:%M" (nth 5 attrs))
1621
(if (equal (ecb-show-node-info-what ecb-sources-buffer-name)
1624
(file-name-nondirectory file)))
1628
(defun ecb-mouse-over-directory-node (node &optional window no-message click-force)
1629
"Displays help text if mouse moves over a node in the directory buffer or if
1630
CLICK-FORCE is not nil and always with regards to the settings in
1631
`ecb-show-node-info-in-minibuffer'. NODE is the node for which help text
1632
should be displayed, WINDOW is the related window, NO-MESSAGE defines if the
1633
help-text should be printed here."
1634
(if (= (tree-node-get-type node) 1)
1635
(ecb-mouse-over-source-node node window no-message click-force)
1636
(if (not (= (tree-node-get-type node) 3))
1637
(let ((str (when (or click-force
1638
(ecb-show-minibuffer-info node window
1639
ecb-directories-buffer-name)
1640
(and (not (equal (ecb-show-node-info-when ecb-directories-buffer-name)
1642
(not (string= (tree-node-get-data node)
1643
(tree-node-get-name node)))
1644
(eq (tree-node-get-parent node)
1645
(tree-buffer-get-root))))
1646
(if (equal (ecb-show-node-info-what ecb-directories-buffer-name)
1648
(tree-node-get-name node)
1649
(tree-node-get-data node)))))
1652
(tree-buffer-nolog-message str)))))))
1655
(defun ecb-mouse-over-source-node (node &optional window no-message click-force)
1656
"Displays help text if mouse moves over a node in the sources buffer or if
1657
CLICK-FORCE is not nil and always with regards to the settings in
1658
`ecb-show-node-info-in-minibuffer'. NODE is the node for which help text
1659
should be displayed, WINDOW is the related window, NO-MESSAGE defines if the
1660
help-text should be printed here."
1661
(let ((str (ignore-errors ;; For buffers that hasn't been saved yet
1662
(when (or click-force
1663
(ecb-show-minibuffer-info node window
1664
ecb-sources-buffer-name))
1665
(if (equal (ecb-show-node-info-what ecb-sources-buffer-name)
1667
(tree-node-get-name node)
1668
(ecb-get-file-info-text (tree-node-get-data node)))))))
1671
(tree-buffer-nolog-message str)))))
1674
(defun ecb-mouse-over-history-node (node &optional window no-message click-force)
1675
"Displays help text if mouse moves over a node in the history buffer or if
1676
CLICK-FORCE is not nil and always with regards to the settings in
1677
`ecb-show-node-info-in-minibuffer'. NODE is the node for which help text
1678
should be displayed, WINDOW is the related window, NO-MESSAGE defines if the
1679
help-text should be printed here."
1680
(let ((str (ignore-errors ;; For buffers that hasn't been saved yet
1681
(when (or click-force
1682
(ecb-show-minibuffer-info node window
1683
ecb-history-buffer-name))
1684
(if (equal (ecb-show-node-info-what ecb-history-buffer-name)
1686
(tree-node-get-name node)
1687
(tree-node-get-data node))))))
1690
(tree-buffer-nolog-message str)))))
1694
(tree-buffer-defpopup-command ecb-create-source
1695
"Creates a new sourcefile in current directory."
1696
(let* ((use-dialog-box nil)
1697
(dir (ecb-fix-filename
1698
(funcall (if (file-directory-p (tree-node-get-data node))
1700
'file-name-directory)
1701
(tree-node-get-data node))))
1702
(filename (file-name-nondirectory
1703
(read-file-name "Source name: " (concat dir "/")))))
1704
(ecb-select-edit-window)
1705
(if (string-match "\\.java$" filename)
1706
(ecb-jde-gen-class-buffer dir filename)
1707
(find-file (concat dir "/" filename)))
1708
(when (= (point-min) (point-max))
1709
(set-buffer-modified-p t)
1710
(let ((ecb-auto-update-methods-after-save nil))
1712
(ecb-rebuild-methods-buffer-with-tagcache nil nil t))
1713
(ecb-remove-dir-from-caches dir)
1714
(ecb-set-selected-directory dir t)
1715
(ecb-current-buffer-sync)))
1718
(defun ecb-grep-directory-internal (node find)
1719
(ecb-select-edit-window)
1720
(let ((default-directory (concat (ecb-fix-filename
1721
(if (file-directory-p
1722
(tree-node-get-data node))
1723
(tree-node-get-data node)
1724
(file-name-directory
1725
(tree-node-get-data node))))
1726
ecb-directory-sep-string)))
1727
(call-interactively (if find
1728
(or (and (fboundp ecb-grep-find-function)
1729
ecb-grep-find-function)
1731
(or (and (fboundp ecb-grep-function)
1736
(tree-buffer-defpopup-command ecb-grep-find-directory
1737
"Runs grep-find for current directory."
1738
(ecb-grep-directory-internal node t))
1741
(tree-buffer-defpopup-command ecb-grep-directory
1742
"Runs grep for current directory."
1743
(ecb-grep-directory-internal node nil))
1746
(defun ecb-create-directory (parent-node)
1747
(make-directory (concat (tree-node-get-data parent-node) "/"
1748
(read-from-minibuffer "Directory name: ")))
1749
(ecb-update-directory-node parent-node)
1750
(tree-buffer-update))
1753
(tree-buffer-defpopup-command ecb-delete-directory
1754
"Delete current directory."
1755
(let ((dir (tree-node-get-data node)))
1756
(when (ecb-confirm (concat "Really delete directory" dir "? "))
1757
(delete-directory (tree-node-get-data node))
1758
(ecb-update-directory-node (tree-node-get-parent node))
1759
(tree-buffer-update))))
1762
(defun ecb-dired-directory-internal (node &optional other)
1763
(ecb-select-edit-window)
1764
(let ((dir (ecb-fix-filename
1765
(funcall (if (file-directory-p (tree-node-get-data node))
1767
'file-name-directory)
1768
(tree-node-get-data node)))))
1769
(ecb-with-adviced-functions
1776
(tree-buffer-defpopup-command ecb-dired-directory
1777
"Run dired for this directory."
1778
(ecb-dired-directory-internal node))
1781
(tree-buffer-defpopup-command ecb-dired-directory-other-window
1782
"Run dired for this directory in the other window."
1783
(ecb-dired-directory-internal node 'other))
1786
(defun ecb-dir-run-cvs-op (node op op-arg-list)
1787
(let ((dir (tree-node-get-data node)))
1788
(funcall op dir op-arg-list)))
1791
(tree-buffer-defpopup-command ecb-dir-popup-cvs-status
1792
"Check status of directory \(and below) in pcl-cvs mode."
1793
(ecb-dir-run-cvs-op node 'cvs-status '("-v")))
1796
(tree-buffer-defpopup-command ecb-dir-popup-cvs-examine
1797
"Examine directory \(and below) in pcl-cvs mode."
1798
(ecb-dir-run-cvs-op node 'cvs-examine '("-d" "-P")))
1801
(tree-buffer-defpopup-command ecb-dir-popup-cvs-update
1802
"Update directory \(and below) in pcl-cvs mode."
1803
(ecb-dir-run-cvs-op node 'cvs-update '("-d" "-P")))
1806
(defvar ecb-common-directories-menu nil)
1809
(setq ecb-common-directories-menu
1811
(ecb-grep-directory "Grep Directory")
1812
(ecb-grep-find-directory "Grep Directory recursive"))
1815
(ecb-dired-directory "Open in Dired")
1816
(ecb-dired-directory-other-window "Open in Dired other window"))
1818
(ecb-create-source "Create Sourcefile")
1819
(ecb-create-directory "Create Child Directory")
1820
(ecb-delete-directory "Delete Directory")
1822
(ecb-add-source-path-node "Add Source Path")))
1825
(defvar ecb-directories-menu nil
1826
"Built-in menu for the directories-buffer for directories which are not a
1827
source-path of `ecb-source-path'.")
1828
(setq ecb-directories-menu
1830
ecb-common-directories-menu
1831
'((ecb-node-to-source-path "Make This a Source Path")
1833
(ecb-maximize-ecb-window-menu-wrapper "Maximize window"))))
1836
(defvar ecb-directories-menu-title-creator
1837
(function (lambda (node)
1838
(let ((node-type (tree-node-get-type node))
1839
(node-data (tree-node-get-name node)))
1840
(cond ((= node-type 0) ;; directory
1841
(format "%s (Directory)" node-data))
1842
((= node-type 1) ;; source-file
1843
(format "%s (File)" node-data))
1844
((= node-type 2) ;; source-path
1845
(format "%s (Source-path)" node-data))))))
1846
"The menu-title for the directories menu. Has to be either a string or a
1847
function which is called with current node and has to return a string.")
1850
(tree-buffer-defpopup-command ecb-open-source-in-editwin1
1851
"Open current source-file the 1. edit-window."
1852
;; We can use `ecb-source-clicked' for history-buffer too because shift-mode
1854
(ecb-source-clicked node 3 1 nil))
1855
(tree-buffer-defpopup-command ecb-open-source-in-editwin2
1856
"Open current source-file the 2. edit-window."
1857
(ecb-source-clicked node 3 2 nil))
1858
(tree-buffer-defpopup-command ecb-open-source-in-editwin3
1859
"Open current source-file the 3. edit-window."
1860
(ecb-source-clicked node 3 3 nil))
1861
(tree-buffer-defpopup-command ecb-open-source-in-editwin4
1862
"Open current source-file the 4. edit-window."
1863
(ecb-source-clicked node 3 4 nil))
1864
(tree-buffer-defpopup-command ecb-open-source-in-editwin5
1865
"Open current source-file the 5. edit-window."
1866
(ecb-source-clicked node 3 5 nil))
1867
(tree-buffer-defpopup-command ecb-open-source-in-editwin6
1868
"Open current source-file the 6. edit-window."
1869
(ecb-source-clicked node 3 6 nil))
1870
(tree-buffer-defpopup-command ecb-open-source-in-editwin7
1871
"Open current source-file the 7. edit-window."
1872
(ecb-source-clicked node 3 7 nil))
1873
(tree-buffer-defpopup-command ecb-open-source-in-editwin8
1874
"Open current source-file the 8. edit-window."
1875
(ecb-source-clicked node 3 8 nil))
1877
(defun ecb-dir/source/hist-menu-editwin-entries ()
1878
"Generate popup-menu-entries for each edit-window if there are at least 2
1879
edit-windows. Otherwise return nil."
1880
(let ((edit-win-list (ecb-canonical-edit-windows-list))
1882
(when (> (length edit-win-list) 1)
1883
(dotimes (i (min 8 (length edit-win-list)))
1886
(list (list (intern (format "ecb-open-source-in-editwin%d" (1+ i)))
1887
(format "edit-window %d" (1+ i)))))))
1888
(append (list (list "---")) ;; we want a separator
1889
(list (append (list "Open source-file in ...")
1893
(defun ecb-directories-menu-creator (tree-buffer-name)
1894
"Creates the popup-menus for the directories-buffer."
1895
(setq ecb-layout-prevent-handle-ecb-window-selection t)
1896
(let ((dyn-user-extension
1897
(and (functionp ecb-directories-menu-user-extension-function)
1898
(funcall ecb-directories-menu-user-extension-function)))
1899
(dyn-builtin-extension (ecb-dir/source/hist-menu-editwin-entries)))
1900
(list (cons 0 (funcall (or ecb-directories-menu-sorter
1902
(append dyn-user-extension
1903
ecb-directories-menu-user-extension
1904
ecb-directories-menu)))
1905
(cons 1 (funcall (or ecb-sources-menu-sorter
1907
(append dyn-user-extension
1908
ecb-sources-menu-user-extension
1910
dyn-builtin-extension)))
1911
(cons 2 (funcall (or ecb-directories-menu-sorter
1913
(append dyn-user-extension
1914
ecb-directories-menu-user-extension
1915
ecb-source-path-menu))))))
1918
(defvar ecb-source-path-menu nil
1919
"Built-in menu for the directories-buffer for directories which are elements of
1920
`ecb-source-path'.")
1921
(setq ecb-source-path-menu
1923
ecb-common-directories-menu
1924
'((ecb-delete-source-path "Delete Source Path")
1926
(ecb-maximize-ecb-window-menu-wrapper "Maximize window"))))
1929
(tree-buffer-defpopup-command ecb-delete-source
1930
"Deletes current sourcefile."
1931
(let* ((file (tree-node-get-data node))
1932
(dir (ecb-fix-filename (file-name-directory file))))
1933
(when (ecb-confirm (concat "Really delete " (file-name-nondirectory file) "? "))
1934
(when (get-file-buffer file)
1935
(kill-buffer (get-file-buffer file)))
1936
(ecb-delete-file file)
1937
(ecb-remove-dir-from-caches dir)
1938
(ecb-set-selected-directory dir t))))
1941
(tree-buffer-defpopup-command ecb-file-popup-ediff-revision
1942
"Diff file against repository with ediff."
1943
(let ((file (tree-node-get-data node)))
1944
(ediff-revision file)))
1947
(tree-buffer-defpopup-command ecb-file-popup-vc-next-action
1949
(let ((file (tree-node-get-data node)))
1951
(vc-next-action nil)))
1954
(tree-buffer-defpopup-command ecb-file-popup-vc-log
1955
"Print revision history of file."
1956
(let ((file (tree-node-get-data node)))
1961
(tree-buffer-defpopup-command ecb-file-popup-vc-annotate
1963
(let ((file (tree-node-get-data node)))
1968
(tree-buffer-defpopup-command ecb-file-popup-vc-diff
1969
"Diff file against last version in repository."
1970
(let ((file (tree-node-get-data node)))
1975
(defvar ecb-sources-menu nil
1976
"Built-in menu for the sources-buffer.")
1979
(setq ecb-sources-menu
1981
(ecb-grep-directory "Grep Directory")
1982
(ecb-grep-find-directory "Grep Directory recursive"))
1984
(ecb-dired-directory "Open Dir in Dired")
1985
(ecb-dired-directory-other-window "Open Dir in Dired other window"))
1987
(ecb-popup-sources-filter-by-ext "Filter by extension")
1988
(ecb-popup-sources-filter-by-regexp "Filter by a regexp")
1989
(ecb-popup-sources-filter-none "No filter"))
1991
(ecb-create-source "Create Sourcefile")
1992
(ecb-delete-source "Delete Sourcefile")
1994
(ecb-maximize-ecb-window-menu-wrapper "Maximize window")))
1997
(defvar ecb-sources-menu-title-creator
1998
(function (lambda (node)
1999
(file-name-nondirectory (tree-node-get-data node))))
2000
"The menu-title for the sources menu. See
2001
`ecb-directories-menu-title-creator'.")
2003
(defun ecb-sources-menu-creator (tree-buffer-name)
2004
"Creates the popup-menus for the sources-buffer."
2005
(setq ecb-layout-prevent-handle-ecb-window-selection t)
2006
(let ((dyn-user-extension
2007
(and (functionp ecb-sources-menu-user-extension-function)
2008
(funcall ecb-sources-menu-user-extension-function)))
2009
(dyn-builtin-extension (ecb-dir/source/hist-menu-editwin-entries)))
2010
(list (cons 0 (funcall (or ecb-sources-menu-sorter
2012
(append dyn-user-extension
2013
ecb-sources-menu-user-extension
2015
dyn-builtin-extension))))))
2019
(tree-buffer-defpopup-command ecb-history-kill-buffer
2020
"Kills the buffer for current entry."
2021
(let ((data (tree-node-get-data node)))
2022
(when (get-file-buffer data)
2023
(kill-buffer (get-file-buffer data)))))
2025
(defun ecb-history-filter-by-ext (ext-str)
2026
"Filter history entries by extension."
2027
(if (= (length ext-str) 0)
2028
(setq ecb-history-filter
2029
(cons `(lambda (filename)
2031
(string-match "^[^.]+$" filename)))
2033
(setq ecb-history-filter
2034
(cons `(lambda (filename)
2036
(string-match ,(format "\\.%s\\'" ext-str)
2038
(format "*.%s" ext-str))))
2039
(ecb-add-buffers-to-history))
2041
(tree-buffer-defpopup-command ecb-popup-history-filter-by-ext
2042
"Filter history entries by extension by popup."
2043
(let ((ext-str (read-string "Insert the filter-extension without leading dot: "
2045
(file-name-extension (tree-node-get-data node))))))
2046
(ecb-history-filter-by-ext ext-str)))
2048
(defun ecb-history-filter-by-regexp ()
2049
"Filter history entries by regexp."
2050
(let ((regexp-str (read-string "Insert the filter-regexp: ")))
2051
(if (> (length regexp-str) 0)
2052
(setq ecb-history-filter
2053
(cons `(lambda (filename)
2055
(string-match ,regexp-str filename)))
2057
(ecb-add-buffers-to-history))
2059
(tree-buffer-defpopup-command ecb-popup-history-filter-by-regexp
2060
"Filter history entries by regexp by popup."
2061
(ecb-history-filter-by-regexp))
2063
(tree-buffer-defpopup-command ecb-popup-history-filter-all-existing
2064
"No history filter, i.e. add all existing file-buffers to the history."
2065
(ecb-add-all-buffers-to-history))
2068
(defun ecb-history-filter ()
2069
"Apply a filter to the history-buffer to reduce the number of entries.
2070
So you get a better overlooking. There are three choices:
2071
- Filter by extension: Just insert the extension you want the History-buffer
2072
being filtered. Insert the extension without leading dot!
2073
- Filter by regexp: Insert the filter as regular expression.
2074
- No filter: This means to display an entry for all currently living
2077
(let ((choice (ecb-query-string "Filter history by:"
2078
'("extension" "regexp" "no filter"))))
2079
(cond ((string= choice "extension")
2080
(ecb-history-filter-by-ext
2081
(read-string "Insert the filter-extension without leading dot: ")))
2082
((string= choice "regexp")
2083
(ecb-history-filter-by-regexp))
2084
(t (ecb-add-all-buffers-to-history)))))
2086
(defvar ecb-history-menu nil
2087
"Built-in menu for the history-buffer.")
2090
(setq ecb-history-menu
2092
(ecb-grep-directory "Grep Directory")
2093
(ecb-grep-find-directory "Grep Directory recursive"))
2096
(ecb-dired-directory "Open Dir in Dired")
2097
(ecb-dired-directory-other-window "Open Dir in Dired other window"))
2099
(ecb-popup-history-filter-by-ext "Filter by extension")
2100
(ecb-popup-history-filter-by-regexp "Filter by regexp")
2101
(ecb-popup-history-filter-all-existing "No filter (all file-buffers)"))
2103
(ecb-history-kill-buffer "Kill Buffer")
2104
(ecb-delete-source "Delete Sourcefile")
2106
(ecb-maximize-ecb-window-menu-wrapper "Maximize window")))
2109
(defvar ecb-history-menu-title-creator
2110
(function (lambda (node)
2111
(tree-node-get-name node)))
2112
"The menu-title for the history menu. See
2113
`ecb-directories-menu-title-creator'.")
2115
(defun ecb-history-menu-creator (tree-buffer-name)
2116
"Creates the popup-menus for the history-buffer."
2117
(setq ecb-layout-prevent-handle-ecb-window-selection t)
2118
(let ((dyn-user-extension
2119
(and (functionp ecb-history-menu-user-extension-function)
2120
(funcall ecb-history-menu-user-extension-function)))
2121
(dyn-builtin-extension (ecb-dir/source/hist-menu-editwin-entries)))
2122
(list (cons 0 (funcall (or ecb-history-menu-sorter
2124
(append dyn-user-extension
2125
ecb-history-menu-user-extension
2127
dyn-builtin-extension))))))
2130
(silentcomp-provide 'ecb-file-browser)
2132
;;; ecb-file-browser.el ends here