~ubuntu-branches/debian/lenny/ecb/lenny

« back to all changes in this revision

Viewing changes to ecb-method-browser.el

  • Committer: Bazaar Package Importer
  • Author(s): Joerg Jaspert
  • Date: 2004-02-16 23:16:24 UTC
  • Revision ID: james.westby@ubuntu.com-20040216231624-brlrnyp41twx033r
Tags: upstream-2.21
ImportĀ upstreamĀ versionĀ 2.21

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;; ecb-method-browser.el --- the method-browser of Emacs
 
2
 
 
3
;; Copyright (C) 2000 - 2003 Jesper Nordenberg,
 
4
;;                           Klaus Berndl,
 
5
;;                           Free Software Foundation, Inc.
 
6
 
 
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
 
12
;; Created: 2000
 
13
 
 
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.
 
17
 
 
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
 
21
;; details.
 
22
 
 
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.
 
26
 
 
27
;; $Id: ecb-method-browser.el,v 1.15 2004/02/16 08:56:25 berndl Exp $
 
28
 
 
29
;;; Commentary:
 
30
 
 
31
;; This file contains the code for the method-browser of ECB
 
32
 
 
33
(require 'tree-buffer)
 
34
(require 'ecb-util)
 
35
(require 'ecb-layout)
 
36
(require 'ecb-mode-line)
 
37
(require 'ecb-navigate)
 
38
(require 'ecb-face)
 
39
(require 'ecb-speedbar)
 
40
 
 
41
(require 'ecb-semantic-wrapper)
 
42
;; This loads the semantic-setups for the major-modes.
 
43
(require 'semantic-load)
 
44
 
 
45
;; various loads
 
46
(require 'assoc)
 
47
 
 
48
(eval-when-compile
 
49
  ;; to avoid compiler grips
 
50
  (require 'cl))
 
51
 
 
52
(eval-when-compile
 
53
  (require 'silentcomp))
 
54
 
 
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)
 
61
 
 
62
(silentcomp-defun ecb-get-tags-for-non-semantic-files)
 
63
(silentcomp-defun ecb-create-non-semantic-tree)
 
64
 
 
65
(defvar ecb-selected-tag nil
 
66
  "The currently selected Semantic tag.")
 
67
(make-variable-buffer-local 'ecb-selected-tag)
 
68
 
 
69
(defvar ecb-methods-root-node nil
 
70
  "Path to currently selected source.")
 
71
 
 
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))
 
76
 
 
77
;;====================================================
 
78
;; Customization
 
79
;;====================================================
 
80
 
 
81
(defgroup ecb-methods nil
 
82
  "Settings for the methods-buffer in the Emacs code browser."
 
83
  :group 'ecb
 
84
  :prefix "ecb-")
 
85
 
 
86
 
 
87
(defgroup ecb-non-semantic nil
 
88
  "Settings for parsing and displaying non-semantic files."
 
89
  :group 'ecb
 
90
  :prefix "ecb-")
 
91
 
 
92
 
 
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*\".
 
97
 
 
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'.
 
100
 
 
101
Changes for this option at runtime will take affect only after deactivating and
 
102
then activating ECB again!"
 
103
  :group 'ecb-methods
 
104
  :type 'string)
 
105
 
 
106
 
 
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'.
 
118
 
 
119
This options takes only effect for semantic-sources - means sources supported
 
120
by semantic!"
 
121
  :group 'ecb-methods
 
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)))
 
125
 
 
126
 
 
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'.
 
131
 
 
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.
 
134
 
 
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."
 
140
  :group 'ecb-methods
 
141
  :type 'boolean)
 
142
 
 
143
 
 
144
(defcustom ecb-auto-update-methods-after-save t
 
145
  "*Automatically updating the ECB method buffer after saving a source."
 
146
  :group 'ecb-methods
 
147
  :type 'boolean)
 
148
 
 
149
 
 
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
 
153
by semantic!"
 
154
  :group 'ecb-methods
 
155
  :set (function (lambda (symbol value)
 
156
                   (set symbol value)
 
157
                   (ecb-clear-tag-tree-cache)))
 
158
  :type 'boolean
 
159
  :initialize 'custom-initialize-default)
 
160
 
 
161
 
 
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."
 
165
  :group 'ecb-methods
 
166
  :type 'boolean)
 
167
 
 
168
(defconst ecb-tag->text-functions
 
169
  (mapcar (lambda (fkt-elem)
 
170
            (cons (intern
 
171
                   (concat "ecb-"
 
172
                           (mapconcat 'identity
 
173
                                      (cdr (split-string (symbol-name
 
174
                                                          (cdr fkt-elem)) "-"))
 
175
                                      "-")))
 
176
                  (intern
 
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'")
 
181
 
 
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
 
186
cons-cells:
 
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
 
191
  major-mode.
 
192
Every function is called with 3 arguments:
 
193
1. The tag
 
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.
 
198
 
 
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'.
 
220
 
 
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.
 
226
 
 
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
 
229
displaying the tags.
 
230
 
 
231
This options takes only effect for semantic-sources - means sources supported
 
232
by semantic!"
 
233
  :group 'ecb-methods
 
234
  :group 'ecb-most-important
 
235
  :set (function (lambda (symbol value)
 
236
                   (set 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")
 
243
                           (append
 
244
                            (mapcar (lambda (f)
 
245
                                      (list 'const ':tag
 
246
                                            (symbol-name (car f)) (car f)))
 
247
                                    ecb-tag->text-functions)
 
248
                            (mapcar (lambda (f)
 
249
                                      (list 'const ':tag
 
250
                                            (symbol-name (cdr f)) (cdr f)))
 
251
                                    ecb-tag->text-functions)
 
252
                            (list '(function :tag "Function"))))))
 
253
  :initialize 'custom-initialize-default)
 
254
 
 
255
 
 
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'!
 
264
 
 
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
 
267
cons-cells:
 
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
 
279
     useless.
 
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
 
293
     versions).
 
294
 
 
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:
 
298
 
 
299
  \(\(default
 
300
     \(\"class\" t ecb-type-tag-class-face)
 
301
     \(\"group\" nil ecb-type-tag-group-face))
 
302
    \(c-mode
 
303
     \(\"struct\" nil ecb-type-tag-struct-face)
 
304
     \(\"typedef\" nil ecb-type-tag-typedef-face)))
 
305
 
 
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.
 
311
 
 
312
This options takes only effect for semantic-sources - means sources supported
 
313
by semantic!"
 
314
  :group 'ecb-methods
 
315
  :group 'ecb-most-important
 
316
  :set (function (lambda (symbol value)
 
317
                   (set 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"
 
323
                                             (const :tag "class"
 
324
                                                    :value "class")
 
325
                                             (const :tag "interface"
 
326
                                                    :value "interface")
 
327
                                             (const :tag "struct"
 
328
                                                    :value "struct")
 
329
                                             (const :tag "typedef"
 
330
                                                    :value "typedef")
 
331
                                             (const :tag "union"
 
332
                                                    :value "union")
 
333
                                             (const :tag "enum"
 
334
                                                    :value "enum")
 
335
                                             (const :tag "group"
 
336
                                                    :value "group")
 
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)
 
342
 
 
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))))))
 
351
 
 
352
 
 
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))))))
 
361
 
 
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').
 
371
 
 
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.
 
375
 
 
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
 
378
cons-cells:
 
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).
 
385
 
 
386
This options takes only effect for semantic-sources - means sources supported
 
387
by semantic!"
 
388
  :group 'ecb-methods
 
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"
 
396
                                              (const :tag "class"
 
397
                                                     :value "class")
 
398
                                              (const :tag "interface"
 
399
                                                     :value "interface")
 
400
                                              (const :tag "struct"
 
401
                                                     :value "struct")
 
402
                                              (const :tag "typedef"
 
403
                                                     :value "typedef")
 
404
                                              (const :tag "union"
 
405
                                                     :value "union")
 
406
                                              (const :tag "enum"
 
407
                                                     :value "enum")
 
408
                                              (const :tag "group"
 
409
                                                     :value "group")
 
410
                                              (string :tag "Any specifier"))))))
 
411
  :set (function (lambda (symbol value)
 
412
                   (set symbol value)
 
413
                   (ecb-clear-tag-tree-cache)))
 
414
  :initialize 'custom-initialize-default)
 
415
  
 
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))))))
 
426
 
 
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)))
 
432
 
 
433
(defun ecb-get-type-specifier (tag)
 
434
  (if (ecb-faux-group-tag-p tag)
 
435
      "group"
 
436
    (ecb--semantic-tag-type tag)))
 
437
  
 
438
 
 
439
(dolist (elem ecb-tag->text-functions)
 
440
  (fset (car elem)
 
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
 
454
                                    type-specifier)))
 
455
                 (save-match-data
 
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
 
461
                   ;; parent-tag.
 
462
                   (when (ecb-faux-group-tag-p tag)
 
463
                     (if (string-match (concat "^\\(.+"
 
464
                                               (ecb--semantic-uml-colon-string)
 
465
                                               "\\)\\("
 
466
                                               (if (ecb--semantic--tag-get-property tag 'faux)
 
467
                                                   (ecb--semantic-orphaned-member-metaparent-type)
 
468
                                                 "struct")
 
469
                                               "\\)") text)
 
470
                         (let ((type-spec-text "group"))
 
471
                           (put-text-property 0 (length type-spec-text)
 
472
                                              'face
 
473
                                              (get-text-property
 
474
                                               0 'face
 
475
                                               (match-string 2 text))
 
476
                                              type-spec-text)
 
477
                           (setq text (concat (match-string 1 text)
 
478
                                              type-spec-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 "\\)")
 
485
                                       text)
 
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
 
496
                       ;; ugly stuff.
 
497
                       (if (string-match "^\\(.+\\){.*}\\(.+\\)$" template-text)
 
498
                           (setq template-text
 
499
                                 (concat (match-string 1 template-text)
 
500
                                         (match-string 2 template-text))))
 
501
                       (put-text-property 0 (length template-text)
 
502
                                          'face
 
503
                                          (get-text-property
 
504
                                           (1- (length col-type-name)) 'face
 
505
                                           col-type-name)
 
506
                                          template-text))
 
507
                     (setq text (concat col-type-name template-text
 
508
                                        col-type-spec))))
 
509
                 ;; now we add some own colorizing if necessary
 
510
                 (if face
 
511
                     (setq text (ecb-merge-face-into-text text face)))
 
512
                 text)
 
513
             (funcall (quote ,(cdr elem)) tag parent-tag colorize)))))
 
514
 
 
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.
 
527
 
 
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.
 
533
 
 
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'.
 
536
 
 
537
This options takes only effect for semantic-sources - means sources supported
 
538
by semantic!"
 
539
  :group 'ecb-methods
 
540
  :type '(repeat (cons (symbol :tag "Major-mode")
 
541
                       (repeat (function :tag "Post-process function")))))
 
542
 
 
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
 
551
not be jumped.
 
552
 
 
553
This options takes only effect for semantic-sources - means sources supported
 
554
by semantic!"
 
555
  :group 'ecb-methods
 
556
  :type 'boolean)
 
557
 
 
558
 
 
559
(defcustom ecb-show-tags '((include collapsed nil)
 
560
                           (parent collapsed nil)
 
561
                           (type flattened nil)
 
562
                           (variable collapsed access)
 
563
                           (function flattened access)
 
564
                           (rule flattened name)
 
565
                           (section flattened nil)
 
566
                           (def collapsed name)
 
567
                           (t collapsed name))
 
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:
 
570
 
 
571
\(<tag type> <display type> <sort method>)
 
572
 
 
573
The tags in the methods buffer are displayed in the order as they appear in
 
574
this list.
 
575
 
 
576
Tag Type
 
577
----------
 
578
 
 
579
A Semantic tag type symbol \(for all possible type symbols see documentation
 
580
of semantic):
 
581
- include
 
582
- type
 
583
- variable
 
584
- function
 
585
- rule
 
586
- section \(chapters and sections in `info-mode')
 
587
- def \(definitions in `info-mode')
 
588
 
 
589
or one of the following:
 
590
 
 
591
- t:      All tag types not specified anywhere else in the list.
 
592
- parent: The parents of a type.
 
593
 
 
594
Display Type
 
595
------------
 
596
 
 
597
A symbol which describes how the tags of this type shall be shown:
 
598
 
 
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.
 
603
 
 
604
Sort Method
 
605
-----------
 
606
 
 
607
A symbol describing how to sort the tags of this type:
 
608
 
 
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
 
612
          buffer.
 
613
 
 
614
This options takes only effect for semantic-sources - means sources supported
 
615
by semantic!"
 
616
  :group 'ecb-methods
 
617
  :group 'ecb-most-important
 
618
  :set (function (lambda (symbol value)
 
619
                   (set 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)
 
632
 
 
633
 
 
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
 
639
`ecb-show-tags'.
 
640
 
 
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'.
 
644
 
 
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
 
650
then 'Parents.
 
651
 
 
652
This options takes only effect for semantic-sources - means sources supported
 
653
by semantic!"
 
654
  :group 'ecb-methods
 
655
  :type '(radio (const :tag "All node-types" :value all)
 
656
                (repeat :tag "Node-type list"
 
657
                        (symbol :tag "Node-type"))))
 
658
 
 
659
 
 
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'!
 
663
 
 
664
This options takes only effect for semantic-sources - means sources supported
 
665
by semantic!"
 
666
  :group 'ecb-methods
 
667
  :type '(radio (const :tag "All node-types" :value all)
 
668
                (repeat :tag "Node-type list"
 
669
                        (symbol :tag "Node-type"))))
 
670
 
 
671
 
 
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.
 
675
 
 
676
This options takes only effect for semantic-sources - means sources supported
 
677
by semantic!"
 
678
  :group 'ecb-methods
 
679
  :set (function (lambda (symbol value)
 
680
                   (set symbol value)
 
681
                   (ecb-clear-tag-tree-cache)))
 
682
  :type '(radio (const :tag "Do not exclude any parents"
 
683
                       :value nil)
 
684
                (regexp :tag "Parents-regexp to exclude"))
 
685
  :initialize 'custom-initialize-default)
 
686
 
 
687
 
 
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'.
 
696
 
 
697
This options takes only effect for semantic-sources - means sources supported
 
698
by semantic!"
 
699
  :group 'ecb-methods
 
700
  :type '(radio (const :tag "Highlight and scroll window"
 
701
                       :value highlight-scroll)
 
702
                (const :tag "Just highlight"
 
703
                       :value highlight)
 
704
                (const :tag "Do not highlight"
 
705
                       :value nil)))
 
706
 
 
707
 
 
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.
 
716
 
 
717
This options takes only effect for semantic-sources - means sources supported
 
718
by semantic!"
 
719
  :group 'ecb-methods
 
720
  :type '(radio (const :tag "No highlighting delay"
 
721
                       :value nil)
 
722
                (number :tag "Idle time before highlighting"
 
723
                        :value 0.25))
 
724
  :set (function (lambda (symbol value)
 
725
                   (set symbol value)
 
726
                   (if ecb-minor-mode
 
727
                       (ecb-activate-ecb-sync-functions value 'ecb-tag-sync))))
 
728
  :initialize 'custom-initialize-default)
 
729
 
 
730
 
 
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)
 
734
 
 
735
 
 
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.
 
743
 
 
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
 
746
cons-cells:
 
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.
 
749
 
 
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).
 
752
 
 
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.
 
761
 
 
762
But you can add any arbitrary function if the following conditions are
 
763
fulfilled:
 
764
- The function gets the semantic tag as argument and
 
765
- the function returns the \(new) point after finishing its job."
 
766
  :group 'ecb-methods
 
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"))))))
 
783
 
 
784
 
 
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)))))
 
788
 
 
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'.
 
792
 
 
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.
 
795
 
 
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'."
 
799
  :group 'ecb-methods
 
800
  :type '(repeat (choice :tag "Menu-entry" :menu-tag "Menu-entry"
 
801
                         :value (ignore "")
 
802
                         (const :tag "Separator" :value ("---"))
 
803
                         (list :tag "Menu-command"
 
804
                               (function :tag "Function" :value ignore)
 
805
                               (string :tag "Entry-name"))
 
806
                         (cons :tag "Submenu"
 
807
                               (string :tag "Submenu-title")
 
808
                               (repeat (choice :tag "Submenu-entry" :menu-tag "Submenu-entry"
 
809
                                               :value (ignore "")
 
810
                                               (const :tag "Separator" :value ("---"))
 
811
                                               (list :tag "Submenu-command"
 
812
                                                     (function :tag "Function"
 
813
                                                               :value ignore)
 
814
                                                     (string :tag "Entry-name"))))))))
 
815
 
 
816
 
 
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'.
 
823
 
 
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'."
 
827
  :group 'ecb-methods
 
828
  :type 'function)
 
829
 
 
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.
 
837
 
 
838
For the guidelines for such a sorter-function see
 
839
`ecb-directories-menu-sorter'."
 
840
  :group 'ecb-methods
 
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)))
 
844
 
 
845
 
 
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."
 
852
  :group 'ecb-methods
 
853
  :type 'hook)
 
854
 
 
855
 
 
856
(defcustom ecb-process-non-semantic-files (if (locate-library "speedbar")
 
857
                                              t)
 
858
  "*Display contents of non-semantic-files in the ECB-methods-buffer.
 
859
See also `ecb-non-semantic-parsing-function'."
 
860
  :group 'ecb-general
 
861
  :group 'ecb-non-semantic
 
862
  :group 'ecb-most-important
 
863
  :type 'boolean)
 
864
 
 
865
 
 
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.
 
876
 
 
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.
 
883
 
 
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.
 
888
 
 
889
IMPORTANT: if imenu-parsing should be used then the option
 
890
`speedbar-use-imenu-flag' must be set to not nil!"
 
891
  :group 'ecb-methods
 
892
  :group 'ecb-non-semantic
 
893
  :type '(repeat (cons (symbol :tag "Major-mode")
 
894
                       (function :tag "Parsing function"))))
 
895
 
 
896
 
 
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."
 
902
  :group 'ecb-methods
 
903
  :group 'ecb-non-semantic
 
904
  :type '(repeat :tag "Expand this modes"
 
905
                 (symbol :tag "major mode")))
 
906
 
 
907
 
 
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
 
918
done!
 
919
 
 
920
For all source supported by semantic or by imenu this option takes no effect."
 
921
  :group 'ecb-methods
 
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"))))
 
925
 
 
926
 
 
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")))
 
941
 
 
942
 
 
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.
 
947
 
 
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
 
953
processed."
 
954
  :group 'ecb-methods
 
955
  :group 'ecb-non-semantic
 
956
  :type 'hook)
 
957
 
 
958
;;====================================================
 
959
;; Internals
 
960
;;====================================================
 
961
 
 
962
 
 
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."
 
966
  (when ecb-debug-mode
 
967
    (let ((debug-on-error t))
 
968
      (apply 'error error-args))))
 
969
 
 
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.
 
973
 
 
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)))
 
985
                (progn
 
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
 
999
                    ;;    1.
 
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)
 
1019
                  nil)
 
1020
              ;; else, tag is OK.
 
1021
              t))
 
1022
        ;; Position-less tags are also OK.
 
1023
        t)
 
1024
    ;; For no semantic-tags a reparse makes no sense!
 
1025
    (ecb-enter-debugger "Not a semantic tag: %S" tag)
 
1026
    nil))
 
1027
 
 
1028
 
 
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))
 
1035
 
 
1036
 
 
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))
 
1043
 
 
1044
 
 
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))
 
1051
 
 
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
 
1055
;; errors!
 
1056
(defun ecb-semantic-current-nonterminal ()
 
1057
  (condition-case nil
 
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)))))
 
1064
 
 
1065
 
 
1066
(defmacro ecb-exec-in-methods-window (&rest body)
 
1067
  `(unwind-protect
 
1068
       (when (ecb-window-select ecb-methods-buffer-name)
 
1069
         ,@body)
 
1070
     ))
 
1071
 
 
1072
 
 
1073
(defun ecb-create-node (parent-node display name data type)
 
1074
  (if (eq 'hidden display)
 
1075
      nil
 
1076
    (if (eq 'flattened display)
 
1077
        parent-node
 
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))
 
1082
        node))))
 
1083
 
 
1084
 
 
1085
(defun ecb-get-tag-type-display (tag-type)
 
1086
  (let ((display (ecb-find-assoc tag-type ecb-show-tags)))
 
1087
    (if display
 
1088
        display
 
1089
      (setq display (ecb-find-assoc t ecb-show-tags))
 
1090
      (if display
 
1091
          display
 
1092
        '(t hidden nil)))))
 
1093
 
 
1094
 
 
1095
(defun ecb-get-tag-parent-names (parents)
 
1096
  (when parents
 
1097
    (let* ((parent (car parents))
 
1098
           (name (cond
 
1099
                  ((ecb--semantic-tag-p parent)
 
1100
                   (ecb--semantic-format-tag-name parent nil ecb-font-lock-tags))
 
1101
                  ((stringp parent)
 
1102
                   (ecb--semantic--format-colorize-text parent 'type)))))
 
1103
      (if name
 
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))))
 
1108
        (if (listp parent)
 
1109
            (append (ecb-get-tag-parent-names parent)
 
1110
                    (ecb-get-tag-parent-names (cdr parents))))))))
 
1111
 
 
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)))
 
1119
 
 
1120
 
 
1121
 
 
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'."
 
1125
  (condition-case nil
 
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))))
 
1134
 
 
1135
 
 
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'."
 
1141
  (when (cdr buckets)
 
1142
    (let ((bucket (cadr buckets)))
 
1143
      (if (eq type (ecb--semantic-tag-class (cadr bucket)))
 
1144
          (progn
 
1145
            (ecb-add-tag-bucket node bucket display sort-method parent-tag
 
1146
                                  no-bucketize)
 
1147
            (setcdr buckets (cddr buckets)))
 
1148
        (ecb-find-add-tag-bucket node type display sort-method
 
1149
                                   (cdr buckets) parent-tag no-bucketize)))))
 
1150
 
 
1151
 
 
1152
(defun ecb-format-bucket-name (name)
 
1153
  (let ((formatted-name (concat (nth 0 ecb-bucket-node-display)
 
1154
                                name
 
1155
                                (nth 1 ecb-bucket-node-display))))
 
1156
    (setq formatted-name (ecb-merge-face-into-text formatted-name (nth 2 ecb-bucket-node-display)))
 
1157
    formatted-name))
 
1158
 
 
1159
 
 
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."
 
1163
  (when bucket
 
1164
    (let ((name (ecb-format-bucket-name (car bucket)))
 
1165
          ;;(type (ecb--semantic-tag-class (cadr bucket)))
 
1166
          (bucket-node node))
 
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))))))
 
1178
 
 
1179
 
 
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
 
1190
      ;; flexible
 
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
 
1195
           node
 
1196
           (and (tree-node-is-expandable node)
 
1197
                (ecb-type-tag-expansion type-specifier))))))))
 
1198
    
 
1199
 
 
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)
 
1206
      (if (fboundp fcn)
 
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)))
 
1210
 
 
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.
 
1216
 
 
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))
 
1220
 
 
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))))
 
1236
                     (throw 'found t)))
 
1237
               nil)
 
1238
             taglist)
 
1239
        (ecb-filter taglist
 
1240
                    (function (lambda (x)
 
1241
                                (not (ecb--semantic-tag-get-attribute x 'prototype))))))))
 
1242
 
 
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.")
 
1249
 
 
1250
 
 
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!
 
1263
 
 
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)))
 
1269
 
 
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)))
 
1276
 
 
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))))
 
1283
 
 
1284
(defun ecb-methods-filter-none (source-buffer)
 
1285
  "Remove any filter from the Methods-buffer."
 
1286
  (ecb-methods-filter-apply nil source-buffer))
 
1287
 
 
1288
(defun ecb-apply-user-filter-to-tags (taglist)
 
1289
  (save-match-data
 
1290
    (let ((filter (cdr (assoc (current-buffer) ecb-methods-user-filter-alist))))
 
1291
      (if (null filter)
 
1292
          taglist
 
1293
        (ecb-filter taglist
 
1294
                    (function
 
1295
                     (lambda (tag)
 
1296
                       (cond ((stringp filter)
 
1297
                              (if (string-match filter
 
1298
                                                (ecb--semantic-tag-name tag))
 
1299
                                  tag))
 
1300
                             ((member filter '(private protected public))
 
1301
                              (if (or (null (ecb--semantic-tag-protection tag))
 
1302
                                      (equal (ecb--semantic-tag-protection tag) filter))
 
1303
                                  tag))
 
1304
                             ((symbolp filter)
 
1305
                              (if (equal (ecb--semantic-tag-class tag) filter)
 
1306
                                  tag))
 
1307
                             (t tag)))))))))
 
1308
 
 
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
 
1319
  `ecb-show-tokens'.
 
1320
 
 
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!
 
1324
 
 
1325
Such a filter is only applied to the current source-buffer, i.e. each
 
1326
source-buffer can have its own tag-filter."
 
1327
  (interactive)
 
1328
  (ecb-error "This command will be offered first in future-versions of ECB!")
 
1329
  (let ((source-buffer (if (ecb-point-in-edit-window)
 
1330
                           (current-buffer)
 
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)))))
 
1342
 
 
1343
 
 
1344
(defun ecb-methods-filter-apply (filter source-buffer)
 
1345
  (let ((filter-elem (assoc source-buffer ecb-methods-user-filter-alist)))
 
1346
    (if filter-elem
 
1347
        (setcdr filter-elem filter)
 
1348
      (if 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))))
 
1356
  
 
1357
 
 
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
 
1362
                         (if no-bucketize
 
1363
                             tags
 
1364
                           (ecb--semantic-bucketize tags))
 
1365
                         no-bucketize))
 
1366
 
 
1367
 
 
1368
(defun ecb-access-order (access)
 
1369
  (cond
 
1370
   ((eq 'public access) 0)
 
1371
   ((eq 'protected access) 1)
 
1372
   ((eq 'private access) 3)
 
1373
   (t  2)))
 
1374
 
 
1375
 
 
1376
(defun ecb-sort-tags (sort-method tags)
 
1377
  (if sort-method
 
1378
      (let ((tags-by-name
 
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)
 
1383
            (sort tags-by-name
 
1384
                  (function
 
1385
                   (lambda (a b)
 
1386
                     (< (ecb-access-order (ecb--semantic-tag-protection a))
 
1387
                        (ecb-access-order (ecb--semantic-tag-protection b))))))
 
1388
          tags-by-name))
 
1389
    tags))
 
1390
 
 
1391
 
 
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)))
 
1401
      (cond
 
1402
       ((eq 'parent type)
 
1403
        (when (and parent-tag
 
1404
                   (eq 'type (ecb--semantic-tag-class parent-tag)))
 
1405
          (let ((parents (ecb-get-tag-parents parent-tag)))
 
1406
            (when parents
 
1407
              (let ((node (ecb-create-node node display (ecb-format-bucket-name "Parents") nil 1)))
 
1408
                (when node
 
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)
 
1413
                                     parent)
 
1414
                                   2 parent t node
 
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))))
 
1422
 
 
1423
 
 
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)))
 
1435
 
 
1436
 
 
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)
 
1441
       (save-excursion
 
1442
         (set-buffer (get-file-buffer filename))
 
1443
         (ecb--semantic-active-p))))
 
1444
 
 
1445
 
 
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)))
 
1460
 
 
1461
 
 
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'!")
 
1466
 
 
1467
 
 
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.
 
1476
 
 
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)
 
1488
 
 
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!
 
1494
                                   (save-excursion
 
1495
                                     (save-restriction
 
1496
                                       (ecb-with-original-basic-functions
 
1497
                                        (widen))
 
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.
 
1508
      ;;
 
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
 
1521
           current-tagcache
 
1522
           (ecb--semantic-active-p)
 
1523
           nil rebuild-non-semantic)))
 
1524
    (when scroll-to-top
 
1525
      (save-selected-window
 
1526
        (ecb-exec-in-methods-window
 
1527
         (tree-buffer-scroll (point-min) (point-min)))))))
 
1528
 
 
1529
 
 
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)
 
1536
 
 
1537
 
 
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))))
 
1545
 
 
1546
 
 
1547
 
 
1548
(defun ecb-rebuild-methods-buffer-with-tagcache (updated-cache
 
1549
                                                   &optional no-update-semantic
 
1550
                                                   force-nil-cache
 
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'.
 
1554
 
 
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!
 
1559
 
 
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.
 
1565
it is cleared.
 
1566
 
 
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!
 
1588
             (or updated-cache
 
1589
                 (not (ecb--semantic-active-p))
 
1590
                 force-nil-cache))
 
1591
 
 
1592
    ;; no-update-semantic has to be nil for non-semantic-sources!
 
1593
    (if (not (ecb--semantic-active-p)) (setq no-update-semantic nil))
 
1594
 
 
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
 
1600
    ;; of ECB.
 
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
 
1605
    ;; source!.
 
1606
    
 
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)
 
1613
      
 
1614
      (if ecb-debug-mode
 
1615
          (dolist (a-tag updated-cache)
 
1616
            (ecb-semantic-assert-valid-tag a-tag)))
 
1617
      
 
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)))
 
1629
 
 
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
 
1635
      ;; 'parsed-failed.
 
1636
 
 
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)))
 
1655
        (if 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))))
 
1659
 
 
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
 
1668
      ;; automatically.
 
1669
      (save-excursion
 
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)))
 
1677
    
 
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!
 
1682
    
 
1683
    (ecb-mode-line-format)
 
1684
 
 
1685
    ;; signalize that the rebuild has already be done
 
1686
    (setq ecb-method-buffer-needs-rebuild nil)))
 
1687
 
 
1688
(defun ecb-save-without-auto-update-methods ()
 
1689
  (let ((ecb-auto-update-methods-after-save nil))
 
1690
    (save-buffer)))
 
1691
 
 
1692
 
 
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!
 
1697
 
 
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.
 
1703
 
 
1704
The option `ecb-auto-save-before-etags-methods-rebuild' is checked before
 
1705
rescanning the source-buffer and rebuilding the methods-buffer.
 
1706
 
 
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
 
1715
           (buffer-file-name))
 
1716
      ;; For etags supported non-semantic-sources we maybe have to save the
 
1717
      ;; buffer first.
 
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)
 
1722
                     (member major-mode
 
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))))
 
1728
 
 
1729
 
 
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)))
 
1742
 
 
1743
 
 
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.
 
1751
 
 
1752
Examples when a call to this function can be necessary:
 
1753
 
 
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!
 
1759
 
 
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'.
 
1764
 
 
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.
 
1768
 
 
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."
 
1772
  (interactive)
 
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))))
 
1780
 
 
1781
 
 
1782
(defvar ecb-auto-expand-tag-tree-old 'expand-spec)
 
1783
 
 
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
 
1789
by this command."
 
1790
  (interactive "P")
 
1791
  (let* ((new-value (if (null arg)
 
1792
                        (if ecb-auto-expand-tag-tree
 
1793
                            (progn
 
1794
                              (setq ecb-auto-expand-tag-tree-old
 
1795
                                    ecb-auto-expand-tag-tree)
 
1796
                              nil)
 
1797
                          ecb-auto-expand-tag-tree-old)
 
1798
                      (if (<= (prefix-numeric-value arg) 0)
 
1799
                          (progn
 
1800
                            (if ecb-auto-expand-tag-tree
 
1801
                                (setq ecb-auto-expand-tag-tree-old
 
1802
                                      ecb-auto-expand-tag-tree))
 
1803
                            nil)
 
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")
 
1809
             new-value)))
 
1810
 
 
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))
 
1814
 
 
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)))
 
1826
             )
 
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
 
1840
                 ;; again.
 
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
 
1847
                    100
 
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))
 
1851
                   )))))))))
 
1852
 
 
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)))
 
1864
             )
 
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
 
1878
                 ;; again.
 
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
 
1885
                    100
 
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))
 
1889
                   )))))))))
 
1890
 
 
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)))
 
1900
 
 
1901
 
 
1902
(defun ecb-string-make-singular (string)
 
1903
  (if (equal (aref string (1- (length string))) ?s)
 
1904
      (substring string 0 (1- (length string)))
 
1905
    string))
 
1906
 
 
1907
 
 
1908
(defun ecb-methods-node-get-semantic-type (node symbol->name-assoc-list)
 
1909
  (cond ((= 1 (tree-node-get-type node))
 
1910
         (let ((bucket-name
 
1911
                (save-match-data
 
1912
                  (if (string-match (concat (regexp-quote (nth 0 ecb-bucket-node-display))
 
1913
                                            "\\(.+\\)"
 
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)
 
1920
                                                                     bucket-name)
 
1921
                                                            (car 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))))
 
1932
        (t nil)))
 
1933
 
 
1934
 
 
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.
 
1940
 
 
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.
 
1944
 
 
1945
Nodes which are not indented have indentation-level 0!
 
1946
 
 
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.
 
1951
 
 
1952
Examples:
 
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
 
1955
  twice
 
1956
- LEVEL ~ 10 should normally expand all nodes unless there are nodes which
 
1957
  are indented deeper than 10.
 
1958
 
 
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].
 
1962
 
 
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!"
 
1966
  (interactive "P")
 
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: "
 
1972
                 (if (and first-node
 
1973
                          (tree-node-is-expandable first-node)
 
1974
                          (tree-node-is-expanded first-node))
 
1975
                     -1
 
1976
                   10))))
 
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)))
 
1985
 
 
1986
 
 
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.
 
1989
 
 
1990
For description of LEVEL and FORCE-ALL see `ecb-expand-methods-nodes'.
 
1991
 
 
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.
 
1994
 
 
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.
 
2001
         (or (save-excursion
 
2002
               (ignore-errors
 
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
 
2017
          level
 
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)))))
 
2031
 
 
2032
    ;; we want resync the new method-buffer to the current tag in the
 
2033
    ;; edit-window.
 
2034
    (if resync-tag (ecb-tag-sync 'force))))
 
2035
 
 
2036
 
 
2037
(defun ecb-normalize-expand-spec (spec)
 
2038
  (if (equal 'all spec)
 
2039
      'all
 
2040
    (mapcar (function (lambda (elem)
 
2041
                        (intern
 
2042
                         (downcase (ecb-string-make-singular
 
2043
                                    (symbol-name elem))))))
 
2044
            spec)))
 
2045
 
 
2046
;; semantic 1.X does not have this
 
2047
(silentcomp-defvar semanticdb-search-system-databases)
 
2048
 
 
2049
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Maybe an option for searching
 
2050
;; system dbs too?!
 
2051
(defun ecb-semanticdb-get-type-definition-list (typename &optional
 
2052
                                                         search-system-dbs)
 
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)))
 
2063
          (when search-result
 
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
 
2073
                   ;; some paranoia
 
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))
 
2081
                            'type)
 
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
 
2092
          ;; package/library.
 
2093
          (delq nil
 
2094
                (mapcar (function (lambda (n)
 
2095
                                    (let ((r (ecb--semanticdb-find-result-nth
 
2096
                                              search-result n)))
 
2097
                                      (if (and (cdr r)
 
2098
                                               (stringp (cdr r))
 
2099
                                               (file-readable-p (cdr r)))
 
2100
                                          (cons (cdr r) (car r))))))
 
2101
                        type-tag-numbers)))))))
 
2102
 
 
2103
(defun ecb-semanticdb-get-type-definition (typename &optional
 
2104
                                                    search-system-dbs)
 
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
 
2112
      ;; choose one.
 
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)))))
 
2118
    
 
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."
 
2124
  (if shift-mode
 
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)
 
2129
        tag found)
 
2130
    ;; Klaus Berndl <klaus.berndl@sdm.de>: We must highlight the tag
 
2131
    (tree-buffer-highlight-node-data data)
 
2132
    (cond
 
2133
     ;; Type 0 = a tag
 
2134
     ((= type 0)
 
2135
      (setq tag data)
 
2136
      ;; If we have a virtual faux-group type-tag then we try to find it via
 
2137
      ;; semanticdb
 
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))))
 
2142
          (when faux-group
 
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
 
2147
     ((= type 1)
 
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
 
2154
     ((= type 2)
 
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
 
2159
      (when (not found)
 
2160
        (let ((parent (ecb-semanticdb-get-type-definition data)))
 
2161
          (when parent
 
2162
            (setq tag (cdr parent))
 
2163
            (setq filename (car parent))))))
 
2164
     )
 
2165
    (when (and tag (not found))
 
2166
      (ecb-semantic-assert-valid-tag tag)
 
2167
      (if (eq 'include (ecb--semantic-tag-class tag))
 
2168
          (progn
 
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
 
2175
                         tag
 
2176
                         (ecb-get-edit-window
 
2177
                          (ecb-combine-ecb-button/edit-win-nr
 
2178
                           ecb-button edit-window-nr))
 
2179
                         no-post-action
 
2180
                         (if (and shift-mode
 
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))))))
 
2186
 
 
2187
 
 
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
 
2191
like:
 
2192
    void
 
2193
    ClassX::methodM\(arg1...)
 
2194
    \{
 
2195
      ...
 
2196
    \}
 
2197
Here we want to jump to the line \"ClassX::...\" and not to line \"void\".
 
2198
 
 
2199
Returns point."
 
2200
  (goto-char (ecb-semantic-tag-start tag))
 
2201
  (beginning-of-line)
 
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
 
2210
  ;; search.
 
2211
  (search-forward (ecb--semantic-tag-name tag)
 
2212
                  (max (ecb-line-end-pos)
 
2213
                       (ecb-semantic-tag-end tag))
 
2214
                  t)
 
2215
  (beginning-of-line-text)
 
2216
  (point))
 
2217
 
 
2218
 
 
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.
 
2223
  ;; in elisp
 
2224
  (let ((comment (ignore-errors (ecb--semantic-documentation-for-tag tag
 
2225
                                                                     'flex))))
 
2226
    (if (and comment
 
2227
             (not (stringp comment)))
 
2228
        ;; probably we have a semantic flex-object
 
2229
        (ecb--semantic-lex-token-start comment))))
 
2230
 
 
2231
 
 
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.
 
2237
 
 
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!
 
2241
 
 
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'!
 
2245
 
 
2246
Returns current point."
 
2247
  (let ((tag-doc-start  (ecb-start-of-tag-doc tag)))
 
2248
    (when tag-doc-start
 
2249
      (goto-char tag-doc-start))
 
2250
    (point)))
 
2251
 
 
2252
 
 
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).")
 
2256
 
 
2257
 
 
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))
 
2266
 
 
2267
 
 
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"
 
2271
  (save-excursion
 
2272
    (ecb-tag-visit-smart-tag-start tag)
 
2273
    (ecb-overlay-move ecb-method-overlay
 
2274
                      (ecb-line-beginning-pos)
 
2275
                      (ecb-line-end-pos)
 
2276
                      (current-buffer)))
 
2277
  (setq ecb-unhighlight-hook-called nil)
 
2278
  (add-hook 'pre-command-hook 'ecb-unhighlight-tag-header)
 
2279
  (point))
 
2280
 
 
2281
 
 
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."
 
2295
                filename))
 
2296
        ((not (ecb--semantic-tag-with-position-p tag))
 
2297
         nil)
 
2298
        (t
 
2299
         (unless window
 
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
 
2307
             (push-mark nil t))
 
2308
         (ecb-with-original-basic-functions
 
2309
          (widen))
 
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)))
 
2315
             (funcall f tag))
 
2316
           ;; now the mode specific actions
 
2317
           (dolist (f (cdr (assoc major-mode ecb-tag-visit-post-actions)))
 
2318
             (funcall f tag)))
 
2319
         ;; now we perform the additional-post-action-list
 
2320
         (dolist (f additional-post-action-list)
 
2321
           (funcall f tag))
 
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)
 
2328
                             (current-buffer)))
 
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
 
2335
                              tag-name
 
2336
                              tag-buf
 
2337
                              tag-start
 
2338
                              tag-end
 
2339
                              ecb-buffer-narrowed-by-ecb))))))
 
2340
 
 
2341
 
 
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))
 
2351
               (concat
 
2352
                (tree-node-get-name node)
 
2353
                (if (and (= 0 (tree-node-get-type node)) (tree-node-get-data
 
2354
                                                          node)
 
2355
                         (equal (ecb-show-node-info-what ecb-methods-buffer-name)
 
2356
                                'name+type))
 
2357
                    (concat ", "
 
2358
                            (symbol-name (ecb--semantic-tag-class (tree-node-get-data node))))
 
2359
                  "")))))
 
2360
    (prog1 str
 
2361
      (unless no-message
 
2362
        (tree-buffer-nolog-message str)))))
 
2363
 
 
2364
;;; popup-menu stuff for the methods-buffer
 
2365
 
 
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)
 
2372
 
 
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))
 
2376
 
 
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))
 
2380
 
 
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))
 
2384
 
 
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))
 
2388
 
 
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.
 
2394
 
 
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
 
2402
    ;; nil! 
 
2403
    (setq ecb-buffer-narrowed-by-ecb t))
 
2404
  (point))
 
2405
 
 
2406
 
 
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'
 
2412
too!
 
2413
 
 
2414
Returns current point."
 
2415
  (set-window-start
 
2416
   (selected-window)
 
2417
   (ecb-line-beginning-pos (- (/ (ecb-window-full-height) 2))))
 
2418
  (point))
 
2419
 
 
2420
 
 
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!
 
2426
 
 
2427
Returns current point."
 
2428
  (set-window-start (selected-window)
 
2429
                    (ecb-line-beginning-pos)))
 
2430
 
 
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)))
 
2435
 
 
2436
 
 
2437
(tree-buffer-defpopup-command ecb-methods-menu-widen
 
2438
  "Widen the current buffer in the current edit-window."
 
2439
  (ecb-select-edit-window)
 
2440
  (widen)
 
2441
  (setq ecb-buffer-narrowed-by-ecb nil))
 
2442
 
 
2443
 
 
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))
 
2449
 
 
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."
 
2453
  (save-excursion
 
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)
 
2458
            (progn
 
2459
              (hs-minor-mode 1)
 
2460
              t)
 
2461
          nil)
 
2462
      t)))
 
2463
 
 
2464
 
 
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))
 
2471
    (save-excursion
 
2472
      (or (looking-at hs-block-start-regexp)
 
2473
          (re-search-forward hs-block-start-regexp nil t))
 
2474
      (hs-show-block))
 
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))))
 
2478
 
 
2479
 
 
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))
 
2486
    (save-excursion
 
2487
      (or (looking-at hs-block-start-regexp)
 
2488
          (re-search-forward hs-block-start-regexp nil t))
 
2489
      (hs-hide-block))
 
2490
    (ecb-tag-visit-highlight-tag-header (tree-node-get-data node))))
 
2491
 
 
2492
 
 
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))
 
2496
 
 
2497
 
 
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))
 
2501
 
 
2502
 
 
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))
 
2506
 
 
2507
 
 
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))
 
2511
 
 
2512
 
 
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))
 
2516
 
 
2517
 
 
2518
(defvar ecb-common-methods-menu nil
 
2519
  "Built-in menu for the methods-buffer.")
 
2520
 
 
2521
 
 
2522
(setq ecb-common-methods-menu
 
2523
      '( ;;("---")
 
2524
        ("Expand/Collapse"
 
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"))
 
2530
        ("---")
 
2531
        (ecb-maximize-ecb-window-menu-wrapper "Maximize window")))
 
2532
 
 
2533
 
 
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"))
 
2539
                ("Narrow/Widen"
 
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))
 
2543
 
 
2544
 
 
2545
(defvar ecb-methods-menu-title-creator
 
2546
  (function (lambda (node)
 
2547
              (let ((data (tree-node-get-data node)))
 
2548
                (if data
 
2549
                    (cond ((ecb--semantic-tag-p data)
 
2550
                           (ecb--semantic-tag-name data))
 
2551
                          ((stringp data)
 
2552
                           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'.")
 
2557
 
 
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))
 
2582
 
 
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))
 
2587
        (result nil))
 
2588
    (when (> (length edit-win-list) 1)
 
2589
      (dotimes (i (min 8 (length edit-win-list)))
 
2590
        (setq result
 
2591
              (append result
 
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 ...")
 
2596
                            result))))))
 
2597
 
 
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
 
2606
                               'identity)
 
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
 
2612
                               'identity)
 
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
 
2617
                               'identity)
 
2618
                           (append dyn-user-extension
 
2619
                                   ecb-methods-menu-user-extension
 
2620
                                   ecb-common-methods-menu))))))
 
2621
 
 
2622
 
 
2623
(defun ecb-dump-semantic-toplevel ()
 
2624
  "Dump the current semantic-tags in special buffer and display them."
 
2625
  (interactive)
 
2626
  (let ((tags (ecb-post-process-taglist (ecb--semantic-bovinate-toplevel t))))
 
2627
    (save-selected-window
 
2628
      (set-buffer (get-buffer-create "ecb-dump"))
 
2629
      (erase-buffer)
 
2630
      (ecb-dump-tags tags "")
 
2631
      (switch-to-buffer-other-window (get-buffer-create "ecb-dump"))
 
2632
      (goto-char (point-min)))))
 
2633
 
 
2634
 
 
2635
(defun ecb-dump-type (a-tag prefix)
 
2636
  (dolist (parent (ecb-get-tag-parents a-tag))
 
2637
    (insert prefix "  " parent)))
 
2638
 
 
2639
 
 
2640
(defun ecb-dump-tags (tags prefix)
 
2641
  (dolist (a-tag tags)
 
2642
    (if (stringp a-tag)
 
2643
        (princ (concat prefix a-tag))
 
2644
      (insert prefix
 
2645
              (ecb--semantic-format-tag-name a-tag nil ecb-font-lock-tags)
 
2646
              ", "
 
2647
              (symbol-name (ecb--semantic-tag-class a-tag))
 
2648
              ", "
 
2649
              (if (stringp (ecb--semantic-tag-type a-tag))
 
2650
                  (ecb--semantic-tag-type a-tag)
 
2651
                "<unknown type>")
 
2652
              "\n")
 
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 "  ")))))
 
2658
 
 
2659
(silentcomp-provide 'ecb-method-browser)
 
2660
 
 
2661
;;; ecb-method-browser.el end here