-
Notifications
You must be signed in to change notification settings - Fork 0
/
ecb-method-browser.el
4798 lines (4304 loc) · 239 KB
/
ecb-method-browser.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;; ecb-method-browser.el --- the method-browser of Emacs
;; Copyright (C) 2000 - 2005 Jesper Nordenberg,
;; Klaus Berndl,
;; Free Software Foundation, Inc.
;; Author: Jesper Nordenberg <[email protected]>
;; Klaus Berndl <[email protected]>
;; Maintainer: Klaus Berndl <[email protected]>
;; Keywords: browser, code, programming, tools
;; Created: 2000
;; This program is free software; you can redistribute it and/or modify it under
;; the terms of the GNU General Public License as published by the Free Software
;; Foundation; either version 2, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
;; details.
;; You should have received a copy of the GNU General Public License along with
;; GNU Emacs; see the file COPYING. If not, write to the Free Software
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;; $Id: ecb-method-browser.el,v 1.99 2010/02/23 16:09:05 berndl Exp $
;;; Commentary:
;; This file contains the code for the method-browser of ECB
(require 'tree-buffer)
(require 'ecb-util)
(require 'ecb-layout)
(require 'ecb-mode-line)
(require 'ecb-navigate)
(require 'ecb-face)
(require 'ecb-speedbar)
(require 'ecb-common-browser)
(require 'ecb-speedbar)
(require 'ecb-cedet-wrapper)
(require 'ecb-semantic)
;; This loads the semantic-setups for the major-modes.
;; (require 'semantic-load)
;; various loads
(require 'assoc)
(eval-when-compile
;; to avoid compiler grips
(require 'cl))
(eval-when-compile
(require 'silentcomp))
(silentcomp-defun hs-minor-mode)
(silentcomp-defun hs-show-block)
(silentcomp-defun hs-hide-block)
(silentcomp-defvar hs-minor-mode)
(silentcomp-defvar hs-block-start-regexp)
(silentcomp-defvar imenu--index-alist)
(silentcomp-defvar semantic-idle-scheduler-mode)
(silentcomp-defun ecb-get-tags-for-non-semantic-files)
(silentcomp-defun ecb-create-non-semantic-tree)
(defvar ecb-selected-tag nil
"The currently selected Semantic tag.")
(make-variable-buffer-local 'ecb-selected-tag)
(defvar ecb-methods-root-node nil
"Path to currently selected source.")
(defconst ecb-methods-nodetype-tag 0)
(defconst ecb-methods-nodetype-bucket 1)
(defconst ecb-methods-nodetype-externtag 2)
(defun ecb-method-browser-initialize-caches ()
"Initialize the caches of the method-browser of ECB."
(ecb-clear-tag-tree-cache))
(defun ecb-method-browser-initialize (&optional no-caches)
"Initialize the method-browser of ECB. If optional arg NO-CACHES is not nil
then the caches used by the method-browser will not be initialized."
(setq ecb-selected-tag nil)
(setq ecb-methods-root-node nil)
(setq ecb-methods-user-filter-alist nil)
(setq ecb-current-post-processed-tag-table nil)
(unless no-caches
(ecb-method-browser-initialize-caches)))
;;====================================================
;; Customization
;;====================================================
(defgroup ecb-methods nil
"Settings for the methods-buffer in the Emacs code browser."
:group 'ecb
:prefix "ecb-")
(defgroup ecb-non-semantic nil
"Settings for parsing and displaying non-semantic files."
:group 'ecb
:prefix "ecb-")
(defcustom ecb-methods-buffer-name " *ECB Methods*"
"*Name of the ECB methods buffer.
Because it is not a normal buffer for editing you should enclose the name with
stars, e.g. \"*ECB Methods*\".
If it is necessary for you you can get emacs-lisp access to the buffer-object of
the ECB-methods-buffer by this name, e.g. by a call of `set-buffer'.
Changes for this option at runtime will take affect only after deactivating and
then activating ECB again!"
:group 'ecb-methods
:type 'string)
(defcustom ecb-auto-expand-tag-tree 'expand-spec
"*Expand the methods-tag-tree automatically if node invisible.
This option has only an effect if option `ecb-highlight-tag-with-point' is
switched on too. There are three possible choices:
- nil: No auto. expanding of the method buffer.
- expand-spec: Auto expand the method-buffer nodes if the node belonging to
current tag under point is invisible because its parent-node is collapsed.
But expanding is only done if the type of the tag under point in the
edit-buffer is contained in `ecb-methods-nodes-expand-spec'.
- all: Like expand-spec but expands all tags regardless of the setting in
`ecb-methods-nodes-expand-spec'.
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:type '(radio (const :tag "No auto. expand" :value nil)
(const :tag "Expand as specified" :value expand-spec)
(const :tag "Expand all" :value all)))
(defcustom ecb-auto-expand-tag-tree-collapse-other nil
"*Auto. expanding the tag-tree collapses all not related nodes.
There are several choices:
- Only if on tag: This means collapsing all nodes which have no relevance for
the currently highlighted node will be collapsed, because they are not
necessary to make the highlighted node visible. But do this only if point
stays onto a tag in the selected edit-window.
- Always: Same as before but collapse also when point doesn't stays on a tag
\(e.g. between two defuns in elisp) in the selected edit-window. This means
in such a situation a full collapsing of the methods-buffer.
- Never: Do not automatically collapse the methods-buffer."
:group 'ecb-methods
:type '(radio (const :tag "Collapse only when point stays on a tag"
:value only-if-on-tag)
(const :tag "Collapse always" :value always)
(const :tag "Never" :value nil)))
(defcustom ecb-expand-methods-switch-off-auto-expand t
"*Switch off auto expanding in the ECB-method buffer.
If on then auto expanding is switched off after explicit expanding or
collapsing by `ecb-expand-methods-nodes'.
This is done with `ecb-toggle-auto-expand-tag-tree' so after the switch off
the auto expanding feature can again switched on quickly.
But after explicitly expanding/collapsing the methods-buffer to a certain
level the auto. expanding could undo this when the node belonging to current
tag under point in the edit-window is invisible after
`ecb-expand-methods-nodes' - then the auto. expand feature would make this
node immediately visible and destroys the explicitly set expand-level."
:group 'ecb-methods
:type 'boolean)
(defcustom ecb-auto-update-methods-after-save nil
"*Automatically updating the ECB method buffer after saving a source."
:group 'ecb-methods
:type 'boolean)
(defcustom ecb-font-lock-tags t
"*Adds font-locking \(means highlighting) to the ECB-method buffer.
This options takes only effect for semantic-sources \(ie. sources supported
by semantic!) and if the font-lock-feature is loaded."
:group 'ecb-methods
:set (function (lambda (symbol value)
(set symbol value)
(ecb-clear-tag-tree-cache)))
:type 'boolean
:initialize 'custom-initialize-default)
(defsubst ecb-font-lock-tags ()
"Returns not nil if `ecb-font-lock-tags' is not nil and font-lock loaded."
(and ecb-font-lock-tags
(featurep 'font-lock)))
(defcustom ecb-tag-jump-sets-mark t
"*Set the mark after jumping to a tag from the ECB-method buffer.
If set the user can easily jump back."
:group 'ecb-methods
:type 'boolean)
(defconst ecb-tag->text-functions
(mapcar (lambda (fkt-elem)
(cons (intern
(concat "ecb-"
(mapconcat 'identity
(cdr (split-string (symbol-name fkt-elem) "-"))
"-")))
(intern
(concat "ecb--" (symbol-name fkt-elem)))))
ecb--semantic-format-function-list)
"Alist containing one element for every member of
`ecb--semantic-format-function-list'")
(defcustom ecb-tag-display-function '((default . ecb-format-tag-uml-prototype))
"*Function to use for displaying tags in the methods buffer.
This functionality is set on major-mode base, i.e. for every major-mode a
different function can be used. The value of this option is a list of
cons-cells:
- The car is either a major-mode symbol or the special symbol 'default which
means if no function for a certain major-mode is defined then the cdr of
the 'default cons-cell is used.
- The cdr is the function used for displaying a tag in the related
major-mode.
Every function is called with 3 arguments:
1. The tag
2. The parent-tag of tag \(can be nil)
3. The value of the function `ecb-font-lock-tags'.
Every function must return the display of the tag as string, colorized if
the third argument is not nil.
The following functions are predefined:
- For each element E of `ecb--semantic-format-function-list' exists a
function with name \"ecb--<E>\". These functions are just aliase to
the builtin format-functions of semantic. See the docstring of these
functions to see what they do.
Example: `semantic-format-tag-name' is an
element of `ecb--semantic-format-function-list'. Therefore the
alias-function for this element is named `ecb--semantic-format-tag-name'.
- For each element in `ecb--semantic-format-function-list' with name
\"semantic-XYZ\" a function with name \"ecb-XYC\" is predefined. The
differences between the semantic- and the ECB-version are:
+ The ECB-version displays for type tags only the type-name and nothing
else \(exceptions: In c++-mode a template specifier is appended to the
type-name if a template instead a normal class. If the tag-name of a
type-tag is the empty-string \(tag has no name) then always the
type-specifier is displayed - see `ecb-type-tag-display'.).
+ The ECB-version displays type-tags according to the setting in
`ecb-type-tag-display'. This is useful for better recognizing
different classes, structs etc. in the ECB-method window.
For all tags which are not types the display of the ECB-version is
identical to the semantic version. Example: For
`ecb--semantic-format-tag-name' \(the builtin semantic formatter) the
pendant is `ecb-format-tag-name'.
This functionality also allows the user to display tags as UML. To enable
this functionality set the function for a major-mode \(e.g. `jde-mode') to
`ecb--semantic-format-tag-uml-concise-prototype',
`ecb--semantic-format-tag-uml-prototype', or
`ecb--semantic-format-tag-uml-abbreviate' the ECB-versions of these functions.
If the value is nil, i.e. neither a function for a major-mode is defined nor
the special 'default, then `ecb--semantic-format-tag-prototype' is used for
displaying the tags.
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:group 'ecb-most-important
:set (function (lambda (symbol value)
(set symbol value)
(ecb-clear-tag-tree-cache)))
:type (list 'repeat ':tag "Display functions per mode"
(list 'cons ':tag "Mode tag display"
'(symbol :tag "Major mode")
(nconc (list 'choice ':tag "Display function"
':menu-tag '"Display function")
(append
(mapcar (lambda (f)
(list 'const ':tag
(symbol-name (car f)) (car f)))
ecb-tag->text-functions)
(mapcar (lambda (f)
(list 'const ':tag
(symbol-name (cdr f)) (cdr f)))
ecb-tag->text-functions)
(list '(function :tag "Function"))))))
:initialize 'custom-initialize-default)
(defun ecb-get-tag-display-function ()
(let ((mode-display-fkt (cdr (assoc major-mode ecb-tag-display-function)))
(default-fkt (cdr (assoc 'default ecb-tag-display-function))))
(or (and (fboundp mode-display-fkt) mode-display-fkt)
(and (fboundp default-fkt) default-fkt)
'ecb--semantic-format-tag-prototype)))
(defcustom ecb-type-tag-display nil
"*How to display semantic type-tags in the methods buffer.
Normally all tag displaying, colorizing and facing is done by semantic
according to the value of `ecb--semantic-format-face-alist' and the semantic
display-function \(e.g. one from `ecb--semantic-format-function-list'). But
sometimes a finer distinction in displaying the different type specifiers of
type-tags can be useful. For a description when this option is evaluated look
at `ecb-tag-display-function'!
This functionality is set on a major-mode base, i.e. for every major-mode a
different setting can be used. The value of this option is a list of
cons-cells:
- The car is either a major-mode symbol or the special symbol 'default which
means if no setting for a certain major-mode is defined then the cdr of
the 'default cons-cell is used.
- The cdr is a list of 3-element-lists:
1. First entry is a semantic type specifier in string-form. Current
available type specifiers are for example \"class\", \"interface\",
\"struct\", \"typedef\", \"union\" and \"enum\". In addition to these
ones there is also a special ECB type specifier \"group\" which is
related to grouping tags \(see `ecb-post-process-semantic-taglist' and
`ecb-group-function-tags-with-parents'). Any arbitrary specifier can be
set here but if it is not \"group\" or not known by semantic it will be
useless.
2. Second entry is a flag which indicates if the type-specifier string from
\(1.) itself should be removed \(if there is any) from the display.
3. Third entry is the face which is used in the ECB-method window to display
type-tags with this specifier. ECB has some predefined faces for this
\(`ecb-type-tag-class-face', `ecb-type-tag-interface-face',
`ecb-type-tag-struct-face', `ecb-type-tag-typedef-face',
`ecb-type-tag-union-face', `ecb-type-tag-enum-face' and
`ecb-type-tag-group-face') but any arbitrary face can be set here. This
face is merged with the faces semantic already uses to display a tag,
i.e. the result is a display where all face-attributes of the ECB-face
take effect plus all face-attributes of the semantic-faces which are not
set in the ECB-face \(with XEmacs this merge doesn't work so here the
ECB-face replaces the semantic-faces; this may be fixed in future
versions).
The default value is nil means there is no special ECB-displaying of
type-tags in addition to the displaying and colorizing semantic does. But a
value like the following could be a useful setting:
\(\(default
\(\"class\" t ecb-type-tag-class-face)
\(\"group\" nil ecb-type-tag-group-face))
\(c-mode
\(\"struct\" nil ecb-type-tag-struct-face)
\(\"typedef\" nil ecb-type-tag-typedef-face)))
This means that in `c-mode' only \"struct\"s and \"typedef\"s are displayed
with special faces \(the specifiers itself are not removed) and in all other
modes \"class\"es and grouping-tags \(see `ecb-tag-display-function',
`ecb-group-function-tags-with-parents') have special faces and the \"class\"
specifier-string is removed from the display.
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:group 'ecb-most-important
:set (function (lambda (symbol value)
(set symbol value)
(ecb-clear-tag-tree-cache)))
:type '(repeat (cons (symbol :tag "Major-mode")
(repeat :tag "Display of type specifiers"
(list (choice :tag "Specifier list"
:menu-tag "Specifier list"
(const :tag "class"
:value "class")
(const :tag "interface"
:value "interface")
(const :tag "struct"
:value "struct")
(const :tag "typedef"
:value "typedef")
(const :tag "union"
:value "union")
(const :tag "enum"
:value "enum")
(const :tag "group"
:value "group")
(string :tag "Any specifier"))
(boolean :tag "Remove the type-specifier" t)
(face :tag "Any face"
:value ecb-type-tag-class-face)))))
:initialize 'custom-initialize-default)
(defun ecb-get-face-for-type-tag (type-specifier)
"Return the face set in `ecb-type-tag-display' for current major-mode and
TYPE-SPECIFIER or nil."
(let ((mode-display (cdr (assoc major-mode ecb-type-tag-display)))
(default-display (cdr (assoc 'default ecb-type-tag-display))))
(or (nth 2 (assoc type-specifier mode-display))
(and (null mode-display)
(nth 2 (assoc type-specifier default-display))))))
(defun ecb-get-remove-specifier-flag-for-type-tag (type-specifier)
"Return the remove-specifier-flag set in `ecb-type-tag-display' for
current major-mode and TYPE-SPECIFIER or nil."
(let ((mode-display (cdr (assoc major-mode ecb-type-tag-display)))
(default-display (cdr (assoc 'default ecb-type-tag-display))))
(or (nth 1 (assoc type-specifier mode-display))
(and (null mode-display)
(nth 1 (assoc type-specifier default-display))))))
(defcustom ecb-type-tag-expansion
'((default . ("class" "interface" "group" "namespace"))
(c-mode . ("struct")))
"*Default expansion of semantic type-tags.
Semantic groups type-tags into different type-specifiers. Current available
type specifiers are for example \"class\", \"interface\", \"struct\",
\"typedef\", \"union\" and \"enum\". In addition to these ones there is also a
special ECB type specifier \"group\" which is related to grouping tags \(see
`ecb-post-process-semantic-taglist').
This option defines which type-specifiers should be expanded at
file-open-time. Any arbitrary specifier can be set here but if it is not
\"group\" or not known by semantic it will be useless.
This functionality is set on a major-mode base, i.e. for every major-mode a
different setting can be used. The value of this option is a list of
cons-cells:
- The car is either a major-mode symbol or the special symbol 'default which
means if no setting for a certain major-mode is defined then the cdr of
the 'default cons-cell is used.
- The cdr is either a list of type-specifiers which should be expanded at
file-open-time or the symbol 'all-specifiers \(then a type-tag is always
expanded regardless of its type-specifier).
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:group 'ecb-most-important
:type '(repeat (cons (symbol :tag "Major-mode")
(radio (const :tag "Expand all type-specifiers"
:value all-specifiers)
(repeat :tag "Expand type specifiers"
(choice :tag "Specifier"
:menu-tag "Specifier"
(const :tag "class"
:value "class")
(const :tag "interface"
:value "interface")
(const :tag "struct"
:value "struct")
(const :tag "typedef"
:value "typedef")
(const :tag "union"
:value "union")
(const :tag "enum"
:value "enum")
(const :tag "group"
:value "group")
(string :tag "Any specifier"))))))
:set (function (lambda (symbol value)
(set symbol value)
(ecb-clear-tag-tree-cache)))
:initialize 'custom-initialize-default)
(defun ecb-type-tag-expansion (type-specifier)
"Return the default expansion-state of TYPE-SPECIFIER for current major-mode
as specified in `ecb-type-tag-expansion'"
(let ((mode-expansion (cdr (assoc major-mode ecb-type-tag-expansion)))
(default-expansion (cdr (assoc 'default ecb-type-tag-expansion))))
(or (equal mode-expansion 'all-specifiers)
(member type-specifier mode-expansion)
(and (null mode-expansion)
(or (equal default-expansion 'all-specifiers)
(member type-specifier default-expansion))))))
(defun ecb-get-type-specifier (tag)
(if (ecb--semantic-tag-faux-p tag)
"group"
(ecb--semantic-tag-type tag)))
(dolist (elem ecb-tag->text-functions)
(fset (car elem)
`(lambda (tag &optional parent-tag colorize)
(if (eq 'type (ecb--semantic-tag-class tag))
(let* (;; we must here distinguish between UML- and
;; not-UML-semantic functions because for UML we must
;; preserve some semantic facing added by semantic (e.g.
;; italic for abstract classes)!
(text (funcall (if (save-match-data
(string-match "-uml-" (symbol-name (quote ,(car elem)))))
'ecb--semantic-format-tag-uml-abbreviate
'ecb--semantic-format-tag-name)
tag parent-tag colorize))
(type-specifier (ecb-get-type-specifier tag))
(face (ecb-get-face-for-type-tag type-specifier))
(remove-flag (ecb-get-remove-specifier-flag-for-type-tag
type-specifier)))
(save-match-data
;; the following is done to replace the "struct" from
;; grouping tags (see
;; ecb-group-function-tags-with-parents) with "group".
;; This code can be removed (or changed) if semantic allows
;; correct protection display for function-tags with
;; parent-tag.
(when (ecb--semantic-tag-faux-p tag)
(save-match-data
(if (string-match (concat "^\\(.+"
(ecb--semantic-uml-colon-string)
"\\)\\("
(if (ecb--semantic-tag-faux-p tag)
(ecb--semantic-orphaned-member-metaparent-type)
"struct")
"\\)") text)
(let ((type-spec-text "group"))
(put-text-property 0 (length type-spec-text)
'face
(get-text-property
0 'face
(match-string 2 text))
type-spec-text)
(setq text (concat (match-string 1 text)
type-spec-text))))))
;; Now we must maybe add a template-spec in c++-mode and
;; maybe remove the type-specifier string.
(let (col-type-name col-type-spec template-text)
(save-match-data
(if (string-match (concat "^\\(.+\\)\\("
(ecb--semantic-uml-colon-string)
type-specifier "\\)")
text)
(setq col-type-name (match-string 1 text)
col-type-spec (if (not remove-flag)
(match-string 2 text)))
;; necessary for anonymous types like unnamed enums etc...
(setq col-type-spec (if (= (length text) 0)
type-specifier
nil))
(setq col-type-name text)))
(when (equal major-mode 'c++-mode)
(setq template-text (ecb--semantic-c-template-string
tag parent-tag colorize))
;; Removing {...} from within the template-text.
;; Normally the semantic-formatters should not add this
;; ugly stuff.
(save-match-data
(if (string-match "^\\(.+\\){.*}\\(.+\\)$" template-text)
(setq template-text
(concat (match-string 1 template-text)
(match-string 2 template-text)))))
(put-text-property 0 (length template-text)
'face
(get-text-property
(1- (length col-type-name)) 'face
col-type-name)
template-text))
(setq text (concat col-type-name template-text
col-type-spec))))
;; now we add some own colorizing if necessary
(if face
(ecb-merge-face-into-text text face))
text)
(funcall (quote ,(cdr elem)) tag parent-tag colorize)))))
(defcustom ecb-find-external-tag-functions
(list (cons 'default
(list (if (fboundp 'semantic-calculate-scope)
'ecb-search-type-tag-by-semantic-analyzer
'ecb-search-type-tag-by-semanticdb)))
(cons 'jde-mode (list 'ecb-jde-show-class-source)))
"*Functions used for searching external tags clicked in the methods buffer.
The methods buffer displays for oo-languages the parents of a
type under a special bucket \"Parents\". Languages like C++, CLOS
and Eieio allow to define the implementation of a method outside
of the class definition and even in another file. In the
methods-buffer of ECB such externaly defined methods are
collected and displayed under a 'virtual' faux type-tag named as
the class-qualifier of the methods. This faux-tag is virtual
because it does not extist in the parsed buffer.
If a user clicks either onto such a faux-type-tag or onto a
parent-tag then ECB tries to find the definition of the
underlying type on a name-basis, displaying the containing file
as buffer in the current edit-window and jumping to the start of
the type-definition in this buffer.
Finding such external types can be very complex and there are
several roads to success. ECB uses per default methods based on
the semantic-analyzer. But this option allows to define own
find-functions and tell ECB to uses them.
This functionality is set on a `major-mode' base, i.e. for every
`major-mode' a different setting can be used. The value of this
option is a list of cons-cells:
- The car is either a `major-mode' symbol or the special symbol 'default.
- The cdr is a list of find-functions or nil.
ECB first performs all find-functions defined for current
`major-mode' \(if any) anf then all find-functions defined for
the special symbol 'default \(if any).
ECB offers some predefined senseful finding-functions. Currently there are:
- `ecb-search-type-tag-by-semantic-analyzer' (most powerful)
- `ecb-search-type-tag-by-semanticdb'
- `ecb-jde-show-class-source' (for major-mode `jde-mode' when coding in java)
This function does not only the searching but displays the founded tag.
See the documentation of these function for details how they work.
But you can add any arbitrary function if the following conditions are
fulfilled:
- The function gets a semantic tag representing the external type which should
be found. This is a positionless-tag \(otherwise it would not be hard to go
to it) and it's either a faux-tag \(for which `ecb--semantic-faux-tag-p' is
not nil; the function can use this check if necessary) or a simple tag
containing only a name an a tag-class. The tag-class for both is 'type.
- The return value of the function must be one of:
+ nil: No tag is found
+ t: A tag has been found and also be displayed in the edit-window \(this
prevents ECB from running further function of this option because the
searched tag is already displayed. So a function should only return t if
all is fine and no further actions are needed.
+ A positioned semantic tag \(for which `ecb--semantic-tag-with-position-p'
returns not nil) which represents the found external type-tag.
It's strongly recommended for the function not to display the found
location for itself but to return a positioned semantic tag! But sometimes
the displaying is integrated in a third-party find-function like
`jde-show-class-source' which is used by `ecb-jde-show-class-source'. In
these cases the function has to return t if the searched tag has been
successfully displayed.
Precondition for a find-function:
Current buffer is the buffer the clicked faux- or parent tag belongs to
Current point depends on the clicked tag:
- In case of a faux-tag it's the start of the first child of the
faux-tag. There must be at least one adopted child-tag because
otherwise we would not have the faux-tag
- In case of an external parent-tag its the the start of the
external tag itself."
:group 'ecb-methods
:type '(repeat (cons (symbol :tag "Major-mode or default")
(repeat (choice :tag "Find external tag function" :menu-tag "Function list"
(const :tag "ecb-search-type-tag-by-semantic-analyzer"
:value ecb-search-type-tag-by-semantic-analyzer)
(const :tag "ecb-search-type-tag-by-semanticdb"
:value ecb-search-type-tag-by-semanticdb)
(const :tag "ecb-jde-show-class-source"
:value ecb-jde-show-class-source)
(function :tag "Function"))))))
(defcustom ecb-display-image-icons-for-semantic-tags t
"*Display nice and pretty icons for semantic-tags in the Methods-buffer.
A non nil value takes only effect if Emacs can display images and if
`ecb-tree-buffer-style' is set to 'image."
:group 'ecb-methods
:type 'boolean)
(defsubst ecb-use-images-for-semantic-tags ()
(and ecb-display-image-icons-for-semantic-tags
(ecb-images-can-be-used)
(equal ecb-tree-buffer-style 'image)))
(defcustom ecb-post-process-semantic-taglist
'((c++-mode . (ecb-group-function-tags-with-parents))
(emacs-lisp-mode . (ecb-group-function-tags-with-parents))
(c-mode . (ecb-filter-c-prototype-tags)))
"*Define mode-dependent post-processing for the semantic-taglist.
This is an alist where the car is a major-mode symbol and the cdr is a list of
function-symbols of functions which should be used for post-processing the
taglist returned by semantic. for a buffer in this
major-mode. The first function in the list is called with current semantic
taglist of current buffer and must return a valid taglist again. All other
functions are called with the result-taglist of its preceding function and
have to return a new taglist again.
For oo-programming languages where the methods of a class can be defined
outside the class-definition \(e.g. C++, Eieio) the function
`ecb-group-function-tags-with-parents' can be used to get a much better
method-display in the methods-window of ECB, because all method
implementations of a class are grouped together.
Another senseful usage is to filter out certain tags, e.g. prototype tags in
`c-mode'. For this you can set `ecb-filter-c-prototype-tags'.
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:type '(repeat (cons (symbol :tag "Major-mode")
(repeat (function :tag "Post-process function")))))
(defcustom ecb-default-tag-filter nil
"*Default tag-filters for certain files.
This option allow to define default tag-filters for certain files which are
applied automatically after loading such a file into a buffer. The possible
filters are the same as offered by the command `ecb-methods-filter' and they
are applied in the same manner - the only difference is they are applied
automatically. Please be aware that symbol-filters \(e.g. protection-symbols
like public or private) must not be inserted with quotes whereas a
filter-regexp has to be inserted with surrounding double-quotes! In addition
backslashes in a regexp have to be doubled!
For each file-spec \(a major-mode plus a file-regexp which both specify a
file for which filters should be applied) there can be as much filters as
needed - they are layered like with `ecb-methods-filter' too.
Tag-classes which are completely hidden or excluded by the option
`ecb-show-tags' will never being displayed in the Methods-buffer regardless of
the filters of this option!"
:group 'ecb-methods
:type '(repeat (cons :tag "Default tag filter"
(cons :tag "Filespec"
(symbol :tag "Major-mode")
(regexp :tag "Filename-regexp"))
(repeat :tag "Default filters"
(list :tag "Filterspec"
(choice :tag "Filter-type"
:menu-tag "Filtertype"
(const :tag "Regexp" :value regexp)
(const :tag "Protection" :value protection)
(const :tag "Tag-class" :value tag-class)
(const :tag "Funtion" :value function))
(sexp :tag "Filter-value")
(boolean :tag "inverse"))))))
(defcustom ecb-show-only-positioned-tags nil
"*Show only nodes in the method-buffer which are \"jump-able\".
If not nil then ECB displays in the method-buffer only nodes which are
\"jump-able\", i.e. after selecting it by clicking or with RET then ECB jumps
to the corresponding location in the edit-window.
Example: With CLOS or Eieio source-code there can exist some position-less
nodes like variable-attributes in a `defclass' form which are only displayed
if this option is nil. Displaying such nodes can be senseful even if they can
not be jumped.
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:type 'boolean)
(defcustom ecb-force-reparse-when-semantic-idle-scheduler-off nil
"*Force a reparse of the semantic-source if the idle-scheduler is off.
Generally ECB calls semantic to get the list of tags for current source-file
of current edit-window. Per default ECB does never automatically force a
reparse of the source-file - this is only done on demand by calling
`ecb-rebuild-methods-buffer'. So per default the idle-scheduler of semantic is
responsible for reparsing the source-file and when this is necessary \(see
`semantic-idle-scheduler-mode' for further details). This is the most
user-resonsible and therefore the recommended approach. So it's strongly
recommended to enable `semantic-idle-scheduler-mode' because then reparsing is
always done during idle-time of Emacs and is also interruptable.
But if this idle-scheduler is switched off then ECB offers two possibilities
\(with this option):
- Not forcing itself a reparse when tags are needed by ECB: then a user
declines knowingly Emacs/semantic-driven parsing of code when he/she
switches off the idle-mode of semantic. This is the default behavior of ECB
and the default value of this option. But this has also the consequence that
the methods-buffer is only filed on demand via `ecb-rebuild-methods-buffer'
\(bound to \[C-c . r])!
- Forcing a reparse when tags are needed: Then ECB forces semantic to parse
the source-file when ECB needs tags to display. For this behavior this
option has to be set to not nil.
Note 1: This option takes only effect when `semantic-idle-scheduler-mode' is
not enabled!
Note 2: The term \"forcing a reparse by semantic\" is a simplification:
It uses the function `semantic-fetch-tags' which can decide that the cached
tags are up-to-date so no real reparsing is necessary - but it can also run a
full reparse and this reparse is not being done when Emacs is idle but
immediatelly and not interruptable \(as with the idle-scheduler of semantic)!"
:group 'ecb-methods
:type 'boolean)
(defcustom ecb-show-tags
'((default . ((include collapsed nil)
(parent collapsed nil)
(type flattened nil)
(variable collapsed access)
(function flattened access)
(label hidden nil)
(t collapsed nil)))
(c++-mode . ((include collapsed nil)
(parent collapsed nil)
(type flattened nil)
(variable collapsed access)
(function flattened access) ;; for Methods
(function collapsed access) ;; for Method-prototypes
(label hidden nil)
(t collapsed nil)))
(c-mode . ((include collapsed nil)
(parent collapsed nil)
(type flattened nil)
(variable collapsed access)
(function flattened access) ;; for Functions
(function collapsed access) ;; for Function-prototypes
(label hidden nil)
(t collapsed nil)))
(bovine-grammar-mode . ((keyword collapsed name)
(token collapsed name)
(nonterminal flattened name)
(rule flattened name)
(t collapsed nil)))
(wisent-grammar-mode . ((keyword collapsed name)
(token collapsed name)
(nonterminal flattened name)
(rule flattened name)
(t collapsed nil)))
(texinfo-mode . ((section flattened nil)
(def collapsed name)
(t collapsed nil))))
"*How to show tags in the methods buffer first time after find-file.
This functionality is set on a major-mode base, i.e. for every major-mode a
different setting can be used. The value of this option is a list of
cons-cells:
The car is either a major-mode symbol or the special symbol 'default which
means if no setting for a certain major-mode is defined then the cdr of
the 'default cons-cell is used. This option should always contain a
default-setting!
The cdr is a list where each element represents a type of tags:
\(<tag type> <display type> <sort method>)
There can be more than 1 element for a certain <tag type>. This is for example
useful for C++ and C because these languages distinct between a
method-prototype \(rsp. function-prototype for C) and the method \(rsp.
function for C) itself. The default value of these option contains two entries
for <tag type> is 'function whereas the first one is responsible for the
\"real\" methods \(rsp. functions) and the second one for the prototypes. So
if the methods should be flattened and the prototypes collapsed the
show-tags-list for C++ and C must contain two entries for <tag type>
'function, the first one defined as 'flattened and the second one defined as
'collapsed. See also `ecb-methods-separate-prototypes'.
The tags in the methods buffer are displayed in the order as they appear in
this list.
Tag Type
----------
A Semantic tag type symbol \(for all possible type symbols see documentation
of semantic):
- include
- type
- variable
- function
- rule
- section \(chapters and sections in `info-mode')
- def \(definitions in `info-mode')
or one of the following:
- t: All tag types not specified anywhere else in the list.
- parent: The parents of a type.
Display Type
------------
A symbol which describes how the tags of this type shall be shown:
- expanded: The tags are shown in an expanded node.
- collapsed: The tags are shown in a collapsed node.
- flattened: The tags are added to the parent node.
- hidden: The tags are not shown.
Sort Method
-----------
A symbol describing how to sort the tags of this type:
- name: Sort by the tag name.
- access: Sort by tag access (public, protected, private) and then by name.
- nil: Don't sort tags. They appear in the same order as in the source
buffer.
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:group 'ecb-most-important
:set (function (lambda (symbol value)
(set symbol value)
(ecb-clear-tag-tree-cache)))
:type '(repeat (cons (symbol :tag "Major-mode")
(repeat (list (symbol :tag "Tag symbol")
(choice :tag "Display type" :value collapsed
(const :tag "Expanded" expanded)
(const :tag "Collapsed" collapsed)
(const :tag "Flattened" flattened)
(const :tag "Hidden" hidden))
(choice :tag "Sort by" :value nil
(const :tag "Name" name)
(const :tag "Access then name" access)
(const :tag "No sort" nil))))))
:initialize 'custom-initialize-default)
(defun ecb-get-show-tags-list ()
"Return the show-tags-list of `ecb-show-tags' for current major-mode."
(let ((mode-show-tag-list (cdr (assoc major-mode ecb-show-tags)))
(default-show-tag-list (cdr (assoc 'default ecb-show-tags))))
(or mode-show-tag-list
(and (null mode-show-tag-list)
default-show-tag-list))))
(defcustom ecb-methods-separate-prototypes t
"*Separate function-prototypes from the real functions.
This is for example useful for C++ and C because these languages distinct
between a method-prototype \(rsp. function-prototype for C) and the method
\(rsp. function for C) itself. If this option is not nil then ECB separates
the prototypes from the real function/methods. Then with `ecb-show-tags' the
user can define different display-settings for each of them. If this option is
nil then the prototypes and the real functions are filled in the same bucket
and displayed plain and there is no sorting between prototypes and functions
possible. If this option is switched on then it is senseful that
`ecb-show-tags' contains for all modes which distinct between prototypes and
real functions/methods two entries for the tag-type 'function - see the
documentation of this option."
:group 'ecb-methods
:type 'boolean)
(defcustom ecb-methods-filter-replace-existing 'never
"*How the methods-filter should be applied to existing filters.
There are three different choices:
- 'never: This is the default and means that calling `ecb-methods-filter'
always adds the new filter on top of already existing filters. So you can
combine several filter to one combined like this example: 'Display only all
public methods having the string \"test\" in its name.' With this setting
the filters can only be cleared by calling `ecb-methods-filter' and then
choosing \"nothing\".
- 'always: This means that `ecb-methods-filter' always clears a previous
filter before applying the new one.
- 'ask: ECB asks if the new filter should replace the existing ones."
:group 'ecb-methods
:type '(radio (const :tag "Do not replace" :value never)
(const :tag "Always replace" :value always)
(const :tag "Ask if to replace" :value ask)))
(defcustom ecb-methods-nodes-expand-spec '(type variable function section
nonterminal keyword token)
"*Semantic tag-types expanded by `ecb-expand-methods-nodes'.
The value of this option is either the symbol 'all \(all tags are expanded
regardless of their type) or a list of symbols where each symbol is a valid
semantic tag-type. For a description of semantic tag types see option
`ecb-show-tags'.
But this option also defines if bucket-nodes in the ECB-method-buffer \(e.g.
\"\[Variables\]\") should be expanded. Therefore valid symbols for this list
are also all cars of the variable `semantic-symbol->name-assoc-list'.
If there is a bucket-name \(the node-name stripped of the settings in
`ecb-bucket-node-display') which is not contained as cdr in
`semantic-symbol->name-assoc-list' then the symbol with this bucket-name as
name is also a valid symbol for this list. Example: In ECB there are buckets
\"\[Parents\]\". The bucket-name is \"Parents\" and the valid symbol-name is
then 'Parents.
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:type '(radio (const :tag "All node-types" :value all)
(repeat :tag "Node-type list"
(symbol :tag "Node-type"))))
(defcustom ecb-methods-nodes-collapse-spec 'all
"*Semantic tag-types collapsed by `ecb-expand-methods-nodes'.
For valid values of this option see `ecb-methods-nodes-expand-spec'!
This options takes only effect for semantic-sources - means sources supported
by semantic!"
:group 'ecb-methods
:type '(radio (const :tag "All node-types" :value all)
(repeat :tag "Node-type list"
(symbol :tag "Node-type"))))
(defcustom ecb-methods-show-node-info '(if-too-long . name+type)
"*When to display which node-info in the methods-buffer.
Define which node info should displayed after moving the mouse over a node
\(or after a shift click onto the node) in the methods-buffer.
You can define \"when\" a node-info should be displayed:
See `ecb-directories-show-node-info' for the possible choices.
You can define what info should be displayed:
- name: Only the full node name is displayed.
- name+type: The full name + the type of the node \(function, class,
variable) is displayed.
Do NOT set this option directly via setq but use always customize!"
:group 'ecb-methods
:type '(cons :tag "* Method-buffer"
(choice :tag "When"
(const :tag "Always" :value always)
(const :tag "If too long" :value if-too-long)
(const :tag "After shift click" :value shift-click)
(const :tag "Never" :value never))
(choice :tag "What"
(const :tag "Node-name" :value name)
(const :tag "Node-name + type" :value name+type))))
(defcustom ecb-exclude-parents-regexps nil