1153
1300
(let ((formatted-name (concat (nth 0 ecb-bucket-node-display)
1155
1302
(nth 1 ecb-bucket-node-display))))
1156
(setq formatted-name (ecb-merge-face-into-text formatted-name (nth 2 ecb-bucket-node-display)))
1303
(ecb-merge-face-into-text formatted-name (nth 2 ecb-bucket-node-display))
1157
1304
formatted-name))
1306
(defsubst ecb-forbid-tag-display (tag)
1307
(ecb--semantic--tag-put-property tag 'hide-tag t))
1309
(defsubst ecb-allow-tag-display (tag)
1310
(ecb--semantic--tag-put-property tag 'hide-tag nil))
1312
(defsubst ecb-tag-forbidden-display-p (tag)
1313
(ecb--semantic--tag-get-property tag 'hide-tag))
1315
(defsubst ecb-show-at-least-one-tag-p (taglist)
1316
"Not nil if at least one of the tags in TAGLIST should be displayed in the
1319
(dolist (tag taglist)
1320
(if (not (ecb-tag-forbidden-display-p tag))
1325
;; The function requires that TAGLIST is a subset of the tag-table returned by
1326
;; semantic for the current-buffer.
1327
(defun ecb-apply-user-filter-to-tags (taglist)
1328
"Applies to the tags of TAGLIST the related filter of
1329
`ecb-methods-user-filter-alist' - if there is any."
1331
(let ((filters (cdr (assoc (current-buffer) ecb-methods-user-filter-alist)))
1336
(dolist (tag taglist)
1337
(dolist (filter-spec filters)
1338
(setq filter-type (nth 0 filter-spec))
1339
(setq filter (car (nth 1 filter-spec))) ;; ignore the attached fcn
1340
(setq inverse (nth 2 filter-spec))
1341
;; we forbid some tags to be displayed when they do not match the
1342
;; filter. Currently we do not apply a filter to tags of class 'type
1343
(unless (equal (ecb--semantic-tag-class tag) 'type)
1344
(cond ((equal filter-type 'regexp)
1345
(if (funcall inverse
1346
(not (string-match filter
1347
(ecb--semantic-tag-name tag))))
1348
(ecb-forbid-tag-display tag)))
1349
((and (member filter '(private protected public))
1350
(equal filter-type 'protection))
1351
(if (funcall inverse
1352
(not (or (null (ecb--semantic-tag-protection tag))
1353
(equal (ecb--semantic-tag-protection tag)
1355
(ecb-forbid-tag-display tag)))
1356
((and (symbolp filter)
1357
(equal filter-type 'tag-class))
1358
(if (funcall inverse
1359
(not (equal (ecb--semantic-tag-class tag) filter)))
1360
(ecb-forbid-tag-display tag)))
1361
((and (functionp filter)
1362
(equal filter-type 'function))
1363
(if (funcall inverse
1364
(not (funcall filter tag (current-buffer))))
1365
(ecb-forbid-tag-display tag)))
1369
(defun ecb-generate-node-name (text-name first-chars icon-name)
1370
"Generate a new name from TEXT-NAME by adding an appropriate image according
1371
to ICON-NAME to the first FIRST-CHARS of TEXT-NAME. If FIRST-CHARS is < 0 then
1372
a string with length abs\(FIRST-CHARS) is created, the image is applied to
1373
this new string and this \"image\"-string is added to the front of TEXT-NAME.
1374
If no image can be found for ICON-NAME then the original TEXT-NAME is
1378
(set-buffer ecb-methods-buffer-name)
1379
(setq image (and icon-name
1380
(ecb-use-images-for-semantic-tags)
1381
(tree-buffer-find-image icon-name)))
1383
(if (> first-chars 0)
1384
(tree-buffer-add-image-icon-maybe
1385
0 first-chars text-name image)
1386
(concat (tree-buffer-add-image-icon-maybe
1387
0 1 (make-string (- first-chars) ? ) image)
1160
1392
(defun ecb-add-tag-bucket (node bucket display sort-method
1161
&optional parent-tag no-bucketize)
1393
&optional parent-tag no-bucketize)
1162
1394
"Adds a tag bucket to a node unless DISPLAY equals 'hidden."
1164
(let ((name (ecb-format-bucket-name (car bucket)))
1165
;;(type (ecb--semantic-tag-class (cadr bucket)))
1396
(let* ((name-bucket (ecb-format-bucket-name (car bucket)))
1397
(image-name (format "%s-bucket" (ecb--semantic-tag-class (cadr bucket))))
1398
(name (ecb-generate-node-name name-bucket -1 image-name))
1399
;;(type (ecb--semantic-tag-class (cadr bucket)))
1167
1401
(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)))
1402
(ecb-apply-user-filter-to-tags (cdr bucket))
1403
(unless (or (eq 'flattened display)
1404
;; we must not create a bucket-node when each tag in the
1405
;; bucket is forbidden to be displayed
1406
(not (ecb-show-at-least-one-tag-p (cdr bucket))))
1408
(tree-node-new name 1
1409
(list 'ecb-bucket-node
1411
(ecb--semantic-tag-class (car (cdr bucket))))
1413
(if ecb-truncate-long-names 'end)))
1171
1414
(tree-node-set-expanded bucket-node (eq 'expanded display)))
1172
1415
(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))))))
1416
;; we create only a new node for a tag of the bucket when the tag is
1417
;; not forbidden to be displayed.
1418
(if (not (ecb-tag-forbidden-display-p tag))
1419
(ecb-update-tag-node tag
1420
(tree-node-new "" 0 tag t bucket-node
1421
(if ecb-truncate-long-names 'end))
1422
parent-tag no-bucketize))
1423
;; now we allow each tag to be displayed. This can be done because
1424
;; here we already excluded the tag from being added as a node to
1425
;; the tree-buffer and therefore from being displayed. So we can
1426
;; reset all tags to be shown by default. So we can apply a complete
1427
;; new filter (or no filter) without resetting the old filter before.
1428
(ecb-allow-tag-display tag))))))
1432
(defconst ecb-tag-image-name-alias-alist
1433
'((abstract . ((static . ((struct . ((nil . "abstract-class-unknown")
1434
(unknown . "abstract-class-unknown")
1435
(private . "abstract-class-private")
1436
(protected . "abstract-class-protected")
1437
(public . "abstract-class-public")))
1438
(class . ((nil . "abstract-class-unknown")
1439
(unknown . "abstract-class-unknown")
1440
(private . "abstract-class-private")
1441
(protected . "abstract-class-protected")
1442
(public . "abstract-class-public")))
1443
;; currently we have no special icon for
1444
;; interfaces - we use the icon for abstract classes
1445
(interface . ((nil . "abstract-class-unknown")
1446
(unknown . "abstract-class-unknown")
1447
(private . "abstract-class-private")
1448
(protected . "abstract-class-protected")
1449
(public . "abstract-class-public")))
1450
;; we have no static and no abstract enum-icon
1451
(enum . ((nil . "enum-unknown")
1452
(unknown . "enum-unknown")
1453
(private . "enum-private")
1454
(protected . "enum-protected")
1455
(public . "enum-public")))
1456
;; we have no icon for static constructors
1457
(constructor . ((nil . "abstract-constructor-unknown")
1458
(unknown . "abstract-constructor-unknown")
1459
(private . "abstract-constructor-private")
1460
(protected . "abstract-constructor-protected")
1461
(public . "abstract-constructor-public")))
1462
(function . ((nil . "abstract-function-unknown-static")
1463
(unknown . "abstract-function-unknown-static")
1464
(private . "abstract-function-private-static")
1465
(protected . "abstract-function-protected-static")
1466
(public . "abstract-function-public-static")))
1467
(variable . ((nil . "abstract-variable-unknown-static")
1468
(unknown . "abstract-variable-unknown-static")
1469
(private . "abstract-variable-private-static")
1470
(protected . "abstract-variable-protected-static")
1471
(public . "abstract-variable-public-static")))))
1472
(not-static . ((struct . ((nil . "abstract-class-unknown")
1473
(unknown . "abstract-class-unknown")
1474
(private . "abstract-class-private")
1475
(protected . "abstract-class-protected")
1476
(public . "abstract-class-public")))
1477
(class . ((nil . "abstract-class-unknown")
1478
(unknown . "abstract-class-unknown")
1479
(private . "abstract-class-private")
1480
(protected . "abstract-class-protected")
1481
(public . "abstract-class-public")))
1482
;; we have currently no special icon for interfaces
1483
(interface . ((nil . "abstract-class-unknown")
1484
(unknown . "abstract-class-unknown")
1485
(private . "abstract-class-private")
1486
(protected . "abstract-class-protected")
1487
(public . "abstract-class-public")))
1488
;; we have no abstract enum-icon
1489
(enum . ((nil . "enum-unknown")
1490
(unknown . "enum-unknown")
1491
(private . "enum-private")
1492
(protected . "enum-protected")
1493
(public . "enum-public")))
1494
(constructor . ((nil . "abstract-constructor-unknown")
1495
(unknown . "abstract-constructor-unknown")
1496
(private . "abstract-constructor-private")
1497
(protected . "abstract-constructor-protected")
1498
(public . "abstract-constructor-public")))
1499
(function . ((nil . "abstract-function-unknown")
1500
(unknown . "abstract-function-unknown")
1501
(private . "abstract-function-private")
1502
(protected . "abstract-function-protected")
1503
(public . "abstract-function-public")))
1504
(variable . ((nil . "abstract-variable-unknown")
1505
(unknown . "abstract-variable-unknown")
1506
(private . "abstract-variable-private")
1507
(protected . "abstract-variable-protected")
1508
(public . "abstract-variable-public")))))))
1509
(not-abstract . ((static . ((struct . ((nil . "class-unknown")
1510
(unknown . "class-unknown")
1511
(private . "class-private")
1512
(protected . "class-protected")
1513
(public . "class-public")))
1514
(class . ((nil . "class-unknown")
1515
(unknown . "class-unknown")
1516
(private . "class-private")
1517
(protected . "class-protected")
1518
(public . "class-public")))
1519
;; we use the icon for abstract classes for interfaces
1520
(interface . ((nil . "abstract-class-unknown")
1521
(unknown . "abstract-class-unknown")
1522
(private . "abstract-class-private")
1523
(protected . "abstract-class-protected")
1524
(public . "abstract-class-public")))
1525
;; we have no static enum-icon
1526
(enum . ((nil . "enum-unknown")
1527
(unknown . "enum-unknown")
1528
(private . "enum-private")
1529
(protected . "enum-protected")
1530
(public . "enum-public")))
1531
(constructor . ((nil . "constructor-unknown")
1532
(unknown . "constructor-unknown")
1533
(private . "constructor-private")
1534
(protected . "constructor-protected")
1535
(public . "constructor-public")))
1536
(function . ((nil . "function-unknown-static")
1537
(unknown . "function-unknown-static")
1538
(private . "function-private-static")
1539
(protected . "function-protected-static")
1540
(public . "function-public-static")))
1541
(variable . ((nil . "variable-unknown-static")
1542
(unknown . "variable-unknown-static")
1543
(private . "variable-private-static")
1544
(protected . "variable-protected-static")
1545
(public . "variable-public-static")))))
1546
(not-static . ((struct . ((nil . "class-unknown")
1547
(unknown . "class-unknown")
1548
(private . "class-private")
1549
(protected . "class-protected")
1550
(public . "class-public")))
1551
(class . ((nil . "class-unknown")
1552
(unknown . "class-unknown")
1553
(private . "class-private")
1554
(protected . "class-protected")
1555
(public . "class-public")))
1556
(interface . ((nil . "abstract-class-unknown")
1557
(unknown . "abstract-class-unknown")
1558
(private . "abstract-class-private")
1559
(protected . "abstract-class-protected")
1560
(public . "abstract-class-public")))
1561
(enum . ((nil . "enum-unknown")
1562
(unknown . "enum-unknown")
1563
(private . "enum-private")
1564
(protected . "enum-protected")
1565
(public . "enum-public")))
1566
(constructor . ((nil . "constructor-unknown")
1567
(unknown . "constructor-unknown")
1568
(private . "constructor-private")
1569
(protected . "constructor-protected")
1570
(public . "constructor-public")))
1571
(function . ((nil . "function-unknown")
1572
(unknown . "function-unknown")
1573
(private . "function-private")
1574
(protected . "function-protected")
1575
(public . "function-public")))
1576
(variable . ((nil . "variable-unknown")
1577
(unknown . "variable-unknown")
1578
(private . "variable-private")
1579
(protected . "variable-protected")
1580
(public . "variable-public"))))))))
1581
"This alist defines the mapping from the combination
1582
abstract-static-tag-protection to an existing icon-file-name.")
1585
(defsubst ecb-get-icon-for-tag (abstract-p static-p type protection)
1586
(cdr (assq protection
1589
(cdr (assq abstract-p
1590
ecb-tag-image-name-alias-alist)))))))))
1593
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: All this tag-icon-display-stuff
1594
;; should be done by semantic - but for now we let do it by ECB because so we
1595
;; can test the whole stuff. If Eric has added such icon-display to semantic
1596
;; then we can throw away all this stuff and just using plain-tag-name as
1597
;; node-name without any modification.
1180
1598
(defun ecb-update-tag-node (tag node &optional parent-tag no-bucketize)
1181
1599
"Updates a node containing a tag."
1182
1600
(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))
1601
tag ecb-show-only-positioned-tags))
1602
(plain-tag-name (ecb-get-tag-name tag parent-tag))
1603
(has-protection (member (ecb-first plain-tag-name)
1605
(icon-name (ecb-get-icon-for-tag
1606
(if (ecb--semantic-tag-abstract-p tag parent-tag)
1609
(if (ecb--semantic-tag-static-p tag parent-tag)
1612
(or (and (equal (ecb--semantic-tag-class tag)
1614
(intern (ecb--semantic-tag-type tag)))
1615
(and (ecb--semantic-tag-function-constructor-p tag)
1617
(ecb--semantic-tag-class tag))
1618
(or (and (ecb--semantic--tag-get-property tag 'adopted)
1620
(and (not (member (ecb--semantic-tag-class tag)
1621
'(type function variable)))
1623
(ecb--semantic-tag-protection tag parent-tag))))
1624
(tag-name (ecb-generate-node-name plain-tag-name
1625
(if has-protection 1 -1)
1627
(tree-node-set-name node tag-name)
1185
1628
(unless (eq 'function (ecb--semantic-tag-class tag))
1186
1629
(ecb-add-tags node children tag no-bucketize)
1187
1630
(tree-node-set-expandable
1221
1712
(defun ecb-filter-c-prototype-tags (taglist)
1222
1713
"Filter out all prototypes.
1714
Beginning with version 2.24 of ECB this function does nothing when
1715
`ecb-methods-separate-prototypes' is set to not nil \(default).
1223
1717
For example this is useful for editing C files which have the function
1224
1718
prototypes defined at the top of the file and the implementations at the
1225
1719
bottom. This means that everything appears twice in the methods buffer, but
1226
1720
probably nobody wants to jump to the prototypes, they are only wasting space
1227
1721
in the methods buffer.
1228
1722
For C-header-files prototypes are never filtered out!"
1229
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Is there a better way to
1230
;; recognize a C-Header-file?
1231
(let ((header-extensions '("\\.h\\'" "\\.H\\'" "\\.HH\\'" "\\.hxx\\'" "\\.hh\\'")))
1232
(or (and (catch 'found
1233
(dolist (ext header-extensions)
1234
(if (save-match-data
1235
(string-match ext (buffer-file-name (current-buffer))))
1240
(function (lambda (x)
1241
(not (ecb--semantic-tag-get-attribute x 'prototype))))))))
1723
;; ;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Is there a better way to
1724
;; ;; recognize a C-Header-file?
1725
(if ecb-methods-separate-prototypes
1727
(let ((header-extensions '("\\.h\\'" "\\.H\\'" "\\.HH\\'" "\\.hxx\\'" "\\.hh\\'")))
1728
(or (and (catch 'found
1729
(dolist (ext header-extensions)
1730
(if (save-match-data
1731
(string-match ext (buffer-file-name (current-buffer))))
1736
(function (lambda (x)
1737
(not (ecb--semantic-tag-prototype-p x)))))))))
1739
;; Filtering the Methods-buffer by the user ----------------
1243
1741
(defvar ecb-methods-user-filter-alist nil
1244
"The filter currently applied to the methods-buffer by the user. It can be a
1245
regexp-string, or one of the symbols 'private, 'protected or 'public or one of
1246
the tag-type-symbols mentioned in the the option `ecb-tag-display-function'.
1247
This cache is an alist where the key is the buffer-object of that buffer the
1248
filter belongs and the value is the applied filter to that buffer.")
1251
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>:
1252
;; - Fuer jede der 4 Funktionen unten ein tree-buffer-defpopup-command
1253
;; schreiben (diese m�ssen tree-buffer-get-data-store verwenden!). Dabei
1254
;; auch `ecb-sources-filter und ecb-history-filter fixen!
1255
;; - Filteranzeige in der Modeline des methods-buffers
1256
;; - Smartere und besser customizable Filterung:
1257
;; + Ev. recursive absteigen - children von tags auch filtern
1258
;; + Start-level bestimmbar (z.B. erst ab dem ersten children-level beginnen
1259
;; + Oder Exclude-tag-classes customizable, z.B. Filterung bezieht sich nie
1260
;; auf types: damit w�rden in Sprachen wie C++ oder Java die Klassen immer
1261
;; angezeigt, nur ihre children w�rden gefiltert.
1262
;; Ohne solche Mechanismen ist die Filterung bei OO-Sprachen fast nutzlos!
1264
(defun ecb-methods-filter-by-prot (source-buffer)
1742
"The filter currently applied to the methods-buffer by the user. This cache
1743
is an alist where the key is the buffer-object of that buffer the filter
1744
belongs and the value is the applied filter to that buffer.
1746
Filters which can work onto single tags are applied by
1747
`ecb-apply-user-filter-to-tags' whereas tag-filters which have to be applied
1748
onto the whole tag-table are performed by `ecb-apply-tag-table-filters'.")
1751
(defun ecb-methods-filter-by-prot (inverse source-buffer &optional prot)
1265
1752
"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)))
1753
(let ((choice (or prot
1754
(ecb-query-string "Protection filter:"
1755
'("private" "protected" "public")))))
1756
(ecb-methods-filter-apply 'protection
1757
(cons (intern choice) nil)
1759
(concat (and inverse "^") "Prot")
1270
(defun ecb-methods-filter-by-tag-class (source-buffer)
1763
(defun ecb-methods-filter-by-tag-class (inverse source-buffer
1764
&optional tag-class)
1271
1765
"Filter the Methods-buffer by a tag-class."
1272
(let ((choice (ecb-query-string "Tag-class filter: "
1273
'("function" "variable" "type"
1274
"include" "rule" "section" "def"))))
1275
(ecb-methods-filter-apply (intern choice) source-buffer)))
1277
(defun ecb-methods-filter-by-regexp (source-buffer)
1766
(let* ((curr-semantic-symbol->name-assoc-list
1768
(set-buffer source-buffer)
1769
(ecb--semantic-symbol->name-assoc-list)))
1770
(choice (or tag-class
1771
(ecb-query-string "Tag-class filter:"
1773
curr-semantic-symbol->name-assoc-list))))
1774
(class (or tag-class
1776
(car (delq nil (mapcar (function (lambda (e)
1777
(if (ecb-string= (cdr e) choice)
1779
curr-semantic-symbol->name-assoc-list)))))))
1780
(ecb-methods-filter-apply 'tag-class
1781
(cons (intern class) nil)
1783
(concat (and inverse "^") "Tagclass")
1784
(cdr (assoc (intern class)
1785
curr-semantic-symbol->name-assoc-list))
1789
;; The popup-menu commands for protection- and tag-class-filters are generated
1790
;; dynamically - see `ecb-methods-menu-tagfilter-entries'.
1792
(defun ecb-methods-filter-by-regexp (inverse source-buffer &optional regexp)
1278
1793
"Filter the Methods-buffer by a regular expression."
1279
(let ((regexp-str (read-string "Insert the filter-regexp: ")))
1280
(if (> (length regexp-str) 0)
1281
(ecb-methods-filter-apply regexp-str source-buffer)
1282
(ecb-methods-filter-apply nil source-buffer))))
1284
(defun ecb-methods-filter-none (source-buffer)
1285
"Remove any filter from the Methods-buffer."
1286
(ecb-methods-filter-apply nil source-buffer))
1288
(defun ecb-apply-user-filter-to-tags (taglist)
1290
(let ((filter (cdr (assoc (current-buffer) ecb-methods-user-filter-alist))))
1296
(cond ((stringp filter)
1297
(if (string-match filter
1298
(ecb--semantic-tag-name tag))
1300
((member filter '(private protected public))
1301
(if (or (null (ecb--semantic-tag-protection tag))
1302
(equal (ecb--semantic-tag-protection tag) filter))
1305
(if (equal (ecb--semantic-tag-class tag) filter)
1309
(defun ecb-methods-filter ()
1794
(let ((regexp-str (or regexp (read-string "Filter-regexp: "))))
1795
(ecb-methods-filter-apply 'regexp
1796
(if (> (length regexp-str) 0)
1797
(cons regexp-str nil)
1800
(concat (and inverse "^") "Regexp")
1801
(if (> (length regexp-str) 0) regexp-str nil)
1804
(tree-buffer-defpopup-command ecb-methods-filter-by-regexp-popup
1805
"Filter the Methods-buffer by regexp from popup."
1806
(ecb-methods-filter-by-regexp nil (ecb-methods-get-data-store 'source-buffer)))
1808
(tree-buffer-defpopup-command ecb-methods-filter-by-regexp-popup-inverse
1809
"Filter the Methods-buffer by inverse regexp from popup."
1810
(ecb-methods-filter-by-regexp t (ecb-methods-get-data-store 'source-buffer)))
1812
(defun ecb-methods-filter-by-function (inverse source-buffer &optional fcn-name)
1813
"Filter the Methods-buffer by a filter-function."
1814
(let ((filter-fcn-name (or fcn-name
1815
(completing-read "Tag-filter-function: "
1816
obarray 'fboundp t))))
1817
(ecb-methods-filter-apply 'function
1818
(cons (intern filter-fcn-name)
1821
(concat (and inverse "^") "Function")
1825
(tree-buffer-defpopup-command ecb-methods-filter-by-function-popup
1826
"Filter the Methods-buffer by function-filter from popup."
1827
(ecb-methods-filter-by-function nil (ecb-methods-get-data-store 'source-buffer)))
1829
(tree-buffer-defpopup-command ecb-methods-filter-by-function-popup-inverse
1830
"Filter the Methods-buffer by inverse function-filter from popup."
1831
(ecb-methods-filter-by-function t (ecb-methods-get-data-store 'source-buffer)))
1833
(tree-buffer-defpopup-command ecb-methods-filter-by-nothing-popup
1834
"Remove any filter from the Methods-buffer from popup."
1835
(ecb-methods-filter-apply nil nil nil "" "" (ecb-methods-get-data-store 'source-buffer)))
1837
(tree-buffer-defpopup-command ecb-methods-filter-delete-last-popup
1838
"Remove the last added filter from the Methods-buffer from popup."
1839
(ecb-methods-filter-apply nil nil nil "" "" (ecb-methods-get-data-store 'source-buffer) t))
1842
(defun ecb-get-type-node-of-node (node)
1843
"Returns that node which data-tag is of class 'type the tag of the node NODE
1844
of the Methods-buffer belongs to. If the tag of NODE do not belong to a type
1845
then nil is returned."
1846
(let ((parent (tree-node-get-parent node)))
1848
(while (not (eq (tree-buffer-get-root) parent))
1849
(if (equal (and (= (tree-node-get-type parent) 0)
1850
(ecb--semantic-tag-class (tree-node-get-data parent)))
1852
(throw 'found parent)
1853
(setq parent (tree-node-get-parent parent))))
1857
(defun ecb-get-type-name-hierarchy-of-current-node ()
1858
"Return the type-name-hierarchy of current node in form of a list whereas the
1859
first element is the name of the tag of the current node itself, the second
1860
element is the name of the type the current node belongs to, the third element
1861
is the name of the parent-type of that type and so on. The last element in
1862
this list is the topmost type-parent of the tag of the current node. If the
1863
current node has no tag as data then nil is returned. If the tag of the
1864
current node does not belong to a type-tag \(e.g. a toplevel function) then
1865
the returned list contains just the name of the tag of the current node."
1866
(let ((type-hierarchy nil)
1867
(curr-node (tree-buffer-get-node-at-point)))
1868
(when (and curr-node
1869
(= (tree-node-get-type curr-node) 0))
1871
(setq type-hierarchy (cons (ecb--semantic-tag-name
1872
(tree-node-get-data curr-node))
1874
(setq curr-node (ecb-get-type-node-of-node curr-node)))))
1875
(nreverse type-hierarchy)))
1878
(defun ecb-get-type-tag-of-tag (&optional tag table always-parent-type)
1879
"Returns that tag of class 'type the tag TAG belongs to. If TAG does not
1880
belong to a type then nil is returned. If TAG is already of class 'type then
1881
the behavior depends on the optional argument ALWAYS-PARENT-TYPE: If nil then
1882
the current tag is returned otherwise the next parent-tag of class 'type is
1885
If TAG is nil the tag returned by `ecb-get-real-curr-tag' is used. If TABLE is
1886
nil then the tag-table of the current buffer is used; otherwise the tag-table
1888
(let* ((table (or table (ecb-get-current-tag-table)))
1889
(curr-tag (or tag (ecb-get-real-curr-tag)))
1890
(function-parent (ecb--semantic-tag-function-parent curr-tag)))
1891
(cond ((ecb-faux-group-tag-p curr-tag)
1892
(and (not always-parent-type) curr-tag))
1893
((and (not always-parent-type)
1894
(equal (ecb--semantic-tag-class curr-tag) 'type))
1896
(t (if function-parent
1897
;; we have an external member and we search the type this
1898
;; external member belongs to. This can either be a type-tag
1899
;; in the current file (which is then contained in table) or
1900
;; a faux-tag (created by semantic-adopt-external-members)
1901
;; when the parent-type of this external member is defined
1902
;; outside the current source - but this faux-type is
1903
;; contained in table too.
1905
(dolist (tag (ecb--semantic-flatten-tags-table table))
1906
(if (and (equal (ecb--semantic-tag-class tag) 'type)
1907
(ecb-string= (ecb--semantic-tag-name tag)
1910
(mapcar (lambda (child)
1911
(if (ecb--semantic-equivalent-tag-p
1914
(ecb--semantic-tag-children-compatibility tag t))))
1915
(throw 'found tag)))
1917
;; we are already inside the parent-type - if there is any, so
1918
;; we simply search the nearest tag of class 'type in the
1919
;; reversed overlay-stack
1921
(dolist (tag (cdr (reverse
1922
(ecb--semantic-find-tag-by-overlay
1923
(ecb--semantic-tag-start curr-tag)
1924
(ecb--semantic-tag-buffer curr-tag)))))
1925
(if (equal (ecb--semantic-tag-class tag) 'type)
1926
(throw 'found tag)))
1930
(defun ecb-get-type-name-hierarchy-of-current-tag (&optional tag)
1931
"Return the type-name-hierarchy of TAG in form of a list whereas the
1932
first element is the name of the TAG itself, the second element is the name of
1933
the type the TAG belongs to, the third element is the name of the parent-type
1934
of that type and so on. The last element in this list is the topmost
1935
type-parent of the TAG. If the TAG does not belong to a type-tag \(e.g. a
1936
toplevel function) then the returned list contains just the name of the
1937
TAG. If TAG is nil then the current tag returned by `ecb-get-real-curr-tag' is
1938
used; if point does not stay on a tag then nil is returned."
1939
(let ((type-hierarchy nil)
1940
(curr-tag (or tag (ecb-get-real-curr-tag))))
1943
(setq type-hierarchy (cons (ecb--semantic-tag-name curr-tag)
1945
(setq curr-tag (ecb-get-type-tag-of-tag curr-tag nil t)))))
1946
(nreverse type-hierarchy)))
1948
(defun ecb-methods-filter-by-current-type (inverse source-buffer &optional
1950
"Display only the current-type and its contents in the methods-buffer. The
1951
argument INVERSE is ignored here."
1952
(let* ((curr-type-tag (or (and (ecb--semantic-tag-p tag)
1954
(set-buffer source-buffer)
1955
(ecb-get-type-tag-of-tag tag)))
1956
(cond ((ecb-point-in-edit-window)
1957
(if (ecb--semantic-active-p)
1959
(set-buffer source-buffer)
1960
(ecb-get-type-tag-of-tag (ecb-get-real-curr-tag)))))
1961
((equal (current-buffer)
1962
(get-buffer ecb-methods-buffer-name))
1963
(let ((node (tree-buffer-get-node-at-point)))
1965
(tree-node-get-data (ecb-get-type-node-of-node node)))))
1966
(t (ecb-error "ECB can not identify the current-type-tag!")))))
1967
(curr-tag-type-name-hierachy (and curr-type-tag
1969
(set-buffer source-buffer)
1970
(ecb-get-type-name-hierarchy-of-current-tag
1972
(if (and curr-type-tag curr-tag-type-name-hierachy)
1973
(ecb-methods-filter-apply 'current-type
1974
(cons curr-tag-type-name-hierachy
1975
'ecb-methods-filter-perform-current-type)
1978
(ecb--semantic-tag-name curr-type-tag)
1980
(ecb-error "ECB can not identify the current-type!"))))
1982
(tree-buffer-defpopup-command ecb-methods-filter-by-current-type-popup
1983
"Display only the current-type from popup."
1984
(ecb-methods-filter-by-current-type nil
1985
(ecb-methods-get-data-store 'source-buffer)
1986
(tree-node-get-data node)))
1989
(defun ecb-get-source-buffer-for-tag-filter ()
1990
"Return the source-buffer of the tag-list which should be filtered."
1991
(cond ((ecb-point-in-edit-window)
1993
((equal (current-buffer)
1994
(get-buffer ecb-methods-buffer-name))
1995
(ecb-methods-get-data-store 'source-buffer))
1996
(t (or (and ecb-last-source-buffer
1997
(buffer-live-p ecb-last-source-buffer)
1998
ecb-last-source-buffer)
1999
(ecb-error "There is no source-file to filter!")))))
2001
(defun ecb-methods-filter-inverse ()
2002
"Apply an inverse filter to the Methods-buffer. This is the same as calling
2003
`ecb-methods-filter' with a prefix arg."
2005
(ecb-methods-filter-internal t))
2007
(defun ecb-methods-filter-protection (&optional inverse)
2008
"Filter the methods-buffer by protection. If INVERSE is not nil \(called
2009
with a prefix arg) then an inverse filter is applied. For further details see
2010
`ecb-methods-filter'."
2012
(ecb-methods-filter-internal inverse "protection"))
2014
(defun ecb-methods-filter-tagclass (&optional inverse)
2015
"Filter the methods-buffer by tag-class. If INVERSE is not nil \(called
2016
with a prefix arg) then an inverse filter is applied. For further details see
2017
`ecb-methods-filter'."
2019
(ecb-methods-filter-internal inverse "tag-class"))
2021
(defun ecb-methods-filter-current-type ()
2022
"Display in the Methods-buffer only the current type and its members. For
2023
further details see `ecb-methods-filter'."
2025
(ecb-methods-filter-internal nil "curr-type"))
2027
(defun ecb-methods-filter-regexp (&optional inverse)
2028
"Filter the methods-buffer by a regexp. If INVERSE is not nil \(called
2029
with a prefix arg) then an inverse filter is applied. For further details see
2030
`ecb-methods-filter'."
2032
(ecb-methods-filter-internal inverse "regexp"))
2034
(defun ecb-methods-filter-function (&optional inverse)
2035
"Filter the methods-buffer by a function. If INVERSE is not nil \(called
2036
with a prefix arg) then an inverse filter is applied. For further details see
2037
`ecb-methods-filter'."
2039
(ecb-methods-filter-internal inverse "function"))
2041
(defun ecb-methods-filter-nofilter ()
2042
"Remove any filter from the Methods-buffer. For further details see
2043
`ecb-methods-filter'."
2045
(ecb-methods-filter-internal nil "no filter"))
2047
(defun ecb-methods-filter-delete-last ()
2048
"Remove the most recent filter from the Methods-buffer. For further details see
2049
`ecb-methods-filter'."
2051
(ecb-methods-filter-internal nil "delete last"))
2053
(defun ecb-methods-filter (&optional inverse)
1310
2054
"Apply a filter to the Methods-buffer to reduce the number of entries.
1311
So you get a better overlooking. There are four choices:
2055
So you get a better overlooking. There are six choices:
1312
2056
- Filter by protection: Just insert the protection you want the Methods-buffer
1313
2057
being filtered: private, protected or public!
1314
2058
- 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
2059
- Filter by tag-class: You can filter by the tag-classes of current
2060
major-mode. The available tag-classes come from the variable
2061
`semantic--symbol->name-assoc-list'. The are normally methods, variables
2063
- Filter by current type: In languages which have types like Java or C++ this
2064
filter displays only the current type and all its members \(e.g. attributes
2065
and methods). If ECB can not identify the current type in the source-buffer
2066
or in the methods-window then nothing will be done.
2067
- Filter by a filter-function: Such a function gets two arguments: a tag and
2068
the source-buffer of this tag. If the tag should be displayed \(i.e. not
2069
being filtered out) then the function has to return not nil otherwise nil.
2070
- No special filter: This means to display all tags specified with the option
2071
`ecb-show-tokens'. If currently some of the above filters are applied they
2072
will be all removed.
2073
- Delete the last added: This removes only the topmost filter-layer, means
2074
that filter added last.
2076
The protection-, the current-type and the tag-class-filter are only available
2077
for semantic-supported sources.
1321
2079
Be aware that the tag-list specified by the option `ecb-show-tags' is the
1322
2080
basis of all filters, i.e. tags which are excluded by that option will never
1323
2081
be shown regardless of the filter type here!
2083
All tags which match the applied filter\(s) will be displayed in the
2086
If called with a prefix-argument or when optional arg INVERSE is not nil then
2087
an inverse filter is applied to the Methods-buffer, i.e. all tags which
2088
do NOT match the choosen filter will be displayed in the Methods-buffer!
2090
Per default the choosen filter will be applied on top of already existing
2091
filters. This means that filters applied before are combined with the new
2092
filter. This behavior can changed via the option
2093
`ecb-methods-filter-replace-existing'. But regardless of the setting in
2094
`ecb-methods-filter-replace-existing' applying one of the not-inverse filters
2095
protection, tag-class or current-type always replaces exactly already existing
2096
filters of that type. On the other hand applying more than one inverse
2097
tag-class- or protection-filter can make sense.
1325
2099
Such a filter is only applied to the current source-buffer, i.e. each
1326
source-buffer can have its own tag-filter."
1328
(ecb-error "This command will be offered first in future-versions of ECB!")
1329
(let ((source-buffer (if (ecb-point-in-edit-window)
1331
(or ecb-last-source-buffer
1332
(ecb-error "There is no source-file to filter!"))))
1333
(choice (ecb-query-string "Filter Methods-buffer by:"
1334
'("regexp" "protection" "tag-class" "nothing"))))
1335
(cond ((string= choice "protection")
1336
(ecb-methods-filter-by-prot source-buffer))
1337
((string= choice "tag-class")
1338
(ecb-methods-filter-by-tag-class source-buffer))
1339
((string= choice "regexp")
1340
(ecb-methods-filter-by-regexp source-buffer))
1341
(t (ecb-methods-filter-none source-buffer)))))
1344
(defun ecb-methods-filter-apply (filter source-buffer)
1345
(let ((filter-elem (assoc source-buffer ecb-methods-user-filter-alist)))
2100
source-buffer can have its own tag-filters.
2102
The current active filter will be displayed in the modeline of the
2103
Methods-buffer \[regexp, prot \(= protection), tag-class, function \(=
2104
filter-function)]. If an inverse filter has been applied then this is
2105
signalized by a preceding caret ^. If currently more than 1 filter is applied
2106
then always the top-most filter is displayed in the modeline but the fact of
2107
more than 1 filter is visualized by the number of the filters - included in
2108
parens. You can see all currently applied filters by moving the mouse over the
2109
filter-string in modeline of the Methods-buffer: They will displayed as
2112
See the option `ecb-default-tag-filter' if you search for automatically
2113
applied default-tag-filters."
2115
(ecb-methods-filter-internal inverse))
2117
(defun ecb-methods-filter-internal (inverse &optional filter-type)
2118
"FILTER-TYPE has to be one of the strings \"regexp\", \"protection\",
2119
\"tag-class\", \"curr-type\", \"function\", \"no filter\" or \"delete last\"."
2121
(set-buffer ecb-methods-buffer-name)
2122
(tree-buffer-empty-p))
2123
(message "There is nothing to filter in an empty Methods-buffer!")
2124
(let* ((source-buffer (ecb-get-source-buffer-for-tag-filter))
2125
(semantic-source-p (save-excursion
2126
(set-buffer source-buffer)
2127
(ecb--semantic-active-p)))
2128
(choice (or filter-type
2130
(format "Apply %sfilter:"
2131
(if inverse "inverse " ""))
2132
(delq nil (list "regexp"
2133
(if semantic-source-p "protection")
2134
(if semantic-source-p "tag-class")
2135
(if semantic-source-p "curr-type")
2136
"function" "no filter" "delete last"))))))
2137
(cond ((ecb-string= choice "protection")
2138
(ecb-methods-filter-by-prot inverse source-buffer))
2139
((ecb-string= choice "tag-class")
2140
(ecb-methods-filter-by-tag-class inverse source-buffer))
2141
((ecb-string= choice "regexp")
2142
(ecb-methods-filter-by-regexp inverse source-buffer))
2143
((ecb-string= choice "curr-type")
2144
(ecb-methods-filter-by-current-type inverse source-buffer))
2145
((ecb-string= choice "function")
2146
(ecb-methods-filter-by-function inverse source-buffer))
2147
((ecb-string= choice "delete last")
2148
(ecb-methods-filter-apply nil nil nil "" "" source-buffer t))
2149
((ecb-string= choice "no filter")
2150
(ecb-methods-filter-apply nil nil nil "" "" source-buffer))
2151
(t (ecb-methods-filter-apply nil nil nil "" "" source-buffer))))))
2153
(defun ecb-methods-filter-apply (filtertype filter inverse filter-type-display
2155
source-buffer &optional remove-last)
2156
"Apply the FILTER of type FILTERTYPE to the buffer SOURCEBUFFER. If INVERSE
2157
is not nil then this filter will be applied inverse. FILTER-TYPE-DISPLAY and
2158
FILTER-DISPLAY are strings and specify how the FILTER of type FILTERTYPE
2159
should be displayed in the modeline of the methods-buffer. If REMOVE-LAST is
2160
not nil then the topmost filter will be removed and all other arguments unless
2161
SOURCE-BUFFER arguments are ignored."
2163
(set-buffer source-buffer)
2164
(if (and (not remove-last)
2165
(member filtertype '(protection tag-class curr-type))
2166
(not (ecb--semantic-active-p)))
2167
(ecb-error "A %s-filter '%s' can only applied to semantic-supported sources!"
2168
filtertype filter)))
2169
(let* ((filter-elem (assoc source-buffer ecb-methods-user-filter-alist))
2170
(new-filter-spec (and filtertype
2171
(list filtertype filter (if inverse 'not 'identity)
2172
filter-type-display filter-display)))
2173
(replace-all (and (not remove-last)
2174
(not (equal ecb-methods-filter-replace-existing 'never))
2175
(or (equal ecb-methods-filter-replace-existing 'always)
2176
(y-or-n-p "Should the new filter replace existing ones? "))))
2177
(replace-filter-type (and (not inverse)
2180
(assoc filtertype (cdr filter-elem))
2181
(member filtertype '(protection tag-class current-type))))
2182
(filters (or (and replace-filter-type
2185
(ecb-remove-assoc filtertype (cdr filter-elem)))
2186
(append (cdr filter-elem) (list new-filter-spec))))
2188
(nreverse (cdr (reverse (cdr filter-elem)))))
2189
(and new-filter-spec ;; if nil there should be no filter anymore
2191
new-filter-spec ;; just the new filter-spec
2192
(append (cdr filter-elem) (list new-filter-spec)))))))
1346
2193
(if filter-elem
1347
(setcdr filter-elem filter)
2194
(setcdr filter-elem filters)
1349
2196
(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))))
2197
(cons (cons source-buffer filters) ecb-methods-user-filter-alist)))))
2198
(when (buffer-live-p source-buffer)
2200
(set-buffer source-buffer)
2201
(if (ecb--semantic-active-p)
2202
;; For semantic-sources we do not use `ecb-rebuild-methods-buffer)'
2203
;; because this would always reparse the source-buffer even if not
2207
(ecb-rebuild-methods-buffer-with-tagcache
2208
(ecb--semantic-fetch-tags t)))
2209
(ecb-rebuild-methods-buffer)))
2210
(when (save-excursion
2211
(set-buffer ecb-methods-buffer-name)
2212
(tree-buffer-empty-p))
2213
(ecb-methods-filter-apply nil nil nil "" "" source-buffer t)
2214
(message "ECB has not applied this filter because it would filter out all nodes!"))))
2217
(defun ecb-methods-filter-modeline-prefix (buffer-name sel-dir sel-source)
2218
"Compute a mode-line prefix for the Methods-buffer so the current filter
2219
applied to the displayed tags is displayed. This function is only for using by
2220
the option `ecb-mode-line-prefixes'."
2221
(let* ((filters (and sel-source
2222
(cdr (assoc (get-file-buffer sel-source)
2223
ecb-methods-user-filter-alist))))
2224
(top-filter-spec (ecb-last filters))
2225
(filter-type-str (nth 3 top-filter-spec))
2226
(filter-str (nth 4 top-filter-spec)))
2227
(if (null top-filter-spec)
2228
nil ;; no prefix if no filter
2229
(let ((str (format "[%s%s: %s]"
2231
(if (> (length filters) 1)
2232
(format "(%d)" (length filters))
2235
(put-text-property 0 (length str) 'help-echo
2236
(mapconcat (function
2238
(let ((f-type-str (nth 3 f-elem) )
2239
(f-str (nth 4 f-elem)))
2241
f-type-str f-str))))
2247
(defun ecb-default-tag-filter-for-current-file ()
2248
"Check if for the file of the current buffer a default-tag-filter should be
2249
applied. If yes, then the filters-list of `ecb-default-tag-filter' is returned
2252
(dolist (spec ecb-default-tag-filter)
2253
(let ((m-mode (caar spec))
2254
(regexp (cdar spec)))
2255
(if (and (equal major-mode m-mode)
2257
(string-match regexp (buffer-file-name (current-buffer)))))
2258
(throw 'found (cdr spec)))))
2261
(defun ecb-apply-default-tag-filter ()
2262
"Applies all default-tag-filters specified in `ecb-default-tag-filter' for
2264
(remove-hook 'post-command-hook 'ecb-apply-default-tag-filter)
2266
(let ((tag-filter-list (ecb-default-tag-filter-for-current-file)))
2267
(dolist (filter-spec tag-filter-list)
2268
(let ((filter-apply-fcn
2269
(cond ((equal (nth 0 filter-spec) 'protection)
2270
'ecb-methods-filter-by-prot)
2271
((equal (nth 0 filter-spec) 'tag-class)
2272
'ecb-methods-filter-by-tag-class)
2273
((equal (nth 0 filter-spec) 'regexp)
2274
'ecb-methods-filter-by-regexp)
2275
((equal (nth 0 filter-spec) 'function)
2276
'ecb-methods-filter-by-function)))
2278
(cond ((equal (nth 0 filter-spec) 'protection)
2279
(cond ((symbolp (nth 1 filter-spec))
2280
(symbol-name (nth 1 filter-spec)))
2281
((stringp (nth 1 filter-spec))
2282
(nth 1 filter-spec))
2283
(t (ecb-error "Not a valid tag-filter: %s"
2284
(nth 1 filter-spec)))))
2285
((equal (nth 0 filter-spec) 'tag-class)
2286
(cond ((symbolp (nth 1 filter-spec))
2287
(symbol-name (nth 1 filter-spec)))
2288
((stringp (nth 1 filter-spec))
2289
(nth 1 filter-spec))
2290
(t (ecb-error "Not a valid tag-filter: %s"
2291
(nth 1 filter-spec)))))
2292
((equal (nth 0 filter-spec) 'regexp)
2293
(if (stringp (nth 1 filter-spec))
2295
(ecb-error "Not a valid tag-filter: %s"
2296
(nth 1 filter-spec))))
2297
((equal (nth 0 filter-spec) 'function)
2298
(cond ((symbolp (nth 1 filter-spec))
2299
(symbol-name (nth 1 filter-spec)))
2300
((stringp (nth 1 filter-spec))
2301
(nth 1 filter-spec))
2302
(t (ecb-error "Not a valid tag-filter: %s"
2303
(nth 1 filter-spec))))))))
2304
(funcall filter-apply-fcn
2305
(nth 2 filter-spec) (current-buffer) filter))))))
2307
(defun ecb-find-file-hook ()
2308
"Adds `ecb-apply-default-tag-filter' to `post-command-hook'. This function
2309
removes itself from the `post-command-hook'."
2310
(add-hook 'post-command-hook 'ecb-apply-default-tag-filter))
2312
;; adding tags to the Methods-buffer
1358
2314
(defun ecb-add-tags (node tags &optional parent-tag no-bucketize)
1359
2315
"If NO-BUCKETIZE is not nil then TAGS will not bucketized by
1360
2316
`ecb--semantic-bucketize' but must already been bucketized!"
1361
(ecb-add-tag-buckets node parent-tag
1364
(ecb--semantic-bucketize tags))
2317
(ecb-add-tag-buckets
2321
(ecb--semantic-bucketize tags
2323
(ecb--semantic-symbol->name-assoc-list-for-type-parts)
2324
(equal (ecb--semantic-tag-class parent-tag)
1368
2329
(defun ecb-access-order (access)
1808
2857
(if new-value "on" "off")
1811
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Hier auch was m�glich mit
1812
;; (ecb-exec-in-methods-window
1813
;; (tree-buffer-find-node-data curr-tag))
2860
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Define this with define-overload
2861
;; when the cedet 1.0 is stable - then we can remove the semantic 1.4 support
2862
;; - but first when cedet 1.0 is also available as XEmacs-package!
2863
(defun ecb-get-real-curr-tag ()
2864
"Get the \"real\" current tag. This will be in most cases the tag returned
2865
by `ecb--semantic-current-tag' but there are exceptions:
1815
(defun ecb-tag-sync-test (&optional force)
1816
(when (and ecb-minor-mode
1817
;; we do not use here `ecb-point-in-ecb-window' because this
1818
;; would slow down Emacs dramatically when tag-synchronization is
1819
;; done via post-command-hook and not via an idle-timer.
1820
(not (ecb-point-in-tree-buffer))
1821
(not (ecb-point-in-compile-window)))
1822
(when ecb-highlight-tag-with-point
1823
(let* ((tagstack (reverse (ecb--semantic-find-tag-by-overlay)))
1824
(curr-tag (car tagstack))
1825
(next-tag (car (cdr tagstack)))
1827
(if (and (equal (ecb--semantic-tag-class curr-tag) 'variable)
2867
- If the current-tag is an argument-tag of a function-tag then we are not
2868
interested in this argument-tag but in its parent-tag which is the
2869
function-tag the argument belongs.
2870
- If the current-tag is a label-tag then we are interested in the type-tag
2871
which contains this label \(e.g. usefull in c++ and the labels public,
2872
protected and private)."
2873
(let* ((tagstack (reverse (ecb--semantic-find-tag-by-overlay)))
2874
(curr-tag (car tagstack))
2875
(next-tag (car (cdr tagstack)))
2877
(if (or (and (equal (ecb--semantic-tag-class curr-tag) 'variable)
1828
2878
(equal (ecb--semantic-tag-class next-tag) 'function)
1829
(member curr-tag (ecb--semantic-tag-function-arguments next-tag)))
1830
(setq curr-tag next-tag))
1831
(when (or force (not (equal ecb-selected-tag curr-tag)))
1832
(setq ecb-selected-tag curr-tag)
1833
(save-selected-window
1834
(ecb-exec-in-methods-window
1835
(or (tree-buffer-highlight-node-data
1836
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight))
1837
;; The node representing CURR-TAG could not be highlighted be
1838
;; `tree-buffer-highlight-node-data' - probably it is
1839
;; invisible. Let's try to make visible and then highlighting
1841
(when (and curr-tag ecb-auto-expand-tag-tree
1842
(or (equal ecb-auto-expand-tag-tree 'all)
1843
(member (ecb--semantic-tag-class curr-tag)
1844
(ecb-normalize-expand-spec
1845
ecb-methods-nodes-expand-spec))))
1846
(ecb-expand-methods-nodes-internal
1848
(equal ecb-auto-expand-tag-tree 'all))
1849
(tree-buffer-highlight-node-data
1850
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight))
2880
(ecb--semantic-tag-function-arguments next-tag)))
2881
(equal (ecb--semantic-tag-class curr-tag) 'label))
2882
(setq curr-tag next-tag))
2885
(defun ecb-try-highlight-tag (highlight-tag curr-tag table)
2886
"First we try to expand only the absolute needed parts of the tree-buffer to
2887
highlight the tag HIGHLIGHT-TAG - this means we recursively go upstairs the
2888
ladder of types the current tag belongs to. If this has still no success then
2889
we return nil otherwise true \(the HIGHLIGHT-TAG is highlighted).
2891
If called from program: HIGHLIGHT-TAG is the tag to highlight, CURR-TAG has to
2892
be equal to HIGHLIGHT-TAG and TABLE must be the current tag-table of the
2894
(let* ((type-tag (and curr-tag
2895
(ecb-get-type-tag-of-tag curr-tag table t)))
2898
(list 'ecb-bucket-node
2899
(cdr (assoc (or (and (ecb--semantic-tag-prototype-p highlight-tag)
2901
(ecb--semantic-tag-class highlight-tag))
2902
(ecb-methods-get-data-store
2903
'semantic-symbol->name-assoc-list)))
2904
(ecb--semantic-tag-class highlight-tag))))
2907
(save-selected-window
2908
(ecb-exec-in-methods-window
2909
(or (tree-buffer-highlight-node-data
2911
(equal ecb-highlight-tag-with-point 'highlight))
2912
;; If the tag could not be highlighted and if there is no
2913
;; containing type for this tag then this tag is probably
2914
;; contained in a toplevel bucket. Then we search the
2915
;; bucket-node for the tag if this tag-class is specified
2916
;; as expanded or collapsed (ie not flattened or hidden
2917
;; because in these cases no bucket would exist). If we
2918
;; find the bucket-node then we expand only this
2919
;; bucket-node and try highlighting again.
2920
(when (and highlight-tag
2921
bucket-data ;; tag has no containing type
2922
;; (member (car (cdr (assoc (ecb--semantic-tag-class highlight-tag)
2923
;; (ecb-get-show-tags-list))))
2924
;; '(expanded collapsed))
2925
(or (equal ecb-auto-expand-tag-tree 'all)
2926
(member (ecb--semantic-tag-class highlight-tag)
2927
(ecb-normalize-expand-spec
2928
ecb-methods-nodes-expand-spec))))
2930
(tree-buffer-search-node-list
2931
(function (lambda (node)
2932
(if (and (tree-buffer-node-data-equal-p
2933
(tree-node-get-data node)
2935
(eq (tree-buffer-get-root)
2936
(tree-node-get-parent node)))
2939
(ecb-expand-methods-node-internal
2942
(equal ecb-auto-expand-tag-tree 'all)
2944
(tree-buffer-highlight-node-data
2946
(equal ecb-highlight-tag-with-point 'highlight)))))
2947
;; The node representing HIGHLIGHT-TAG could not be
2948
;; highlighted by `tree-buffer-highlight-node-data' -
2949
;; probably it is invisible. Let's try to make expand its
2950
;; containing type (if there is any) and then highlighting
2952
(when (and highlight-tag
2954
(or (equal ecb-auto-expand-tag-tree 'all)
2955
(member (ecb--semantic-tag-class highlight-tag)
2956
(ecb-normalize-expand-spec
2957
ecb-methods-nodes-expand-spec))))
2959
(cdr (tree-buffer-find-name-node-data type-tag)))
2961
(ecb-expand-methods-node-internal
2963
;; TODO: Klaus Berndl <klaus.berndl@sdm.de>: Maybe we
2964
;; should not immediately fully expand the type but
2966
;; 1. We expand only the first level of the type and
2967
;; check if the tag is contained in a flattended
2968
;; bucket. If yes we will have success and are
2969
;; finished because the tag must be contained in
2970
;; the type-tag. If no we go to step 2.
2971
;; 2. because the tag MUST be contained in that
2972
;; type-node we now know that it must be contained
2973
;; in a collapsed bucket-subnode of this
2974
;; type-node. So we have to expand this
2975
;; bucket-subnode (similar to the mechanism above)
2976
;; and then try again...
2978
(equal ecb-auto-expand-tag-tree 'all)
2980
(tree-buffer-highlight-node-data
2982
(equal ecb-highlight-tag-with-point 'highlight))
2985
(ecb-try-highlight-tag highlight-tag type-tag table)))))
2987
(defvar ecb-tag-sync-do-nothing nil
2988
"Only set by `ecb-jump-to-tag' and only evaluated by `ecb-tag-sync'")
2990
;; This approach only expands the needed parts of the tree-buffer when
2991
;; the current-tag is not visible as node and not the whole tree-buffer.
1853
2992
(defun ecb-tag-sync (&optional force)
1854
2993
(when (and ecb-minor-mode
1855
2994
;; we do not use here `ecb-point-in-ecb-window' because this
1856
2995
;; would slow down Emacs dramatically when tag-synchronization is
1857
2996
;; done via post-command-hook and not via an idle-timer.
1858
(not (ecb-point-in-tree-buffer))
2997
(not (ecb-point-in-dedicated-special-buffer))
1859
2998
(not (ecb-point-in-compile-window)))
1860
(when ecb-highlight-tag-with-point
1861
(let* ((tagstack (reverse (ecb--semantic-find-tag-by-overlay)))
1862
(curr-tag (car tagstack))
1863
(next-tag (car (cdr tagstack)))
1865
(if (and (equal (ecb--semantic-tag-class curr-tag) 'variable)
1866
(equal (ecb--semantic-tag-class next-tag) 'function)
1867
(member curr-tag (ecb--semantic-tag-function-arguments next-tag)))
1868
(setq curr-tag next-tag))
1869
(when (or force (not (equal ecb-selected-tag curr-tag)))
1870
(setq ecb-selected-tag curr-tag)
1871
(save-selected-window
1872
(ecb-exec-in-methods-window
1873
(or (tree-buffer-highlight-node-data
1874
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight))
1875
;; The node representing CURR-TAG could not be highlighted be
1876
;; `tree-buffer-highlight-node-data' - probably it is
1877
;; invisible. Let's try to make visible and then highlighting
1879
(when (and curr-tag ecb-auto-expand-tag-tree
1880
(or (equal ecb-auto-expand-tag-tree 'all)
1881
(member (ecb--semantic-tag-class curr-tag)
1882
(ecb-normalize-expand-spec
1883
ecb-methods-nodes-expand-spec))))
1884
(ecb-expand-methods-nodes-internal
1886
(equal ecb-auto-expand-tag-tree 'all))
1887
(tree-buffer-highlight-node-data
1888
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight))
2999
(if nil ;; ecb-tag-sync-do-nothing
3000
;; user has selected a tag via the Methods-window so there is nothing
3001
;; to sync - we must prevent from syncing here because in some modes
3002
;; the point stays after a click outside of the selected tag (see
3003
;; `ecb-tag-visit-post-actions') and if we would sync then in the
3004
;; methods-buffer the selected tag will be unhighlighted and the
3005
;; surrounding one will be highlighted (e.g. java the class of the
3006
;; tag). But we must reset this flag so the resync-mechanism runs
3008
;; Klaus Berndl <klaus.berndl@sdm.de>: Now all functions of
3009
;; ecb-tag-visit-post-actions are forbidden to put the point outside
3010
;; of the tag-boundaries. Therefore we can now remove this mechanism
3011
;; so now synching can take place also after a click. But i let the
3012
;; code in because im not at 100% sure if there are other needs in ECB
3013
;; which need this mechanism - but for now we can disable it.... ;-)
3014
(setq ecb-tag-sync-do-nothing nil)
3015
(when ecb-highlight-tag-with-point
3016
(let ((curr-tag (ecb-get-real-curr-tag)))
3017
(when (or force (not (equal ecb-selected-tag curr-tag)))
3018
(setq ecb-selected-tag curr-tag)
3020
(save-selected-window
3021
(ecb-exec-in-methods-window
3022
;; If there is no tag to highlight then we remove the
3024
(tree-buffer-highlight-node-data nil)
3025
(if (equal ecb-auto-expand-tag-tree-collapse-other 'always)
3026
;; If this option is t (means always) we collapse also
3027
;; when point is not on a tag!
3028
(ecb-expand-methods-node-internal
3029
(tree-buffer-get-root)
3031
(equal ecb-auto-expand-tag-tree 'all)
3033
;; Maybe we must first collapse all so only the needed parts are
3034
;; expanded afterwards. Klaus Berndl <klaus.berndl@sdm.de>: Is it
3035
;; necessary to update the tree-buffer after collapsing? IMO yes,
3036
;; because otherwise we set the expansion-state of the tree-buffer
3037
;; to all collapsed and if we find really nothing to highlight and
3038
;; do also no node-expanding (which would update the tree-buffer)
3039
;; then we have an inconsistent state - would be probably very
3040
;; seldom but could be - so let us be somehow paranoid ;-)
3041
(if ecb-auto-expand-tag-tree-collapse-other
3042
(save-selected-window
3043
(ecb-exec-in-methods-window
3045
(or (equal ecb-auto-expand-tag-tree 'all)
3046
(member (ecb--semantic-tag-class curr-tag)
3047
(ecb-normalize-expand-spec
3048
ecb-methods-nodes-expand-spec))))
3049
(ecb-expand-methods-node-internal
3050
(tree-buffer-get-root)
3052
(equal ecb-auto-expand-tag-tree 'all)
3054
;; First we try to expand only the absolute needed parts - this
3055
;; means we go upstairs the ladder of types the current tag
3056
;; belongs to. If there is no containing type then we try to
3057
;; expand only the containing toplevel bucket. If this has no
3058
;; success then we expand the full tree-buffer and try it again.
3059
(if (not (ecb-try-highlight-tag curr-tag curr-tag
3060
(ecb-get-current-tag-table)))
3061
;; The node representing CURR-TAG could not be highlighted by
3062
;; `tree-buffer-highlight-node-data' - probably it is still
3063
;; invisible. Let's try to make visible all nodes and then
3064
;; highlighting again.
3065
(save-selected-window
3066
(ecb-exec-in-methods-window
3068
(or (equal ecb-auto-expand-tag-tree 'all)
3069
(member (ecb--semantic-tag-class curr-tag)
3070
(ecb-normalize-expand-spec
3071
ecb-methods-nodes-expand-spec))))
3072
(ecb-expand-methods-node-internal
3073
(tree-buffer-get-root)
3074
100 ;; this should be enough levels ;-)
3075
(equal ecb-auto-expand-tag-tree 'all)
3077
(tree-buffer-highlight-node-data
3078
curr-tag nil (equal ecb-highlight-tag-with-point 'highlight)))
1891
3082
(defun ecb-find-file-and-display (filename other-edit-window)
1892
3083
"Finds the file in the correct window. What the correct window is depends on
2589
3768
(dotimes (i (min 8 (length edit-win-list)))
2592
(list (list (intern (format "ecb-jump-to-token-in-editwin%d" (1+ i)))
3771
(list (list (intern (format "ecb-jump-to-tag-in-editwin%d" (1+ i)))
2593
3772
(format "edit-window %d" (1+ i)))))))
2594
3773
(append (list (list "---")) ;; we want a separator
2595
(list (append (list "Jump to token in ...")
3774
(list (append (list "Jump to tag in ...")
3778
(defun ecb-methods-menu-tagfilter-entries ()
3779
"Generate popup-menu-entries for the tag-filtering"
3780
(let* ((curr-semantic-symbol->name-assoc-list
3781
;; we must not use here (ecb-methods-get-data-store
3782
;; 'semantic-symbol->name-assoc-list) because we do not want the
3783
;; function-prototypes...
3785
(set-buffer (ecb-methods-get-data-store 'source-buffer))
3786
(ecb--semantic-symbol->name-assoc-list)))
3787
(prot-list '("private" "protected" "public"))
3788
(prot-menu-elems nil)
3789
(prot-menu-elems-inverse nil)
3790
(prot-menu-entries nil)
3791
(prot-menu-entries-inverse)
3792
(tag-menu-class-elems nil)
3793
(tag-menu-class-elems-inverse nil)
3794
(tag-menu-class-entries nil)
3795
(tag-menu-class-entries-inverse nil))
3796
;; First we have to define all the needed tree-buffer-commands for
3797
;; protection- and tagclass-filtering. But this is only done for
3798
;; semantic-sources and also the first time.
3799
(when curr-semantic-symbol->name-assoc-list
3800
(dolist (tag-class curr-semantic-symbol->name-assoc-list)
3801
(let ((fcn-sym (intern (format "ecb-methods-filter-by-%s-tagclass"
3803
(setq tag-menu-class-elems (cons (cons fcn-sym (cdr tag-class))
3804
tag-menu-class-elems))
3805
(when (not (fboundp fcn-sym))
3806
(eval `(tree-buffer-defpopup-command ,fcn-sym
3807
,(format "Filter all tags with tag-class '%s." (car tag-class))
3808
(ecb-methods-filter-by-tag-class nil
3809
(ecb-methods-get-data-store 'source-buffer)
3810
,(symbol-name (car tag-class))))))))
3811
(dolist (tag-class curr-semantic-symbol->name-assoc-list)
3812
(let ((fcn-sym (intern (format "ecb-methods-filter-by-%s-tagclass-inverse"
3814
(setq tag-menu-class-elems-inverse
3815
(cons (cons fcn-sym (concat "not " (cdr tag-class)))
3816
tag-menu-class-elems-inverse))
3817
(when (not (fboundp fcn-sym))
3818
(eval `(tree-buffer-defpopup-command ,fcn-sym
3819
,(format "Filter all tags with tag-class unequal '%s."
3821
(ecb-methods-filter-by-tag-class t
3822
(ecb-methods-get-data-store 'source-buffer)
3823
,(symbol-name (car tag-class))))))))
3824
(dolist (prot prot-list)
3825
(let ((fcn-sym (intern (format "ecb-methods-filter-by-%s-prot" prot))))
3826
(setq prot-menu-elems (cons (cons fcn-sym prot)
3828
(when (not (fboundp fcn-sym))
3829
(eval `(tree-buffer-defpopup-command ,fcn-sym
3830
,(format "Filter all tags with %s protection." prot)
3831
(ecb-methods-filter-by-prot nil
3832
(ecb-methods-get-data-store 'source-buffer)
3834
(dolist (prot prot-list)
3835
(let ((fcn-sym (intern (format "ecb-methods-filter-by-%s-prot-inverse" prot))))
3836
(setq prot-menu-elems-inverse
3837
(cons (cons fcn-sym (concat "not " prot))
3838
prot-menu-elems-inverse))
3839
(when (not (fboundp fcn-sym))
3840
(eval `(tree-buffer-defpopup-command ,fcn-sym
3841
,(format "Filter all tags with not %s protection." prot)
3842
(ecb-methods-filter-by-prot t
3843
(ecb-methods-get-data-store 'source-buffer)
3845
;; building the menu-entries-list for tag-classes and protections.
3846
(dolist (elem tag-menu-class-elems)
3847
(setq tag-menu-class-entries
3848
(append tag-menu-class-entries
3849
(list (list (car elem) (cdr elem))))))
3850
(dolist (elem tag-menu-class-elems-inverse)
3851
(setq tag-menu-class-entries-inverse
3852
(append tag-menu-class-entries-inverse
3853
(list (list (car elem) (cdr elem))))))
3854
(dolist (elem prot-menu-elems)
3855
(setq prot-menu-entries
3856
(append prot-menu-entries
3857
(list (list (car elem) (cdr elem))))))
3858
(dolist (elem prot-menu-elems-inverse)
3859
(setq prot-menu-entries-inverse
3860
(append prot-menu-entries-inverse
3861
(list (list (car elem) (cdr elem))))))
3862
;; building the complete filter-menu
3863
(append nil ;; (list (list "---")) ;; we want a separator
3864
(list (append (list "Filter tags")
3865
(list '(ecb-methods-filter-by-nothing-popup
3867
'(ecb-methods-filter-delete-last-popup
3868
"Remove last added")
3870
'(ecb-methods-filter-by-regexp-popup
3872
(when prot-menu-entries
3873
(list (append (list "By protection")
3874
prot-menu-entries)))
3875
(when tag-menu-class-entries
3876
(list (append (list "By tag-class")
3877
tag-menu-class-entries)))
3878
(when curr-semantic-symbol->name-assoc-list
3879
(list '(ecb-methods-filter-by-current-type-popup
3880
"By current type")))
3881
(list '(ecb-methods-filter-by-function-popup
3882
"By a filter-function")
3884
'(ecb-methods-filter-by-regexp-popup-inverse
3885
"By inverse regexp"))
3886
(when prot-menu-entries-inverse
3887
(list (append (list "By inverse protection")
3888
prot-menu-entries-inverse)))
3889
(when tag-menu-class-entries-inverse
3890
(list (append (list "By inverse tag-class")
3891
tag-menu-class-entries-inverse)))
3892
(list '(ecb-methods-filter-by-function-popup-inverse
3893
"By a inverse filter-function")))))))
2598
3895
(defun ecb-methods-menu-creator (tree-buffer-name)
2599
3896
"Creates the popup-menus for the methods-buffer."
2600
3897
(setq ecb-layout-prevent-handle-ecb-window-selection t)
2601
3898
(let ((dyn-user-extension
2602
3899
(and (functionp ecb-methods-menu-user-extension-function)
2603
3900
(funcall ecb-methods-menu-user-extension-function)))
2604
(dyn-builtin-extension (ecb-methods-menu-editwin-entries)))
3901
(dyn-builtin-extension-edit-win (ecb-methods-menu-editwin-entries))
3902
(dyn-builtin-extension-tagfilter (ecb-methods-menu-tagfilter-entries)))
2605
3903
(list (cons 0 (funcall (or ecb-methods-menu-sorter
2607
3905
(append dyn-user-extension
2608
3906
ecb-methods-menu-user-extension
3907
dyn-builtin-extension-tagfilter
2609
3908
ecb-methods-tag-menu
2610
dyn-builtin-extension)))
3909
dyn-builtin-extension-edit-win)))
2611
3910
(cons 1 (funcall (or ecb-methods-menu-sorter
2613
3912
(append dyn-user-extension
2614
3913
ecb-methods-menu-user-extension
3914
dyn-builtin-extension-tagfilter
2615
3915
ecb-common-methods-menu)))
2616
3916
(cons 2 (funcall (or ecb-methods-menu-sorter
2618
3918
(append dyn-user-extension
2619
3919
ecb-methods-menu-user-extension
3920
dyn-builtin-extension-tagfilter
2620
3921
ecb-common-methods-menu))))))
3923
(defconst ecb-methods-incr-searchpattern-node-prefix
3924
'("\\([-+#(]\\|[^-+#(][^ \n]+ \\)?" . 1)
3925
"Prefix-pattern which ignores all not interesting stuff of a node-name at
3926
incr. search. The following contents of a node-name are ignored by this
3928
- types of a variable or return-types of a method
3929
- const specifier of variables
3930
- protection sign of a variable/method: +, - or #
3932
Format: cons with car is the pattern and cdr is the number of subexpr in this
3935
;; Function which compares the node-data of a tree-buffer-node in the
3936
;; method-buffer for equality. We must compare semantic-tags but we must not
3937
;; compare the tags with eq or equal because they can be re-grouped by
3938
;; ecb--semantic-adopt-external-members. the following function is a save
3939
;; "equal"-condition for ECB because currently the method buffer always
3940
;; displays only tags from exactly the buffer of the current edit-window. If
3941
;; `ecb--semantic-equivalent-tag-p' fails we return the result of an
3943
(defun ecb-compare-methods-buffer-node-data (l r)
3944
(cond ((or (stringp l) (stringp r))
3946
((or (equal 'ecb-bucket-node (car l))
3947
(equal 'ecb-bucket-node (car r)))
3951
(ecb--semantic-equivalent-tag-p l r)
3952
(error (eq l r))))))
3954
(defun ecb-create-methods-tree-buffer ()
3955
"Create the tree-buffer for methods."
3957
ecb-methods-buffer-name
3959
ecb-tree-mouse-action-trigger
3960
'ecb-interpret-mouse-click
3961
'ecb-tree-buffer-node-select-callback
3962
'ecb-tree-buffer-node-expand-callback
3963
'ecb-tree-buffer-node-collapsed-callback
3964
'ecb-mouse-over-method-node
3965
'ecb-compare-methods-buffer-node-data
3968
'ecb-methods-menu-creator
3969
(list (cons 0 ecb-methods-menu-title-creator)
3970
(cons 1 ecb-methods-menu-title-creator)
3971
(cons 2 ecb-methods-menu-title-creator))
3972
(nth 2 ecb-truncate-lines)
3975
ecb-tree-incremental-search
3976
ecb-methods-incr-searchpattern-node-prefix
3977
ecb-tree-navigation-by-arrow
3978
ecb-tree-easy-hor-scroll
3979
(nth 0 ecb-tree-image-icons-directories)
3980
(nth 3 ecb-tree-image-icons-directories)
3981
ecb-tree-buffer-style
3982
ecb-tree-guide-line-face
3984
ecb-tree-expand-symbol-before
3986
ecb-methods-general-face
3988
(list (function (lambda ()
3989
(local-set-key (kbd "C-t")
3990
'ecb-toggle-RET-selects-edit-window)
3991
(if (not ecb-running-xemacs)
3992
(define-key tree-buffer-key-map
3994
'ecb-toggle-maximize-ecb-window-with-mouse))
3995
(setq ecb-methods-root-node (tree-buffer-get-root)))))
3996
ecb-common-tree-buffer-after-create-hook
3997
ecb-directories-buffer-after-create-hook)))
2623
3999
(defun ecb-dump-semantic-toplevel ()
2624
4000
"Dump the current semantic-tags in special buffer and display them."
2626
(let ((tags (ecb-post-process-taglist (ecb--semantic-bovinate-toplevel t))))
4002
(let ((tags (ecb--semantic-fetch-tags))
4003
(source-buf (current-buffer)))
2627
4004
(save-selected-window
2628
(set-buffer (get-buffer-create "ecb-dump"))
4005
(set-buffer (get-buffer-create "*ecb-tag-dump*"))
2630
(ecb-dump-tags tags "")
2631
(switch-to-buffer-other-window (get-buffer-create "ecb-dump"))
4007
(ecb-dump-semantic-tags-internal tags nil source-buf 1)
4008
(switch-to-buffer-other-window (get-buffer-create "*ecb-tag-dump*"))
2632
4009
(goto-char (point-min)))))
2635
(defun ecb-dump-type (a-tag prefix)
2636
(dolist (parent (ecb-get-tag-parents a-tag))
2637
(insert prefix " " parent)))
2640
(defun ecb-dump-tags (tags prefix)
2641
(dolist (a-tag tags)
2643
(princ (concat prefix a-tag))
2645
(ecb--semantic-format-tag-name a-tag nil ecb-font-lock-tags)
2647
(symbol-name (ecb--semantic-tag-class a-tag))
2649
(if (stringp (ecb--semantic-tag-type a-tag))
2650
(ecb--semantic-tag-type a-tag)
2653
(if (eq 'type (ecb--semantic-tag-class a-tag))
2654
(ecb-dump-type a-tag prefix))
2655
(ecb-dump-tags (ecb--semantic-tag-children-compatibility
2656
a-tag ecb-show-only-positioned-tags)
2657
(concat prefix " ")))))
4012
(defun ecb-dump-semantic-tags-internal (table parent source-buffer indent)
4014
(insert (format "%s%s, tag-class: %s\n" (make-string indent ? )
4016
(set-buffer source-buffer)
4017
(ecb--semantic-format-tag-uml-prototype tag parent t))
4018
(ecb--semantic-tag-class tag)))
4019
(ecb-dump-semantic-tags-internal (ecb--semantic-tag-children-compatibility tag t)
4020
(if (equal (ecb--semantic-tag-class tag)
2659
4026
(silentcomp-provide 'ecb-method-browser)
2661
4028
;;; ecb-method-browser.el end here