1
;;; ecb-method-browser.el --- the method-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
;; Kevin A. Burton <burton@openprivacy.org>
11
;; Keywords: browser, code, programming, tools
14
;; This program is free software; you can redistribute it and/or modify it under
15
;; the terms of the GNU General Public License as published by the Free Software
16
;; Foundation; either version 2, or (at your option) any later version.
18
;; This program is distributed in the hope that it will be useful, but WITHOUT
19
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
23
;; You should have received a copy of the GNU General Public License along with
24
;; GNU Emacs; see the file COPYING. If not, write to the Free Software
25
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
;; $Id: ecb-method-browser.el,v 1.15 2004/02/16 08:56:25 berndl Exp $
31
;; This file contains the code for the method-browser of ECB
33
(require 'tree-buffer)
36
(require 'ecb-mode-line)
37
(require 'ecb-navigate)
39
(require 'ecb-speedbar)
41
(require 'ecb-semantic-wrapper)
42
;; This loads the semantic-setups for the major-modes.
43
(require 'semantic-load)
49
;; to avoid compiler grips
53
(require 'silentcomp))
55
(silentcomp-defun hs-minor-mode)
56
(silentcomp-defun hs-show-block)
57
(silentcomp-defun hs-hide-block)
58
(silentcomp-defvar hs-minor-mode)
59
(silentcomp-defvar hs-block-start-regexp)
60
(silentcomp-defvar imenu--index-alist)
62
(silentcomp-defun ecb-get-tags-for-non-semantic-files)
63
(silentcomp-defun ecb-create-non-semantic-tree)
65
(defvar ecb-selected-tag nil
66
"The currently selected Semantic tag.")
67
(make-variable-buffer-local 'ecb-selected-tag)
69
(defvar ecb-methods-root-node nil
70
"Path to currently selected source.")
72
(defun ecb-method-browser-initialize ()
73
(setq ecb-selected-tag nil)
74
(setq ecb-methods-root-node nil)
75
(setq ecb-methods-user-filter-alist nil))
77
;;====================================================
79
;;====================================================
81
(defgroup ecb-methods nil
82
"Settings for the methods-buffer in the Emacs code browser."
87
(defgroup ecb-non-semantic nil
88
"Settings for parsing and displaying non-semantic files."
93
(defcustom ecb-methods-buffer-name " *ECB Methods*"
94
"*Name of the ECB methods buffer.
95
Because it is not a normal buffer for editing you should enclose the name with
96
stars, e.g. \"*ECB Methods*\".
98
If it is necessary for you you can get emacs-lisp access to the buffer-object of
99
the ECB-methods-buffer by this name, e.g. by a call of `set-buffer'.
101
Changes for this option at runtime will take affect only after deactivating and
102
then activating ECB again!"
107
(defcustom ecb-auto-expand-tag-tree 'expand-spec
108
"*Expand the methods-tag-tree automatically if node invisible.
109
This option has only an effect if option `ecb-highlight-tag-with-point' is
110
switched on too. There are three possible choices:
111
- nil: No auto. expanding of the method buffer.
112
- expand-spec: Auto expand the method-buffer nodes if the node belonging to
113
current tag under point is invisible because its parent-node is collapsed.
114
But expanding is only done if the type of the tag under point in the
115
edit-buffer is contained in `ecb-methods-nodes-expand-spec'.
116
- all: Like expand-spec but expands all tags regardless of the setting in
117
`ecb-methods-nodes-expand-spec'.
119
This options takes only effect for semantic-sources - means sources supported
122
:type '(radio (const :tag "No auto. expand" :value nil)
123
(const :tag "Expand as specified" :value expand-spec)
124
(const :tag "Expand all" :value all)))
127
(defcustom ecb-expand-methods-switch-off-auto-expand t
128
"*Switch off auto expanding in the ECB-method buffer.
129
If on then auto expanding is switched off after explicit expanding or
130
collapsing by `ecb-expand-methods-nodes'.
132
This is done with `ecb-toggle-auto-expand-tag-tree' so after the switch off
133
the auto expanding feature can again switched on quickly.
135
But after explicitly expanding/collapsing the methods-buffer to a certain
136
level the auto. expanding could undo this when the node belonging to current
137
tag under point in the edit-window is invisible after
138
`ecb-expand-methods-nodes' - then the auto. expand feature would make this
139
node immediately visible and destroys the explicitly set expand-level."
144
(defcustom ecb-auto-update-methods-after-save t
145
"*Automatically updating the ECB method buffer after saving a source."
150
(defcustom ecb-font-lock-tags t
151
"*Adds font-locking \(means highlighting) to the ECB-method buffer.
152
This options takes only effect for semantic-sources - means sources supported
155
:set (function (lambda (symbol value)
157
(ecb-clear-tag-tree-cache)))
159
:initialize 'custom-initialize-default)
162
(defcustom ecb-tag-jump-sets-mark t
163
"*Set the mark after jumping to a tag from the ECB-method buffer.
164
If set the user can easily jump back."
168
(defconst ecb-tag->text-functions
169
(mapcar (lambda (fkt-elem)
173
(cdr (split-string (symbol-name
174
(cdr fkt-elem)) "-"))
177
(concat "ecb--" (symbol-name (cdr fkt-elem))))))
178
ecb--semantic-format-function-alist)
179
"Alist containing one element for every member of
180
`ecb--semantic-format-function-alist'")
182
(defcustom ecb-tag-display-function '((default . ecb-format-tag-uml-prototype))
183
"*Function to use for displaying tags in the methods buffer.
184
This functionality is set on major-mode base, i.e. for every major-mode a
185
different function can be used. The value of this option is a list of
187
- The car is either a major-mode symbol or the special symbol 'default which
188
means if no function for a certain major-mode is defined then the cdr of
189
the 'default cons-cell is used.
190
- The cdr is the function used for displaying a tag in the related
192
Every function is called with 3 arguments:
194
2. The parent-tag of tag \(can be nil)
195
3. The value of `ecb-font-lock-tags'.
196
Every function must return the display of the tag as string, colorized if
197
the third argument is not nil.
199
The following functions are predefined:
200
- For each element E of `ecb--semantic-format-function-alist' exists a
201
function with name \"ecb--<\(cdr E)>\". These functions are just aliase to
202
the builtin format-functions of semantic. See the docstring of these
203
functions to see what they do.
204
Example: \(semantic-name-nonterminal . semantic-format-tag-name) is an
205
element of `ecb--semantic-format-function-alist'. Therefore the
206
alias-function for this element is named `ecb--semantic-format-tag-name'.
207
- For every cdr in `ecb--semantic-format-function-alist' with name
208
\"semantic-XYZ\" a function with name \"ecb-XYC\" is predefined. The
209
differences between the semantic- and the ECB-version are:
210
+ The ECB-version displays for type tags only the type-name and nothing
211
else \(exception: In c++-mode a template specifier is appended to the
212
type-name if a template instead a normal class).
213
+ The ECB-version displays type-tags according to the setting in
214
`ecb-type-tag-display'. This is useful for better recognizing
215
different classes, structs etc. in the ECB-method window.
216
For all tags which are not types the display of the ECB-version is
217
identical to the semantic version. Example: For
218
`ecb--semantic-format-tag-name' \(the builtin semantic formatter) the
219
pendant is `ecb-format-tag-name'.
221
This functionality also allows the user to display tags as UML. To enable
222
this functionality set the function for a major-mode \(e.g. `jde-mode') to
223
`ecb--semantic-format-tag-uml-concise-prototype',
224
`ecb--semantic-format-tag-uml-prototype', or
225
`ecb--semantic-format-tag-uml-abbreviate' the ECB-versions of these functions.
227
If the value is nil, i.e. neither a function for a major-mode is defined nor
228
the special 'default, then `ecb--semantic-format-tag-prototype' is used for
231
This options takes only effect for semantic-sources - means sources supported
234
:group 'ecb-most-important
235
:set (function (lambda (symbol value)
237
(ecb-clear-tag-tree-cache)))
238
:type (list 'repeat ':tag "Display functions per mode"
239
(list 'cons ':tag "Mode tag display"
240
'(symbol :tag "Major mode")
241
(nconc (list 'choice ':tag "Display function"
242
':menu-tag '"Display function")
246
(symbol-name (car f)) (car f)))
247
ecb-tag->text-functions)
250
(symbol-name (cdr f)) (cdr f)))
251
ecb-tag->text-functions)
252
(list '(function :tag "Function"))))))
253
:initialize 'custom-initialize-default)
256
(defcustom ecb-type-tag-display nil
257
"*How to display semantic type-tags in the methods buffer.
258
Normally all tag displaying, colorizing and facing is done by semantic
259
according to the value of `ecb--semantic-format-face-alist' and the semantic
260
display-function \(e.g. one from `ecb--semantic-format-function-alist'). But
261
sometimes a finer distinction in displaying the different type specifiers of
262
type-tags can be useful. For a description when this option is evaluated look
263
at `ecb-tag-display-function'!
265
This functionality is set on a major-mode base, i.e. for every major-mode a
266
different setting can be used. The value of this option is a list of
268
- The car is either a major-mode symbol or the special symbol 'default which
269
means if no setting for a certain major-mode is defined then the cdr of
270
the 'default cons-cell is used.
271
- The cdr is a list of 3-element-lists:
272
1. First entry is a semantic type specifier in string-form. Current
273
available type specifiers are for example \"class\", \"interface\",
274
\"struct\", \"typedef\", \"union\" and \"enum\". In addition to these
275
ones there is also a special ECB type specifier \"group\" which is
276
related to grouping tags \(see `ecb-post-process-semantic-taglist' and
277
`ecb-group-function-tags-with-parents'). Any arbitrary specifier can be
278
set here but if it is not \"group\" or not known by semantic it will be
280
2. Second entry is a flag which indicates if the type-specifier string from
281
\(1.) itself should be removed \(if there is any) from the display.
282
3. Third entry is the face which is used in the ECB-method window to display
283
type-tags with this specifier. ECB has some predefined faces for this
284
\(`ecb-type-tag-class-face', `ecb-type-tag-interface-face',
285
`ecb-type-tag-struct-face', `ecb-type-tag-typedef-face',
286
`ecb-type-tag-union-face', `ecb-type-tag-enum-face' and
287
`ecb-type-tag-group-face') but any arbitrary face can be set here. This
288
face is merged with the faces semantic already uses to display a tag,
289
i.e. the result is a display where all face-attributes of the ECB-face
290
take effect plus all face-attributes of the semantic-faces which are not
291
set in the ECB-face \(with XEmacs this merge doesn't work so here the
292
ECB-face replaces the semantic-faces; this may be fixed in future
295
The default value is nil means there is no special ECB-displaying of
296
type-tags in addition to the displaying and colorizing semantic does. But a
297
value like the following could be a useful setting:
300
\(\"class\" t ecb-type-tag-class-face)
301
\(\"group\" nil ecb-type-tag-group-face))
303
\(\"struct\" nil ecb-type-tag-struct-face)
304
\(\"typedef\" nil ecb-type-tag-typedef-face)))
306
This means that in `c-mode' only \"struct\"s and \"typedef\"s are displayed
307
with special faces \(the specifiers itself are not removed) and in all other
308
modes \"class\"es and grouping-tags \(see `ecb-tag-display-function',
309
`ecb-group-function-tags-with-parents') have special faces and the \"class\"
310
specifier-string is removed from the display.
312
This options takes only effect for semantic-sources - means sources supported
315
:group 'ecb-most-important
316
:set (function (lambda (symbol value)
318
(ecb-clear-tag-tree-cache)))
319
:type '(repeat (cons (symbol :tag "Major-mode")
320
(repeat :tag "Display of type specifiers"
321
(list (choice :tag "Specifier list"
322
:menu-tag "Specifier list"
325
(const :tag "interface"
329
(const :tag "typedef"
337
(string :tag "Any specifier"))
338
(boolean :tag "Remove the type-specifier" t)
339
(face :tag "Any face"
340
:value ecb-type-tag-class-face)))))
341
:initialize 'custom-initialize-default)
343
(defun ecb-get-face-for-type-tag (type-specifier)
344
"Return the face set in `ecb-type-tag-display' for current major-mode and
345
TYPE-SPECIFIER or nil."
346
(let ((mode-display (cdr (assoc major-mode ecb-type-tag-display)))
347
(default-display (cdr (assoc 'default ecb-type-tag-display))))
348
(or (nth 2 (assoc type-specifier mode-display))
349
(and (null mode-display)
350
(nth 2 (assoc type-specifier default-display))))))
353
(defun ecb-get-remove-specifier-flag-for-type-tag (type-specifier)
354
"Return the remove-specifier-flag set in `ecb-type-tag-display' for
355
current major-mode and TYPE-SPECIFIER or nil."
356
(let ((mode-display (cdr (assoc major-mode ecb-type-tag-display)))
357
(default-display (cdr (assoc 'default ecb-type-tag-display))))
358
(or (nth 1 (assoc type-specifier mode-display))
359
(and (null mode-display)
360
(nth 1 (assoc type-specifier default-display))))))
362
(defcustom ecb-type-tag-expansion
363
'((default . ("class" "interface" "group"))
364
(c-mode . ("struct")))
365
"*Default expansion of semantic type-tags.
366
Semantic groups type-tags into different type-specifiers. Current available
367
type specifiers are for example \"class\", \"interface\", \"struct\",
368
\"typedef\", \"union\" and \"enum\". In addition to these ones there is also a
369
special ECB type specifier \"group\" which is related to grouping tags \(see
370
`ecb-post-process-semantic-taglist').
372
This option defines which type-specifiers should be expanded at
373
file-open-time. Any arbitrary specifier can be set here but if it is not
374
\"group\" or not known by semantic it will be useless.
376
This functionality is set on a major-mode base, i.e. for every major-mode a
377
different setting can be used. The value of this option is a list of
379
- The car is either a major-mode symbol or the special symbol 'default which
380
means if no setting for a certain major-mode is defined then the cdr of
381
the 'default cons-cell is used.
382
- The cdr is either a list of type-specifiers which should be expanded at
383
file-open-time or the symbol 'all-specifiers \(then a type-tag is always
384
expanded regardless of its type-specifier).
386
This options takes only effect for semantic-sources - means sources supported
389
:group 'ecb-most-important
390
:type '(repeat (cons (symbol :tag "Major-mode")
391
(radio (const :tag "Expand all type-specifiers"
392
:value all-specifiers)
393
(repeat :tag "Expand type specifiers"
394
(choice :tag "Specifier"
395
:menu-tag "Specifier"
398
(const :tag "interface"
402
(const :tag "typedef"
410
(string :tag "Any specifier"))))))
411
:set (function (lambda (symbol value)
413
(ecb-clear-tag-tree-cache)))
414
:initialize 'custom-initialize-default)
416
(defun ecb-type-tag-expansion (type-specifier)
417
"Return the default expansion-state of TYPE-SPECIFIER for current major-mode
418
as specified in `ecb-type-tag-expansion'"
419
(let ((mode-expansion (cdr (assoc major-mode ecb-type-tag-expansion)))
420
(default-expansion (cdr (assoc 'default ecb-type-tag-expansion))))
421
(or (equal mode-expansion 'all-specifiers)
422
(member type-specifier mode-expansion)
423
(and (null mode-expansion)
424
(or (equal default-expansion 'all-specifiers)
425
(member type-specifier default-expansion))))))
427
(defsubst ecb-faux-group-tag-p (tag)
428
"Returns not nil if TAG is a \"virtual\" faux-group token which has no
429
position but groups some external members having the same parent-tag."
430
(or (ecb--semantic--tag-get-property tag 'ecb-group-tag)
431
(ecb--semantic--tag-get-property tag 'faux)))
433
(defun ecb-get-type-specifier (tag)
434
(if (ecb-faux-group-tag-p tag)
436
(ecb--semantic-tag-type tag)))
439
(dolist (elem ecb-tag->text-functions)
441
`(lambda (tag &optional parent-tag colorize)
442
(if (eq 'type (ecb--semantic-tag-class tag))
443
(let* (;; we must here distinguish between UML- and
444
;; not-UML-semantic functions because for UML we must
445
;; preserve some semantic facing added by semantic (e.g.
446
;; italic for abstract classes)!
447
(text (funcall (if (string-match "-uml-" (symbol-name (quote ,(car elem))))
448
'ecb--semantic-format-tag-uml-abbreviate
449
'ecb--semantic-format-tag-name)
450
tag parent-tag colorize))
451
(type-specifier (ecb-get-type-specifier tag))
452
(face (ecb-get-face-for-type-tag type-specifier))
453
(remove-flag (ecb-get-remove-specifier-flag-for-type-tag
456
;; the following is done to replace the "struct" from
457
;; grouping tags (see
458
;; ecb-group-function-tags-with-parents) with "group".
459
;; This code can be removed (or changed) if semantic allows
460
;; correct protection display for function-tags with
462
(when (ecb-faux-group-tag-p tag)
463
(if (string-match (concat "^\\(.+"
464
(ecb--semantic-uml-colon-string)
466
(if (ecb--semantic--tag-get-property tag 'faux)
467
(ecb--semantic-orphaned-member-metaparent-type)
470
(let ((type-spec-text "group"))
471
(put-text-property 0 (length type-spec-text)
475
(match-string 2 text))
477
(setq text (concat (match-string 1 text)
479
;; Now we must maybe add a template-spec in c++-mode and
480
;; maybe remove the type-specifier string.
481
(let (col-type-name col-type-spec template-text)
482
(if (string-match (concat "^\\(.+\\)\\("
483
(ecb--semantic-uml-colon-string)
484
type-specifier "\\)")
486
(setq col-type-name (match-string 1 text)
487
col-type-spec (if (not remove-flag)
488
(match-string 2 text)))
489
(setq col-type-name text))
490
(when (and (equal major-mode 'c++-mode)
491
(fboundp 'ecb--semantic-c-template-string))
492
(setq template-text (ecb--semantic-c-template-string
493
tag parent-tag colorize))
494
;; Removing {...} from within the template-text.
495
;; Normally the semantic-formatters should not add this
497
(if (string-match "^\\(.+\\){.*}\\(.+\\)$" template-text)
499
(concat (match-string 1 template-text)
500
(match-string 2 template-text))))
501
(put-text-property 0 (length template-text)
504
(1- (length col-type-name)) 'face
507
(setq text (concat col-type-name template-text
509
;; now we add some own colorizing if necessary
511
(setq text (ecb-merge-face-into-text text face)))
513
(funcall (quote ,(cdr elem)) tag parent-tag colorize)))))
515
(defcustom ecb-post-process-semantic-taglist
516
'((c++-mode . (ecb-group-function-tags-with-parents))
517
(emacs-lisp-mode . (ecb-group-function-tags-with-parents))
518
(c-mode . (ecb-filter-c-prototype-tags)))
519
"*Define mode-dependent post-processing for the semantic-taglist.
520
This is an alist where the car is a major-mode symbol and the cdr is a list of
521
function-symbols of functions which should be used for post-processing the
522
taglist \(returned by `ecb--semantic-bovinate-toplevel') for a buffer in this
523
major-mode. The first function in the list is called with current semantic
524
taglist of current buffer and must return a valid taglist again. All other
525
functions are called with the result-taglist of its preceding function and
526
have to return a new taglist again.
528
For oo-programming languages where the methods of a class can be defined
529
outside the class-definition \(e.g. C++, Eieio) the function
530
`ecb-group-function-tags-with-parents' can be used to get a much better
531
method-display in the methods-window of ECB, because all method
532
implementations of a class are grouped together.
534
Another senseful usage is to filter out certain tags, e.g. prototype tags in
535
`c-mode'. For this you can set `ecb-filter-c-prototype-tags'.
537
This options takes only effect for semantic-sources - means sources supported
540
:type '(repeat (cons (symbol :tag "Major-mode")
541
(repeat (function :tag "Post-process function")))))
543
(defcustom ecb-show-only-positioned-tags t
544
"*Show only nodes in the method-buffer which are \"jump-able\".
545
If not nil then ECB displays in the method-buffer only nodes which are
546
\"jump-able\", i.e. after selecting it by clicking or with RET then ECB jumps
547
to the corresponding location in the edit-window.
548
Example: With CLOS or Eieio source-code there can exist some position-less
549
nodes like variable-attributes in a `defclass' form which are only displayed
550
if this option is nil. Displaying such nodes can be senseful even if they can
553
This options takes only effect for semantic-sources - means sources supported
559
(defcustom ecb-show-tags '((include collapsed nil)
560
(parent collapsed nil)
562
(variable collapsed access)
563
(function flattened access)
564
(rule flattened name)
565
(section flattened nil)
568
"*How to show tags in the methods buffer first time after find-file.
569
This variable is a list where each element represents a type of tags:
571
\(<tag type> <display type> <sort method>)
573
The tags in the methods buffer are displayed in the order as they appear in
579
A Semantic tag type symbol \(for all possible type symbols see documentation
586
- section \(chapters and sections in `info-mode')
587
- def \(definitions in `info-mode')
589
or one of the following:
591
- t: All tag types not specified anywhere else in the list.
592
- parent: The parents of a type.
597
A symbol which describes how the tags of this type shall be shown:
599
- expanded: The tags are shown in an expanded node.
600
- collapsed: The tags are shown in a collapsed node.
601
- flattened: The tags are added to the parent node.
602
- hidden: The tags are not shown.
607
A symbol describing how to sort the tags of this type:
609
- name: Sort by the tag name.
610
- access: Sort by tag access (public, protected, private) and then by name.
611
- nil: Don't sort tags. They appear in the same order as in the source
614
This options takes only effect for semantic-sources - means sources supported
617
:group 'ecb-most-important
618
:set (function (lambda (symbol value)
620
(ecb-clear-tag-tree-cache)))
621
:type '(repeat (list (symbol :tag "Tag symbol")
622
(choice :tag "Display type" :value collapsed
623
(const :tag "Expanded" expanded)
624
(const :tag "Collapsed" collapsed)
625
(const :tag "Flattened" flattened)
626
(const :tag "Hidden" hidden))
627
(choice :tag "Sort by" :value nil
628
(const :tag "Name" name)
629
(const :tag "Access then name" access)
630
(const :tag "No sort" nil))))
631
:initialize 'custom-initialize-default)
634
(defcustom ecb-methods-nodes-expand-spec '(type variable function section)
635
"*Semantic tag-types expanded by `ecb-expand-methods-nodes'.
636
The value of this option is either the symbol 'all \(all tags are expanded
637
regardless of their type) or a list of symbols where each symbol is a valid
638
semantic tag-type. For a description of semantic tag types see option
641
But this option also defines if bucket-nodes in the ECB-method-buffer \(e.g.
642
\"\[Variables\]\") should be expanded. Therefore valid symbols for this list
643
are also all cars of the variable `semantic-symbol->name-assoc-list'.
645
If there is a bucket-name \(the node-name stripped of the settings in
646
`ecb-bucket-node-display') which is not contained as cdr in
647
`semantic-symbol->name-assoc-list' then the symbol with this bucket-name as
648
name is also a valid symbol for this list. Example: In ECB there are buckets
649
\"\[Parents\]\". The bucket-name is \"Parents\" and the valid symbol-name is
652
This options takes only effect for semantic-sources - means sources supported
655
:type '(radio (const :tag "All node-types" :value all)
656
(repeat :tag "Node-type list"
657
(symbol :tag "Node-type"))))
660
(defcustom ecb-methods-nodes-collapse-spec 'all
661
"*Semantic tag-types collapsed by `ecb-expand-methods-nodes'.
662
For valid values of this option see `ecb-methods-nodes-expand-spec'!
664
This options takes only effect for semantic-sources - means sources supported
667
:type '(radio (const :tag "All node-types" :value all)
668
(repeat :tag "Node-type list"
669
(symbol :tag "Node-type"))))
672
(defcustom ecb-exclude-parents-regexp nil
673
"*Regexp which parent classes should not be shown in the methods buffer.
674
If nil then all parents will be shown if `ecb-show-parents' is not nil.
676
This options takes only effect for semantic-sources - means sources supported
679
:set (function (lambda (symbol value)
681
(ecb-clear-tag-tree-cache)))
682
:type '(radio (const :tag "Do not exclude any parents"
684
(regexp :tag "Parents-regexp to exclude"))
685
:initialize 'custom-initialize-default)
688
(defcustom ecb-highlight-tag-with-point 'highlight-scroll
689
"*How to highlight the method or variable under the cursor.
690
- highlight-scroll: Always scroll the method buffer, so the current method of the
691
edit-window is highlighted in the method-window.
692
- highlight: Only highlight the current method of the edit window in the
693
method window if the method is visible in the method-window.
694
- nil: No highlighting is done.
695
See also `ecb-highlight-tag-with-point-delay'.
697
This options takes only effect for semantic-sources - means sources supported
700
:type '(radio (const :tag "Highlight and scroll window"
701
:value highlight-scroll)
702
(const :tag "Just highlight"
704
(const :tag "Do not highlight"
708
(defcustom ecb-highlight-tag-with-point-delay 0.25
709
"*Time Emacs must be idle before current tag is highlighted.
710
If nil then there is no delay, means current tag is highlighted immediately.
711
A small value of about 0.25 seconds saves CPU resources and you get even
712
though almost the same effect as if you set no delay. But such a delay
713
prevents also \"jumping backward/forward\" during scrolling within
714
java-classes if point goes out of method-definition into class-definition.
715
Therefore the default value is a delay of 0.25 seconds.
717
This options takes only effect for semantic-sources - means sources supported
720
:type '(radio (const :tag "No highlighting delay"
722
(number :tag "Idle time before highlighting"
724
:set (function (lambda (symbol value)
727
(ecb-activate-ecb-sync-functions value 'ecb-tag-sync))))
728
:initialize 'custom-initialize-default)
731
(defvar ecb-method-overlay (ecb-make-overlay 1 1)
732
"Internal overlay used for the first line of a method.")
733
(ecb-overlay-put ecb-method-overlay 'face ecb-tag-header-face)
736
(defcustom ecb-tag-visit-post-actions '((default . (ecb-tag-visit-smart-tag-start
737
ecb-tag-visit-highlight-tag-header))
738
(java-mode . (ecb-tag-visit-goto-doc-start))
739
(jde-mode . (ecb-tag-visit-goto-doc-start)))
740
"*Actions to perform after visiting a tag from the Method-buffer.
741
With this option actions can be added which will be performed after visiting
742
the start of the tag in the source-buffer.
744
This functionality is set on a `major-mode' base, i.e. for every `major-mode' a
745
different setting can be used. The value of this option is a list of
747
- The car is either a `major-mode' symbol or the special symbol 'default.
748
- The cdr is a list of action-functions or nil.
750
ECB first performs all actions defined for the special symbol 'default \(if
751
any) and then all actions defined for current `major-mode' \(if any).
753
ECB offers some predefined senseful action-functions. Currently there are:
754
- `ecb-tag-visit-highlight-tag-header'
755
- `ecb-tag-visit-smart-tag-start'
756
- `ecb-tag-visit-recenter'
757
- `ecb-tag-visit-recenter-top'
758
- `ecb-tag-visit-goto-doc-start'
759
- `ecb-tag-visit-narrow-tag'
760
See the documentation of these function for details what they do.
762
But you can add any arbitrary function if the following conditions are
764
- The function gets the semantic tag as argument and
765
- the function returns the \(new) point after finishing its job."
767
:type '(repeat (cons :value (nil . (ecb-tag-visit-recenter))
768
(symbol :tag "Major-mode or default")
769
(repeat (choice :tag "Post action" :menu-tag "Post action"
770
(const :tag "ecb-tag-visit-smart-tag-start"
771
:value ecb-tag-visit-smart-tag-start)
772
(const :tag "ecb-tag-visit-highlight-tag-header"
773
:value ecb-tag-visit-highlight-tag-header)
774
(const :tag "ecb-tag-visit-goto-doc-start"
775
:value ecb-tag-visit-goto-doc-start)
776
(const :tag "ecb-tag-visit-narrow-tag"
777
:value ecb-tag-visit-narrow-tag)
778
(const :tag "ecb-tag-visit-recenter-top"
779
:value ecb-tag-visit-recenter-top)
780
(const :tag "ecb-tag-visit-recenter"
781
:value ecb-tag-visit-recenter)
782
(function :tag "Function"))))))
785
(defun ecb-tag-visit-function-member-p (fnc)
786
(or (member fnc (cdr (assoc 'default ecb-tag-visit-post-actions)))
787
(member fnc (cdr (assoc major-mode ecb-tag-visit-post-actions)))))
789
(defcustom ecb-methods-menu-user-extension nil
790
"*Static user extensions for the popup-menu of the methods buffer.
791
For further explanations see `ecb-directories-menu-user-extension'.
793
The node-argument of a menu-function contains as data the semantic-tag of
794
the method/variable/tag for which the popup-menu has been opened.
796
Per default the static user-extensions are added at the beginning of the
797
built-in menu-entries of `ecb-methods-menu' but the whole menu can be
798
re-arranged with `ecb-methods-menu-sorter'."
800
:type '(repeat (choice :tag "Menu-entry" :menu-tag "Menu-entry"
802
(const :tag "Separator" :value ("---"))
803
(list :tag "Menu-command"
804
(function :tag "Function" :value ignore)
805
(string :tag "Entry-name"))
807
(string :tag "Submenu-title")
808
(repeat (choice :tag "Submenu-entry" :menu-tag "Submenu-entry"
810
(const :tag "Separator" :value ("---"))
811
(list :tag "Submenu-command"
812
(function :tag "Function"
814
(string :tag "Entry-name"))))))))
817
(defcustom ecb-methods-menu-user-extension-function nil
818
"*Dynamic user extensions for the popup-menu of the methods buffer.
819
A function which has to return a list in the same format like the option
820
`ecb-methods-menu-user-extension'. This function is called when the user opens
821
the popup-menu for the methods buffer. For an example how such a function can
822
be programmed see `ecb-methods-menu-editwin-entries'.
824
Per default the dynamic user-extensions are added in front of the static
825
extensions of `ecb-methods-menu-user-extension' but the whole menu can be
826
re-arranged with `ecb-methods-menu-sorter'."
830
(defcustom ecb-methods-menu-sorter nil
831
"*Function which re-sorts the menu-entries of the directories buffer.
832
If a function then this function is called to sort the menu-entries of the
833
combined menu-entries of the user-menu-extensions of
834
`ecb-methods-menu-user-extension' and the built-in-menu
835
`ecb-methods-menu'. If nil then no special sorting will be done and the
836
user-extensions are placed in front of the built-in-entries.
838
For the guidelines for such a sorter-function see
839
`ecb-directories-menu-sorter'."
841
:type '(choice :tag "Menu-sorter" :menu-tag "Menu-sorter"
842
(const :tag "No special sorting" :value nil)
843
(function :tag "Sort-function" :value identity)))
846
(defcustom ecb-methods-buffer-after-create-hook nil
847
"*Local hook running after the creation of the methods-buffer.
848
Every function of this hook is called once without arguments direct after
849
creating the methods-buffer of ECB and it's local key-map. So for example a
850
function could be added which performs calls of `local-set-key' to define new
851
key-bindings only for the methods-buffer of ECB."
856
(defcustom ecb-process-non-semantic-files (if (locate-library "speedbar")
858
"*Display contents of non-semantic-files in the ECB-methods-buffer.
859
See also `ecb-non-semantic-parsing-function'."
861
:group 'ecb-non-semantic
862
:group 'ecb-most-important
866
(defcustom ecb-non-semantic-parsing-function nil
867
"*Define mode-dependent parsing functions for non-semantic files.
868
This is an alist where the car is a major-mode symbol and the cdr is a
869
function-symbol of a function which should be used for parsing a non-semantic
870
buffer, i.h. a buffer for which no semantic grammar exists. Such a function
871
gets one argument - the filename of current buffer - and has to generate and
872
return a tag/tag list which is understandable by
873
`speedbar-insert-generic-list'. speedbar has already included two functions
874
`speedbar-fetch-dynamic-imenu' and `speedbar-fetch-dynamic-etags' which can be
875
used for parsing buffers with imenu rsp. etags.
877
This option takes only effect if `ecb-process-non-semantic-files' is not nil:
878
Then ECB checks for non-semantic buffers if current `major-mode' is contained
879
in this option and if yes, then the specified parsing function is called;
880
if not then the cars of the elements of `speedbar-dynamic-tags-function-list'
881
are called in that sequence they are listed in this variable. See option
882
`speedbar-dynamic-tags-function-list' for further details.
884
In most cases imenu-parsing is preferable over etags-parsing because imenu
885
operates on Emacs-buffers and needs no external tool and therefore parsing
886
works also if current contents of a buffer are not saved to disk. But maybe
887
sometimes etags may return better parsing results.
889
IMPORTANT: if imenu-parsing should be used then the option
890
`speedbar-use-imenu-flag' must be set to not nil!"
892
:group 'ecb-non-semantic
893
:type '(repeat (cons (symbol :tag "Major-mode")
894
(function :tag "Parsing function"))))
897
(defcustom ecb-non-semantic-methods-initial-expand nil
898
"*Initially expand all tags for not by semantic supported sources.
899
This option can be customized on a major-mode basis, i.e. if a `major-mode' is
900
contained in this option then all tags for this modes will be initially
901
expanded - otherwise not."
903
:group 'ecb-non-semantic
904
:type '(repeat :tag "Expand this modes"
905
(symbol :tag "major mode")))
908
(defcustom ecb-auto-save-before-etags-methods-rebuild t
909
"*Automatic saving of current buffer before rebuilding its methods.
910
This option is only relevant for sources which are supported and parsed by
911
etags \(see `ecb-process-non-semantic-files'). Because etags is an external
912
tool a source-buffer can only be reparsed if the buffer is saved to disk. So
913
the command `ecb-rebuild-methods-buffer' checks for sources which are not
914
supported by semantic or imenu if either this option is t or if the major-mode
915
of the source-buffer is contained in this list: In both cases ECB saves the
916
current source-buffer before it re-runs etags for reparsing the source.
917
If nil or if the major-mode is not contained then no automatic saving will be
920
For all source supported by semantic or by imenu this option takes no effect."
922
:group 'ecb-non-semantic
923
:type '(radio (const :tag "For all etags modes" :value t)
924
(repeat :tag "For these modes" (symbol :tag "Major-mode"))))
927
(defcustom ecb-non-semantic-exclude-modes '(sh-mode fundamental-mode text-mode)
928
"*Exclude modes from parsing with imenu or etags.
929
Per default, ECB tries to parse all file-types not supported by semantic with
930
imenu or etags or some other method \(for details see the option
931
`ecb-non-semantic-parsing-function'). If a file-type can not be parsed by
932
semantic, imenu or etags than this simply results in an empty method-buffer
933
for this file. But nevertheless you will get a message \"Sorry, no support for
934
a file of that extension\" which comes from the speedbar-library and can not
935
switched off. Therefore if a `major-mode' is known as not parse-able by
936
semantic, imenu or etags it can be added to this option and then it will be
937
excluded from being tried to parsed."
938
:group 'ecb-non-semantic
939
:type '(repeat :tag "Modes to exclude"
940
(symbol :tag "Major-mode")))
943
(defcustom ecb-rebuild-non-semantic-methods-before-hook nil
944
"*Hook at beginning of `ecb-rebuild-methods-buffer-for-non-semantic'.
945
So this function is always called by the command `ecb-rebuild-methods-buffer'
946
for not semantic supported source-types.
948
Every function of this hook gets one argument: The complete filename of the
949
current source-buffer in the edit-window. The Method-buffer is only rebuild by
950
`ecb-rebuild-methods-buffer-for-non-semantic' if either the hook contains no
951
function \(the default) or if no function of this hook returns nil! See
952
`run-hook-with-args-until-failure' for description how these function are
955
:group 'ecb-non-semantic
958
;;====================================================
960
;;====================================================
963
(defun ecb-enter-debugger (&rest error-args)
964
"If `ecb-debug-mode' is not nil then enter the Emacs-debugger and signal an
965
error with ERROR-ARGS."
967
(let ((debug-on-error t))
968
(apply 'error error-args))))
970
;; encapsulation all semantic-functions ECB uses if they operate with the
971
;; semantic-overlays, so we can handle an error if these overlays (extends for
972
;; XEmacs) are destroyed and invalid cause of some mysterious circumstances.
974
(defun ecb-semantic-assert-valid-tag (tag &optional no-reparse)
975
"Assert that TAG is a valid tag. If not valid then `ecb-enter-debugger'
976
is called. If NO-REPARSE is not nil then the buffer is not autom. reparsed. It
977
returns nil if the assertion fails otherwise not nil. So the caller can even
978
check the result if `ecb-debug-mode' is nil in which case the function
979
`ecb-enter-debugger' is a no-op."
980
(if (ecb--semantic-tag-p tag)
981
(if (ecb--semantic-tag-with-position-p tag)
982
(let ((o (ecb--semantic-tag-overlay tag)))
983
(if (and (ecb--semantic-overlay-p o)
984
(not (ecb--semantic-overlay-live-p o)))
986
(when (not no-reparse)
987
;; we need this because:
988
;; 1. After every jump to a tag X via the method-buffer of
989
;; ECB this tag X is added to the navigation history list
990
;; as new ecb-nav-tag-history-item.
991
;; 2. Before every select of a source in the sources- or
992
;; history-buffer or of a node in the method-buffer
993
;; `ecb-nav-save-current' is called which operates onto
994
;; the last saved history-item which is often a
995
;; tag-history-item (see 1.): `ecb-nav-save-current'
996
;; saves for tag-history-items current-position and
997
;; window-start relative to the tag position of the
998
;; last saved tag-history-item which is tag X from
1000
;; Now suppose that after 1. and before 2. the overlay of
1001
;; tag X has been destroyed cause of some reason. Then
1002
;; the tag-history-item of 1. contains now a tag with
1003
;; a destroyed overlay. Now step 2. is performed and now
1004
;; we see why from this moment every click onto a node in
1005
;; the source-, history- or method-buffer must fail:
1006
;; During step 2. `ecb-nav-save-current' gets the tag
1007
;; from the last tag-history-item and calls for this
1008
;; tag `ecb--semantic-tag-start' which fails now because
1009
;; the contained overlay of this tag is destroyed in the
1010
;; meanwhile. Therefore we must throw away this last
1011
;; tag-history-item containing the tag with the
1012
;; destroyed overlay. Then after a complete reparse of the
1013
;; source-buffer and following rebuild of the
1014
;; ECB-method-buffer ECB is in correct state again!
1015
(ecb-nav-initialize)
1016
(ecb--semantic-clear-toplevel-cache)
1017
(ecb-update-methods-buffer--internal))
1018
(ecb-enter-debugger "Tag %S is invalid!" tag)
1022
;; Position-less tags are also OK.
1024
;; For no semantic-tags a reparse makes no sense!
1025
(ecb-enter-debugger "Not a semantic tag: %S" tag)
1029
(defun ecb-semantic-tag-buffer (tag)
1030
(ecb-semantic-assert-valid-tag tag)
1031
;; if ecb-debug-mode is not nil then the TAG is valid if we pass the
1032
;; assert. If ecb-debug-mode is nil then we call simply the semantic
1033
;; function and see what happens.
1034
(ecb--semantic-tag-buffer tag))
1037
(defun ecb-semantic-tag-start (tag)
1038
(ecb-semantic-assert-valid-tag tag)
1039
;; if ecb-debug-mode is not nil then the TAG is valid if we pass the
1040
;; assert. If ecb-debug-mode is nil then we call simply the semantic
1041
;; function and see what happens.
1042
(ecb--semantic-tag-start tag))
1045
(defun ecb-semantic-tag-end (tag)
1046
(ecb-semantic-assert-valid-tag tag)
1047
;; if ecb-debug-mode is not nil then the TAG is valid if we pass the
1048
;; assert. If ecb-debug-mode is nil then we call simply the semantic
1049
;; function and see what happens.
1050
(ecb--semantic-tag-end tag))
1052
;; Klaus: We must not reparse the buffer if `ecb--semantic-current-tag'
1053
;; returns nil because here this is no error but nil is always returned for
1054
;; example if point stays within a comment. Therefore here we only catch real
1056
(defun ecb-semantic-current-nonterminal ()
1058
(ecb--semantic-current-tag)
1059
(error (message "ecb--semantic-current-tag has problems --> reparsed is performed!")
1060
(when (ecb-point-in-edit-window)
1061
(ecb--semantic-clear-toplevel-cache)
1062
(ecb-update-methods-buffer--internal)
1063
(ecb--semantic-current-tag)))))
1066
(defmacro ecb-exec-in-methods-window (&rest body)
1068
(when (ecb-window-select ecb-methods-buffer-name)
1073
(defun ecb-create-node (parent-node display name data type)
1074
(if (eq 'hidden display)
1076
(if (eq 'flattened display)
1078
(let ((node (tree-node-new name type data nil parent-node
1079
(if ecb-truncate-long-names 'end))))
1080
(when (eq 'expanded display)
1081
(tree-node-set-expanded node t))
1085
(defun ecb-get-tag-type-display (tag-type)
1086
(let ((display (ecb-find-assoc tag-type ecb-show-tags)))
1089
(setq display (ecb-find-assoc t ecb-show-tags))
1095
(defun ecb-get-tag-parent-names (parents)
1097
(let* ((parent (car parents))
1099
((ecb--semantic-tag-p parent)
1100
(ecb--semantic-format-tag-name parent nil ecb-font-lock-tags))
1102
(ecb--semantic--format-colorize-text parent 'type)))))
1104
(if (and ecb-exclude-parents-regexp
1105
(string-match ecb-exclude-parents-regexp name))
1106
(ecb-get-tag-parent-names (cdr parents))
1107
(cons name (ecb-get-tag-parent-names (cdr parents))))
1109
(append (ecb-get-tag-parent-names parent)
1110
(ecb-get-tag-parent-names (cdr parents))))))))
1112
(defun ecb-get-tag-parents (tag)
1113
"Return a list of parent-names already colorized by semantic. Currently
1114
there is no distinction between superclasses and interfaces."
1115
(ecb-get-tag-parent-names
1116
(append (ecb--semantic-tag-type-superclass tag)
1117
(ecb--semantic-tag-type-interfaces tag))))
1118
;; (ecb--semantic-tag-type-parent tag)))
1122
(defun ecb-get-tag-name (tag &optional parent-tag)
1123
"Get the name of TAG with the appropriate fcn from
1124
`ecb-tag-display-function'."
1126
(let* ((mode-display-fkt (cdr (assoc major-mode ecb-tag-display-function)))
1127
(default-fkt (cdr (assoc 'default ecb-tag-display-function)))
1128
(display-fkt (or (and (fboundp mode-display-fkt) mode-display-fkt)
1129
(and (fboundp default-fkt) default-fkt)
1130
'ecb--semantic-format-tag-prototype)))
1131
(funcall display-fkt tag parent-tag ecb-font-lock-tags))
1132
(error (ecb--semantic-format-tag-prototype tag parent-tag
1133
ecb-font-lock-tags))))
1136
(defun ecb-find-add-tag-bucket (node type display sort-method buckets
1137
&optional parent-tag no-bucketize)
1138
"Finds a bucket containing tags of the given type, creates nodes for them
1139
and adds them to the given node. The bucket is removed from the buckets list.
1140
PARENT-TAG is only propagated to `ecb-add-tag-bucket'."
1142
(let ((bucket (cadr buckets)))
1143
(if (eq type (ecb--semantic-tag-class (cadr bucket)))
1145
(ecb-add-tag-bucket node bucket display sort-method parent-tag
1147
(setcdr buckets (cddr buckets)))
1148
(ecb-find-add-tag-bucket node type display sort-method
1149
(cdr buckets) parent-tag no-bucketize)))))
1152
(defun ecb-format-bucket-name (name)
1153
(let ((formatted-name (concat (nth 0 ecb-bucket-node-display)
1155
(nth 1 ecb-bucket-node-display))))
1156
(setq formatted-name (ecb-merge-face-into-text formatted-name (nth 2 ecb-bucket-node-display)))
1160
(defun ecb-add-tag-bucket (node bucket display sort-method
1161
&optional parent-tag no-bucketize)
1162
"Adds a tag bucket to a node unless DISPLAY equals 'hidden."
1164
(let ((name (ecb-format-bucket-name (car bucket)))
1165
;;(type (ecb--semantic-tag-class (cadr bucket)))
1167
(unless (eq 'hidden display)
1168
(unless (eq 'flattened display)
1169
(setq bucket-node (tree-node-new name 1 nil nil node
1170
(if ecb-truncate-long-names 'end)))
1171
(tree-node-set-expanded bucket-node (eq 'expanded display)))
1172
(dolist (tag (ecb-sort-tags sort-method (cdr bucket)))
1173
;; (ecb--semantic--tag-put-property tag 'parent-tag parent-tag)
1174
(ecb-update-tag-node tag
1175
(tree-node-new "" 0 tag t bucket-node
1176
(if ecb-truncate-long-names 'end))
1177
parent-tag no-bucketize))))))
1180
(defun ecb-update-tag-node (tag node &optional parent-tag no-bucketize)
1181
"Updates a node containing a tag."
1182
(let* ((children (ecb--semantic-tag-children-compatibility
1183
tag ecb-show-only-positioned-tags)))
1184
(tree-node-set-name node (ecb-get-tag-name tag parent-tag))
1185
(unless (eq 'function (ecb--semantic-tag-class tag))
1186
(ecb-add-tags node children tag no-bucketize)
1187
(tree-node-set-expandable
1188
node (not (eq nil (tree-node-get-children node))))
1189
;; Always expand types, maybe this should be customizable and more
1191
(if (not (eq 'type (ecb--semantic-tag-class tag)))
1192
(tree-node-set-expanded node nil)
1193
(let ((type-specifier (ecb-get-type-specifier tag)))
1194
(tree-node-set-expanded
1196
(and (tree-node-is-expandable node)
1197
(ecb-type-tag-expansion type-specifier))))))))
1200
(defun ecb-post-process-taglist (taglist)
1201
"If for current major-mode a post-process function is found in
1202
`ecb-post-process-semantic-taglist' then this function is called with
1203
TAGLIST otherwise TAGLIST is returned."
1204
(let ((fcn-list (cdr (assoc major-mode ecb-post-process-semantic-taglist))))
1205
(dolist (fcn fcn-list)
1207
(setq taglist (funcall fcn taglist))))
1208
;; at the end we apply the user-filter if there is any.
1209
(ecb-apply-user-filter-to-tags taglist)))
1211
(defun ecb-group-function-tags-with-parents (taglist)
1212
"Return a new taglist based on TAGLIST where all function-tags in
1213
TAGLIST having a parent tag are grouped together under a new faux tag
1214
for this parent-tag. The new taglist contains first all parent-less tags
1215
and then all grouped tags.
1217
This is useful for oo-programming languages where the methods of a class can
1218
be defined outside the class-definition, e.g. C++, Eieio."
1219
(ecb--semantic-adopt-external-members taglist))
1221
(defun ecb-filter-c-prototype-tags (taglist)
1222
"Filter out all prototypes.
1223
For example this is useful for editing C files which have the function
1224
prototypes defined at the top of the file and the implementations at the
1225
bottom. This means that everything appears twice in the methods buffer, but
1226
probably nobody wants to jump to the prototypes, they are only wasting space
1227
in the methods buffer.
1228
For C-header-files prototypes are never filtered out!"
1229
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Is there a better way to
1230
;; recognize a C-Header-file?
1231
(let ((header-extensions '("\\.h\\'" "\\.H\\'" "\\.HH\\'" "\\.hxx\\'" "\\.hh\\'")))
1232
(or (and (catch 'found
1233
(dolist (ext header-extensions)
1234
(if (save-match-data
1235
(string-match ext (buffer-file-name (current-buffer))))
1240
(function (lambda (x)
1241
(not (ecb--semantic-tag-get-attribute x 'prototype))))))))
1243
(defvar ecb-methods-user-filter-alist nil
1244
"The filter currently applied to the methods-buffer by the user. It can be a
1245
regexp-string, or one of the symbols 'private, 'protected or 'public or one of
1246
the tag-type-symbols mentioned in the the option `ecb-tag-display-function'.
1247
This cache is an alist where the key is the buffer-object of that buffer the
1248
filter belongs and the value is the applied filter to that buffer.")
1251
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>:
1252
;; - Fuer jede der 4 Funktionen unten ein tree-buffer-defpopup-command
1253
;; schreiben (diese mļæ½ssen tree-buffer-get-data-store verwenden!). Dabei
1254
;; auch `ecb-sources-filter und ecb-history-filter fixen!
1255
;; - Filteranzeige in der Modeline des methods-buffers
1256
;; - Smartere und besser customizable Filterung:
1257
;; + Ev. recursive absteigen - children von tags auch filtern
1258
;; + Start-level bestimmbar (z.B. erst ab dem ersten children-level beginnen
1259
;; + Oder Exclude-tag-classes customizable, z.B. Filterung bezieht sich nie
1260
;; auf types: damit wļæ½rden in Sprachen wie C++ oder Java die Klassen immer
1261
;; angezeigt, nur ihre children wļæ½rden gefiltert.
1262
;; Ohne solche Mechanismen ist die Filterung bei OO-Sprachen fast nutzlos!
1264
(defun ecb-methods-filter-by-prot (source-buffer)
1265
"Filter the Methods-buffer by protection."
1266
(let ((choice (ecb-query-string "Protection filter: "
1267
'("private" "protected" "public"))))
1268
(ecb-methods-filter-apply (intern choice) source-buffer)))
1270
(defun ecb-methods-filter-by-tag-class (source-buffer)
1271
"Filter the Methods-buffer by a tag-class."
1272
(let ((choice (ecb-query-string "Tag-class filter: "
1273
'("function" "variable" "type"
1274
"include" "rule" "section" "def"))))
1275
(ecb-methods-filter-apply (intern choice) source-buffer)))
1277
(defun ecb-methods-filter-by-regexp (source-buffer)
1278
"Filter the Methods-buffer by a regular expression."
1279
(let ((regexp-str (read-string "Insert the filter-regexp: ")))
1280
(if (> (length regexp-str) 0)
1281
(ecb-methods-filter-apply regexp-str source-buffer)
1282
(ecb-methods-filter-apply nil source-buffer))))
1284
(defun ecb-methods-filter-none (source-buffer)
1285
"Remove any filter from the Methods-buffer."
1286
(ecb-methods-filter-apply nil source-buffer))
1288
(defun ecb-apply-user-filter-to-tags (taglist)
1290
(let ((filter (cdr (assoc (current-buffer) ecb-methods-user-filter-alist))))
1296
(cond ((stringp filter)
1297
(if (string-match filter
1298
(ecb--semantic-tag-name tag))
1300
((member filter '(private protected public))
1301
(if (or (null (ecb--semantic-tag-protection tag))
1302
(equal (ecb--semantic-tag-protection tag) filter))
1305
(if (equal (ecb--semantic-tag-class tag) filter)
1309
(defun ecb-methods-filter ()
1310
"Apply a filter to the Methods-buffer to reduce the number of entries.
1311
So you get a better overlooking. There are four choices:
1312
- Filter by protection: Just insert the protection you want the Methods-buffer
1313
being filtered: private, protected or public!
1314
- Filter by regexp: Insert the filter as regular expression.
1315
- Filter by tag-class: You can filter by the tag-classes include, type,
1316
variable, function, rule, section \(chapters and sections in `info-mode'),
1317
def \(definitions in `info-mode').
1318
- No filter: This means to display all tags specified with the option
1321
Be aware that the tag-list specified by the option `ecb-show-tags' is the
1322
basis of all filters, i.e. tags which are excluded by that option will never
1323
be shown regardless of the filter type here!
1325
Such a filter is only applied to the current source-buffer, i.e. each
1326
source-buffer can have its own tag-filter."
1328
(ecb-error "This command will be offered first in future-versions of ECB!")
1329
(let ((source-buffer (if (ecb-point-in-edit-window)
1331
(or ecb-last-source-buffer
1332
(ecb-error "There is no source-file to filter!"))))
1333
(choice (ecb-query-string "Filter Methods-buffer by:"
1334
'("regexp" "protection" "tag-class" "nothing"))))
1335
(cond ((string= choice "protection")
1336
(ecb-methods-filter-by-prot source-buffer))
1337
((string= choice "tag-class")
1338
(ecb-methods-filter-by-tag-class source-buffer))
1339
((string= choice "regexp")
1340
(ecb-methods-filter-by-regexp source-buffer))
1341
(t (ecb-methods-filter-none source-buffer)))))
1344
(defun ecb-methods-filter-apply (filter source-buffer)
1345
(let ((filter-elem (assoc source-buffer ecb-methods-user-filter-alist)))
1347
(setcdr filter-elem filter)
1349
(setq ecb-methods-user-filter-alist
1350
(cons (cons source-buffer filter)
1351
ecb-methods-user-filter-alist)))))
1352
(if (get-buffer-window source-buffer ecb-frame)
1353
(save-selected-window
1354
(select-window (get-buffer-window source-buffer ecb-frame))
1355
(ecb-rebuild-methods-buffer))))
1358
(defun ecb-add-tags (node tags &optional parent-tag no-bucketize)
1359
"If NO-BUCKETIZE is not nil then TAGS will not bucketized by
1360
`ecb--semantic-bucketize' but must already been bucketized!"
1361
(ecb-add-tag-buckets node parent-tag
1364
(ecb--semantic-bucketize tags))
1368
(defun ecb-access-order (access)
1370
((eq 'public access) 0)
1371
((eq 'protected access) 1)
1372
((eq 'private access) 3)
1376
(defun ecb-sort-tags (sort-method tags)
1379
(sort tags (function (lambda (a b)
1380
(string< (ecb--semantic-tag-name a)
1381
(ecb--semantic-tag-name b)))))))
1382
(if (eq 'access sort-method)
1386
(< (ecb-access-order (ecb--semantic-tag-protection a))
1387
(ecb-access-order (ecb--semantic-tag-protection b))))))
1392
(defun ecb-add-tag-buckets (node parent-tag buckets &optional no-bucketize)
1393
"Creates and adds tag nodes to the given node.
1394
The PARENT-TAG is propagated to the functions `ecb-add-tag-bucket' and
1395
`ecb-find-add-tag-bucket'."
1396
(setq buckets (cons nil buckets))
1397
(dolist (tag-display ecb-show-tags)
1398
(let* ((type (car tag-display))
1399
(display (cadr tag-display))
1400
(sort-method (caddr tag-display)))
1403
(when (and parent-tag
1404
(eq 'type (ecb--semantic-tag-class parent-tag)))
1405
(let ((parents (ecb-get-tag-parents parent-tag)))
1407
(let ((node (ecb-create-node node display (ecb-format-bucket-name "Parents") nil 1)))
1409
(dolist (parent (if sort-method
1410
(sort parents 'string<) parents))
1411
(tree-node-new (if ecb-font-lock-tags
1412
(ecb--semantic--format-colorize-text parent 'type)
1415
(if ecb-truncate-long-names 'end)))))))))
1416
(t (ecb-find-add-tag-bucket node type display sort-method buckets
1417
parent-tag no-bucketize)))))
1418
(let ((type-display (ecb-get-tag-type-display t)))
1419
(dolist (bucket buckets)
1420
(ecb-add-tag-bucket node bucket (cadr type-display)
1421
(caddr type-display) parent-tag no-bucketize))))
1424
(defun ecb-update-after-partial-reparse (updated-tags)
1425
"Updates the method buffer and all internal ECB-caches after a partial
1426
semantic-reparse. This function is added to the hook
1427
`semantic-after-partial-cache-change-hook'."
1428
;; TODO: Currently we get simply the whole cache from semantic (already up
1429
;; to date at this time!) and then we rebuild the whole tree-buffer with
1430
;; this cache-contents. This is for great sources slow. We should implement
1431
;; a mechanism where only the UPDATED-TAGS are used and only this ones are
1432
;; updated. But for this we need also a tree-buffer-update which can update
1433
;; single nodes without refreshing the whole tree-buffer like now.
1434
(ecb-rebuild-methods-buffer-with-tagcache (ecb--semantic-bovinate-toplevel t)))
1437
(defun ecb-semantic-active-for-file (filename)
1438
"Return not nil if FILENAME is already displayed in a buffer and if semantic
1439
is active for this buffer."
1440
(and (get-file-buffer filename)
1442
(set-buffer (get-file-buffer filename))
1443
(ecb--semantic-active-p))))
1446
(defun ecb-update-methods-after-saving ()
1447
"Updates the methods-buffer after saving if this option is turned on and if
1448
current-buffer is saved."
1449
(when (and (equal (selected-frame) ecb-frame)
1450
ecb-auto-update-methods-after-save
1451
ecb-last-edit-window-with-point
1452
;; this prevents updating the method buffer after saving a not
1453
;; current buffer (e.g. with `save-some-buffers'), because this
1454
;; would result in displaying a method-buffer not belonging to the
1455
;; current source-buffer.
1456
(equal (current-buffer)
1457
(window-buffer ecb-last-edit-window-with-point)))
1458
(ecb-select-source-file ecb-path-selected-source)
1459
(ecb-rebuild-methods-buffer)))
1462
(defvar ecb-method-buffer-needs-rebuild t
1463
"This variable is only set and evaluated by the functions
1464
`ecb-update-methods-buffer--internal' and
1465
`ecb-rebuild-methods-buffer-with-tagcache'!")
1468
(defun ecb-update-methods-buffer--internal (&optional scroll-to-top
1469
rebuild-non-semantic)
1470
"Updates the methods buffer with the current buffer. The only thing what
1471
must be done is to start the toplevel parsing of semantic, because the rest is
1472
done by `ecb-rebuild-methods-buffer-with-tagcache' because this function is in
1473
the `semantic-after-toplevel-cache-change-hook'.
1474
If optional argument SCROLL-TO-TOP is non nil then the method-buffer is
1475
displayed with window-start and point at beginning of buffer.
1477
If second optional argument REBUILD-NON-SEMANTIC is not nil then non-semantic
1478
sources are forced to be rescanned and reparsed by
1479
`ecb-rebuild-methods-buffer-with-tagcache'. The function
1480
`ecb-rebuild-methods-buffer-for-non-semantic' is the only one settings this
1481
argument to not nil!"
1482
(when (and (equal (selected-frame) ecb-frame)
1483
(get-buffer-window ecb-methods-buffer-name))
1484
;; Set here `ecb-method-buffer-needs-rebuild' to t so we can see below if
1485
;; `ecb-rebuild-methods-buffer-with-tagcache' was called auto. after
1486
;; `ecb--semantic-bovinate-toplevel'.
1487
(setq ecb-method-buffer-needs-rebuild t)
1489
(let ((current-tagcache (and (ecb--semantic-active-p)
1490
;; if we manually bovinate the buffer we
1491
;; must widen the source to get all tags.
1492
;; But here we must not use the adviced
1493
;; version of widen!
1496
(ecb-with-original-basic-functions
1498
(ecb--semantic-bovinate-toplevel t))))))
1499
;; If the `ecb--semantic-bovinate-toplevel' has done no reparsing but only
1500
;; used itļæ½s still valid `semantic-toplevel-bovine-cache' then neither
1501
;; the hooks of `semantic-after-toplevel-cache-change-hook' nor the
1502
;; hooks in `semantic-after-partial-cache-change-hook' are evaluated and
1503
;; therefore `ecb-rebuild-methods-buffer-with-tagcache' was not
1504
;; called. Therefore we call it here manually.
1505
;; `ecb-rebuild-methods-buffer-with-tagcache' is the only function
1506
;; which sets `ecb-method-buffer-needs-rebuild' to nil to signalize that
1507
;; a "manually" rebuild of the method buffer is not necessary.
1509
;; `ecb-update-methods-buffer--internal' is called by
1510
;; `ecb-current-buffer-sync' and `ecb-set-selected-source' (depending on
1511
;; the method switching to current buffer) which both are called also
1512
;; for buffers which are not setup for semantic (e.g. text-,
1513
;; tex-buffers). current-tagcache is nil for such buffers so we call
1514
;; the rebuilding of the method buffer with a nil cache and therefore
1515
;; the method-buffer will be cleared out for such buffers. This is what
1516
;; we want! For further explanation see
1517
;; `ecb-rebuild-methods-buffer-with-tagcache'...
1518
(if ecb-method-buffer-needs-rebuild
1519
;; the hook was not called therefore here manually
1520
(ecb-rebuild-methods-buffer-with-tagcache
1522
(ecb--semantic-active-p)
1523
nil rebuild-non-semantic)))
1525
(save-selected-window
1526
(ecb-exec-in-methods-window
1527
(tree-buffer-scroll (point-min) (point-min)))))))
1530
(defvar ecb-tag-tree-cache nil
1531
"This is the tag-tree-cache for already opened file-buffers. The cache is
1532
a list of cons-cells where the car is the name of the source and the cdr is
1533
the current tag-tree for this source. The cache contains exactly one element
1534
for a certain source.")
1535
(setq ecb-tag-tree-cache nil)
1538
(defun ecb-clear-tag-tree-cache (&optional source-file-name)
1539
"Clears wither the whole tag-tree-cache \(SOURCE-FILE-NAME is nil) or
1540
removes only the tag-tree for SOURCE-FILE-NAME from the cache."
1541
(if (not source-file-name)
1542
(setq ecb-tag-tree-cache nil)
1543
(setq ecb-tag-tree-cache
1544
(adelete 'ecb-tag-tree-cache source-file-name))))
1548
(defun ecb-rebuild-methods-buffer-with-tagcache (updated-cache
1549
&optional no-update-semantic
1551
non-semantic-rebuild)
1552
"Rebuilds the ECB-method buffer after toplevel-parsing by semantic. This
1553
function is added to the hook `semantic-after-toplevel-cache-change-hook'.
1555
If NO-UPDATE-SEMANTIC is not nil then the tags of the ECB-methods-buffer are
1556
not updated with UPDATED-CACHE but the method-buffer is rebuild with these
1557
tags ECB has already cached in it `ecb-tag-tree-cache'. Only relevant for
1558
semantic-parsed sources!
1560
If FORCE-NIL-CACHE is not nil then the method-buffer is even rebuild if
1561
UPDATED-CACHE is nil. Normally a nil cache is ignored if it belongs to a
1562
buffer witch is setup for semantic-parsing; only nil caches for non-semantic
1563
buffers \(like plain text-buffers) are used for updating the method-buffers.
1564
With FORCE-NIL-CACHE the method-buffer is updated with a nil cache too, i.e.
1567
IF NON-SEMANTIC-REBUILD is not nil then current non-semantic-source is forced
1568
to be rescanned/reparsed and therefore the Method-buffer will be rebuild too."
1569
;; The most important function for (re)building the Method-buffer
1570
(when (and ecb-minor-mode
1571
(equal (selected-frame) ecb-frame)
1572
(get-buffer-window ecb-methods-buffer-name)
1573
(buffer-file-name (current-buffer))
1574
;; The functions of the hook
1575
;; `semantic-after-toplevel-cache-change-hook' are also called
1576
;; after clearing the cache to set the cache to nil if a buffer
1577
;; is parsed which has no tags. But buffers with no tags are
1578
;; really seldom so cause of better performance here we do not
1579
;; want rebuilding the method-buffer if the cache is nil but the
1580
;; current buffer is set up for semantic-parsing, because the
1581
;; real rebuild should be done after the cache is filled again.
1582
;; If this hook is called "manually" by
1583
;; `ecb-update-methods-buffer--internal' then we do an update
1584
;; also for a nil cache if the buffer is not setup for semantic
1585
;; (like text-buffers or non-semantic-sources) so we can either
1586
;; clear out the method-buffer or fill it with parsing
1587
;; information of non-semantic-sources!
1589
(not (ecb--semantic-active-p))
1592
;; no-update-semantic has to be nil for non-semantic-sources!
1593
(if (not (ecb--semantic-active-p)) (setq no-update-semantic nil))
1595
;; the following cache-mechanism MUST use the (buffer-file-name
1596
;; (current-buffer)) instead of ecb-path-selected-source because in case
1597
;; of opening a buffer not via directory-window but via the
1598
;; standard-mechanism of Emacs this function is called via hook BEFORE
1599
;; ecb-path-selected-source is set currently by the synchronize-mechanism
1601
;; Also if we create a new cache-element for the tag-tree we MUST look
1602
;; if in the cache is already an element with this key and if we MUST
1603
;; update this cache-element instead of always adding a new one to the
1604
;; cache. Otherwise we would get more than one cache-element for the same
1607
(let* ((norm-buffer-file-name (ecb-fix-filename
1608
(buffer-file-name (current-buffer))))
1609
(cache (assoc norm-buffer-file-name ecb-tag-tree-cache))
1610
(curr-buff (current-buffer))
1611
(curr-major-mode major-mode)
1612
new-tree non-semantic-handling)
1615
(dolist (a-tag updated-cache)
1616
(ecb-semantic-assert-valid-tag a-tag)))
1618
;; here we process non-semantic buffers if the user wants this. But only
1619
;; if either non-semantic-rebuild is true or no cache exists.
1620
(when (and ecb-process-non-semantic-files
1621
(null updated-cache)
1622
(not (ecb--semantic-active-p))
1623
(buffer-file-name (current-buffer))
1624
(or non-semantic-rebuild (null cache)))
1625
(setq updated-cache (ignore-errors
1626
(ecb-get-tags-for-non-semantic-files)))
1627
(setq non-semantic-handling
1628
(if updated-cache 'parsed 'parsed-failed)))
1630
;; Now non-semantic-handling is only nil either for semantic-sources or
1631
;; for non-semantic-sources if already a cache exists and
1632
;; non-semantic-rebuild is nil (i.e. no rescan and rebuild is
1633
;; necessary). A not-nil value is only possible for non-semantic-sources
1634
;; and is then either 'parsed in case the parsing was successful or
1637
;; We always make a new tag-tree with updated-cache except for
1638
;; - semantic-sources if no-update-semantic is true and already a
1639
;; cache exists. This means this function is NOT called by
1640
;; `semantic-after-toplevel-cache-change-hook'.
1641
;; - non-semantic-sources if non-semantic-handling is false, because
1642
;; then no rescan has been performed and updated-cache contains
1643
;; nothing; see comment above.
1644
(unless (or (and no-update-semantic cache) ;; for semantic-sources
1645
(and (not (ecb--semantic-active-p)) ;; for non-semantic-sources
1646
(not non-semantic-handling)
1647
;; for clearing out non-semantic-buffers too after
1648
;; killing one; see `ecb-kill-buffer-hook'.
1649
(not force-nil-cache)))
1650
(setq new-tree (tree-node-new-root))
1651
(if non-semantic-handling
1652
(if (equal non-semantic-handling 'parsed)
1653
(ecb-create-non-semantic-tree new-tree updated-cache))
1654
(ecb-add-tags new-tree (ecb-post-process-taglist updated-cache)))
1656
(setcdr cache new-tree)
1657
(setq cache (cons norm-buffer-file-name new-tree))
1658
(setq ecb-tag-tree-cache (cons cache ecb-tag-tree-cache))))
1660
;; Now we either update the method-buffer with a newly created
1661
;; tag-tree or with the tag-tree from the cache (with all its
1662
;; existing expansions). This work because we store in the cache not a
1663
;; copy of the tree but the tree itself, so every expansion of nodes in
1664
;; the tree (e.g. by clicking onto the expand-button) expands the nodes
1665
;; in the cache!! Cause of this storing the buffer-string too in the
1666
;; cache can not work because the buffer-string is a "copy" of the
1667
;; tree-buffer and therefore the cached buffer-string can not be updated
1670
(ecb-buffer-select ecb-methods-buffer-name)
1671
;; we store in the tree-buffer the buffer and the major-mode for which
1672
;; the tree-buffer has been build
1673
(tree-buffer-set-data-store (cons curr-buff curr-major-mode))
1674
(tree-buffer-set-root (cdr cache))
1675
(setq ecb-methods-root-node (cdr cache))
1676
(tree-buffer-update)))
1678
;; Klaus Berndl <klaus.berndl@sdm.de>: after a full reparse all overlays
1679
;; stored in the dnodes of the navigation-list now are invalid. Therefore
1680
;; we have changed the implementation of ecb-navigate.el from storing
1681
;; whole tags to storing buffer and start- and end-markers!
1683
(ecb-mode-line-format)
1685
;; signalize that the rebuild has already be done
1686
(setq ecb-method-buffer-needs-rebuild nil)))
1688
(defun ecb-save-without-auto-update-methods ()
1689
(let ((ecb-auto-update-methods-after-save nil))
1693
(defun ecb-rebuild-methods-buffer-for-non-semantic ()
1694
"Rebuild the ECB-method-buffer for current source-file of the edit-window.
1695
This function does nothing if point stays not in an edit-window of the
1696
ECB-frame or if current source-file is supported by semantic!
1698
Before rebuilding the Methods-buffer the hook
1699
`ecb-rebuild-non-semantic-methods-before-hook' is called. The Method-buffer is
1700
only rebuild if either the hook contains no function \(the default) or if no
1701
function of this hook returns nil! See `run-hook-with-args-until-failure' for
1702
description how these function are pressed.
1704
The option `ecb-auto-save-before-etags-methods-rebuild' is checked before
1705
rescanning the source-buffer and rebuilding the methods-buffer.
1707
This function is called by the command `ecb-rebuild-methods-buffer'."
1708
(when (and ecb-minor-mode
1709
(equal (selected-frame) ecb-frame)
1710
(not (ecb--semantic-active-p))
1711
(not (member major-mode ecb-non-semantic-exclude-modes))
1712
(ecb-point-in-edit-window))
1713
(when (run-hook-with-args-until-failure
1714
'ecb-rebuild-non-semantic-methods-before-hook
1716
;; For etags supported non-semantic-sources we maybe have to save the
1718
(when (and (buffer-modified-p)
1719
(not (and (boundp 'imenu--index-alist)
1720
imenu--index-alist))
1721
(or (equal ecb-auto-save-before-etags-methods-rebuild t)
1723
ecb-auto-save-before-etags-methods-rebuild)))
1724
;; to prevent files from being parsed too often we need to temp.
1725
;; switch off the auto-method-updating-after-save feature
1726
(ecb-save-without-auto-update-methods))
1727
(ecb-update-methods-buffer--internal nil t))))
1730
(defun ecb-rebuild-methods-buffer-for-semantic ()
1731
"Rebuild the ECB-method-buffer for current source-file of the edit-window.
1732
This function does nothing if point stays not in an edit-window of the
1733
ECB-frame or if current source-file is not supported by semantic!"
1734
(when (and ecb-minor-mode
1735
(equal (selected-frame) ecb-frame)
1736
(ecb--semantic-active-p)
1737
(ecb-point-in-edit-window))
1738
;; to force a really complete rebuild we must completely clear the
1739
;; semantic cache for semantic-files.
1740
(ecb--semantic-clear-toplevel-cache)
1741
(ecb-update-methods-buffer--internal)))
1744
(defun ecb-rebuild-methods-buffer ()
1745
"Updates the methods buffer with the current source-buffer.
1746
The complete previous parser-information is deleted before, means no
1747
semantic-cache is used! Point must stay in an edit-window otherwise nothing is
1748
done. This method is merely needed for semantic parsed buffers if semantic
1749
parses not the whole buffer because it reaches a not parse-able code or for
1750
buffers not supported by semantic but by imenu or etags.
1752
Examples when a call to this function can be necessary:
1754
+ If an elisp-file is parsed which contains in the middle a defun X where the
1755
closing ) is missing then semantic parses only until this defun X is reached
1756
and you will get an incomplete ECB-method buffer. In such a case you must
1757
complete the defun X and then call this function to completely reparse the
1758
elisp-file and rebuild the ECB method buffer!
1760
+ For not semantic supported buffers which can be parsed by imenu or etags
1761
\(see `ecb-process-non-semantic-files') because for these buffers there is
1762
no built-in auto-rebuild mechanism. For these buffers this command calls
1763
`ecb-rebuild-methods-buffer-for-non-semantic'.
1765
For non-semantic-sources supported by etags the option
1766
`ecb-auto-save-before-etags-methods-rebuild' is checked before rescanning the
1767
source-buffer and rebuilding the methods-buffer.
1769
If point is in one of the ecb-windows or in the compile-window then this
1770
command rebuids the methods-buffer with the contents of the source-buffer the
1771
last selected edit-window."
1773
(save-selected-window
1774
(when (not (ecb-point-in-edit-window))
1775
(let ((ecb-mouse-click-destination 'last-point))
1776
(ecb-select-edit-window)))
1777
(if (ecb--semantic-active-p)
1778
(ecb-rebuild-methods-buffer-for-semantic)
1779
(ecb-rebuild-methods-buffer-for-non-semantic))))
1782
(defvar ecb-auto-expand-tag-tree-old 'expand-spec)
1784
(defun ecb-toggle-auto-expand-tag-tree (&optional arg)
1785
"Toggle auto expanding of the ECB-methods-buffer.
1786
With prefix argument ARG, switch on if positive, otherwise switch off. If the
1787
effect is that auto-expanding is switched off then the current value of
1788
`ecb-auto-expand-tag-tree' is saved so it can be used for the next switch on
1791
(let* ((new-value (if (null arg)
1792
(if ecb-auto-expand-tag-tree
1794
(setq ecb-auto-expand-tag-tree-old
1795
ecb-auto-expand-tag-tree)
1797
ecb-auto-expand-tag-tree-old)
1798
(if (<= (prefix-numeric-value arg) 0)
1800
(if ecb-auto-expand-tag-tree
1801
(setq ecb-auto-expand-tag-tree-old
1802
ecb-auto-expand-tag-tree))
1804
(or ecb-auto-expand-tag-tree
1805
ecb-auto-expand-tag-tree-old)))))
1806
(setq ecb-auto-expand-tag-tree new-value)
1807
(message "Auto. expanding of the methods-buffer is switched %s \(Value: %s\)."
1808
(if new-value "on" "off")
1811
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Hier auch was mļæ½glich mit
1812
;; (ecb-exec-in-methods-window
1813
;; (tree-buffer-find-node-data curr-tag))
1815
(defun ecb-tag-sync-test (&optional force)
1816
(when (and ecb-minor-mode
1817
;; we do not use here `ecb-point-in-ecb-window' because this
1818
;; would slow down Emacs dramatically when tag-synchronization is
1819
;; done via post-command-hook and not via an idle-timer.
1820
(not (ecb-point-in-tree-buffer))
1821
(not (ecb-point-in-compile-window)))
1822
(when ecb-highlight-tag-with-point
1823
(let* ((tagstack (reverse (ecb--semantic-find-tag-by-overlay)))
1824
(curr-tag (car tagstack))
1825
(next-tag (car (cdr tagstack)))
1827
(if (and (equal (ecb--semantic-tag-class curr-tag) 'variable)
1828
(equal (ecb--semantic-tag-class next-tag) 'function)
1829
(member curr-tag (ecb--semantic-tag-function-arguments next-tag)))
1830
(setq curr-tag next-tag))
1831
(when (or force (not (equal ecb-selected-tag curr-tag)))
1832
(setq ecb-selected-tag curr-tag)
1833
(save-selected-window
1834
(ecb-exec-in-methods-window
1835
(or (tree-buffer-highlight-node-data
1836
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight))
1837
;; The node representing CURR-TAG could not be highlighted be
1838
;; `tree-buffer-highlight-node-data' - probably it is
1839
;; invisible. Let's try to make visible and then highlighting
1841
(when (and curr-tag ecb-auto-expand-tag-tree
1842
(or (equal ecb-auto-expand-tag-tree 'all)
1843
(member (ecb--semantic-tag-class curr-tag)
1844
(ecb-normalize-expand-spec
1845
ecb-methods-nodes-expand-spec))))
1846
(ecb-expand-methods-nodes-internal
1848
(equal ecb-auto-expand-tag-tree 'all))
1849
(tree-buffer-highlight-node-data
1850
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight))
1853
(defun ecb-tag-sync (&optional force)
1854
(when (and ecb-minor-mode
1855
;; we do not use here `ecb-point-in-ecb-window' because this
1856
;; would slow down Emacs dramatically when tag-synchronization is
1857
;; done via post-command-hook and not via an idle-timer.
1858
(not (ecb-point-in-tree-buffer))
1859
(not (ecb-point-in-compile-window)))
1860
(when ecb-highlight-tag-with-point
1861
(let* ((tagstack (reverse (ecb--semantic-find-tag-by-overlay)))
1862
(curr-tag (car tagstack))
1863
(next-tag (car (cdr tagstack)))
1865
(if (and (equal (ecb--semantic-tag-class curr-tag) 'variable)
1866
(equal (ecb--semantic-tag-class next-tag) 'function)
1867
(member curr-tag (ecb--semantic-tag-function-arguments next-tag)))
1868
(setq curr-tag next-tag))
1869
(when (or force (not (equal ecb-selected-tag curr-tag)))
1870
(setq ecb-selected-tag curr-tag)
1871
(save-selected-window
1872
(ecb-exec-in-methods-window
1873
(or (tree-buffer-highlight-node-data
1874
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight))
1875
;; The node representing CURR-TAG could not be highlighted be
1876
;; `tree-buffer-highlight-node-data' - probably it is
1877
;; invisible. Let's try to make visible and then highlighting
1879
(when (and curr-tag ecb-auto-expand-tag-tree
1880
(or (equal ecb-auto-expand-tag-tree 'all)
1881
(member (ecb--semantic-tag-class curr-tag)
1882
(ecb-normalize-expand-spec
1883
ecb-methods-nodes-expand-spec))))
1884
(ecb-expand-methods-nodes-internal
1886
(equal ecb-auto-expand-tag-tree 'all))
1887
(tree-buffer-highlight-node-data
1888
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight))
1891
(defun ecb-find-file-and-display (filename other-edit-window)
1892
"Finds the file in the correct window. What the correct window is depends on
1893
the setting in `ecb-mouse-click-destination' and the value of
1894
OTHER-EDIT-WINDOW \(for this see `ecb-combine-ecb-button/edit-win-nr')."
1895
(select-window (ecb-get-edit-window other-edit-window))
1896
(ecb-nav-save-current)
1897
(ecb-with-original-functions
1898
(find-file filename))
1899
(ecb-nav-add-item (ecb-nav-file-history-item-new)))
1902
(defun ecb-string-make-singular (string)
1903
(if (equal (aref string (1- (length string))) ?s)
1904
(substring string 0 (1- (length string)))
1908
(defun ecb-methods-node-get-semantic-type (node symbol->name-assoc-list)
1909
(cond ((= 1 (tree-node-get-type node))
1912
(if (string-match (concat (regexp-quote (nth 0 ecb-bucket-node-display))
1914
(regexp-quote (nth 1 ecb-bucket-node-display)))
1915
(tree-node-get-name node))
1916
(match-string 1 (tree-node-get-name node))))))
1917
(if (stringp bucket-name)
1918
(or (car (delete nil (mapcar (function (lambda (elem)
1919
(if (string= (cdr elem)
1922
symbol->name-assoc-list)))
1923
;; This is a little hack for bucket-names not defined in
1924
;; symbol->name-assoc-list: First we strip a trailing 's'
1925
;; if there is any to be consistent with the singular names
1926
;; of the cars of symbol->name-assoc-list. Then we downcase
1927
;; the bucket-name and convert it to a symbol. This is done
1928
;; for example for the ECB created bucket-name "Parents"!
1929
(intern (downcase (ecb-string-make-singular bucket-name)))))))
1930
((= 0 (tree-node-get-type node))
1931
(ignore-errors (ecb--semantic-tag-class (tree-node-get-data node))))
1935
(defun ecb-expand-methods-nodes (&optional force-all)
1936
"Set the expand level of the nodes in the ECB-methods-buffer.
1937
This command asks in the minibuffer for an indentation level LEVEL. With this
1938
LEVEL you can precisely specify which level of nodes should be expanded. LEVEL
1939
means the indentation-level of the nodes.
1941
A LEVEL value X means that all nodes with an indentation-level <= X are
1942
expanded and all other are collapsed. A negative LEVEL value means all visible
1943
nodes are collapsed.
1945
Nodes which are not indented have indentation-level 0!
1947
Which node-types are expanded \(rsp. collapsed) by this command depends on
1948
the options `ecb-methods-nodes-expand-spec' and
1949
`ecb-methods-nodes-collapse-spec'! With optional argument FORCE-ALL all tags
1950
will be expanded/collapsed regardless of the values of these options.
1953
- LEVEL = 0 expands only nodes which have no indentation itself.
1954
- LEVEL = 2 expands nodes which are either not indented or indented once or
1956
- LEVEL ~ 10 should normally expand all nodes unless there are nodes which
1957
are indented deeper than 10.
1959
Note 1: This command switches off auto. expanding of the method-buffer if
1960
`ecb-expand-methods-switch-off-auto-expand' is not nil. But it can be switched
1961
on again quickly with `ecb-toggle-auto-expand-tag-tree' or \[C-c . a].
1963
Note 2: All this is only valid for file-types parsed by semantic. For other
1964
file types which are parsed by imenu or etags \(see
1965
`ecb-process-non-semantic-files') FORCE-ALL is always true!"
1967
(let* ((first-node (save-excursion
1968
(goto-char (point-min))
1969
(tree-buffer-get-node-at-point)))
1970
(level (ecb-read-number
1971
"Expand indentation-level: "
1973
(tree-node-is-expandable first-node)
1974
(tree-node-is-expanded first-node))
1977
;; here we should switch off autom. expanding tag-tree because otherwise
1978
;; our expanding to a certain level takes no effect because if the current
1979
;; tag in the edit-buffer would be invisible afterwards (after the
1980
;; expanding/collapsing) then immediately the tag would be autom.
1981
;; expanded to max level...
1982
(when ecb-expand-methods-switch-off-auto-expand
1983
(ecb-toggle-auto-expand-tag-tree -1))
1984
(ecb-expand-methods-nodes-internal level force-all t)))
1987
(defun ecb-expand-methods-nodes-internal (level &optional force-all resync-tag)
1988
"Set the expand level of the nodes in the ECB-methods-buffer.
1990
For description of LEVEL and FORCE-ALL see `ecb-expand-methods-nodes'.
1992
If RESYNC-TAG is not nil then after expanding/collapsing the methods-buffer
1993
is resynced to the current tag of the edit-window.
1995
Note: All this is only valid for file-types parsed by semantic. For other file
1996
types which are parsed by imenu or etags \(see
1997
`ecb-process-non-semantic-files') FORCE-ALL is always true!"
1998
(let ((symbol->name-assoc-list
1999
;; if possible we get the local semantic-symbol->name-assoc-list of
2000
;; the source-buffer.
2003
(set-buffer (get-file-buffer ecb-path-selected-source))
2004
;; for non-semantic buffers we set force-all always to t
2005
(setq force-all (not (ecb--semantic-active-p)))
2006
(ecb--semantic-symbol->name-assoc-list)))
2007
(ecb--semantic-symbol->name-assoc-list))))
2008
(save-selected-window
2009
(ecb-exec-in-methods-window
2010
(let ( ;; normalizing the elements of `ecb-methods-nodes-expand-spec'
2011
;; and `ecb-methods-nodes-collapse-spec'.
2012
(norm-expand-types (ecb-normalize-expand-spec
2013
ecb-methods-nodes-expand-spec))
2014
(norm-collapse-types (ecb-normalize-expand-spec
2015
ecb-methods-nodes-collapse-spec)))
2016
(tree-buffer-expand-nodes
2018
(and (not force-all)
2019
(function (lambda (node current-level)
2020
(or (equal norm-expand-types 'all)
2021
(member (ecb-methods-node-get-semantic-type
2022
node symbol->name-assoc-list)
2023
norm-expand-types)))))
2024
(and (not force-all)
2025
(function (lambda (node current-level)
2026
(or (equal norm-collapse-types 'all)
2027
(member (ecb-methods-node-get-semantic-type
2028
node symbol->name-assoc-list)
2029
norm-collapse-types))))))
2030
(tree-buffer-scroll (point-min) (point-min)))))
2032
;; we want resync the new method-buffer to the current tag in the
2034
(if resync-tag (ecb-tag-sync 'force))))
2037
(defun ecb-normalize-expand-spec (spec)
2038
(if (equal 'all spec)
2040
(mapcar (function (lambda (elem)
2042
(downcase (ecb-string-make-singular
2043
(symbol-name elem))))))
2046
;; semantic 1.X does not have this
2047
(silentcomp-defvar semanticdb-search-system-databases)
2049
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Maybe an option for searching
2051
(defun ecb-semanticdb-get-type-definition-list (typename &optional
2053
"Search with semanticdb for the definition of the type with name TYPENAME.
2054
The value of SEARCH-SYSTEM-DBS is propagated to the semanticdb variable
2055
`semanticdb-search-system-databases'. Return-value is an alist where each
2056
element represents a found location for TYPENAME. The car of an element is the
2057
full filename and the cdr is the tag in this file. If no type-definition can
2058
be found or if the semanticdb is not active then nil is returned."
2059
(when (and (featurep 'semanticdb) (ecb--semanticdb-minor-mode-p))
2060
(if (not ecb-semantic-2-loaded)
2061
;; With semantic 1.X we just run a very simplified database search.
2062
(let ((search-result (ecb--semanticdb-find-tags-by-name typename)))
2064
(list (cons (ecb--semanticdb-full-filename (caar search-result))
2065
(cdar search-result)))))
2066
;; With semantic 2.X we do a full featured database-search.
2067
(let* ((semanticdb-search-system-databases search-system-dbs)
2068
(search-result (ecb--semanticdb-find-tags-by-name typename))
2069
(result-tags (and search-result
2070
(ecb--semanticdb-strip-find-results search-result)))
2071
(type-tag-numbers nil))
2072
(when (and result-tags
2074
(= (length result-tags)
2075
(ecb--semanticdb-find-result-length search-result)))
2076
;; First we check which tags in the stripped search-result
2077
;; (result-tags) are types with positions (means associated with a
2078
;; file) and collect their sequence-positions in type-tag-numbers.
2079
(dotimes (i (length result-tags))
2080
(if (and (equal (ecb--semantic-tag-class (nth i result-tags))
2082
(ecb--semantic-tag-with-position-p (nth i result-tags)))
2083
(setq type-tag-numbers
2084
(cons i type-tag-numbers))))
2085
(setq type-tag-numbers (nreverse type-tag-numbers))
2086
;; Now we get for each element in type-tag-numbers the related
2087
;; filename (where the tag is defined) and collect them in an alist
2088
;; where each element is a cons-cell where car is the filename and
2089
;; cdr is the tag in this file. Especially with scoped languages
2090
;; like C++ or Java a type with the same name can be defined in more
2091
;; than one file - each of these files belonging to another
2094
(mapcar (function (lambda (n)
2095
(let ((r (ecb--semanticdb-find-result-nth
2099
(file-readable-p (cdr r)))
2100
(cons (cdr r) (car r))))))
2101
type-tag-numbers)))))))
2103
(defun ecb-semanticdb-get-type-definition (typename &optional
2105
"Runs `ecb-semanticdb-get-type-definition-list' for TYPENAME and
2106
SEARCH-SYSTEM-DBS and return exactly one type-definition cons-cell where car
2107
is a full filename and cdr is a tag for TYPENAME. "
2108
(let ((type-definition-alist (ecb-semanticdb-get-type-definition-list
2109
typename search-system-dbs)))
2110
(when type-definition-alist
2111
;; if we got more than one file for TYPENAME then the user has to
2113
(if (> (length type-definition-alist) 1)
2114
(assoc (ecb-offer-choices "Select a definition-file: "
2115
(mapcar #'car type-definition-alist))
2116
type-definition-alist)
2117
(car type-definition-alist)))))
2119
(defun ecb-method-clicked (node ecb-button edit-window-nr shift-mode
2120
&optional no-post-action additional-post-action-list)
2121
"Handle clicking onto NODE in the methods-buffer. ECB-BUTTON can be 1, 2 or
2122
3. If 3 then EDIT-WINDOW-NR contains the number of the edit-window the NODE
2123
should be displayed. For 1 and 2 the value of EDIT-WINDOW-NR is ignored."
2125
(ecb-mouse-over-method-node node nil nil 'force))
2126
(let ((data (tree-node-get-data node))
2127
(type (tree-node-get-type node))
2128
(filename ecb-path-selected-source)
2130
;; Klaus Berndl <klaus.berndl@sdm.de>: We must highlight the tag
2131
(tree-buffer-highlight-node-data data)
2136
;; If we have a virtual faux-group type-tag then we try to find it via
2138
(when (ecb-faux-group-tag-p tag)
2139
(set-buffer (get-file-buffer ecb-path-selected-source))
2140
(let ((faux-group (ecb-semanticdb-get-type-definition
2141
(ecb--semantic-tag-name data))))
2143
(setq tag (cdr faux-group))
2144
(setq filename (car faux-group))))))
2145
;; Type 1 = a title of a group
2146
;; Just expand/collapse the node
2148
(tree-node-toggle-expanded node)
2149
;; Update the tree-buffer with optimized display of NODE
2150
(tree-buffer-update node))
2151
;; Type 2 = a tag name for a tag not defined in current buffer; e.g.
2152
;; parent or include tags can be such tags!
2153
;; Try to find the tag
2155
(set-buffer (get-file-buffer ecb-path-selected-source))
2156
;; Try to find source using JDE
2157
(setq found (ecb-jde-show-class-source data))
2158
;; Try to find source using Semantic DB
2160
(let ((parent (ecb-semanticdb-get-type-definition data)))
2162
(setq tag (cdr parent))
2163
(setq filename (car parent))))))
2165
(when (and tag (not found))
2166
(ecb-semantic-assert-valid-tag tag)
2167
(if (eq 'include (ecb--semantic-tag-class tag))
2169
(set-buffer (get-file-buffer ecb-path-selected-source))
2170
(let ((file (ecb--semantic-dependency-tag-file tag)))
2171
(when (and file (file-exists-p file))
2172
(ecb-find-file-and-display
2173
file (ecb-combine-ecb-button/edit-win-nr ecb-button edit-window-nr)))))
2174
(ecb-jump-to-tag filename
2176
(ecb-get-edit-window
2177
(ecb-combine-ecb-button/edit-win-nr
2178
ecb-button edit-window-nr))
2181
(not (member 'ecb-tag-visit-narrow-tag
2182
additional-post-action-list)))
2183
(cons 'ecb-tag-visit-narrow-tag
2184
additional-post-action-list)
2185
additional-post-action-list))))))
2188
(defun ecb-tag-visit-smart-tag-start (tag)
2189
"Go to the real tag-name of TAG in a somehow smart way.
2190
This is especially needed for languages like c++ where a often used style is
2193
ClassX::methodM\(arg1...)
2197
Here we want to jump to the line \"ClassX::...\" and not to line \"void\".
2200
(goto-char (ecb-semantic-tag-start tag))
2202
;; We must bind the search to the max. of either the end-of-line-pos or the
2203
;; tag-end, because in some languages the tag-name displayed in the
2204
;; Methods-buffer and returned by the parsing engine can not be found in the
2205
;; source-buffer. Perl is an example, because here imenu returns tag-names
2206
;; like <package>::<function> (e.g. bigfloat::norm) but in the source buffer
2207
;; only "sub <function>" (e.g. "sub norm...") can be found. So to avoid
2208
;; finding a wrong position in the source-buffer (e.g. if the tag-name
2209
;; returned by imenu is mentioned in a comment somewhere) we bind the
2211
(search-forward (ecb--semantic-tag-name tag)
2212
(max (ecb-line-end-pos)
2213
(ecb-semantic-tag-end tag))
2215
(beginning-of-line-text)
2219
(defun ecb-start-of-tag-doc (tag)
2220
"If TAG has an outside documentation located direct before TAG then
2221
return the start of the documentation. Otherwise return nil"
2222
;; there can be an error if tag has no documentation - e.g.
2224
(let ((comment (ignore-errors (ecb--semantic-documentation-for-tag tag
2227
(not (stringp comment)))
2228
;; probably we have a semantic flex-object
2229
(ecb--semantic-lex-token-start comment))))
2232
(defun ecb-tag-visit-goto-doc-start (tag)
2233
"Go to the beginning of the documentation of TAG if defined outside.
2234
This is useful especially for languages like Java where the documentation
2235
resides direct before the TAG in Javadoc format.
2236
If the documentation is located within TAG then nothing is done.
2238
If this function is set in `ecb-tag-visit-post-actions' then it's strongly
2239
recommended to add `ecb-tag-visit-recenter' or
2240
`ecb-tag-visit-recenter-top' at the end too!
2242
This action is not recommended for sources of type TeX, texinfo etc. So you
2243
should not add this action to the 'default element of
2244
`ecb-tag-visit-post-actions'!
2246
Returns current point."
2247
(let ((tag-doc-start (ecb-start-of-tag-doc tag)))
2249
(goto-char tag-doc-start))
2253
(defvar ecb-unhighlight-hook-called nil
2254
"This mechanism is necessary because tree-buffer creates for mouse releasing a
2255
new nop-command \(otherwise the cursor jumps back to the tree-buffer).")
2258
(defun ecb-unhighlight-tag-header ()
2259
(let ((key (tree-buffer-event-to-key last-input-event)))
2260
(when (not (or (and (equal key 'mouse-release)
2261
(not ecb-unhighlight-hook-called))
2262
(equal key 'mouse-movement)))
2263
(ecb-overlay-delete ecb-method-overlay)
2264
(remove-hook 'pre-command-hook 'ecb-unhighlight-tag-header)))
2265
(setq ecb-unhighlight-hook-called t))
2268
(defun ecb-tag-visit-highlight-tag-header (tag)
2269
"Highlights line where `ecb-tag-visit-smart-tag-start' puts point for
2270
TAG. Returns current point"
2272
(ecb-tag-visit-smart-tag-start tag)
2273
(ecb-overlay-move ecb-method-overlay
2274
(ecb-line-beginning-pos)
2277
(setq ecb-unhighlight-hook-called nil)
2278
(add-hook 'pre-command-hook 'ecb-unhighlight-tag-header)
2282
(defun ecb-jump-to-tag (filename tag &optional window
2283
no-tag-visit-post-actions
2284
additional-post-action-list)
2285
"Jump to tag TAG in buffer FILENAME.
2286
If NO-TAG-VISIT-POST-ACTIONS is not nil then the functions of
2287
`ecb-tag-visit-post-actions' are not performed. If
2288
ADDITIONAL-POST-ACTION-LIST is a list of function-symbols then these functions
2289
are performed after these ones of `ecb-tag-visit-post-actions'. So if
2290
NO-TAG-VISIT-POST-ACTIONS is not nil then only the functions of
2291
ADDITIONAL-POST-ACTION-LIST are performed. If ADDITIONAL-POST-ACTION-LIST is
2292
nil too then no post-actions are performed."
2293
(cond ((not (ecb-buffer-or-file-readable-p filename))
2294
(error "ECB: ecb-jump-to-tag: Can not open filename %s."
2296
((not (ecb--semantic-tag-with-position-p tag))
2300
(setq window (selected-window)))
2301
(select-window window)
2302
(ecb-semantic-assert-valid-tag tag)
2303
(ecb-nav-save-current)
2304
(find-file filename)
2305
;; let us set the mark so the user can easily jump back.
2306
(if ecb-tag-jump-sets-mark
2308
(ecb-with-original-basic-functions
2310
(goto-char (ecb-semantic-tag-start tag))
2311
;; process post action
2312
(unless no-tag-visit-post-actions
2313
;; first the default post actions
2314
(dolist (f (cdr (assoc 'default ecb-tag-visit-post-actions)))
2316
;; now the mode specific actions
2317
(dolist (f (cdr (assoc major-mode ecb-tag-visit-post-actions)))
2319
;; now we perform the additional-post-action-list
2320
(dolist (f additional-post-action-list)
2322
;; Klaus Berndl <klaus.berndl@sdm.de>: Now we use a different
2323
;; implementation of ecb-nav-tag-history-item. Not longer storing
2324
;; the whole tag but the tag-buffer and markers of tag-start
2325
;; and tag-end. This prevents the navigation-tree from getting
2326
;; unusable cause of invalid overlays after a full reparse!
2327
(let* ((tag-buf (or (ecb-semantic-tag-buffer tag)
2329
(tag-name (ecb--semantic-tag-name tag))
2330
(tag-start (move-marker (make-marker)
2331
(ecb-semantic-tag-start tag) tag-buf))
2332
(tag-end (move-marker (make-marker)
2333
(ecb-semantic-tag-end tag) tag-buf)))
2334
(ecb-nav-add-item (ecb-nav-tag-history-item-new
2339
ecb-buffer-narrowed-by-ecb))))))
2342
(defun ecb-mouse-over-method-node (node &optional window no-message click-force)
2343
"Displays help text if mouse moves over a node in the method buffer or if
2344
CLICK-FORCE is not nil and always with regards to the settings in
2345
`ecb-show-node-info-in-minibuffer'. NODE is the node for which help text
2346
should be displayed, WINDOW is the related window, NO-MESSAGE defines if the
2347
help-text should be printed here."
2348
(let ((str (when (or click-force
2349
(ecb-show-minibuffer-info node window
2350
ecb-methods-buffer-name))
2352
(tree-node-get-name node)
2353
(if (and (= 0 (tree-node-get-type node)) (tree-node-get-data
2355
(equal (ecb-show-node-info-what ecb-methods-buffer-name)
2358
(symbol-name (ecb--semantic-tag-class (tree-node-get-data node))))
2362
(tree-buffer-nolog-message str)))))
2364
;;; popup-menu stuff for the methods-buffer
2366
(defvar ecb-buffer-narrowed-by-ecb nil
2367
"If not nil then current buffer is narrowed to a tag by ECB. Otherwise
2368
the buffer is not narrowed or it is narrowed by ECB but one of the
2369
interactive commands `narrow-to-*' or function/commands which use in turn one
2370
of these `narrow-to-*'-functions.")
2371
(make-variable-buffer-local 'ecb-buffer-narrowed-by-ecb)
2373
(defadvice narrow-to-region (before ecb)
2374
"Set an internal ECB-state. This does not influence the behavior."
2375
(setq ecb-buffer-narrowed-by-ecb nil))
2377
(defadvice narrow-to-defun (before ecb)
2378
"Set an internal ECB-state. This does not influence the behavior."
2379
(setq ecb-buffer-narrowed-by-ecb nil))
2381
(defadvice narrow-to-page (before ecb)
2382
"Set an internal ECB-state. This does not influence the behavior."
2383
(setq ecb-buffer-narrowed-by-ecb nil))
2385
(defadvice widen (before ecb)
2386
"Set an internal ECB-state. This does not influence the behavior."
2387
(setq ecb-buffer-narrowed-by-ecb nil))
2389
(defun ecb-tag-visit-narrow-tag (tag)
2390
"Narrow the source buffer to TAG.
2391
If an outside located documentation belongs to TAG and if this documentation
2392
is located direct before TAG \(e.g. Javadoc in Java) then this documentation
2393
is included in the narrow.
2395
Returns current point."
2396
(when (not (ecb-speedbar-sb-tag-p tag))
2397
(narrow-to-region (or (ecb-start-of-tag-doc tag)
2398
(ecb-semantic-tag-start tag))
2399
(ecb-semantic-tag-end tag))
2400
;; This is the only location where this variable is set to not nil!
2401
;; before every call to `narrow-to-*' or `widen' this variable is reset to
2403
(setq ecb-buffer-narrowed-by-ecb t))
2407
(defun ecb-tag-visit-recenter (tag)
2408
"Recenter the source-buffer, so current line is in the middle of the window.
2409
If this function is added to `ecb-tag-visit-post-actions' then it's
2410
recommended to add this function add the end of the action list for 'default
2411
or a `major-mode' and not to add the function `ecb-tag-visit-recenter-top'
2414
Returns current point."
2417
(ecb-line-beginning-pos (- (/ (ecb-window-full-height) 2))))
2421
(defun ecb-tag-visit-recenter-top (tag)
2422
"Recenter the source-buffer, so current line is in the middle of the window.
2423
If this function is added to `ecb-tag-visit-post-actions' then it's
2424
recommended to add this function add the end of the action list for 'default
2425
or a `major-mode' and not to add the function `ecb-tag-visit-recenter' too!
2427
Returns current point."
2428
(set-window-start (selected-window)
2429
(ecb-line-beginning-pos)))
2431
(tree-buffer-defpopup-command ecb-methods-menu-jump-and-narrow
2432
"Jump to the token related to the node under point an narrow to this token."
2433
(ecb-method-clicked node 1 nil nil t '(ecb-tag-visit-narrow-tag
2434
ecb-tag-visit-highlight-tag-header)))
2437
(tree-buffer-defpopup-command ecb-methods-menu-widen
2438
"Widen the current buffer in the current edit-window."
2439
(ecb-select-edit-window)
2441
(setq ecb-buffer-narrowed-by-ecb nil))
2444
(if (not ecb-running-xemacs)
2445
;; Klaus Berndl <klaus.berndl@sdm.de>: This is for silencing the
2446
;; byte-compiler. Normally there should be no warning when
2447
;; silentcomp-defun is used for hs-minor-mode but....argghhh.
2448
(require 'hideshow))
2450
(defun ecb-methods-menu-activate-hs ()
2451
"Activates `hs-minor-mode' in the buffer of `ecb-path-selected-source'. If
2452
this fails then nil is returned otherwise t."
2454
(set-buffer (get-file-buffer ecb-path-selected-source))
2455
(if (or (not (boundp 'hs-minor-mode))
2456
(not hs-minor-mode))
2457
(if (fboundp 'hs-minor-mode)
2465
(tree-buffer-defpopup-command ecb-methods-menu-show-block
2466
"Runs `hs-show-block' for the current node under point."
2467
(if (not (ecb-methods-menu-activate-hs))
2468
(ecb-error "hs-minor-mode can not be activated!")
2469
;; point must be at beginning of tag-name
2470
(ecb-method-clicked node 1 nil nil t '(ecb-tag-visit-smart-tag-start))
2472
(or (looking-at hs-block-start-regexp)
2473
(re-search-forward hs-block-start-regexp nil t))
2475
;; Now we are at the beginning of the block or - with other word - on that
2476
;; position `ecb-method-clicked' has set the point.
2477
(ecb-tag-visit-highlight-tag-header (tree-node-get-data node))))
2480
(tree-buffer-defpopup-command ecb-methods-menu-hide-block
2481
"Runs `hs-hide-block' for the current node under point."
2482
(if (not (ecb-methods-menu-activate-hs))
2483
(ecb-error "hs-minor-mode can not be activated!")
2484
;; point must be at beginning of tag-name
2485
(ecb-method-clicked node 1 nil nil t '(ecb-tag-visit-smart-tag-start))
2487
(or (looking-at hs-block-start-regexp)
2488
(re-search-forward hs-block-start-regexp nil t))
2490
(ecb-tag-visit-highlight-tag-header (tree-node-get-data node))))
2493
(tree-buffer-defpopup-command ecb-methods-menu-collapse-all
2494
"Collapse all expandable and expanded nodes"
2495
(ecb-expand-methods-nodes-internal -1 nil t))
2498
(tree-buffer-defpopup-command ecb-methods-menu-expand-0
2499
"Expand all nodes with level 0."
2500
(ecb-expand-methods-nodes-internal 0 nil t))
2503
(tree-buffer-defpopup-command ecb-methods-menu-expand-1
2504
"Expand all nodes with level 1."
2505
(ecb-expand-methods-nodes-internal 1 nil t))
2508
(tree-buffer-defpopup-command ecb-methods-menu-expand-2
2509
"Expand all nodes with level 2."
2510
(ecb-expand-methods-nodes-internal 2 nil t))
2513
(tree-buffer-defpopup-command ecb-methods-menu-expand-all
2514
"Expand all expandable nodes recursively."
2515
(ecb-expand-methods-nodes-internal 100 nil t))
2518
(defvar ecb-common-methods-menu nil
2519
"Built-in menu for the methods-buffer.")
2522
(setq ecb-common-methods-menu
2525
(ecb-methods-menu-collapse-all "Collapse all")
2526
(ecb-methods-menu-expand-0 "Expand level 0")
2527
(ecb-methods-menu-expand-1 "Expand level 1")
2528
(ecb-methods-menu-expand-2 "Expand level 2")
2529
(ecb-methods-menu-expand-all "Expand all"))
2531
(ecb-maximize-ecb-window-menu-wrapper "Maximize window")))
2534
(defvar ecb-methods-tag-menu nil)
2535
(setq ecb-methods-tag-menu
2536
(append '(("Hide/Show"
2537
(ecb-methods-menu-hide-block "Jump to tag and hide block")
2538
(ecb-methods-menu-show-block "Jump to tag and show block"))
2540
(ecb-methods-menu-jump-and-narrow "Jump to tag and narrow")
2541
(ecb-methods-menu-widen "Undo narrowing of edit-window")))
2542
ecb-common-methods-menu))
2545
(defvar ecb-methods-menu-title-creator
2546
(function (lambda (node)
2547
(let ((data (tree-node-get-data node)))
2549
(cond ((ecb--semantic-tag-p data)
2550
(ecb--semantic-tag-name data))
2553
(t (tree-node-get-name node)))
2554
(tree-node-get-name node)))))
2555
"The menu-title for the methods menu. See
2556
`ecb-directories-menu-title-creator'.")
2558
(tree-buffer-defpopup-command ecb-jump-to-token-in-editwin1
2559
"Jump to current token in the 1. edit-window."
2560
(ecb-method-clicked node 3 1 nil))
2561
(tree-buffer-defpopup-command ecb-jump-to-token-in-editwin2
2562
"Jump to current token in the 2. edit-window."
2563
(ecb-method-clicked node 3 2 nil))
2564
(tree-buffer-defpopup-command ecb-jump-to-token-in-editwin3
2565
"Jump to current token in the 3. edit-window."
2566
(ecb-method-clicked node 3 3 nil))
2567
(tree-buffer-defpopup-command ecb-jump-to-token-in-editwin4
2568
"Jump to current token in the 4. edit-window."
2569
(ecb-method-clicked node 3 4 nil))
2570
(tree-buffer-defpopup-command ecb-jump-to-token-in-editwin5
2571
"Jump to current token in the 5. edit-window."
2572
(ecb-method-clicked node 3 5 nil))
2573
(tree-buffer-defpopup-command ecb-jump-to-token-in-editwin6
2574
"Jump to current token in the 6. edit-window."
2575
(ecb-method-clicked node 3 6 nil))
2576
(tree-buffer-defpopup-command ecb-jump-to-token-in-editwin7
2577
"Jump to current token in the 7. edit-window."
2578
(ecb-method-clicked node 3 7 nil))
2579
(tree-buffer-defpopup-command ecb-jump-to-token-in-editwin8
2580
"Jump to current token in the 8. edit-window."
2581
(ecb-method-clicked node 3 8 nil))
2583
(defun ecb-methods-menu-editwin-entries ()
2584
"Generate popup-menu-entries for each edit-window if there are at least 2
2585
edit-windows. Otherwise return nil."
2586
(let ((edit-win-list (ecb-canonical-edit-windows-list))
2588
(when (> (length edit-win-list) 1)
2589
(dotimes (i (min 8 (length edit-win-list)))
2592
(list (list (intern (format "ecb-jump-to-token-in-editwin%d" (1+ i)))
2593
(format "edit-window %d" (1+ i)))))))
2594
(append (list (list "---")) ;; we want a separator
2595
(list (append (list "Jump to token in ...")
2598
(defun ecb-methods-menu-creator (tree-buffer-name)
2599
"Creates the popup-menus for the methods-buffer."
2600
(setq ecb-layout-prevent-handle-ecb-window-selection t)
2601
(let ((dyn-user-extension
2602
(and (functionp ecb-methods-menu-user-extension-function)
2603
(funcall ecb-methods-menu-user-extension-function)))
2604
(dyn-builtin-extension (ecb-methods-menu-editwin-entries)))
2605
(list (cons 0 (funcall (or ecb-methods-menu-sorter
2607
(append dyn-user-extension
2608
ecb-methods-menu-user-extension
2609
ecb-methods-tag-menu
2610
dyn-builtin-extension)))
2611
(cons 1 (funcall (or ecb-methods-menu-sorter
2613
(append dyn-user-extension
2614
ecb-methods-menu-user-extension
2615
ecb-common-methods-menu)))
2616
(cons 2 (funcall (or ecb-methods-menu-sorter
2618
(append dyn-user-extension
2619
ecb-methods-menu-user-extension
2620
ecb-common-methods-menu))))))
2623
(defun ecb-dump-semantic-toplevel ()
2624
"Dump the current semantic-tags in special buffer and display them."
2626
(let ((tags (ecb-post-process-taglist (ecb--semantic-bovinate-toplevel t))))
2627
(save-selected-window
2628
(set-buffer (get-buffer-create "ecb-dump"))
2630
(ecb-dump-tags tags "")
2631
(switch-to-buffer-other-window (get-buffer-create "ecb-dump"))
2632
(goto-char (point-min)))))
2635
(defun ecb-dump-type (a-tag prefix)
2636
(dolist (parent (ecb-get-tag-parents a-tag))
2637
(insert prefix " " parent)))
2640
(defun ecb-dump-tags (tags prefix)
2641
(dolist (a-tag tags)
2643
(princ (concat prefix a-tag))
2645
(ecb--semantic-format-tag-name a-tag nil ecb-font-lock-tags)
2647
(symbol-name (ecb--semantic-tag-class a-tag))
2649
(if (stringp (ecb--semantic-tag-type a-tag))
2650
(ecb--semantic-tag-type a-tag)
2653
(if (eq 'type (ecb--semantic-tag-class a-tag))
2654
(ecb-dump-type a-tag prefix))
2655
(ecb-dump-tags (ecb--semantic-tag-children-compatibility
2656
a-tag ecb-show-only-positioned-tags)
2657
(concat prefix " ")))))
2659
(silentcomp-provide 'ecb-method-browser)
2661
;;; ecb-method-browser.el end here