(dos-windows-version): Add defvar.
[bpt/emacs.git] / lisp / progmodes / ebrowse.el
CommitLineData
be0dbdab
GM
1;;; ebrowse.el --- Emacs C++ class browser & tags facility
2
ea81d57e 3;; Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002, 2005
8c8f9bc1 4;; Free Software Foundation Inc.
be0dbdab
GM
5
6;; Author: Gerd Moellmann <gerd@gnu.org>
7;; Maintainer: FSF
8;; Keywords: C++ tags tools
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to
24;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25
26;;; Commentary:
27
28;; This package implements
29
30;; - A class browser for C++
31;; - A complete set of tags-like functions working on class trees
32;; - An electric buffer list showing class browser buffers only
33
106ba1bb 34;; Documentation is found in a separate Info file.
be0dbdab
GM
35
36;;; Code:
37
38(require 'easymenu)
39(require 'view)
40(require 'ebuff-menu)
41
42(eval-when-compile
43 (require 'cl)
44 (require 'helper))
45
46\f
47;;; User-options
48
49(defgroup ebrowse nil
50 "Settings for the C++ class browser."
51 :group 'tools)
52
53
54(defcustom ebrowse-search-path nil
55 "*List of directories to search for source files in a class tree.
56Elements should be directory names; nil as an element means to try
183c2d42 57to find source files relative to the location of the BROWSE file loaded."
be0dbdab
GM
58 :group 'ebrowse
59 :type '(repeat (choice (const :tag "Default" nil)
60 (string :tag "Directory"))))
61
62
63(defcustom ebrowse-view/find-hook nil
64 "*Hooks run after finding or viewing a member or class."
65 :group 'ebrowse
66 :type 'hook)
67
68
69(defcustom ebrowse-not-found-hook nil
70 "*Hooks run when finding or viewing a member or class was not successful."
71 :group 'ebrowse
72 :type 'hook)
73
74
75(defcustom ebrowse-electric-list-mode-hook nil
76 "*Hook called by `ebrowse-electric-position-mode'."
77 :group 'ebrowse
78 :type 'hook)
79
80
81(defcustom ebrowse-max-positions 50
82 "*Number of markers saved on electric position stack."
83 :group 'ebrowse
84 :type 'integer)
85
86
87\f
88(defgroup ebrowse-tree nil
89 "Settings for class tree buffers."
90 :group 'ebrowse)
91
92
93(defcustom ebrowse-tree-mode-hook nil
94 "*Hook run in each new tree buffer."
95 :group 'ebrowse-tree
96 :type 'hook)
97
98
99(defcustom ebrowse-tree-buffer-name "*Tree*"
100 "*The default name of class tree buffers."
101 :group 'ebrowse-tree
102 :type 'string)
103
104
105(defcustom ebrowse--indentation 4
106 "*The amount by which subclasses are indented in the tree."
107 :group 'ebrowse-tree
108 :type 'integer)
109
110
111(defcustom ebrowse-source-file-column 40
112 "*The column in which source file names are displayed in the tree."
113 :group 'ebrowse-tree
114 :type 'integer)
115
116
117(defcustom ebrowse-tree-left-margin 2
118 "*Amount of space left at the left side of the tree display.
119This space is used to display markers."
120 :group 'ebrowse-tree
121 :type 'integer)
122
123
124\f
125(defgroup ebrowse-member nil
126 "Settings for member buffers."
127 :group 'ebrowse)
128
129
130(defcustom ebrowse-default-declaration-column 25
131 "*The column in which member declarations are displayed in member buffers."
132 :group 'ebrowse-member
133 :type 'integer)
134
135
136(defcustom ebrowse-default-column-width 25
137 "*The width of the columns in member buffers (short display form)."
138 :group 'ebrowse-member
139 :type 'integer)
140
141
142(defcustom ebrowse-member-buffer-name "*Members*"
143 "*The name of the buffer for member display."
144 :group 'ebrowse-member
145 :type 'string)
146
147
148(defcustom ebrowse-member-mode-hook nil
149 "*Run in each new member buffer."
150 :group 'ebrowse-member
151 :type 'hook)
152
153
154\f
155(defgroup ebrowse-faces nil
156 "Faces used by Ebrowse."
157 :group 'ebrowse)
158
159
4f2d55da 160(defface ebrowse-tree-mark
ea81d57e
DN
161 '((((min-colors 88)) (:foreground "red1"))
162 (t (:foreground "red")))
be0dbdab
GM
163 "*The face used for the mark character in the tree."
164 :group 'ebrowse-faces)
4f2d55da
MB
165;; backward-compatibility alias
166(put 'ebrowse-tree-mark-face 'face-alias 'ebrowse-tree-mark)
be0dbdab
GM
167
168
4f2d55da 169(defface ebrowse-root-class
ea81d57e
DN
170 '((((min-colors 88)) (:weight bold :foreground "blue1"))
171 (t (:weight bold :foreground "blue")))
be0dbdab
GM
172 "*The face used for root classes in the tree."
173 :group 'ebrowse-faces)
4f2d55da
MB
174;; backward-compatibility alias
175(put 'ebrowse-root-class-face 'face-alias 'ebrowse-root-class)
be0dbdab
GM
176
177
4f2d55da 178(defface ebrowse-file-name
be0dbdab
GM
179 '((t (:italic t)))
180 "*The face for filenames displayed in the tree."
181 :group 'ebrowse-faces)
4f2d55da
MB
182;; backward-compatibility alias
183(put 'ebrowse-file-name-face 'face-alias 'ebrowse-file-name)
be0dbdab
GM
184
185
4f2d55da 186(defface ebrowse-default
be0dbdab
GM
187 '((t nil))
188 "*Face for everything else in the tree not having other faces."
189 :group 'ebrowse-faces)
4f2d55da
MB
190;; backward-compatibility alias
191(put 'ebrowse-default-face 'face-alias 'ebrowse-default)
be0dbdab
GM
192
193
4f2d55da 194(defface ebrowse-member-attribute
ea81d57e
DN
195 '((((min-colors 88)) (:foreground "red1"))
196 (t (:foreground "red")))
be0dbdab
GM
197 "*Face used to display member attributes."
198 :group 'ebrowse-faces)
4f2d55da
MB
199;; backward-compatibility alias
200(put 'ebrowse-member-attribute-face 'face-alias 'ebrowse-member-attribute)
be0dbdab
GM
201
202
4f2d55da 203(defface ebrowse-member-class
be0dbdab
GM
204 '((t (:foreground "purple")))
205 "*Face used to display the class title in member buffers."
206 :group 'ebrowse-faces)
4f2d55da
MB
207;; backward-compatibility alias
208(put 'ebrowse-member-class-face 'face-alias 'ebrowse-member-class)
be0dbdab
GM
209
210
4f2d55da 211(defface ebrowse-progress
ea81d57e
DN
212 '((((min-colors 88)) (:background "blue1"))
213 (t (:background "blue")))
be0dbdab
GM
214 "*Face for progress indicator."
215 :group 'ebrowse-faces)
4f2d55da
MB
216;; backward-compatibility alias
217(put 'ebrowse-progress-face 'face-alias 'ebrowse-progress)
be0dbdab
GM
218
219
220\f
221;;; Utilities.
222
223(defun ebrowse-some (predicate vector)
224 "Return true if PREDICATE is true of some element of VECTOR.
225If so, return the value returned by PREDICATE."
226 (let ((length (length vector))
227 (i 0)
228 result)
229 (while (and (< i length) (not result))
230 (setq result (funcall predicate (aref vector i))
231 i (1+ i)))
232 result))
233
234
235(defun ebrowse-every (predicate vector)
236 "Return true if PREDICATE is true of every element of VECTOR."
237 (let ((length (length vector))
238 (i 0)
239 (result t))
240 (while (and (< i length) result)
241 (setq result (funcall predicate (aref vector i))
242 i (1+ i)))
243 result))
244
245
246(defun ebrowse-position (item list &optional test)
247 "Return the position of ITEM in LIST or nil if not found.
248Compare items with `eq' or TEST if specified."
249 (let ((i 0) found)
250 (cond (test
251 (while list
252 (when (funcall test item (car list))
253 (setq found i list nil))
254 (setq list (cdr list) i (1+ i))))
255 (t
256 (while list
257 (when (eq item (car list))
258 (setq found i list nil))
259 (setq list (cdr list) i (1+ i)))))
260 found))
261
262
263(defun ebrowse-delete-if-not (predicate list)
264 "Remove elements not satisfying PREDICATE from LIST and return the result.
265This is a destructive operation."
266 (let (result)
267 (while list
268 (let ((next (cdr list)))
269 (when (funcall predicate (car list))
270 (setq result (nconc result list))
271 (setf (cdr list) nil))
272 (setq list next)))
273 result))
274
275
be0dbdab
GM
276(defmacro ebrowse-output (&rest body)
277 "Eval BODY with a writable current buffer.
278Preserve buffer's modified state."
6f4070e0 279 (let ((modified (make-symbol "--ebrowse-output--")))
be0dbdab
GM
280 `(let (buffer-read-only (,modified (buffer-modified-p)))
281 (unwind-protect
282 (progn ,@body)
283 (set-buffer-modified-p ,modified)))))
284
285
286(defmacro ebrowse-ignoring-completion-case (&rest body)
287 "Eval BODY with `completion-ignore-case' bound to t."
288 `(let ((completion-ignore-case t))
289 ,@body))
290
291
292(defmacro ebrowse-save-selective (&rest body)
293 "Eval BODY with `selective-display' restored at the end."
294 (let ((var (make-symbol "var")))
295 `(let ((,var selective-display))
296 (unwind-protect
297 (progn ,@body)
298 (setq selective-display ,var)))))
299
300
301(defmacro ebrowse-for-all-trees (spec &rest body)
302 "For all trees in SPEC, eval BODY."
303 (let ((var (make-symbol "var"))
304 (spec-var (car spec))
305 (array (cadr spec)))
306 `(loop for ,var being the symbols of ,array
307 as ,spec-var = (get ,var 'ebrowse-root) do
308 (when (vectorp ,spec-var)
309 ,@body))))
310
311;;; Set indentation for macros above.
312
313(put 'ebrowse-output 'lisp-indent-hook 0)
314(put 'ebrowse-ignoring-completion-case 'lisp-indent-hook 0)
315(put 'ebrowse-save-selective 'lisp-indent-hook 0)
316(put 'ebrowse-for-all-trees 'lisp-indent-hook 1)
317
318
319(defsubst ebrowse-set-face (start end face)
320 "Set face of a region START END to FACE."
321 (overlay-put (make-overlay start end) 'face face))
322
323
324(defun ebrowse-completing-read-value (prompt table initial-input)
325 "Read a string in the minibuffer, with completion.
326Case is ignored in completions.
327
328PROMPT is a string to prompt with; normally it ends in a colon and a space.
329TABLE is an alist whose elements' cars are strings, or an obarray.
330TABLE can also be a function to do the completion itself.
331If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
332If it is (STRING . POSITION), the initial input
333is STRING, but point is placed POSITION characters into the string."
334 (ebrowse-ignoring-completion-case
335 (completing-read prompt table nil t initial-input)))
336
337
338(defun ebrowse-value-in-buffer (sym buffer)
339 "Return the value of SYM in BUFFER."
340 (let ((old-buffer (current-buffer)))
341 (unwind-protect
342 (progn
343 (set-buffer buffer)
344 (symbol-value sym))
345 (set-buffer old-buffer))))
346
347
348(defun ebrowse-rename-buffer (new-name)
349 "Rename current buffer to NEW-NAME.
350If a buffer with name NEW-NAME already exists, delete it first."
351 (let ((old-buffer (get-buffer new-name)))
352 (unless (eq old-buffer (current-buffer))
353 (when old-buffer
354 (save-excursion (kill-buffer old-buffer)))
355 (rename-buffer new-name))))
356
357
358(defun ebrowse-trim-string (string)
359 "Return a copy of STRING with leading white space removed.
360Replace sequences of newlines with a single space."
361 (when (string-match "^[ \t\n\r]+" string)
362 (setq string (substring string (match-end 0))))
363 (loop while (string-match "[\n]+" string)
364 finally return string do
365 (setq string (replace-match " " nil t string))))
366
367
368(defun ebrowse-width-of-drawable-area ()
369 "Return the width of the display area for the current buffer.
370If buffer is displayed in a window, use that window's width,
371otherwise use the current frame's width."
372 (let ((window (get-buffer-window (current-buffer))))
373 (if window
374 (window-width window)
375 (frame-width))))
376
377\f
378;;; Structure definitions
379
380(defstruct (ebrowse-hs (:type vector) :named)
183c2d42 381 "Header structure found at the head of BROWSE files."
be0dbdab
GM
382 ;; A version string that is compared against the version number of
383 ;; the Lisp package when the file is loaded. This is done to
384 ;; detect file format changes.
385 version
183c2d42 386 ;; Command line options used for producing the BROWSE file.
be0dbdab
GM
387 command-line-options
388 ;; The following slot is currently not used. It's kept to keep
389 ;; the file format compatible.
390 unused
391 ;; A slot that is filled out after the tree is loaded. This slot is
392 ;; set to a hash table mapping members to lists of classes in which
393 ;; they are defined.
394 member-table)
395
106ba1bb 396
be0dbdab
GM
397(defstruct (ebrowse-ts (:type vector) :named)
398 "Tree structure.
106ba1bb 399Following the header structure, a BROWSE file contains a number
be0dbdab
GM
400of `ebrowse-ts' structures, each one describing one root class of
401the class hierarchy with all its subclasses."
402 ;; A `ebrowse-cs' structure describing the root class.
403 class
404 ;; A list of `ebrowse-ts' structures for all subclasses.
405 subclasses
406 ;; Lists of `ebrowse-ms' structures for each member in a group of
407 ;; members.
408 member-variables member-functions static-variables static-functions
409 friends types
410 ;; List of `ebrowse-ts' structures for base classes. This slot is
411 ;; filled at load time.
412 base-classes
413 ;; A marker slot used in the tree buffer (can be saved back to disk.
414 mark)
415
416
417(defstruct (ebrowse-bs (:type vector) :named)
418 "Common sub-structure.
419A common structure defining an occurrence of some name in the
420source files."
421 ;; The class or member name as a string constant
422 name
423 ;; An optional string for the scope of nested classes or for
424 ;; namespaces.
425 scope
426 ;; Various flags describing properties of classes/members, e.g. is
427 ;; template, is const etc.
428 flags
429 ;; File in which the entity is found. If this is part of a
430 ;; `ebrowse-ms' member description structure, and FILE is nil, then
431 ;; search for the name in the SOURCE-FILE of the members class.
432 file
433 ;; Regular expression to search for. This slot can be a number in
434 ;; which case the number is the file position at which the regular
435 ;; expression is found in a separate regexp file (see the header
436 ;; structure). This slot can be nil in which case the regular
437 ;; expression will be generated from the class/member name.
438 pattern
439 ;; The buffer position at which the search for the class or member
440 ;; will start.
441 point)
442
443
444(defstruct (ebrowse-cs (:include ebrowse-bs) (:type vector) :named)
445 "Class structure.
446This is the structure stored in the CLASS slot of a `ebrowse-ts'
447structure. It describes the location of the class declaration."
448 source-file)
449
450
451(defstruct (ebrowse-ms (:include ebrowse-bs) (:type vector) :named)
452 "Member structure.
453This is the structure describing a single member. The `ebrowse-ts'
454structure contains various lists for the different types of
455members."
456 ;; Public, protected, private
457 visibility
458 ;; The file in which the member's definition can be found.
459 definition-file
460 ;; Same as PATTERN above, but for the member definition.
461 definition-pattern
462 ;; Same as POINT above but for member definition.
463 definition-point)
464
465
466\f
467;;; Some macros to access the FLAGS slot of a MEMBER.
468
469(defsubst ebrowse-member-bit-set-p (member bit)
470 "Value is non-nil if MEMBER's bit BIT is set."
471 (/= 0 (logand (ebrowse-bs-flags member) bit)))
472
473
474(defsubst ebrowse-virtual-p (member)
475 "Value is non-nil if MEMBER is virtual."
476 (ebrowse-member-bit-set-p member 1))
477
478
479(defsubst ebrowse-inline-p (member)
480 "Value is non-nil if MEMBER is inline."
481 (ebrowse-member-bit-set-p member 2))
482
483
484(defsubst ebrowse-const-p (member)
485 "Value is non-nil if MEMBER is const."
486 (ebrowse-member-bit-set-p member 4))
487
488
489(defsubst ebrowse-pure-virtual-p (member)
490 "Value is non-nil if MEMBER is a pure virtual function."
491 (ebrowse-member-bit-set-p member 8))
492
493
494(defsubst ebrowse-mutable-p (member)
495 "Value is non-nil if MEMBER is mutable."
496 (ebrowse-member-bit-set-p member 16))
497
498
499(defsubst ebrowse-template-p (member)
500 "Value is non-nil if MEMBER is a template."
501 (ebrowse-member-bit-set-p member 32))
502
503
504(defsubst ebrowse-explicit-p (member)
505 "Value is non-nil if MEMBER is explicit."
506 (ebrowse-member-bit-set-p member 64))
507
508
509(defsubst ebrowse-throw-list-p (member)
510 "Value is non-nil if MEMBER has a throw specification."
511 (ebrowse-member-bit-set-p member 128))
512
513
514(defsubst ebrowse-extern-c-p (member)
515 "Value is non-nil if MEMBER.is `extern \"C\"'."
516 (ebrowse-member-bit-set-p member 256))
517
518
519(defsubst ebrowse-define-p (member)
520 "Value is non-nil if MEMBER is a define."
521 (ebrowse-member-bit-set-p member 512))
522
523
524(defconst ebrowse-version-string "ebrowse 5.0"
183c2d42 525 "Version string expected in BROWSE files.")
be0dbdab
GM
526
527
528(defconst ebrowse-globals-name "*Globals*"
529 "The name used for the surrogate class.containing global entities.
530This must be the same that `ebrowse' uses.")
531
532
533(defvar ebrowse--last-regexp nil
534 "Last regular expression searched for in tree and member buffers.
52dcc114 535Each tree and member buffer maintains its own search history.")
be0dbdab
GM
536(make-variable-buffer-local 'ebrowse--last-regexp)
537
538
539(defconst ebrowse-member-list-accessors
540 '(ebrowse-ts-member-variables
541 ebrowse-ts-member-functions
542 ebrowse-ts-static-variables
543 ebrowse-ts-static-functions
544 ebrowse-ts-friends
545 ebrowse-ts-types)
546 "List of accessors for member lists.
547Each element is the symbol of an accessor function.
548The nth element must be the accessor for the nth member list
549in an `ebrowse-ts' structure.")
550
551
552;;; FIXME: Add more doc strings for the buffer-local variables below.
553
554(defvar ebrowse--tree-obarray nil
555 "Obarray holding all `ebrowse-ts' structures of a class tree.
556Buffer-local in Ebrowse buffers.")
557
558
559(defvar ebrowse--tags-file-name nil
183c2d42 560 "File from which BROWSE file was loaded.
be0dbdab
GM
561Buffer-local in Ebrowse buffers.")
562
563
564(defvar ebrowse--header nil
565 "Header structure of type `ebrowse-hs' of a class tree.
566Buffer-local in Ebrowse buffers.")
567
568
569(defvar ebrowse--frozen-flag nil
570 "Non-nil means an Ebrowse buffer won't be reused.
571Buffer-local in Ebrowse buffers.")
106ba1bb 572
be0dbdab
GM
573
574(defvar ebrowse--show-file-names-flag nil
575 "Non-nil means show file names in a tree buffer.
576Buffer-local in Ebrowse tree buffers.")
577
578
579(defvar ebrowse--long-display-flag nil
580 "Non-nil means show members in long display form.
581Buffer-local in Ebrowse member buffers.")
582
583
584(defvar ebrowse--n-columns nil
585 "Number of columns to display for short member display form.
586Buffer-local in Ebrowse member buffers.")
587
588
589(defvar ebrowse--column-width nil
590 "Width of a columns to display for short member display form.
591Buffer-local in Ebrowse member buffers.")
592
106ba1bb 593
be0dbdab
GM
594(defvar ebrowse--virtual-display-flag nil
595 "Non-nil means display virtual members in a member buffer.
596Buffer-local in Ebrowse member buffers.")
597
598
599(defvar ebrowse--inline-display-flag nil
600 "Non-nil means display inline members in a member buffer.
601Buffer-local in Ebrowse member buffers.")
602
603
604(defvar ebrowse--const-display-flag nil
605 "Non-nil means display const members in a member buffer.
606Buffer-local in Ebrowse member buffers.")
607
608
609(defvar ebrowse--pure-display-flag nil
610 "Non-nil means display pure virtual members in a member buffer.
611Buffer-local in Ebrowse member buffers.")
612
613
614(defvar ebrowse--filters nil
615 "Filter for display of public, protected, and private members.
616This is a vector of three elements. An element nil means the
617corresponding members are not shown.
618Buffer-local in Ebrowse member buffers.")
619
620
621(defvar ebrowse--show-inherited-flag nil
622 "Non-nil means display inherited members in a member buffer.
623Buffer-local in Ebrowse member buffers.")
624
625
626(defvar ebrowse--attributes-flag nil
627 "Non-nil means display member attributes in a member buffer.
628Buffer-local in Ebrowse member buffers.")
629
630
631(defvar ebrowse--source-regexp-flag nil
632 "Non-nil means display member regexps in a member buffer.
633Buffer-local in Ebrowse member buffers.")
634
635
636(defvar ebrowse--displayed-class nil
637 "Class displayed in a member buffer, a `ebrowse-ts' structure.
638Buffer-local in Ebrowse member buffers.")
639
640
641(defvar ebrowse--accessor nil
642 "Member list displayed in a member buffer.
643This is a symbol whose function definition is an accessor for the
644member list in `ebrowse-cs' structures.
645Buffer-local in Ebrowse member buffers.")
646
647
648(defvar ebrowse--member-list nil
649 "The list of `ebrowse-ms' structures displayed in a member buffer.
650Buffer-local in Ebrowse member buffers.")
651
652
653(defvar ebrowse--decl-column nil
654 "Column in which declarations are displayed in member buffers.
655Buffer-local in Ebrowse member buffers.")
656
657
be0dbdab
GM
658(defvar ebrowse--frame-configuration nil
659 "Frame configuration saved when viewing a class/member in another frame.
660Buffer-local in Ebrowse buffers.")
661
662
663(defvar ebrowse--view-exit-action nil
664 "Action to perform after viewing a class/member.
665Either `kill-buffer' or nil.
666Buffer-local in Ebrowse buffers.")
667
668
669(defvar ebrowse--tree nil
670 "Class tree.
671Buffer-local in Ebrowse buffers.")
672
673
be0dbdab
GM
674;;; Temporaries used to communicate with `ebrowse-find-pattern'.
675
676(defvar ebrowse-temp-position-to-view nil)
677(defvar ebrowse-temp-info-to-view nil)
678
679
680(defvar ebrowse-tree-mode-map ()
681 "The keymap used in tree mode buffers.")
682
683
684(defvar ebrowse--member-mode-strings nil
685 "Strings displayed in the mode line of member buffers.")
686
687
688(defvar ebrowse-member-mode-map ()
689 "The keymap used in the member buffers.")
690
691
692;;; Define mode line titles for each member list.
693
694(put 'ebrowse-ts-member-variables 'ebrowse-title "Member Variables")
695(put 'ebrowse-ts-member-functions 'ebrowse-title "Member Functions")
696(put 'ebrowse-ts-static-variables 'ebrowse-title "Static Variables")
697(put 'ebrowse-ts-static-functions 'ebrowse-title "Static Functions")
698(put 'ebrowse-ts-friends 'ebrowse-title "Friends")
699(put 'ebrowse-ts-types 'ebrowse-title "Types")
700
701(put 'ebrowse-ts-member-variables 'ebrowse-global-title "Global Variables")
702(put 'ebrowse-ts-member-functions 'ebrowse-global-title "Global Functions")
703(put 'ebrowse-ts-static-variables 'ebrowse-global-title "Static Variables")
704(put 'ebrowse-ts-static-functions 'ebrowse-global-title "Static Functions")
705(put 'ebrowse-ts-friends 'ebrowse-global-title "Defines")
706(put 'ebrowse-ts-types 'ebrowse-global-title "Types")
707
708
709\f
710;;; Operations on `ebrowse-ts' structures
711
712(defun ebrowse-files-table (&optional marked-only)
713 "Return an obarray containing all files mentioned in the current tree.
714The tree is expected in the buffer-local variable `ebrowse--tree-obarray'.
715MARKED-ONLY non-nil means include marked classes only."
716 (let ((files (make-hash-table :test 'equal))
717 (i -1))
718 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
719 (when (or (not marked-only) (ebrowse-ts-mark tree))
720 (let ((class (ebrowse-ts-class tree)))
721 (when (zerop (% (incf i) 20))
722 (ebrowse-show-progress "Preparing file list" (zerop i)))
723 ;; Add files mentioned in class description
724 (let ((source-file (ebrowse-cs-source-file class))
725 (file (ebrowse-cs-file class)))
726 (when source-file
727 (puthash source-file source-file files))
728 (when file
729 (puthash file file files))
730 ;; For all member lists in this class
731 (loop for accessor in ebrowse-member-list-accessors do
732 (loop for m in (funcall accessor tree)
733 for file = (ebrowse-ms-file m)
734 for def-file = (ebrowse-ms-definition-file m) do
735 (when file
736 (puthash file file files))
737 (when def-file
738 (puthash def-file def-file files))))))))
739 files))
740
741
742(defun ebrowse-files-list (&optional marked-only)
743 "Return a list containing all files mentioned in a tree.
744MARKED-ONLY non-nil means include marked classes only."
745 (let (list)
746 (maphash #'(lambda (file dummy) (setq list (cons file list)))
747 (ebrowse-files-table marked-only))
748 list))
749
750
751(defun* ebrowse-marked-classes-p ()
752 "Value is non-nil if any class in the current class tree is marked."
753 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
754 (when (ebrowse-ts-mark tree)
755 (return-from ebrowse-marked-classes-p tree))))
756
757
758(defsubst ebrowse-globals-tree-p (tree)
759 "Return t if TREE is the one for global entities."
760 (string= (ebrowse-bs-name (ebrowse-ts-class tree))
761 ebrowse-globals-name))
762
763
764(defsubst ebrowse-qualified-class-name (class)
765 "Return the name of CLASS with scope prepended, if any."
766 (if (ebrowse-cs-scope class)
767 (concat (ebrowse-cs-scope class) "::" (ebrowse-cs-name class))
768 (ebrowse-cs-name class)))
769
770
771(defun ebrowse-tree-obarray-as-alist (&optional qualified-names-p)
772 "Return an alist describing all classes in a tree.
773Each elements in the list has the form (CLASS-NAME . TREE).
774CLASS-NAME is the name of the class. TREE is the
775class tree whose root is QUALIFIED-CLASS-NAME.
776QUALIFIED-NAMES-P non-nil means return qualified names as CLASS-NAME.
777The class tree is found in the buffer-local variable `ebrowse--tree-obarray'."
778 (let (alist)
779 (if qualified-names-p
780 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
781 (setq alist
782 (acons (ebrowse-qualified-class-name (ebrowse-ts-class tree))
783 tree alist)))
784 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
785 (setq alist
786 (acons (ebrowse-cs-name (ebrowse-ts-class tree))
787 tree alist))))
788 alist))
789
790
791(defun ebrowse-sort-tree-list (list)
792 "Sort a LIST of `ebrowse-ts' structures by qualified class names."
793 (sort list
794 #'(lambda (a b)
795 (string< (ebrowse-qualified-class-name (ebrowse-ts-class a))
796 (ebrowse-qualified-class-name (ebrowse-ts-class b))))))
797
798
799(defun ebrowse-class-in-tree (class tree)
800 "Search for a class with name CLASS in TREE.
8b3a75ac
EZ
801If CLASS is found, return the tail of TREE starting at CLASS. This function
802is used during the load phase where classes appended to a file replace older
803class information."
be0dbdab
GM
804 (let ((tclass (ebrowse-ts-class class))
805 found)
806 (while (and tree (not found))
8b3a75ac
EZ
807 (let ((root-ptr tree))
808 (when (string= (ebrowse-qualified-class-name (ebrowse-ts-class (car root-ptr)))
be0dbdab 809 (ebrowse-qualified-class-name tclass))
8b3a75ac 810 (setq found root-ptr))
be0dbdab
GM
811 (setq tree (cdr tree))))
812 found))
813
814
815(defun ebrowse-base-classes (tree)
816 "Return list of base-classes of TREE by searching subclass lists.
106ba1bb 817This function must be used instead of the struct slot
be0dbdab
GM
818`base-classes' to access the base-class list directly because it
819computes this information lazily."
820 (or (ebrowse-ts-base-classes tree)
821 (setf (ebrowse-ts-base-classes tree)
822 (loop with to-search = (list tree)
823 with result = nil
824 as search = (pop to-search)
825 while search finally return result
826 do (ebrowse-for-all-trees (ti ebrowse--tree-obarray)
827 (when (memq search (ebrowse-ts-subclasses ti))
828 (unless (memq ti result)
829 (setq result (nconc result (list ti))))
830 (push ti to-search)))))))
831
832
833(defun ebrowse-direct-base-classes (tree)
834 "Return the list of direct super classes of TREE."
835 (let (result)
836 (dolist (s (ebrowse-base-classes tree))
837 (when (memq tree (ebrowse-ts-subclasses s))
838 (setq result (cons s result))))
839 result))
840
841
842\f
843;;; Operations on MEMBER structures/lists
844
845(defun ebrowse-name/accessor-alist (tree accessor)
846 "Return an alist containing all members of TREE in group ACCESSOR.
847ACCESSOR is the accessor function for the member list.
848Elements of the result have the form (NAME . ACCESSOR), where NAME
849is the member name."
850 (loop for member in (funcall accessor tree)
851 collect (cons (ebrowse-ms-name member) accessor)))
852
853
854(defun ebrowse-name/accessor-alist-for-visible-members ()
855 "Return an alist describing all members visible in the current buffer.
856Each element of the list has the form (MEMBER-NAME . ACCESSOR),
857where MEMBER-NAME is the member's name, and ACCESSOR is the struct
858accessor with which the member's list can be accessed in an `ebrowse-ts'
859structure. The list includes inherited members if these are visible."
860 (let* ((list (ebrowse-name/accessor-alist ebrowse--displayed-class
861 ebrowse--accessor)))
862 (if ebrowse--show-inherited-flag
863 (nconc list
864 (loop for tree in (ebrowse-base-classes
865 ebrowse--displayed-class)
866 nconc (ebrowse-name/accessor-alist
867 tree ebrowse--accessor)))
868 list)))
869
870
871(defun ebrowse-name/accessor-alist-for-class-members ()
872 "Like `ebrowse-name/accessor-alist-for-visible-members'.
873This function includes members of base classes if base class members
874are visible in the buffer."
875 (let (list)
876 (dolist (func ebrowse-member-list-accessors list)
877 (setq list (nconc list (ebrowse-name/accessor-alist
878 ebrowse--displayed-class func)))
879 (when ebrowse--show-inherited-flag
880 (dolist (class (ebrowse-base-classes ebrowse--displayed-class))
881 (setq list
882 (nconc list (ebrowse-name/accessor-alist class func))))))))
883
884\f
885;;; Progress indication
886
887(defvar ebrowse-n-boxes 0)
888(defconst ebrowse-max-boxes 60)
889
890(defun ebrowse-show-progress (title &optional start)
891 "Display a progress indicator.
892TITLE is the title of the progress message. START non-nil means
893this is the first progress message displayed."
894 (let (message-log-max)
895 (when start (setq ebrowse-n-boxes 0))
896 (setq ebrowse-n-boxes (mod (1+ ebrowse-n-boxes) ebrowse-max-boxes))
897 (message (concat title ": "
898 (propertize (make-string ebrowse-n-boxes
899 (if (display-color-p) ?\ ?+))
4f2d55da 900 'face 'ebrowse-progress)))))
be0dbdab
GM
901
902\f
903;;; Reading a tree from disk
904
be0dbdab 905(defun ebrowse-read ()
106ba1bb 906 "Read `ebrowse-hs' and `ebrowse-ts' structures in the current buffer.
be0dbdab
GM
907Return a list (HEADER TREE) where HEADER is the file header read
908and TREE is a list of `ebrowse-ts' structures forming the class tree."
909 (let ((header (condition-case nil
910 (read (current-buffer))
911 (error (error "No Ebrowse file header found"))))
912 tree)
913 ;; Check file format.
914 (unless (ebrowse-hs-p header)
915 (error "No Ebrowse file header found"))
916 (unless (string= (ebrowse-hs-version header) ebrowse-version-string)
917 (error "File has wrong version `%s' (`%s' expected)"
918 (ebrowse-hs-version header) ebrowse-version-string))
919 ;; Read Lisp objects. Temporarily increase `gc-cons-threshold' to
920 ;; prevent a GC that would not free any memory.
921 (let ((gc-cons-threshold 2000000))
86b58346 922 (while (not (progn (skip-chars-forward " \t\n\r") (eobp)))
be0dbdab 923 (let* ((root (read (current-buffer)))
8b3a75ac 924 (old-root-ptr (ebrowse-class-in-tree root tree)))
be0dbdab 925 (ebrowse-show-progress "Reading data" (null tree))
8b3a75ac
EZ
926 (if old-root-ptr
927 (setcar old-root-ptr root)
be0dbdab
GM
928 (push root tree)))))
929 (garbage-collect)
930 (list header tree)))
931
932
be0dbdab
GM
933(defun ebrowse-revert-tree-buffer-from-file (ignore-auto-save noconfirm)
934 "Function installed as `revert-buffer-function' in tree buffers.
935See that variable's documentation for the meaning of IGNORE-AUTO-SAVE and
936NOCONFIRM."
86b58346
GM
937 (when (or noconfirm (yes-or-no-p "Revert tree from disk? "))
938 (loop for member-buffer in (ebrowse-same-tree-member-buffer-list)
939 do (kill-buffer member-buffer))
940 (erase-buffer)
941 (insert-file (or buffer-file-name ebrowse--tags-file-name))
942 (ebrowse-tree-mode)
943 (current-buffer)))
be0dbdab 944
106ba1bb 945
86b58346 946(defun ebrowse-create-tree-buffer (tree tags-file header obarray pop)
be0dbdab
GM
947 "Create a new tree buffer for tree TREE.
948The tree was loaded from file TAGS-FILE.
949HEADER is the header structure of the file.
950OBARRAY is an obarray with a symbol for each class in the tree.
951POP non-nil means popup the buffer up at the end.
be0dbdab 952Return the buffer created."
86b58346
GM
953 (let ((name ebrowse-tree-buffer-name))
954 (set-buffer (get-buffer-create name))
be0dbdab 955 (ebrowse-tree-mode)
86b58346 956 (setq ebrowse--tree tree
be0dbdab 957 ebrowse--tags-file-name tags-file
86b58346
GM
958 ebrowse--tree-obarray obarray
959 ebrowse--header header
960 ebrowse--frozen-flag nil)
be0dbdab
GM
961 (ebrowse-redraw-tree)
962 (set-buffer-modified-p nil)
86b58346
GM
963 (case pop
964 (switch (switch-to-buffer name))
965 (pop (pop-to-buffer name)))
be0dbdab
GM
966 (current-buffer)))
967
968
969\f
970;;; Operations for member obarrays
971
972(defun ebrowse-fill-member-table ()
973 "Return an obarray holding all members of all classes in the current tree.
974
975For each member, a symbol is added to the obarray. Members are
976extracted from the buffer-local tree `ebrowse--tree-obarray'.
977
978Each symbol has its property `ebrowse-info' set to a list (TREE MEMBER-LIST
979MEMBER) where TREE is the tree in which the member is defined,
980MEMBER-LIST is a symbol describing the member list in which the member
981is found, and MEMBER is a MEMBER structure describing the member.
982
983The slot `member-table' of the buffer-local header structure of
984type `ebrowse-hs' is set to the resulting obarray."
985 (let ((members (make-hash-table :test 'equal))
986 (i -1))
987 (setf (ebrowse-hs-member-table ebrowse--header) nil)
988 (garbage-collect)
989 ;; For all classes...
990 (ebrowse-for-all-trees (c ebrowse--tree-obarray)
991 (when (zerop (% (incf i) 10))
992 (ebrowse-show-progress "Preparing member lookup" (zerop i)))
993 (loop for f in ebrowse-member-list-accessors do
994 (loop for m in (funcall f c) do
995 (let* ((member-name (ebrowse-ms-name m))
996 (value (gethash member-name members)))
997 (push (list c f m) value)
998 (puthash member-name value members)))))
999 (setf (ebrowse-hs-member-table ebrowse--header) members)))
1000
1001
1002(defun ebrowse-member-table (header)
1003 "Return the member obarray. Build it it hasn't been set up yet.
1004HEADER is the tree header structure of the class tree."
1005 (when (null (ebrowse-hs-member-table header))
1006 (loop for buffer in (ebrowse-browser-buffer-list)
1007 until (eq header (ebrowse-value-in-buffer 'ebrowse--header buffer))
1008 finally do
1009 (save-excursion
1010 (set-buffer buffer)
1011 (ebrowse-fill-member-table))))
1012 (ebrowse-hs-member-table header))
1013
1014
1015\f
1016;;; Operations on TREE obarrays
1017
1018(defun ebrowse-build-tree-obarray (tree)
1019 "Make sure every class in TREE is represented by a unique object.
1020Build obarray of all classes in TREE."
1021 (let ((classes (make-vector 127 0)))
1022 ;; Add root classes...
1023 (loop for root in tree
1024 as sym =
1025 (intern (ebrowse-qualified-class-name (ebrowse-ts-class root)) classes)
1026 do (unless (get sym 'ebrowse-root)
1027 (setf (get sym 'ebrowse-root) root)))
1028 ;; Process subclasses
1029 (ebrowse-insert-supers tree classes)
1030 classes))
1031
1032
1033(defun ebrowse-insert-supers (tree classes)
1034 "Build base class lists in class tree TREE.
1035CLASSES is an obarray used to collect classes.
1036
1037Helper function for `ebrowse-build-tree-obarray'. Base classes should
1038be ordered so that immediate base classes come first, then the base
1039class of the immediate base class and so on. This means that we must
1040construct the base-class list top down with adding each level at the
1041beginning of the base-class list.
1042
1043We have to be cautious here not to end up in an infinite recursion
1044if for some reason a circle is in the inheritance graph."
1045 (loop for class in tree
1046 as subclasses = (ebrowse-ts-subclasses class) do
1047 ;; Make sure every class is represented by a unique object
1048 (loop for subclass on subclasses
1049 as sym = (intern
1050 (ebrowse-qualified-class-name (ebrowse-ts-class (car subclass)))
1051 classes)
1052 as next = nil
1053 do
1054 ;; Replace the subclass tree with the one found in
1055 ;; CLASSES if there is already an entry for that class
1056 ;; in it. Otherwise make a new entry.
1057 ;;
1058 ;; CAVEAT: If by some means (e.g., use of the
1059 ;; preprocessor in class declarations, a name is marked
1060 ;; as a subclass of itself on some path, we would end up
1061 ;; in an endless loop. We have to omit subclasses from
1062 ;; the recursion that already have been processed.
1063 (if (get sym 'ebrowse-root)
1064 (setf (car subclass) (get sym 'ebrowse-root))
1065 (setf (get sym 'ebrowse-root) (car subclass))))
1066 ;; Process subclasses
1067 (ebrowse-insert-supers subclasses classes)))
1068
1069\f
1070;;; Tree buffers
1071
1072(unless ebrowse-tree-mode-map
1073 (let ((map (make-keymap)))
1074 (setf ebrowse-tree-mode-map map)
1075 (suppress-keymap map)
1076
f4a2b0a4 1077 (when (display-mouse-p)
be0dbdab
GM
1078 (define-key map [down-mouse-3] 'ebrowse-mouse-3-in-tree-buffer)
1079 (define-key map [mouse-2] 'ebrowse-mouse-2-in-tree-buffer)
1080 (define-key map [down-mouse-1] 'ebrowse-mouse-1-in-tree-buffer))
106ba1bb 1081
be0dbdab
GM
1082 (let ((map1 (make-sparse-keymap)))
1083 (suppress-keymap map1 t)
1084 (define-key map "L" map1)
1085 (define-key map1 "d" 'ebrowse-tree-command:show-friends)
1086 (define-key map1 "f" 'ebrowse-tree-command:show-member-functions)
1087 (define-key map1 "F" 'ebrowse-tree-command:show-static-member-functions)
1088 (define-key map1 "t" 'ebrowse-tree-command:show-types)
1089 (define-key map1 "v" 'ebrowse-tree-command:show-member-variables)
1090 (define-key map1 "V" 'ebrowse-tree-command:show-static-member-variables))
1091
1092 (let ((map1 (make-sparse-keymap)))
1093 (suppress-keymap map1 t)
1094 (define-key map "M" map1)
1095 (define-key map1 "a" 'ebrowse-mark-all-classes)
1096 (define-key map1 "t" 'ebrowse-toggle-mark-at-point))
1097
1098 (let ((map1 (make-sparse-keymap)))
1099 (suppress-keymap map1 t)
1100 (define-key map "T" map1)
1101 (define-key map1 "f" 'ebrowse-toggle-file-name-display)
1102 (define-key map1 "s" 'ebrowse-show-file-name-at-point)
1103 (define-key map1 "w" 'ebrowse-set-tree-indentation)
1104 (define-key map "x" 'ebrowse-statistics))
1105
1106 (define-key map "n" 'ebrowse-repeat-member-search)
1107 (define-key map "q" 'bury-buffer)
1108 (define-key map "*" 'ebrowse-expand-all)
1109 (define-key map "+" 'ebrowse-expand-branch)
1110 (define-key map "-" 'ebrowse-collapse-branch)
1111 (define-key map "/" 'ebrowse-read-class-name-and-go)
1112 (define-key map " " 'ebrowse-view-class-declaration)
1113 (define-key map "?" 'describe-mode)
1114 (define-key map "\C-i" 'ebrowse-pop/switch-to-member-buffer-for-same-tree)
1115 (define-key map "\C-k" 'ebrowse-remove-class-at-point)
1116 (define-key map "\C-l" 'ebrowse-redraw-tree)
1117 (define-key map "\C-m" 'ebrowse-find-class-declaration)))
1118
1119
1120\f
1121;;; Tree-mode - mode for tree buffers
1122
1123;;;###autoload
1124(defun ebrowse-tree-mode ()
1125 "Major mode for Ebrowse class tree buffers.
1126Each line corresponds to a class in a class tree.
1127Letters do not insert themselves, they are commands.
1128File operations in the tree buffer work on class tree data structures.
1129E.g.\\[save-buffer] writes the tree to the file it was loaded from.
1130
1131Tree mode key bindings:
1132\\{ebrowse-tree-mode-map}"
86b58346 1133 (interactive)
8b2affc5 1134 (let* ((ident (propertized-buffer-identification "C++ Tree"))
86b58346 1135 header tree buffer-read-only)
106ba1bb 1136
86b58346
GM
1137 (kill-all-local-variables)
1138 (use-local-map ebrowse-tree-mode-map)
106ba1bb 1139
86b58346
GM
1140 (unless (zerop (buffer-size))
1141 (goto-char (point-min))
1142 (multiple-value-setq (header tree) (ebrowse-read))
1143 (message "Sorting. Please be patient...")
1144 (setq tree (ebrowse-sort-tree-list tree))
1145 (erase-buffer)
1146 (message nil))
106ba1bb 1147
86b58346
GM
1148 (mapcar 'make-local-variable
1149 '(ebrowse--tags-file-name
1150 ebrowse--indentation
1151 ebrowse--tree
1152 ebrowse--header
1153 ebrowse--show-file-names-flag
1154 ebrowse--frozen-flag
1155 ebrowse--tree-obarray
86b58346 1156 revert-buffer-function))
106ba1bb 1157
be0dbdab
GM
1158 (setf ebrowse--show-file-names-flag nil
1159 ebrowse--tree-obarray (make-vector 127 0)
1160 ebrowse--frozen-flag nil
1161 major-mode 'ebrowse-tree-mode
1162 mode-name "Ebrowse-Tree"
8b2affc5 1163 mode-line-buffer-identification ident
be0dbdab
GM
1164 buffer-read-only t
1165 selective-display t
1166 selective-display-ellipses t
86b58346
GM
1167 revert-buffer-function 'ebrowse-revert-tree-buffer-from-file
1168 ebrowse--header header
1169 ebrowse--tree tree
1170 ebrowse--tags-file-name (buffer-file-name)
1171 ebrowse--tree-obarray (and tree (ebrowse-build-tree-obarray tree))
1172 ebrowse--frozen-flag nil)
1173
1174 (add-hook 'local-write-file-hooks 'ebrowse-write-file-hook-fn)
1175 (modify-syntax-entry ?_ (char-to-string (char-syntax ?a)))
1176 (when tree
1177 (ebrowse-redraw-tree)
1178 (set-buffer-modified-p nil))
9a969196 1179 (run-mode-hooks 'ebrowse-tree-mode-hook)))
106ba1bb 1180
be0dbdab
GM
1181
1182
1183(defun ebrowse-update-tree-buffer-mode-line ()
1184 "Update the tree buffer mode line."
be0dbdab
GM
1185 (ebrowse-rename-buffer (if ebrowse--frozen-flag
1186 (ebrowse-frozen-tree-buffer-name
1187 ebrowse--tags-file-name)
1188 ebrowse-tree-buffer-name))
1189 (force-mode-line-update))
1190
1191
1192\f
1193;;; Removing classes from trees
1194
1195(defun ebrowse-remove-class-and-kill-member-buffers (tree class)
1196 "Remove from TREE class CLASS.
1197Kill all member buffers still containing a reference to the class."
1198 (let ((sym (intern-soft (ebrowse-cs-name (ebrowse-ts-class class))
1199 ebrowse--tree-obarray)))
1200 (setf tree (delq class tree)
1201 (get sym 'ebrowse-root) nil)
1202 (dolist (root tree)
1203 (setf (ebrowse-ts-subclasses root)
1204 (delq class (ebrowse-ts-subclasses root))
1205 (ebrowse-ts-base-classes root) nil)
1206 (ebrowse-remove-class-and-kill-member-buffers
1207 (ebrowse-ts-subclasses root) class))
1208 (ebrowse-kill-member-buffers-displaying class)
1209 tree))
1210
1211
1212(defun ebrowse-remove-class-at-point (forced)
1213 "Remove the class point is on from the class tree.
1214Do not ask for confirmation if FORCED is non-nil."
1215 (interactive "P")
1216 (let* ((class (ebrowse-tree-at-point))
1217 (class-name (ebrowse-cs-name (ebrowse-ts-class class)))
1218 (subclasses (ebrowse-ts-subclasses class)))
1219 (cond ((or forced
1220 (y-or-n-p (concat "Delete class " class-name "? ")))
1221 (setf ebrowse--tree (ebrowse-remove-class-and-kill-member-buffers
1222 ebrowse--tree class))
1223 (set-buffer-modified-p t)
1224 (message "%s %sdeleted." class-name
1225 (if subclasses "and derived classes " ""))
1226 (ebrowse-redraw-tree))
1227 (t (message "Aborted")))))
1228
1229
1230\f
1231;;; Marking classes in the tree buffer
1232
1233(defun ebrowse-toggle-mark-at-point (&optional n-times)
1234 "Toggle mark for class cursor is on.
1235If given a numeric N-TIMES argument, mark that many classes."
1236 (interactive "p")
1237 (let (to-change pnt)
1238 ;; Get the classes whose mark must be toggled. Note that
1239 ;; ebrowse-tree-at-point might issue an error.
1240 (condition-case error
1241 (loop repeat (or n-times 1)
1242 as tree = (ebrowse-tree-at-point)
106ba1bb 1243 do (progn
be0dbdab
GM
1244 (setf (ebrowse-ts-mark tree) (not (ebrowse-ts-mark tree)))
1245 (forward-line 1)
1246 (push tree to-change)))
1247 (error nil))
1248 (save-excursion
1249 ;; For all these classes, reverse the mark char in the display
1250 ;; by a regexp replace over the whole buffer. The reason for this
1251 ;; is that classes might have multiple base classes. If this is
1252 ;; the case, they are displayed more than once in the tree.
1253 (ebrowse-output
1254 (loop for tree in to-change
1255 as regexp = (concat "^.*\\b"
1256 (regexp-quote
1257 (ebrowse-cs-name (ebrowse-ts-class tree)))
1258 "\\b")
1259 do
1260 (goto-char (point-min))
1261 (loop while (re-search-forward regexp nil t)
1262 do (progn
1263 (goto-char (match-beginning 0))
1264 (delete-char 1)
1265 (insert-char (if (ebrowse-ts-mark tree) ?> ? ) 1)
1266 (ebrowse-set-mark-props (1- (point)) (point) tree)
1267 (goto-char (match-end 0)))))))))
1268
1269
1270(defun ebrowse-mark-all-classes (prefix)
1271 "Unmark, with PREFIX mark, all classes in the tree."
1272 (interactive "P")
1273 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
1274 (setf (ebrowse-ts-mark tree) prefix))
1275 (ebrowse-redraw-marks (point-min) (point-max)))
1276
1277
1278(defun ebrowse-redraw-marks (start end)
1279 "Display class marker signs in the tree between START and END."
1280 (interactive)
1281 (save-excursion
1282 (ebrowse-output
1283 (catch 'end
1284 (goto-char (point-min))
1285 (dolist (root ebrowse--tree)
1286 (ebrowse-draw-marks-fn root start end))))
1287 (ebrowse-update-tree-buffer-mode-line)))
1288
1289
1290(defun ebrowse-draw-marks-fn (tree start end)
1291 "Display class marker signs in TREE between START and END."
1292 (when (>= (point) start)
1293 (delete-char 1)
1294 (insert (if (ebrowse-ts-mark tree) ?> ? ))
1295 (ebrowse-set-mark-props (1- (point)) (point) tree))
1296 (forward-line 1)
1297 (when (> (point) end)
1298 (throw 'end nil))
1299 (dolist (sub (ebrowse-ts-subclasses tree))
1300 (ebrowse-draw-marks-fn sub start end)))
1301
1302
1303\f
1304;;; File name display in tree buffers
1305
1306(defun ebrowse-show-file-name-at-point (prefix)
1307 "Show filename in the line point is in.
1308With PREFIX, insert that many filenames."
1309 (interactive "p")
1310 (unless ebrowse--show-file-names-flag
1311 (ebrowse-output
1312 (dotimes (i prefix)
1313 (let ((tree (ebrowse-tree-at-point))
1314 start
1315 file-name-existing)
be0dbdab
GM
1316 (beginning-of-line)
1317 (skip-chars-forward " \t*a-zA-Z0-9_")
1318 (setq start (point)
1319 file-name-existing (looking-at "("))
1320 (delete-region start (save-excursion (end-of-line) (point)))
1321 (unless file-name-existing
1322 (indent-to ebrowse-source-file-column)
1323 (insert "(" (or (ebrowse-cs-file
1324 (ebrowse-ts-class tree))
1325 "unknown")
1326 ")"))
4f2d55da 1327 (ebrowse-set-face start (point) 'ebrowse-file-name)
be0dbdab
GM
1328 (beginning-of-line)
1329 (forward-line 1))))))
1330
1331
1332(defun ebrowse-toggle-file-name-display ()
1333 "Toggle display of filenames in tree buffer."
1334 (interactive)
1335 (setf ebrowse--show-file-names-flag (not ebrowse--show-file-names-flag))
1336 (let ((old-line (count-lines (point-min) (point))))
1337 (ebrowse-redraw-tree)
1338 (goto-line old-line)))
1339
1340
1341\f
1342;;; General member and tree buffer functions
1343
1344(defun ebrowse-member-buffer-p (buffer)
1345 "Value is non-nil if BUFFER is a member buffer."
1346 (eq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
1347 'ebrowse-member-mode))
1348
1349
1350(defun ebrowse-tree-buffer-p (buffer)
1351 "Value is non-nil if BUFFER is a class tree buffer."
1352 (eq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
1353 'ebrowse-tree-mode))
1354
1355
1356(defun ebrowse-buffer-p (buffer)
1357 "Value is non-nil if BUFFER is a tree or member buffer."
1358 (memq (cdr (assoc 'major-mode (buffer-local-variables buffer)))
1359 '(ebrowse-tree-mode ebrowse-member-mode)))
1360
1361
1362(defun ebrowse-browser-buffer-list ()
1363 "Return a list of all tree or member buffers."
1364 (ebrowse-delete-if-not 'ebrowse-buffer-p (buffer-list)))
1365
1366
1367(defun ebrowse-member-buffer-list ()
1368 "Return a list of all member buffers."
1369 (ebrowse-delete-if-not 'ebrowse-member-buffer-p (buffer-list)))
1370
1371
1372(defun ebrowse-tree-buffer-list ()
1373 "Return a list of all tree buffers."
1374 (ebrowse-delete-if-not 'ebrowse-tree-buffer-p (buffer-list)))
1375
1376
1377(defun ebrowse-known-class-trees-buffer-list ()
1378 "Return a list of buffers containing class trees.
1379The list will contain, for each class tree loaded,
1380one buffer. Prefer tree buffers over member buffers."
1381 (let ((buffers (nconc (ebrowse-tree-buffer-list)
1382 (ebrowse-member-buffer-list)))
1383 (set (make-hash-table))
1384 result)
1385 (dolist (buffer buffers)
1386 (let ((tree (ebrowse-value-in-buffer 'ebrowse--tree buffer)))
1387 (unless (gethash tree set)
1388 (push buffer result))
1389 (puthash tree t set)))
1390 result))
1391
1392
1393(defun ebrowse-same-tree-member-buffer-list ()
1394 "Return a list of members buffers with same tree as current buffer."
1395 (ebrowse-delete-if-not
1396 #'(lambda (buffer)
1397 (eq (ebrowse-value-in-buffer 'ebrowse--tree buffer)
1398 ebrowse--tree))
1399 (ebrowse-member-buffer-list)))
1400
1401
1402\f
1403(defun ebrowse-pop/switch-to-member-buffer-for-same-tree (arg)
1404 "Pop to the buffer displaying members.
1405Switch to buffer if prefix ARG.
1406If no member buffer exists, make one."
1407 (interactive "P")
1408 (let ((buf (or (first (ebrowse-same-tree-member-buffer-list))
1409 (get-buffer ebrowse-member-buffer-name)
1410 (ebrowse-tree-command:show-member-functions))))
1411 (when buf
1412 (if arg
1413 (switch-to-buffer buf)
1414 (pop-to-buffer buf)))
1415 buf))
1416
1417
1418(defun ebrowse-switch-to-next-member-buffer ()
1419 "Switch to next member buffer."
1420 (interactive)
1421 (let* ((list (ebrowse-member-buffer-list))
1422 (next-list (cdr (memq (current-buffer) list)))
1423 (next-buffer (if next-list (car next-list) (car list))))
1424 (if (eq next-buffer (current-buffer))
1425 (error "No next buffer")
1426 (bury-buffer)
1427 (switch-to-buffer next-buffer))))
1428
1429
1430(defun ebrowse-kill-member-buffers-displaying (tree)
1431 "Kill all member buffers displaying TREE."
1432 (loop for buffer in (ebrowse-member-buffer-list)
1433 as class = (ebrowse-value-in-buffer 'ebrowse--displayed-class buffer)
1434 when (eq class tree) do (kill-buffer buffer)))
1435
1436
1437(defun ebrowse-frozen-tree-buffer-name (tags-file-name)
1438 "Return the buffer name of a tree which is associated TAGS-FILE-NAME."
1439 (concat ebrowse-tree-buffer-name " (" tags-file-name ")"))
1440
1441
1442(defun ebrowse-pop-to-browser-buffer (arg)
1443 "Pop to a browser buffer from any other buffer.
1444Pop to member buffer if no prefix ARG, to tree buffer otherwise."
1445 (interactive "P")
106ba1bb 1446 (let ((buffer (get-buffer (if arg
be0dbdab
GM
1447 ebrowse-tree-buffer-name
1448 ebrowse-member-buffer-name))))
1449 (unless buffer
106ba1bb 1450 (setq buffer
be0dbdab
GM
1451 (get-buffer (if arg
1452 ebrowse-member-buffer-name
1453 ebrowse-tree-buffer-name))))
1454 (unless buffer
1455 (error "No browser buffer found"))
1456 (pop-to-buffer buffer)))
1457
1458
1459\f
1460;;; Misc tree buffer commands
1461
1462(defun ebrowse-set-tree-indentation ()
1463 "Set the indentation width of the tree display."
1464 (interactive)
027a4b6b
JB
1465 (let ((width (string-to-number (read-from-minibuffer
1466 (concat "Indentation ("
1467 (int-to-string ebrowse--indentation)
1468 "): ")))))
be0dbdab
GM
1469 (when (plusp width)
1470 (setf ebrowse--indentation width)
1471 (ebrowse-redraw-tree))))
1472
1473
1474(defun ebrowse-read-class-name-and-go (&optional class)
1475 "Position cursor on CLASS.
1476Read a class name from the minibuffer if CLASS is nil."
1477 (interactive)
1478 (ebrowse-ignoring-completion-case
1479 ;; If no class specified, read the class name from mini-buffer
1480 (unless class
1481 (setf class
1482 (completing-read "Goto class: "
1483 (ebrowse-tree-obarray-as-alist) nil t)))
1484 (ebrowse-save-selective
1485 (goto-char (point-min))
1486 (widen)
1487 (setf selective-display nil)
1488 (setq ebrowse--last-regexp (concat "\\b" class "\\b"))
1489 (if (re-search-forward ebrowse--last-regexp nil t)
1490 (progn
1491 (goto-char (match-beginning 0))
1492 (ebrowse-unhide-base-classes))
1493 (error "Not found")))))
1494
1495
1496\f
1497;;; Showing various kinds of member buffers
1498
1499(defun ebrowse-tree-command:show-member-variables (arg)
1500 "Display member variables; with prefix ARG in frozen member buffer."
1501 (interactive "P")
1502 (ebrowse-display-member-buffer 'ebrowse-ts-member-variables arg))
1503
1504
1505(defun ebrowse-tree-command:show-member-functions (&optional arg)
1506 "Display member functions; with prefix ARG in frozen member buffer."
1507 (interactive "P")
1508 (ebrowse-display-member-buffer 'ebrowse-ts-member-functions arg))
1509
1510
1511(defun ebrowse-tree-command:show-static-member-variables (arg)
1512 "Display static member variables; with prefix ARG in frozen member buffer."
1513 (interactive "P")
1514 (ebrowse-display-member-buffer 'ebrowse-ts-static-variables arg))
1515
1516
1517(defun ebrowse-tree-command:show-static-member-functions (arg)
1518 "Display static member functions; with prefix ARG in frozen member buffer."
1519 (interactive "P")
1520 (ebrowse-display-member-buffer 'ebrowse-ts-static-functions arg))
1521
1522
1523(defun ebrowse-tree-command:show-friends (arg)
1524 "Display friend functions; with prefix ARG in frozen member buffer."
1525 (interactive "P")
1526 (ebrowse-display-member-buffer 'ebrowse-ts-friends arg))
1527
1528
1529(defun ebrowse-tree-command:show-types (arg)
1530 "Display types defined in a class; with prefix ARG in frozen member buffer."
1531 (interactive "P")
1532 (ebrowse-display-member-buffer 'ebrowse-ts-types arg))
1533
1534
1535\f
1536;;; Viewing or finding a class declaration
1537
1538(defun ebrowse-tree-at-point ()
1539 "Return the class structure for the class point is on."
1540 (or (get-text-property (point) 'ebrowse-tree)
1541 (error "Not on a class")))
1542
1543
1544(defun* ebrowse-view/find-class-declaration (&key view where)
1545 "View or find the declarator of the class point is on.
1546VIEW non-nil means view it. WHERE is additional position info."
1547 (let* ((class (ebrowse-ts-class (ebrowse-tree-at-point)))
1548 (file (ebrowse-cs-file class))
1549 (browse-struct (make-ebrowse-bs
1550 :name (ebrowse-cs-name class)
1551 :pattern (ebrowse-cs-pattern class)
1552 :flags (ebrowse-cs-flags class)
1553 :file (ebrowse-cs-file class)
1554 :point (ebrowse-cs-point class))))
1555 (ebrowse-view/find-file-and-search-pattern
106ba1bb 1556 browse-struct
be0dbdab
GM
1557 (list ebrowse--header class nil)
1558 file
1559 ebrowse--tags-file-name
1560 view
1561 where)))
1562
1563
1564(defun ebrowse-find-class-declaration (prefix-arg)
1565 "Find a class declaration and position cursor on it.
1566PREFIX-ARG 4 means find it in another window.
1567PREFIX-ARG 5 means find it in another frame."
1568 (interactive "p")
1569 (ebrowse-view/find-class-declaration
1570 :view nil
1571 :where (cond ((= prefix-arg 4) 'other-window)
1572 ((= prefix-arg 5) 'other-frame)
1573 (t 'this-window))))
1574
1575
1576(defun ebrowse-view-class-declaration (prefix-arg)
1577 "View class declaration and position cursor on it.
1578PREFIX-ARG 4 means view it in another window.
1579PREFIX-ARG 5 means view it in another frame."
1580 (interactive "p")
1581 (ebrowse-view/find-class-declaration
1582 :view 'view
1583 :where (cond ((= prefix-arg 4) 'other-window)
1584 ((= prefix-arg 5) 'other-frame)
1585 (t 'this-window))))
1586
1587
1588\f
1589;;; The FIND engine
1590
1591(defun ebrowse-find-source-file (file tags-file-name)
1592 "Find source file FILE.
1593Source files are searched for (a) relative to TAGS-FILE-NAME
1594which is the path of the BROWSE file from which the class tree was loaded,
1595and (b) in the directories named in `ebrowse-search-path'."
1596 (let (file-name
1597 (try-file (expand-file-name file
1598 (file-name-directory tags-file-name))))
1599 (if (file-readable-p try-file)
1600 (setq file-name try-file)
1601 (let ((search-in ebrowse-search-path))
1602 (while (and search-in
1603 (null file-name))
1604 (let ((try-file (expand-file-name file (car search-in))))
1605 (if (file-readable-p try-file)
1606 (setq file-name try-file))
1607 (setq search-in (cdr search-in))))))
1608 (unless file-name
1609 (error "File `%s' not found" file))
1610 file-name))
1611
1612
1613(defun ebrowse-view-file-other-window (file)
1614 "View a file FILE in another window.
1615This is a replacement for `view-file-other-window' which does not
1616seem to work. It should be removed when `view.el' is fixed."
1617 (interactive)
1618 (let ((old-arrangement (current-window-configuration))
1619 (had-a-buf (get-file-buffer file))
1620 (buf-to-view (find-file-noselect file)))
1621 (switch-to-buffer-other-window buf-to-view)
1622 (view-mode-enter old-arrangement
1623 (and (not had-a-buf)
1624 (not (buffer-modified-p buf-to-view))
1625 'kill-buffer))))
1626
1627
1628(defun ebrowse-view-exit-fn (buffer)
1629 "Function called when exiting View mode in BUFFER.
1630Restore frame configuration active before viewing the file,
1631and possibly kill the viewed buffer."
1632 (let (exit-action original-frame-configuration)
1633 (save-excursion
1634 (set-buffer buffer)
1635 (setq original-frame-configuration ebrowse--frame-configuration
1636 exit-action ebrowse--view-exit-action))
1637 ;; Delete the frame in which we viewed.
1638 (mapcar 'delete-frame
1639 (loop for frame in (frame-list)
1640 when (not (assq frame original-frame-configuration))
1641 collect frame))
1642 (when exit-action
1643 (funcall exit-action buffer))))
1644
1645
1646(defun ebrowse-view-file-other-frame (file)
1647 "View a file FILE in another frame.
1648The new frame is deleted when it is no longer used."
1649 (interactive)
1650 (let ((old-frame-configuration (current-frame-configuration))
1651 (old-arrangement (current-window-configuration))
1652 (had-a-buf (get-file-buffer file))
1653 (buf-to-view (find-file-noselect file)))
1654 (switch-to-buffer-other-frame buf-to-view)
1655 (make-local-variable 'ebrowse--frame-configuration)
1656 (setq ebrowse--frame-configuration old-frame-configuration)
1657 (make-local-variable 'ebrowse--view-exit-action)
106ba1bb 1658 (setq ebrowse--view-exit-action
be0dbdab
GM
1659 (and (not had-a-buf)
1660 (not (buffer-modified-p buf-to-view))
1661 'kill-buffer))
1662 (view-mode-enter old-arrangement 'ebrowse-view-exit-fn)))
1663
1664
1665(defun ebrowse-view/find-file-and-search-pattern
1666 (struc info file tags-file-name &optional view where)
1667 "Find or view a member or class.
1668STRUC is an `ebrowse-bs' structure (or a structure including that)
1669describing what to search.
1670INFO is a list (HEADER MEMBER-OR-CLASS ACCESSOR). HEADER is the
1671header structure of a class tree. MEMBER-OR-CLASS is either an
1672`ebrowse-ms' or `ebrowse-cs' structure depending on what is searched.
106ba1bb 1673ACCESSOR is an accessor function for the member list of a member
be0dbdab
GM
1674if MEMBER-OR-CLASS is an `ebrowse-ms'.
1675FILE is the file to search the member in.
1676FILE is not taken out of STRUC here because the filename in STRUC
1677may be nil in which case the filename of the class description is used.
183c2d42 1678TAGS-FILE-NAME is the name of the BROWSE file from which the
be0dbdab
GM
1679tree was loaded.
1680If VIEW is non-nil, view file else find the file.
1681WHERE is either `other-window', `other-frame' or `this-window' and
1682specifies where to find/view the result."
1683 (unless file
1684 (error "Sorry, no file information available for %s"
1685 (ebrowse-bs-name struc)))
1686 ;; Get the source file to view or find.
1687 (setf file (ebrowse-find-source-file file tags-file-name))
1688 ;; If current window is dedicated, use another frame.
1689 (when (window-dedicated-p (selected-window))
5bc2ca83 1690 (setf where 'other-window))
be0dbdab
GM
1691 (cond (view
1692 (setf ebrowse-temp-position-to-view struc
1693 ebrowse-temp-info-to-view info)
1694 (unless (boundp 'view-mode-hook)
1695 (setq view-mode-hook nil))
1696 (push 'ebrowse-find-pattern view-mode-hook)
1697 (case where
1698 (other-window (ebrowse-view-file-other-window file))
1699 (other-frame (ebrowse-view-file-other-frame file))
1700 (t (view-file file))))
1701 (t
1702 (case where
1703 (other-window (find-file-other-window file))
1704 (other-frame (find-file-other-frame file))
1705 (t (find-file file)))
1706 (ebrowse-find-pattern struc info))))
1707
1708
1709(defun ebrowse-symbol-regexp (name)
1710 "Generate a suitable regular expression for a member or class NAME.
1711This is `regexp-quote' for most symbols, except for operator names
1712which may contain whitespace. For these symbols, replace white
183c2d42 1713space in the symbol name (generated by BROWSE) with a regular
be0dbdab
GM
1714expression matching any number of whitespace characters."
1715 (loop with regexp = (regexp-quote name)
1716 with start = 0
1717 finally return regexp
1718 while (string-match "[ \t]+" regexp start)
47932cf8
SM
1719 do (setq regexp (concat (substring regexp 0 (match-beginning 0))
1720 "[ \t]*"
1721 (substring regexp (match-end 0)))
be0dbdab
GM
1722 start (+ (match-beginning 0) 5))))
1723
1724
1725(defun ebrowse-class-declaration-regexp (name)
106ba1bb 1726 "Construct a regexp for a declaration of class NAME."
be0dbdab
GM
1727 (concat "^[ \t]*\\(template[ \t\n]*<.*>\\)?"
1728 "[ \t\n]*\\(class\\|struct\\|union\\).*\\S_"
1729 (ebrowse-symbol-regexp name)
1730 "\\S_"))
1731
1732
1733(defun ebrowse-variable-declaration-regexp (name)
1734 "Construct a regexp for matching a variable NAME."
1735 (concat "\\S_" (ebrowse-symbol-regexp name) "\\S_"))
1736
1737
1738(defun ebrowse-function-declaration/definition-regexp (name)
1739 "Construct a regexp for matching a function NAME."
1740 (concat "^[a-zA-Z0-9_:*&<>, \t]*\\S_"
1741 (ebrowse-symbol-regexp name)
1742 "[ \t\n]*("))
1743
1744
1745(defun ebrowse-pp-define-regexp (name)
1746 "Construct a regexp matching a define of NAME."
1747 (concat "^[ \t]*#[ \t]*define[ \t]+" (regexp-quote name)))
1748
1749
1750(defun* ebrowse-find-pattern (&optional position info &aux viewing)
1751 "Find a pattern.
1752
1753This is a kluge: Ebrowse allows you to find or view a file containing
1754a pattern. To be able to do a search in a viewed buffer,
1755`view-mode-hook' is temporarily set to this function;
1756`ebrowse-temp-position-to-view' holds what to search for.
1757
1758INFO is a list (TREE-HEADER TREE-OR-MEMBER MEMBER-LIST)."
1759 (unless position
1760 (pop view-mode-hook)
1761 (setf viewing t
1762 position ebrowse-temp-position-to-view
1763 info ebrowse-temp-info-to-view))
1764 (widen)
1765 (let* ((pattern (ebrowse-bs-pattern position))
1766 (start (ebrowse-bs-point position))
1767 (offset 100)
1768 found)
1769 (destructuring-bind (header class-or-member member-list) info
1770 ;; If no pattern is specified, construct one from the member name.
1771 (when (stringp pattern)
1772 (setq pattern (concat "^.*" (regexp-quote pattern))))
1773 ;; Construct a regular expression if none given.
1774 (unless pattern
1775 (typecase class-or-member
1776 (ebrowse-ms
1777 (case member-list
1778 ((ebrowse-ts-member-variables
1779 ebrowse-ts-static-variables
1780 ebrowse-ts-types)
1781 (setf pattern (ebrowse-variable-declaration-regexp
1782 (ebrowse-bs-name position))))
1783 (otherwise
1784 (if (ebrowse-define-p class-or-member)
1785 (setf pattern (ebrowse-pp-define-regexp (ebrowse-bs-name position)))
1786 (setf pattern (ebrowse-function-declaration/definition-regexp
1787 (ebrowse-bs-name position)))))))
1788 (ebrowse-cs
1789 (setf pattern (ebrowse-class-declaration-regexp
1790 (ebrowse-bs-name position))))))
1791 ;; Begin searching some OFFSET from the original point where the
1792 ;; regular expression was found by the parse, and step forward.
1793 ;; When there is no regular expression in the database and a
1794 ;; member definition/declaration was not seen by the parser,
1795 ;; START will be 0.
1796 (when (and (boundp 'ebrowse-debug)
1797 (symbol-value 'ebrowse-debug))
1798 (y-or-n-p (format "start = %d" start))
1799 (y-or-n-p pattern))
1800 (setf found
1801 (loop do (goto-char (max (point-min) (- start offset)))
1802 when (re-search-forward pattern (+ start offset) t) return t
1803 never (bobp)
1804 do (incf offset offset)))
1805 (cond (found
1806 (beginning-of-line)
1807 (run-hooks 'ebrowse-view/find-hook))
1808 ((numberp (ebrowse-bs-pattern position))
1809 (goto-char start)
1810 (if ebrowse-not-found-hook
1811 (run-hooks 'ebrowse-not-found-hook)
1812 (message "Not found")
1813 (sit-for 2)))
1814 (t
1815 (if ebrowse-not-found-hook
1816 (run-hooks 'ebrowse-not-found-hook)
1817 (unless viewing
1818 (error "Not found"))
1819 (message "Not found")
1820 (sit-for 2)))))))
1821
1822\f
1823;;; Drawing the tree
1824
1825(defun ebrowse-redraw-tree (&optional quietly)
1826 "Redisplay the complete tree.
1827QUIETLY non-nil means don't display progress messages."
1828 (interactive)
1829 (or quietly (message "Displaying..."))
1830 (save-excursion
1831 (ebrowse-output
1832 (erase-buffer)
1833 (ebrowse-draw-tree-fn)))
1834 (ebrowse-update-tree-buffer-mode-line)
1835 (or quietly (message nil)))
1836
1837
1838(defun ebrowse-set-mark-props (start end tree)
1839 "Set text properties for class marker signs between START and END.
1840TREE denotes the class shown."
1841 (add-text-properties
1842 start end
1843 `(mouse-face highlight ebrowse-what mark ebrowse-tree ,tree
1844 help-echo "double-mouse-1: mark/unmark"))
4f2d55da 1845 (ebrowse-set-face start end 'ebrowse-tree-mark))
be0dbdab
GM
1846
1847
1848(defun* ebrowse-draw-tree-fn (&aux stack1 stack2 start)
b2f6a2ab 1849 "Display a single class and recursively its subclasses.
be0dbdab
GM
1850This function may look weird, but this is faster than recursion."
1851 (setq stack1 (make-list (length ebrowse--tree) 0)
658397fb 1852 stack2 (copy-sequence ebrowse--tree))
be0dbdab
GM
1853 (loop while stack2
1854 as level = (pop stack1)
1855 as tree = (pop stack2)
1856 as class = (ebrowse-ts-class tree) do
1857 (let ((start-of-line (point))
1858 start-of-class-name end-of-class-name)
1859 ;; Insert mark
1860 (insert (if (ebrowse-ts-mark tree) ">" " "))
106ba1bb 1861
be0dbdab
GM
1862 ;; Indent and insert class name
1863 (indent-to (+ (* level ebrowse--indentation)
1864 ebrowse-tree-left-margin))
1865 (setq start (point))
1866 (insert (ebrowse-qualified-class-name class))
106ba1bb 1867
be0dbdab
GM
1868 ;; If template class, add <>
1869 (when (ebrowse-template-p class)
1870 (insert "<>"))
1871 (ebrowse-set-face start (point) (if (zerop level)
4f2d55da
MB
1872 'ebrowse-root-class
1873 'ebrowse-default))
be0dbdab
GM
1874 (setf start-of-class-name start
1875 end-of-class-name (point))
1876 ;; If filenames are to be displayed...
1877 (when ebrowse--show-file-names-flag
1878 (indent-to ebrowse-source-file-column)
1879 (setq start (point))
1880 (insert "("
1881 (or (ebrowse-cs-file class)
1882 "unknown")
1883 ")")
4f2d55da 1884 (ebrowse-set-face start (point) 'ebrowse-file-name))
be0dbdab
GM
1885 (ebrowse-set-mark-props start-of-line (1+ start-of-line) tree)
1886 (add-text-properties
1887 start-of-class-name end-of-class-name
1888 `(mouse-face highlight ebrowse-what class-name
1889 ebrowse-tree ,tree
1890 help-echo "double-mouse-1: (un)expand tree; mouse-2: member functions, mouse-3: menu"))
1891 (insert "\n"))
1892 ;; Push subclasses, if any.
1893 (when (ebrowse-ts-subclasses tree)
1894 (setq stack2
658397fb 1895 (nconc (copy-sequence (ebrowse-ts-subclasses tree)) stack2)
be0dbdab
GM
1896 stack1
1897 (nconc (make-list (length (ebrowse-ts-subclasses tree))
1898 (1+ level)) stack1)))))
1899
1900
1901\f
1902;;; Expanding/ collapsing tree branches
1903
1904(defun ebrowse-expand-branch (arg)
1905 "Expand a sub-tree that has been previously collapsed.
1906With prefix ARG, expand all sub-trees."
1907 (interactive "P")
1908 (if arg
1909 (ebrowse-expand-all arg)
1910 (ebrowse-collapse-fn nil)))
1911
1912
1913(defun ebrowse-collapse-branch (arg)
1914 "Fold (do no longer display) the subclasses of the current class.
1915\(The class cursor is on.) With prefix ARG, fold all trees in the buffer."
1916 (interactive "P")
1917 (if arg
1918 (ebrowse-expand-all (not arg))
1919 (ebrowse-collapse-fn t)))
1920
1921
1922(defun ebrowse-expand-all (collapse)
1923 "Expand or fold all trees in the buffer.
1924COLLAPSE non-nil means fold them."
1925 (interactive "P")
1926 (let ((line-end (if collapse "^\n" "^\r"))
1927 (insertion (if collapse "\r" "\n")))
1928 (ebrowse-output
1929 (save-excursion
1930 (goto-char (point-min))
1931 (while (not (progn (skip-chars-forward line-end) (eobp)))
1932 (when (or (not collapse)
1933 (looking-at "\n "))
1934 (delete-char 1)
1935 (insert insertion))
1936 (when collapse
1937 (skip-chars-forward "\n ")))))))
1938
1939
1940(defun ebrowse-unhide-base-classes ()
1941 "Unhide the line the cursor is on and all base classes."
1942 (ebrowse-output
1943 (save-excursion
1944 (let (indent last-indent)
1945 (skip-chars-backward "^\r\n")
1946 (when (not (looking-at "[\r\n][^ \t]"))
1947 (skip-chars-forward "\r\n \t")
1948 (while (and (or (null last-indent) ;first time
1949 (> indent 1)) ;not root class
1950 (re-search-backward "[\r\n][ \t]*" nil t))
1951 (setf indent (- (match-end 0)
1952 (match-beginning 0)))
1953 (when (or (null last-indent)
1954 (< indent last-indent))
1955 (setf last-indent indent)
1956 (when (looking-at "\r")
1957 (delete-char 1)
1958 (insert 10)))
1959 (backward-char 1)))))))
1960
1961
1962(defun ebrowse-hide-line (collapse)
1963 "Hide/show a single line in the tree.
1964COLLAPSE non-nil means hide."
1965 (save-excursion
1966 (ebrowse-output
1967 (skip-chars-forward "^\r\n")
1968 (delete-char 1)
1969 (insert (if collapse 13 10)))))
1970
1971
1972(defun ebrowse-collapse-fn (collapse)
1973 "Collapse or expand a branch of the tree.
1974COLLAPSE non-nil means collapse the branch."
1975 (ebrowse-output
1976 (save-excursion
1977 (beginning-of-line)
1978 (skip-chars-forward "> \t")
1979 (let ((indentation (current-column)))
1980 (while (and (not (eobp))
1981 (save-excursion
1982 (skip-chars-forward "^\r\n")
1983 (goto-char (1+ (point)))
1984 (skip-chars-forward "> \t")
1985 (> (current-column) indentation)))
1986 (ebrowse-hide-line collapse)
1987 (skip-chars-forward "^\r\n")
1988 (goto-char (1+ (point))))))))
1989
1990\f
1991;;; Electric tree selection
1992
1993(defvar ebrowse-electric-list-mode-map ()
1994 "Keymap used in electric Ebrowse buffer list window.")
1995
1996
1997(unless ebrowse-electric-list-mode-map
1998 (let ((map (make-keymap))
1999 (submap (make-keymap)))
2000 (setq ebrowse-electric-list-mode-map map)
2001 (fillarray (car (cdr map)) 'ebrowse-electric-list-undefined)
2002 (fillarray (car (cdr submap)) 'ebrowse-electric-list-undefined)
2003 (define-key map "\e" submap)
2004 (define-key map "\C-z" 'suspend-emacs)
2005 (define-key map "\C-h" 'Helper-help)
2006 (define-key map "?" 'Helper-describe-bindings)
2007 (define-key map "\C-c" nil)
2008 (define-key map "\C-c\C-c" 'ebrowse-electric-list-quit)
2009 (define-key map "q" 'ebrowse-electric-list-quit)
2010 (define-key map " " 'ebrowse-electric-list-select)
2011 (define-key map "\C-l" 'recenter)
2012 (define-key map "\C-u" 'universal-argument)
2013 (define-key map "\C-p" 'previous-line)
2014 (define-key map "\C-n" 'next-line)
2015 (define-key map "p" 'previous-line)
2016 (define-key map "n" 'next-line)
2017 (define-key map "v" 'ebrowse-electric-view-buffer)
2018 (define-key map "\C-v" 'scroll-up)
2019 (define-key map "\ev" 'scroll-down)
2020 (define-key map "\e\C-v" 'scroll-other-window)
2021 (define-key map "\e>" 'end-of-buffer)
2022 (define-key map "\e<" 'beginning-of-buffer)
2023 (define-key map "\e>" 'end-of-buffer)))
2024
2025(put 'ebrowse-electric-list-mode 'mode-class 'special)
2026(put 'ebrowse-electric-list-undefined 'suppress-keymap t)
2027
2028
2029(defun ebrowse-electric-list-mode ()
2030 "Mode for electric tree list mode."
2031 (kill-all-local-variables)
2032 (use-local-map ebrowse-electric-list-mode-map)
2033 (setq mode-name "Electric Position Menu"
2034 mode-line-buffer-identification "Electric Tree Menu")
2035 (when (memq 'mode-name mode-line-format)
2036 (setq mode-line-format (copy-sequence mode-line-format))
2037 (setcar (memq 'mode-name mode-line-format) "Tree Buffers"))
2038 (make-local-variable 'Helper-return-blurb)
2039 (setq Helper-return-blurb "return to buffer editing"
2040 truncate-lines t
2041 buffer-read-only t
2042 major-mode 'ebrowse-electric-list-mode)
9a969196 2043 (run-mode-hooks 'ebrowse-electric-list-mode-hook))
be0dbdab
GM
2044
2045
2046(defun ebrowse-list-tree-buffers ()
2047 "Display a list of all tree buffers."
2048 (set-buffer (get-buffer-create "*Tree Buffers*"))
2049 (setq buffer-read-only nil)
2050 (erase-buffer)
2051 (insert "Tree\n" "----\n")
2052 (dolist (buffer (ebrowse-known-class-trees-buffer-list))
2053 (insert (buffer-name buffer) "\n"))
2054 (setq buffer-read-only t))
2055
2056
2057;;;###autoload
2058(defun ebrowse-electric-choose-tree ()
2059 "Return a buffer containing a tree or nil if no tree found or canceled."
2060 (interactive)
2061 (unless (car (ebrowse-known-class-trees-buffer-list))
2062 (error "No tree buffers"))
2063 (let (select buffer window)
2064 (save-window-excursion
2065 (save-window-excursion (ebrowse-list-tree-buffers))
2066 (setq window (Electric-pop-up-window "*Tree Buffers*")
2067 buffer (window-buffer window))
2068 (shrink-window-if-larger-than-buffer window)
2069 (unwind-protect
2070 (progn
2071 (set-buffer buffer)
2072 (ebrowse-electric-list-mode)
2073 (setq select
2074 (catch 'ebrowse-electric-list-select
2075 (message "<<< Press Space to bury the list >>>")
2076 (let ((first (progn (goto-char (point-min))
2077 (forward-line 2)
2078 (point)))
2079 (last (progn (goto-char (point-max))
2080 (forward-line -1)
2081 (point)))
2082 (goal-column 0))
2083 (goto-char first)
2084 (Electric-command-loop 'ebrowse-electric-list-select
2085 nil
2086 t
2087 'ebrowse-electric-list-looper
2088 (cons first last))))))
2089 (set-buffer buffer)
2090 (bury-buffer buffer)
2091 (message nil)))
2092 (when select
2093 (set-buffer buffer)
2094 (setq select (ebrowse-electric-get-buffer select)))
2095 (kill-buffer buffer)
2096 select))
2097
2098
2099(defun ebrowse-electric-list-looper (state condition)
2100 "Prevent cursor from moving beyond the buffer end.
2101Don't let it move into the title lines.
2102See 'Electric-command-loop' for a description of STATE and CONDITION."
2103 (cond ((and condition
2104 (not (memq (car condition)
2105 '(buffer-read-only end-of-buffer
2106 beginning-of-buffer))))
2107 (signal (car condition) (cdr condition)))
2108 ((< (point) (car state))
2109 (goto-char (point-min))
2110 (forward-line 2))
2111 ((> (point) (cdr state))
2112 (goto-char (point-max))
2113 (forward-line -1)
2114 (if (pos-visible-in-window-p (point-max))
2115 (recenter -1)))))
2116
2117
2118(defun ebrowse-electric-list-undefined ()
2119 "Function called for keys that are undefined."
2120 (interactive)
2121 (message "Type C-h for help, ? for commands, q to quit, Space to select.")
2122 (sit-for 4))
2123
2124
2125(defun ebrowse-electric-list-quit ()
2126 "Discard the buffer list."
2127 (interactive)
2128 (throw 'ebrowse-electric-list-select nil))
2129
2130
2131(defun ebrowse-electric-list-select ()
2132 "Select a buffer from the buffer list."
2133 (interactive)
2134 (throw 'ebrowse-electric-list-select (point)))
2135
2136
2137(defun ebrowse-electric-get-buffer (point)
2138 "Get a buffer corresponding to the line POINT is in."
2139 (let ((index (- (count-lines (point-min) point) 2)))
2140 (nth index (ebrowse-known-class-trees-buffer-list))))
2141
2142
2143;;; View a buffer for a tree.
2144
2145(defun ebrowse-electric-view-buffer ()
2146 "View buffer point is on."
2147 (interactive)
2148 (let ((buffer (ebrowse-electric-get-buffer (point))))
2149 (cond (buffer
2150 (view-buffer buffer))
2151 (t
2152 (error "Buffer no longer exists")))))
2153
2154
2155(defun ebrowse-choose-from-browser-buffers ()
2156 "Read a browser buffer name from the minibuffer and return that buffer."
2157 (let* ((buffers (ebrowse-known-class-trees-buffer-list)))
2158 (if buffers
2159 (if (not (second buffers))
2160 (first buffers)
2161 (or (ebrowse-electric-choose-tree) (error "No tree buffer")))
2162 (let* ((insert-default-directory t)
2163 (file (read-file-name "Find tree: " nil nil t)))
2164 (save-excursion
2165 (find-file file))
2166 (find-buffer-visiting file)))))
2167
2168\f
2169;;; Member buffers
2170
2171(unless ebrowse-member-mode-map
2172 (let ((map (make-keymap)))
2173 (setf ebrowse-member-mode-map map)
2174 (suppress-keymap map)
2175
f4a2b0a4 2176 (when (display-mouse-p)
be0dbdab
GM
2177 (define-key map [down-mouse-3] 'ebrowse-member-mouse-3)
2178 (define-key map [mouse-2] 'ebrowse-member-mouse-2))
2179
2180 (let ((map1 (make-sparse-keymap)))
2181 (suppress-keymap map1 t)
2182 (define-key map "C" map1)
2183 (define-key map1 "b" 'ebrowse-switch-member-buffer-to-base-class)
2184 (define-key map1 "c" 'ebrowse-switch-member-buffer-to-any-class)
2185 (define-key map1 "d" 'ebrowse-switch-member-buffer-to-derived-class)
2186 (define-key map1 "n" 'ebrowse-switch-member-buffer-to-next-sibling-class)
2187 (define-key map1 "p" 'ebrowse-switch-member-buffer-to-previous-sibling-class))
106ba1bb 2188
be0dbdab
GM
2189 (let ((map1 (make-sparse-keymap)))
2190 (suppress-keymap map1 t)
2191 (define-key map "D" map1)
2192 (define-key map1 "a" 'ebrowse-toggle-member-attributes-display)
2193 (define-key map1 "b" 'ebrowse-toggle-base-class-display)
2194 (define-key map1 "f" 'ebrowse-freeze-member-buffer)
2195 (define-key map1 "l" 'ebrowse-toggle-long-short-display)
2196 (define-key map1 "r" 'ebrowse-toggle-regexp-display)
2197 (define-key map1 "w" 'ebrowse-set-member-buffer-column-width))
106ba1bb 2198
be0dbdab
GM
2199 (let ((map1 (make-sparse-keymap)))
2200 (suppress-keymap map1 t)
2201 (define-key map "F" map1)
2202 (let ((map2 (make-sparse-keymap)))
2203 (suppress-keymap map2 t)
2204 (define-key map1 "a" map2)
2205 (define-key map2 "i" 'ebrowse-toggle-private-member-filter)
2206 (define-key map2 "o" 'ebrowse-toggle-protected-member-filter)
2207 (define-key map2 "u" 'ebrowse-toggle-public-member-filter))
2208 (define-key map1 "c" 'ebrowse-toggle-const-member-filter)
2209 (define-key map1 "i" 'ebrowse-toggle-inline-member-filter)
2210 (define-key map1 "p" 'ebrowse-toggle-pure-member-filter)
2211 (define-key map1 "r" 'ebrowse-remove-all-member-filters)
2212 (define-key map1 "v" 'ebrowse-toggle-virtual-member-filter))
106ba1bb 2213
be0dbdab
GM
2214 (let ((map1 (make-sparse-keymap)))
2215 (suppress-keymap map1 t)
2216 (define-key map "L" map1)
2217 (define-key map1 "d" 'ebrowse-display-friends-member-list)
2218 (define-key map1 "f" 'ebrowse-display-function-member-list)
2219 (define-key map1 "F" 'ebrowse-display-static-functions-member-list)
2220 (define-key map1 "n" 'ebrowse-display-next-member-list)
2221 (define-key map1 "p" 'ebrowse-display-previous-member-list)
2222 (define-key map1 "t" 'ebrowse-display-types-member-list)
2223 (define-key map1 "v" 'ebrowse-display-variables-member-list)
2224 (define-key map1 "V" 'ebrowse-display-static-variables-member-list))
106ba1bb 2225
be0dbdab
GM
2226 (let ((map1 (make-sparse-keymap)))
2227 (suppress-keymap map1 t)
2228 (define-key map "G" map1)
2229 (define-key map1 "m" 'ebrowse-goto-visible-member/all-member-lists)
2230 (define-key map1 "n" 'ebrowse-repeat-member-search)
2231 (define-key map1 "v" 'ebrowse-goto-visible-member))
106ba1bb 2232
be0dbdab
GM
2233 (define-key map "f" 'ebrowse-find-member-declaration)
2234 (define-key map "m" 'ebrowse-switch-to-next-member-buffer)
2235 (define-key map "q" 'bury-buffer)
2236 (define-key map "t" 'ebrowse-show-displayed-class-in-tree)
2237 (define-key map "v" 'ebrowse-view-member-declaration)
2238 (define-key map " " 'ebrowse-view-member-definition)
2239 (define-key map "?" 'describe-mode)
2240 (define-key map "\C-i" 'ebrowse-pop-from-member-to-tree-buffer)
2241 (define-key map "\C-l" 'ebrowse-redisplay-member-buffer)
2242 (define-key map "\C-m" 'ebrowse-find-member-definition)))
2243
2244
2245\f
2246;;; Member mode
2247
8cbb7c61 2248;;;###autoload
be0dbdab
GM
2249(defun ebrowse-member-mode ()
2250 "Major mode for Ebrowse member buffers.
2251
2252\\{ebrowse-member-mode-map}"
2253 (kill-all-local-variables)
2254 (use-local-map ebrowse-member-mode-map)
2255 (setq major-mode 'ebrowse-member-mode)
2256 (mapcar 'make-local-variable
2257 '(ebrowse--decl-column ;display column
2258 ebrowse--n-columns ;number of short columns
2259 ebrowse--column-width ;width of columns above
2260 ebrowse--show-inherited-flag ;include inherited members?
2261 ebrowse--filters ;public, protected, private
2262 ebrowse--accessor ;vars, functions, friends
2263 ebrowse--displayed-class ;class displayed
2264 ebrowse--long-display-flag ;display with regexps?
2265 ebrowse--source-regexp-flag ;show source regexp?
2266 ebrowse--attributes-flag ;show `virtual' and `inline'
2267 ebrowse--member-list ;list of members displayed
2268 ebrowse--tree ;the class tree
2269 ebrowse--member-mode-strings ;part of mode line
2270 ebrowse--tags-file-name ;
2271 ebrowse--header
2272 ebrowse--tree-obarray
2273 ebrowse--virtual-display-flag
2274 ebrowse--inline-display-flag
2275 ebrowse--const-display-flag
2276 ebrowse--pure-display-flag
be0dbdab 2277 ebrowse--frozen-flag)) ;buffer not automagically reused
8b2affc5
GM
2278 (setq mode-name "Ebrowse-Members"
2279 mode-line-buffer-identification
2280 (propertized-buffer-identification "C++ Members")
be0dbdab
GM
2281 buffer-read-only t
2282 ebrowse--long-display-flag nil
2283 ebrowse--attributes-flag t
2284 ebrowse--show-inherited-flag t
2285 ebrowse--source-regexp-flag nil
2286 ebrowse--filters [0 1 2]
2287 ebrowse--decl-column ebrowse-default-declaration-column
2288 ebrowse--column-width ebrowse-default-column-width
2289 ebrowse--virtual-display-flag nil
2290 ebrowse--inline-display-flag nil
2291 ebrowse--const-display-flag nil
2292 ebrowse--pure-display-flag nil)
2293 (modify-syntax-entry ?_ (char-to-string (char-syntax ?a)))
9a969196 2294 (run-mode-hooks 'ebrowse-member-mode-hook))
be0dbdab
GM
2295
2296
2297\f
2298;;; Member mode mode line
2299
2300(defsubst ebrowse-class-name-displayed-in-member-buffer ()
2301 "Return the name of the class displayed in the member buffer."
2302 (ebrowse-cs-name (ebrowse-ts-class ebrowse--displayed-class)))
2303
2304
2305(defsubst ebrowse-member-list-name ()
2306 "Return a string describing what is displayed in the member buffer."
2307 (get ebrowse--accessor (if (ebrowse-globals-tree-p ebrowse--displayed-class)
2308 'ebrowse-global-title
2309 'ebrowse-title)))
2310
2311
2312(defun ebrowse-update-member-buffer-mode-line ()
2313 "Update the mode line of member buffers."
2314 (let* ((name (when ebrowse--frozen-flag
2315 (concat (ebrowse-class-name-displayed-in-member-buffer)
2316 " ")))
2317 (ident (concat name (ebrowse-member-list-name))))
8b2affc5
GM
2318 (setq mode-line-buffer-identification
2319 (propertized-buffer-identification ident))
be0dbdab
GM
2320 (ebrowse-rename-buffer (if name ident ebrowse-member-buffer-name))
2321 (force-mode-line-update)))
2322
2323
2324;;; Misc member buffer commands
2325
2326(defun ebrowse-freeze-member-buffer ()
2327 "Toggle frozen status of current buffer."
2328 (interactive)
2329 (setq ebrowse--frozen-flag (not ebrowse--frozen-flag))
2330 (ebrowse-redisplay-member-buffer))
2331
2332
2333(defun ebrowse-show-displayed-class-in-tree (arg)
2334 "Show the currently displayed class in the tree window.
2335With prefix ARG, switch to the tree buffer else pop to it."
2336 (interactive "P")
2337 (let ((class-name (ebrowse-class-name-displayed-in-member-buffer)))
2338 (when (ebrowse-pop-from-member-to-tree-buffer arg)
2339 (ebrowse-read-class-name-and-go class-name))))
2340
2341
2342(defun ebrowse-set-member-buffer-column-width ()
2343 "Set the column width of the member display.
2344The new width is read from the minibuffer."
2345 (interactive)
027a4b6b 2346 (let ((width (string-to-number
be0dbdab
GM
2347 (read-from-minibuffer
2348 (concat "Column width ("
2349 (int-to-string (if ebrowse--long-display-flag
2350 ebrowse--decl-column
2351 ebrowse--column-width))
2352 "): ")))))
2353 (when (plusp width)
2354 (if ebrowse--long-display-flag
2355 (setq ebrowse--decl-column width)
2356 (setq ebrowse--column-width width))
2357 (ebrowse-redisplay-member-buffer))))
2358
2359
2360(defun ebrowse-pop-from-member-to-tree-buffer (arg)
2361 "Pop from a member buffer to the matching tree buffer.
2362Switch to the buffer if prefix ARG. If no tree buffer exists,
2363make one."
2364 (interactive "P")
2365 (let ((buf (or (get-buffer (ebrowse-frozen-tree-buffer-name
2366 ebrowse--tags-file-name))
2367 (get-buffer ebrowse-tree-buffer-name)
2368 (ebrowse-create-tree-buffer ebrowse--tree
2369 ebrowse--tags-file-name
2370 ebrowse--header
2371 ebrowse--tree-obarray
2372 'pop))))
2373 (and buf
2374 (funcall (if arg 'switch-to-buffer 'pop-to-buffer) buf))
2375 buf))
2376
2377
2378\f
2379;;; Switching between member lists
2380
2381(defun ebrowse-display-member-list-for-accessor (accessor)
2382 "Switch the member buffer to display the member list for ACCESSOR."
2383 (setf ebrowse--accessor accessor
2384 ebrowse--member-list (funcall accessor ebrowse--displayed-class))
2385 (ebrowse-redisplay-member-buffer))
2386
2387
2388(defun ebrowse-cyclic-display-next/previous-member-list (incr)
2389 "Switch buffer to INCR'th next/previous list of members."
2390 (let ((index (ebrowse-position ebrowse--accessor
2391 ebrowse-member-list-accessors)))
2392 (setf ebrowse--accessor
2393 (cond ((plusp incr)
2394 (or (nth (1+ index)
2395 ebrowse-member-list-accessors)
2396 (first ebrowse-member-list-accessors)))
2397 ((minusp incr)
2398 (or (and (>= (decf index) 0)
2399 (nth index
2400 ebrowse-member-list-accessors))
2401 (first (last ebrowse-member-list-accessors))))))
2402 (ebrowse-display-member-list-for-accessor ebrowse--accessor)))
2403
2404
2405(defun ebrowse-display-next-member-list ()
2406 "Switch buffer to next member list."
2407 (interactive)
2408 (ebrowse-cyclic-display-next/previous-member-list 1))
2409
2410
2411(defun ebrowse-display-previous-member-list ()
2412 "Switch buffer to previous member list."
2413 (interactive)
2414 (ebrowse-cyclic-display-next/previous-member-list -1))
2415
2416
2417(defun ebrowse-display-function-member-list ()
2418 "Display the list of member functions."
2419 (interactive)
2420 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-member-functions))
2421
2422
2423(defun ebrowse-display-variables-member-list ()
2424 "Display the list of member variables."
2425 (interactive)
2426 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-member-variables))
2427
2428
2429(defun ebrowse-display-static-variables-member-list ()
2430 "Display the list of static member variables."
2431 (interactive)
2432 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-static-variables))
2433
2434
2435(defun ebrowse-display-static-functions-member-list ()
2436 "Display the list of static member functions."
2437 (interactive)
2438 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-static-functions))
2439
2440
2441(defun ebrowse-display-friends-member-list ()
2442 "Display the list of friends."
2443 (interactive)
2444 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-friends))
2445
2446
2447(defun ebrowse-display-types-member-list ()
2448 "Display the list of types."
2449 (interactive)
2450 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-types))
2451
2452
2453\f
2454;;; Filters and other display attributes
2455
2456(defun ebrowse-toggle-member-attributes-display ()
2457 "Toggle display of `virtual', `inline', `const' etc."
2458 (interactive)
2459 (setq ebrowse--attributes-flag (not ebrowse--attributes-flag))
2460 (ebrowse-redisplay-member-buffer))
2461
2462
2463(defun ebrowse-toggle-base-class-display ()
2464 "Toggle the display of members inherited from base classes."
2465 (interactive)
2466 (setf ebrowse--show-inherited-flag (not ebrowse--show-inherited-flag))
2467 (ebrowse-redisplay-member-buffer))
2468
2469
2470(defun ebrowse-toggle-pure-member-filter ()
2471 "Toggle display of pure virtual members."
2472 (interactive)
2473 (setf ebrowse--pure-display-flag (not ebrowse--pure-display-flag))
2474 (ebrowse-redisplay-member-buffer))
2475
2476
2477(defun ebrowse-toggle-const-member-filter ()
2478 "Toggle display of const members."
2479 (interactive)
2480 (setf ebrowse--const-display-flag (not ebrowse--const-display-flag))
2481 (ebrowse-redisplay-member-buffer))
2482
2483
2484(defun ebrowse-toggle-inline-member-filter ()
2485 "Toggle display of inline members."
2486 (interactive)
2487 (setf ebrowse--inline-display-flag (not ebrowse--inline-display-flag))
2488 (ebrowse-redisplay-member-buffer))
2489
2490
2491(defun ebrowse-toggle-virtual-member-filter ()
2492 "Toggle display of virtual members."
2493 (interactive)
2494 (setf ebrowse--virtual-display-flag (not ebrowse--virtual-display-flag))
2495 (ebrowse-redisplay-member-buffer))
2496
2497
2498(defun ebrowse-remove-all-member-filters ()
2499 "Remove all filters."
2500 (interactive)
2501 (dotimes (i 3)
2502 (aset ebrowse--filters i i))
2503 (setq ebrowse--pure-display-flag nil
2504 ebrowse--const-display-flag nil
2505 ebrowse--virtual-display-flag nil
2506 ebrowse--inline-display-flag nil)
2507 (ebrowse-redisplay-member-buffer))
2508
2509
2510(defun ebrowse-toggle-public-member-filter ()
2511 "Toggle visibility of public members."
2512 (interactive)
2513 (ebrowse-set-member-access-visibility 0)
2514 (ebrowse-redisplay-member-buffer))
2515
2516
2517(defun ebrowse-toggle-protected-member-filter ()
2518 "Toggle visibility of protected members."
2519 (interactive)
2520 (ebrowse-set-member-access-visibility 1)
2521 (ebrowse-redisplay-member-buffer))
2522
2523
2524(defun ebrowse-toggle-private-member-filter ()
2525 "Toggle visibility of private members."
2526 (interactive)
2527 (ebrowse-set-member-access-visibility 2)
2528 (ebrowse-redisplay-member-buffer))
2529
2530
2531(defun ebrowse-set-member-access-visibility (vis)
2532 (setf (aref ebrowse--filters vis)
2533 (if (aref ebrowse--filters vis) nil vis)))
2534
2535
2536(defun ebrowse-toggle-long-short-display ()
2537 "Toggle between long and short display form of member buffers."
2538 (interactive)
2539 (setf ebrowse--long-display-flag (not ebrowse--long-display-flag))
2540 (ebrowse-redisplay-member-buffer))
2541
2542
2543(defun ebrowse-toggle-regexp-display ()
2544 "Toggle declaration/definition regular expression display.
2545Used in member buffers showing the long display form."
2546 (interactive)
2547 (setf ebrowse--source-regexp-flag (not ebrowse--source-regexp-flag))
2548 (ebrowse-redisplay-member-buffer))
2549
2550
2551\f
2552;;; Viewing/finding members
2553
2554(defun ebrowse-find-member-definition (&optional prefix)
2555 "Find the file containing a member definition.
2556With PREFIX 4. find file in another window, with prefix 5
2557find file in another frame."
2558 (interactive "p")
2559 (ebrowse-view/find-member-declaration/definition prefix nil t))
2560
2561
2562(defun ebrowse-view-member-definition (prefix)
2563 "View the file containing a member definition.
2564With PREFIX 4. find file in another window, with prefix 5
2565find file in another frame."
2566 (interactive "p")
2567 (ebrowse-view/find-member-declaration/definition prefix t t))
2568
2569
2570(defun ebrowse-find-member-declaration (prefix)
2571 "Find the file containing a member's declaration.
2572With PREFIX 4. find file in another window, with prefix 5
2573find file in another frame."
2574 (interactive "p")
2575 (ebrowse-view/find-member-declaration/definition prefix nil))
2576
2577
2578(defun ebrowse-view-member-declaration (prefix)
2579 "View the file containing a member's declaration.
2580With PREFIX 4. find file in another window, with prefix 5
2581find file in another frame."
2582 (interactive "p")
2583 (ebrowse-view/find-member-declaration/definition prefix t))
2584
2585
2586(defun* ebrowse-view/find-member-declaration/definition
2587 (prefix view &optional definition info header tags-file-name)
2588 "Find or view a member declaration or definition.
2589With PREFIX 4. find file in another window, with prefix 5
2590find file in another frame.
2591DEFINITION non-nil means find the definition, otherwise find the
2592declaration.
2593INFO is a list (TREE ACCESSOR MEMBER) describing the member to
2594search.
183c2d42 2595TAGS-FILE-NAME is the file name of the BROWSE file."
be0dbdab
GM
2596 (unless header
2597 (setq header ebrowse--header))
2598 (unless tags-file-name
2599 (setq tags-file-name ebrowse--tags-file-name))
2600 (let (tree member accessor file on-class
2601 (where (if (= prefix 4) 'other-window
2602 (if (= prefix 5) 'other-frame 'this-window))))
2603 ;; If not given as parameters, get the necessary information
2604 ;; out of the member buffer.
2605 (if info
2606 (setq tree (first info)
2607 accessor (second info)
2608 member (third info))
2609 (multiple-value-setq (tree member on-class)
2610 (ebrowse-member-info-from-point))
2611 (setq accessor ebrowse--accessor))
2612 ;; View/find class if on a line containing a class name.
2613 (when on-class
2614 (return-from ebrowse-view/find-member-declaration/definition
2615 (ebrowse-view/find-file-and-search-pattern
2616 (ebrowse-ts-class tree)
2617 (list ebrowse--header (ebrowse-ts-class tree) nil)
2618 (ebrowse-cs-file (ebrowse-ts-class tree))
2619 tags-file-name view where)))
2620 ;; For some member lists, it doesn't make sense to search for
2621 ;; a definition. If this is requested, silently search for the
2622 ;; declaration.
2623 (when (and definition
2624 (eq accessor 'ebrowse-ts-member-variables))
2625 (setq definition nil))
2626 ;; Construct a suitable `browse' struct for definitions.
2627 (when definition
2628 (setf member (make-ebrowse-ms
2629 :name (ebrowse-ms-name member)
2630 :file (ebrowse-ms-definition-file member)
2631 :pattern (ebrowse-ms-definition-pattern
2632 member)
2633 :flags (ebrowse-ms-flags member)
2634 :point (ebrowse-ms-definition-point
2635 member))))
2636 ;; When no file information in member, use that of the class
2637 (setf file (or (ebrowse-ms-file member)
2638 (if definition
2639 (ebrowse-cs-source-file (ebrowse-ts-class tree))
2640 (ebrowse-cs-file (ebrowse-ts-class tree)))))
2641 ;; When we have no regular expressions in the database the only
2642 ;; indication that the parser hasn't seen a definition/declaration
2643 ;; is that the search start point will be zero.
2644 (if (or (null file) (zerop (ebrowse-ms-point member)))
2645 (if (y-or-n-p (concat "No information about "
2646 (if definition "definition" "declaration")
2647 ". Search for "
2648 (if definition "declaration" "definition")
2649 " of `"
2650 (ebrowse-ms-name member)
2651 "'? "))
2652 (progn
2653 (message nil)
2654 ;; Recurse with new info.
2655 (ebrowse-view/find-member-declaration/definition
2656 prefix view (not definition) info header tags-file-name))
2657 (error "Search canceled"))
2658 ;; Find that thing.
2659 (ebrowse-view/find-file-and-search-pattern
2660 (make-ebrowse-bs :name (ebrowse-ms-name member)
2661 :pattern (ebrowse-ms-pattern member)
2662 :file (ebrowse-ms-file member)
2663 :flags (ebrowse-ms-flags member)
2664 :point (ebrowse-ms-point member))
2665 (list header member accessor)
2666 file
2667 tags-file-name
2668 view
2669 where))))
2670
2671
2672\f
2673;;; Drawing the member buffer
2674
2675(defun ebrowse-redisplay-member-buffer ()
2676 "Force buffer redisplay."
2677 (interactive)
2678 (let ((display-fn (if ebrowse--long-display-flag
2679 'ebrowse-draw-member-long-fn
2680 'ebrowse-draw-member-short-fn)))
2681 (ebrowse-output
2682 (erase-buffer)
2683 ;; Show this class
2684 (ebrowse-draw-member-buffer-class-line)
2685 (funcall display-fn ebrowse--member-list ebrowse--displayed-class)
2686 ;; Show inherited members if corresponding switch is on
2687 (when ebrowse--show-inherited-flag
2688 (dolist (super (ebrowse-base-classes ebrowse--displayed-class))
2689 (goto-char (point-max))
2690 (insert (if (bolp) "\n\n" "\n"))
2691 (ebrowse-draw-member-buffer-class-line super)
2692 (funcall display-fn (funcall ebrowse--accessor super) super)))
2693 (ebrowse-update-member-buffer-mode-line))))
2694
2695
2696(defun ebrowse-draw-member-buffer-class-line (&optional class)
2697 "Display the title line for a class section in the member buffer.
2698CLASS non-nil means display that class' title. Otherwise use
2699the class cursor is on."
2700 (let ((start (point))
2701 (tree (or class ebrowse--displayed-class))
106ba1bb 2702 class-name-start
be0dbdab
GM
2703 class-name-end)
2704 (insert "class ")
2705 (setq class-name-start (point))
2706 (insert (ebrowse-qualified-class-name (ebrowse-ts-class tree)))
2707 (when (ebrowse-template-p (ebrowse-ts-class tree))
2708 (insert "<>"))
2709 (setq class-name-end (point))
2710 (insert ":\n\n")
4f2d55da 2711 (ebrowse-set-face start (point) 'ebrowse-member-class)
be0dbdab
GM
2712 (add-text-properties
2713 class-name-start class-name-end
2714 '(ebrowse-what class-name
2715 mouse-face highlight
2716 help-echo "mouse-3: menu"))
2717 (put-text-property start class-name-end 'ebrowse-tree tree)))
2718
2719
2720(defun ebrowse-display-member-buffer (list &optional stand-alone class)
2721 "Start point for member buffer creation.
2722LIST is the member list to display. STAND-ALONE non-nil
2723means the member buffer is standalone. CLASS is its class."
2724 (let* ((classes ebrowse--tree-obarray)
2725 (tree ebrowse--tree)
2726 (tags-file-name ebrowse--tags-file-name)
2727 (header ebrowse--header)
2728 temp-buffer-setup-hook
2729 (temp-buffer (get-buffer ebrowse-member-buffer-name)))
2730 ;; Get the class description from the name the cursor
2731 ;; is on if not specified as an argument.
2732 (unless class
2733 (setq class (ebrowse-tree-at-point)))
2734 (with-output-to-temp-buffer ebrowse-member-buffer-name
2735 (save-excursion
2736 (set-buffer standard-output)
2737 ;; If new buffer, set the mode and initial values of locals
2738 (unless temp-buffer
2739 (ebrowse-member-mode))
2740 ;; Set local variables
2741 (setq ebrowse--member-list (funcall list class)
2742 ebrowse--displayed-class class
2743 ebrowse--accessor list
2744 ebrowse--tree-obarray classes
2745 ebrowse--frozen-flag stand-alone
2746 ebrowse--tags-file-name tags-file-name
2747 ebrowse--header header
2748 ebrowse--tree tree
2749 buffer-read-only t)
2750 (ebrowse-redisplay-member-buffer)
2751 (current-buffer)))))
2752
2753
2754(defun ebrowse-member-display-p (member)
2755 "Return t if MEMBER must be displayed under the current filter settings."
2756 (if (and (aref ebrowse--filters (ebrowse-ms-visibility member))
2757 (or (null ebrowse--const-display-flag)
2758 (ebrowse-const-p member))
2759 (or (null ebrowse--inline-display-flag)
2760 (ebrowse-inline-p member))
2761 (or (null ebrowse--pure-display-flag)
2762 (ebrowse-bs-p member))
2763 (or (null ebrowse--virtual-display-flag)
2764 (ebrowse-virtual-p member)))
2765 member))
2766
2767
2768(defun ebrowse-draw-member-attributes (member)
2769 "Insert a string for the attributes of MEMBER."
2770 (insert (if (ebrowse-template-p member) "T" "-")
2771 (if (ebrowse-extern-c-p member) "C" "-")
2772 (if (ebrowse-virtual-p member) "v" "-")
2773 (if (ebrowse-inline-p member) "i" "-")
2774 (if (ebrowse-const-p member) "c" "-")
2775 (if (ebrowse-pure-virtual-p member) "0" "-")
2776 (if (ebrowse-mutable-p member) "m" "-")
2777 (if (ebrowse-explicit-p member) "e" "-")
2778 (if (ebrowse-throw-list-p member) "t" "-")))
2779
2780
2781(defun ebrowse-draw-member-regexp (member-struc)
2782 "Insert a string for the regular expression matching MEMBER-STRUC."
2783 (let ((pattern (if ebrowse--source-regexp-flag
2784 (ebrowse-ms-definition-pattern
2785 member-struc)
2786 (ebrowse-ms-pattern member-struc))))
2787 (cond ((stringp pattern)
2788 (insert (ebrowse-trim-string pattern) "...\n")
2789 (beginning-of-line 0)
2790 (move-to-column (+ 4 ebrowse--decl-column))
2791 (while (re-search-forward "[ \t]+" nil t)
2792 (delete-region (match-beginning 0) (match-end 0))
2793 (insert " "))
2794 (beginning-of-line 2))
2795 (t
2796 (insert "[not recorded or unknown]\n")))))
2797
2798
2799(defun ebrowse-draw-member-long-fn (member-list tree)
2800 "Display member buffer for MEMBER-LIST in long form.
2801TREE is the class tree of MEMBER-LIST."
2802 (dolist (member-struc (mapcar 'ebrowse-member-display-p member-list))
2803 (when member-struc
2804 (let ((name (ebrowse-ms-name member-struc))
2805 (start (point)))
2806 ;; Insert member name truncated to the right length
2807 (insert (substring name
2808 0
2809 (min (length name)
2810 (1- ebrowse--decl-column))))
2811 (add-text-properties
2812 start (point)
2813 `(mouse-face highlight ebrowse-what member-name
2814 ebrowse-member ,member-struc
2815 ebrowse-tree ,tree
2816 help-echo "mouse-2: view definition; mouse-3: menu"))
2817 ;; Display virtual, inline, and const status
2818 (setf start (point))
2819 (indent-to ebrowse--decl-column)
2820 (put-text-property start (point) 'mouse-face nil)
2821 (when ebrowse--attributes-flag
2822 (let ((start (point)))
2823 (insert "<")
2824 (ebrowse-draw-member-attributes member-struc)
2825 (insert ">")
2826 (ebrowse-set-face start (point)
4f2d55da 2827 'ebrowse-member-attribute)))
be0dbdab
GM
2828 (insert " ")
2829 (ebrowse-draw-member-regexp member-struc))))
2830 (insert "\n")
2831 (goto-char (point-min)))
2832
2833
2834(defun ebrowse-draw-member-short-fn (member-list tree)
2835 "Display MEMBER-LIST in short form.
2836TREE is the class tree in which the members are found."
2837 (let ((i 0)
2838 (column-width (+ ebrowse--column-width
2839 (if ebrowse--attributes-flag 12 0))))
2840 ;; Get the number of columns to draw.
2841 (setq ebrowse--n-columns
2842 (max 1 (/ (ebrowse-width-of-drawable-area) column-width)))
2843 (dolist (member (mapcar #'ebrowse-member-display-p member-list))
2844 (when member
2845 (let ((name (ebrowse-ms-name member))
2846 start-of-entry
2847 (start-of-column (point))
2848 start-of-name)
2849 (indent-to (* i column-width))
2850 (put-text-property start-of-column (point) 'mouse-face nil)
2851 (setq start-of-entry (point))
106ba1bb 2852 ;; Show various attributes
be0dbdab
GM
2853 (when ebrowse--attributes-flag
2854 (insert "<")
2855 (ebrowse-draw-member-attributes member)
2856 (insert "> ")
2857 (ebrowse-set-face start-of-entry (point)
4f2d55da 2858 'ebrowse-member-attribute))
be0dbdab
GM
2859 ;; insert member name truncated to column width
2860 (setq start-of-name (point))
2861 (insert (substring name 0
2862 (min (length name)
2863 (1- ebrowse--column-width))))
2864 ;; set text properties
2865 (add-text-properties
2866 start-of-name (point)
2867 `(ebrowse-what member-name
2868 ebrowse-member ,member
2869 mouse-face highlight
2870 ebrowse-tree ,tree
2871 help-echo "mouse-2: view definition; mouse-3: menu"))
2872 (incf i)
2873 (when (>= i ebrowse--n-columns)
2874 (setf i 0)
2875 (insert "\n")))))
2876 (when (plusp i)
2877 (insert "\n"))
2878 (goto-char (point-min))))
2879
2880
2881\f
2882;;; Killing members from tree
2883
2884(defun ebrowse-member-info-from-point ()
2885 "Ger information about the member at point.
2886The result has the form (TREE MEMBER NULL-P). TREE is the tree
2887we're in, MEMBER is the member we're on. NULL-P is t if MEMBER
2888is nil."
2889 (let ((tree (or (get-text-property (point) 'ebrowse-tree)
2890 (error "No information at point")))
2891 (member (get-text-property (point) 'ebrowse-member)))
2892 (list tree member (null member))))
2893
2894
2895\f
2896;;; Switching member buffer to display a selected member
2897
2898(defun ebrowse-goto-visible-member/all-member-lists (prefix)
2899 "Position cursor on a member read from the minibuffer.
2900With PREFIX, search all members in the tree. Otherwise consider
2901only members visible in the buffer."
2902 (interactive "p")
2903 (ebrowse-ignoring-completion-case
2904 (let* ((completion-list (ebrowse-name/accessor-alist-for-class-members))
2905 (member (completing-read "Goto member: " completion-list nil t))
2906 (accessor (cdr (assoc member completion-list))))
2907 (unless accessor
2908 (error "`%s' not found" member))
2909 (unless (eq accessor ebrowse--accessor)
2910 (setf ebrowse--accessor accessor
2911 ebrowse--member-list (funcall accessor ebrowse--displayed-class))
2912 (ebrowse-redisplay-member-buffer))
2913 (ebrowse-move-point-to-member member))))
2914
2915
2916(defun ebrowse-goto-visible-member (repeat)
2917 "Position point on a member.
2918Read the member's name from the minibuffer. Consider only members
2919visible in the member buffer.
2920REPEAT non-nil means repeat the search that number of times."
2921 (interactive "p")
2922 (ebrowse-ignoring-completion-case
2923 ;; Read member name
2924 (let* ((completion-list (ebrowse-name/accessor-alist-for-visible-members))
2925 (member (completing-read "Goto member: " completion-list nil t)))
2926 (ebrowse-move-point-to-member member repeat))))
2927
2928
2929\f
2930;;; Searching a member in the member buffer
2931
2932(defun ebrowse-repeat-member-search (repeat)
2933 "Repeat the last regular expression search.
2934REPEAT, if specified, says repeat the search REPEAT times."
2935 (interactive "p")
2936 (unless ebrowse--last-regexp
2937 (error "No regular expression remembered"))
2938 ;; Skip over word the point is on
2939 (skip-chars-forward "^ \t\n")
2940 ;; Search for regexp from point
2941 (if (re-search-forward ebrowse--last-regexp nil t repeat)
2942 (progn
2943 (goto-char (match-beginning 0))
2944 (skip-chars-forward " \t\n"))
2945 ;; If not found above, repeat search from buffer start
2946 (goto-char (point-min))
2947 (if (re-search-forward ebrowse--last-regexp nil t)
2948 (progn
2949 (goto-char (match-beginning 0))
2950 (skip-chars-forward " \t\n"))
2951 (error "Not found"))))
2952
2953
2954(defun* ebrowse-move-point-to-member (name &optional count &aux member)
2955 "Set point on member NAME in the member buffer
2956COUNT, if specified, says search the COUNT'th member with the same name."
2957 (goto-char (point-min))
2958 (widen)
2959 (setq member
2960 (substring name 0 (min (length name) (1- ebrowse--column-width)))
2961 ebrowse--last-regexp
2962 (concat "[ \t\n]" (regexp-quote member) "[ \n\t]"))
2963 (if (re-search-forward ebrowse--last-regexp nil t count)
2964 (goto-char (1+ (match-beginning 0)))
2965 (error "Not found")))
2966
2967
2968\f
2969;;; Switching member buffer to another class.
2970
2971(defun ebrowse-switch-member-buffer-to-other-class (title compl-list)
2972 "Switch member buffer to a class read from the minibuffer.
2973Use TITLE as minibuffer prompt.
2974COMPL-LIST is a completion list to use."
2975 (let* ((initial (unless (second compl-list)
2976 (first (first compl-list))))
2977 (class (or (ebrowse-completing-read-value title compl-list initial)
2978 (error "Not found"))))
2979 (setf ebrowse--displayed-class class
2980 ebrowse--member-list (funcall ebrowse--accessor ebrowse--displayed-class))
2981 (ebrowse-redisplay-member-buffer)))
2982
2983
2984(defun ebrowse-switch-member-buffer-to-any-class ()
2985 "Switch member buffer to a class read from the minibuffer."
2986 (interactive)
2987 (ebrowse-switch-member-buffer-to-other-class
2988 "Goto class: " (ebrowse-tree-obarray-as-alist)))
2989
2990
2991(defun ebrowse-switch-member-buffer-to-base-class (arg)
2992 "Switch buffer to ARG'th base class."
2993 (interactive "P")
2994 (let ((supers (or (ebrowse-direct-base-classes ebrowse--displayed-class)
2995 (error "No base classes"))))
2996 (if (and arg (second supers))
2997 (let ((alist (loop for s in supers
2998 collect (cons (ebrowse-qualified-class-name
2999 (ebrowse-ts-class s))
3000 s))))
3001 (ebrowse-switch-member-buffer-to-other-class
3002 "Goto base class: " alist))
3003 (setq ebrowse--displayed-class (first supers)
3004 ebrowse--member-list
3005 (funcall ebrowse--accessor ebrowse--displayed-class))
3006 (ebrowse-redisplay-member-buffer))))
3007
3008(defun ebrowse-switch-member-buffer-to-next-sibling-class (arg)
3009 "Move to ARG'th next sibling."
3010 (interactive "p")
3011 (ebrowse-switch-member-buffer-to-sibling-class arg))
3012
3013
3014(defun ebrowse-switch-member-buffer-to-previous-sibling-class (arg)
3015 "Move to ARG'th previous sibling."
3016 (interactive "p")
3017 (ebrowse-switch-member-buffer-to-sibling-class (- arg)))
3018
3019
3020(defun ebrowse-switch-member-buffer-to-sibling-class (inc)
3021 "Switch member display to nth sibling class.
3022Prefix arg INC specifies which one."
3023 (interactive "p")
3024 (let ((containing-list ebrowse--tree)
3025 index cls
3026 (supers (ebrowse-direct-base-classes ebrowse--displayed-class)))
3027 (flet ((trees-alist (trees)
3028 (loop for tr in trees
3029 collect (cons (ebrowse-cs-name
3030 (ebrowse-ts-class tr)) tr))))
3031 (when supers
3032 (let ((tree (if (second supers)
3033 (ebrowse-completing-read-value
3034 "Relative to base class: "
3035 (trees-alist supers) nil)
3036 (first supers))))
3037 (unless tree (error "Not found"))
3038 (setq containing-list (ebrowse-ts-subclasses tree)))))
3039 (setq index (+ inc (ebrowse-position ebrowse--displayed-class
3040 containing-list)))
3041 (cond ((minusp index) (message "No previous class"))
3042 ((null (nth index containing-list)) (message "No next class")))
3043 (setq index (max 0 (min index (1- (length containing-list)))))
3044 (setq cls (nth index containing-list))
3045 (setf ebrowse--displayed-class cls
3046 ebrowse--member-list (funcall ebrowse--accessor cls))
3047 (ebrowse-redisplay-member-buffer)))
3048
3049
3050(defun ebrowse-switch-member-buffer-to-derived-class (arg)
3051 "Switch member display to nth derived class.
3052Prefix arg ARG says which class should be displayed. Default is
3053the first derived class."
3054 (interactive "P")
106ba1bb 3055 (flet ((ebrowse-tree-obarray-as-alist ()
be0dbdab
GM
3056 (loop for s in (ebrowse-ts-subclasses
3057 ebrowse--displayed-class)
3058 collect (cons (ebrowse-cs-name
3059 (ebrowse-ts-class s)) s))))
3060 (let ((subs (or (ebrowse-ts-subclasses ebrowse--displayed-class)
3061 (error "No derived classes"))))
3062 (if (and arg (second subs))
3063 (ebrowse-switch-member-buffer-to-other-class
3064 "Goto derived class: " (ebrowse-tree-obarray-as-alist))
3065 (setq ebrowse--displayed-class (first subs)
3066 ebrowse--member-list
3067 (funcall ebrowse--accessor ebrowse--displayed-class))
3068 (ebrowse-redisplay-member-buffer)))))
3069
3070
3071\f
3072;;; Member buffer mouse functions
3073
3074(defun ebrowse-displaying-functions ()
3075 (eq ebrowse--accessor 'ebrowse-ts-member-functions))
3076(defun ebrowse-displaying-variables ()
3077 (eq ebrowse--accessor 'ebrowse-ts-member-variables))
3078(defun ebrowse-displaying-static-functions ()
3079 )
3080(defun ebrowse-displaying-static-variables ()
3081 )
3082(defun ebrowse-displaying-types ()
3083 (eq ebrowse--accessor 'ebrowse-ts-types))
3084(defun ebrowse-displaying-friends ()
3085 (eq ebrowse--accessor 'ebrowse-ts-friends))
3086
3087(easy-menu-define
3088 ebrowse-member-buffer-object-menu ebrowse-member-mode-map
3089 "Object menu for the member buffer itself."
3090 '("Members"
3091 ("Members List"
3092 ["Functions" ebrowse-display-function-member-list
3093 :help "Show the list of member functions"
3094 :style radio
3095 :selected (eq ebrowse--accessor 'ebrowse-ts-member-functions)
3096 :active t]
3097 ["Variables" ebrowse-display-variables-member-list
3098 :help "Show the list of member variables"
3099 :style radio
3100 :selected (eq ebrowse--accessor 'ebrowse-ts-member-variables)
3101 :active t]
3102 ["Static Functions" ebrowse-display-static-functions-member-list
3103 :help "Show the list of static member functions"
3104 :style radio
3105 :selected (eq ebrowse--accessor 'ebrowse-ts-static-functions)
3106 :active t]
3107 ["Static Variables" ebrowse-display-static-variables-member-list
3108 :help "Show the list of static member variables"
3109 :style radio
3110 :selected (eq ebrowse--accessor 'ebrowse-ts-static-variables)
3111 :active t]
3112 ["Types" ebrowse-display-types-member-list
3113 :help "Show the list of nested types"
3114 :style radio
3115 :selected (eq ebrowse--accessor 'ebrowse-ts-types)
3116 :active t]
3117 ["Friends/Defines" ebrowse-display-friends-member-list
3118 :help "Show the list of friends or defines"
3119 :style radio
3120 :selected (eq ebrowse--accessor 'ebrowse-ts-friends)
3121 :active t])
3122 ("Class"
3123 ["Up" ebrowse-switch-member-buffer-to-base-class
3124 :help "Show the base class of this class"
3125 :active t]
3126 ["Down" ebrowse-switch-member-buffer-to-derived-class
3127 :help "Show a derived class class of this class"
3128 :active t]
3129 ["Next Sibling" ebrowse-switch-member-buffer-to-next-sibling-class
3130 :help "Show the next sibling class"
3131 :active t]
3132 ["Previous Sibling" ebrowse-switch-member-buffer-to-previous-sibling-class
3133 :help "Show the previous sibling class"
3134 :active t])
3135 ("Member"
3136 ["Show in Tree" ebrowse-show-displayed-class-in-tree
3137 :help "Show this class in the class tree"
3138 :active t]
3139 ["Find in this Class" ebrowse-goto-visible-member
3140 :help "Search for a member of this class"
3141 :active t]
3142 ["Find in Tree" ebrowse-goto-visible-member/all-member-lists
3143 :help "Search for a member in any class"
3144 :active t])
106ba1bb 3145 ("Display"
be0dbdab
GM
3146 ["Inherited" ebrowse-toggle-base-class-display
3147 :help "Toggle display of inherited members"
3148 :style toggle
3149 :selected ebrowse--show-inherited-flag
3150 :active t]
3151 ["Attributes" ebrowse-toggle-member-attributes-display
3152 :help "Show member attributes"
3153 :style toggle
3154 :selected ebrowse--attributes-flag
3155 :active t]
3156 ["Long Display" ebrowse-toggle-long-short-display
3157 :help "Toggle the member display format"
3158 :style toggle
3159 :selected ebrowse--long-display-flag
3160 :active t]
3161 ["Column Width" ebrowse-set-member-buffer-column-width
3162 :help "Set the display's column width"
3163 :active t])
3164 ("Filter"
3165 ["Public" ebrowse-toggle-public-member-filter
3166 :help "Toggle the visibility of public members"
3167 :style toggle
3168 :selected (not (aref ebrowse--filters 0))
3169 :active t]
3170 ["Protected" ebrowse-toggle-protected-member-filter
3171 :help "Toggle the visibility of protected members"
3172 :style toggle
3173 :selected (not (aref ebrowse--filters 1))
3174 :active t]
3175 ["Private" ebrowse-toggle-private-member-filter
3176 :help "Toggle the visibility of private members"
3177 :style toggle
3178 :selected (not (aref ebrowse--filters 2))
3179 :active t]
3180 ["Virtual" ebrowse-toggle-virtual-member-filter
3181 :help "Toggle the visibility of virtual members"
3182 :style toggle
3183 :selected ebrowse--virtual-display-flag
3184 :active t]
3185 ["Inline" ebrowse-toggle-inline-member-filter
3186 :help "Toggle the visibility of inline members"
3187 :style toggle
3188 :selected ebrowse--inline-display-flag
3189 :active t]
3190 ["Const" ebrowse-toggle-const-member-filter
3191 :help "Toggle the visibility of const members"
3192 :style toggle
3193 :selected ebrowse--const-display-flag
3194 :active t]
3195 ["Pure" ebrowse-toggle-pure-member-filter
3196 :help "Toggle the visibility of pure virtual members"
3197 :style toggle
3198 :selected ebrowse--pure-display-flag
3199 :active t]
3200 "-----------------"
3201 ["Show all" ebrowse-remove-all-member-filters
3202 :help "Remove any display filters"
3203 :active t])
3204 ("Buffer"
3205 ["Tree" ebrowse-pop-from-member-to-tree-buffer
3206 :help "Pop to the class tree buffer"
3207 :active t]
3208 ["Next Member Buffer" ebrowse-switch-to-next-member-buffer
3209 :help "Switch to the next member buffer of this class tree"
3210 :active t]
3211 ["Freeze" ebrowse-freeze-member-buffer
3212 :help "Freeze (do not reuse) this member buffer"
3213 :active t])))
3214
3215
3216(defun ebrowse-on-class-name ()
3217 "Value is non-nil if point is on a class name."
3218 (eq (get-text-property (point) 'ebrowse-what) 'class-name))
3219
3220
3221(defun ebrowse-on-member-name ()
3222 "Value is non-nil if point is on a member name."
3223 (eq (get-text-property (point) 'ebrowse-what) 'member-name))
3224
3225
3226(easy-menu-define
3227 ebrowse-member-class-name-object-menu ebrowse-member-mode-map
3228 "Object menu for class names in member buffer."
3229 '("Class"
3230 ["Find" ebrowse-find-member-definition
3231 :help "Find this class in the source files"
3232 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
3233 ["View" ebrowse-view-member-definition
3234 :help "View this class in the source files"
3235 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]))
3236
3237
106ba1bb 3238(easy-menu-define
be0dbdab
GM
3239 ebrowse-member-name-object-menu ebrowse-member-mode-map
3240 "Object menu for member names"
3241 '("Ebrowse"
3242 ["Find Definition" ebrowse-find-member-definition
3243 :help "Find this member's definition in the source files"
3244 :active (ebrowse-on-member-name)]
3245 ["Find Declaration" ebrowse-find-member-declaration
3246 :help "Find this member's declaration in the source files"
3247 :active (ebrowse-on-member-name)]
3248 ["View Definition" ebrowse-view-member-definition
3249 :help "View this member's definition in the source files"
3250 :active (ebrowse-on-member-name)]
3251 ["View Declaration" ebrowse-view-member-declaration
3252 :help "View this member's declaration in the source files"
3253 :active (ebrowse-on-member-name)]))
3254
3255
3256(defun ebrowse-member-mouse-3 (event)
3257 "Handle `mouse-3' events in member buffers.
3258EVENT is the mouse event."
3259 (interactive "e")
3260 (mouse-set-point event)
3261 (case (event-click-count event)
3262 (2 (ebrowse-find-member-definition))
3263 (1 (case (get-text-property (posn-point (event-start event))
3264 'ebrowse-what)
3265 (member-name
3266 (ebrowse-popup-menu ebrowse-member-name-object-menu event))
3267 (class-name
3268 (ebrowse-popup-menu ebrowse-member-class-name-object-menu event))
3269 (t
3270 (ebrowse-popup-menu ebrowse-member-buffer-object-menu event))))))
3271
3272
3273(defun ebrowse-member-mouse-2 (event)
3274 "Handle `mouse-2' events in member buffers.
3275EVENT is the mouse event."
3276 (interactive "e")
3277 (mouse-set-point event)
3278 (case (event-click-count event)
3279 (2 (ebrowse-find-member-definition))
3280 (1 (case (get-text-property (posn-point (event-start event))
3281 'ebrowse-what)
3282 (member-name
3283 (ebrowse-view-member-definition 0))))))
3284
3285
3286\f
3287;;; Tags view/find
3288
3289(defun ebrowse-class-alist-for-member (tree-header name)
3290 "Return information about a member in a class tree.
3291TREE-HEADER is the header structure of the class tree.
3292NAME is the name of the member.
3293Value is an alist of elements (CLASS-NAME . (CLASS LIST NAME)),
3294where each element describes one occurrence of member NAME in the tree.
106ba1bb 3295CLASS-NAME is the qualified name of the class in which the
be0dbdab
GM
3296member was found. The CDR of the acons is described in function
3297`ebrowse-class/index/member-for-member'."
3298 (let ((table (ebrowse-member-table tree-header))
3299 known-classes
3300 alist)
3301 (when name
3302 (dolist (info (gethash name table) alist)
3303 (unless (memq (first info) known-classes)
3304 (setf alist (acons (ebrowse-qualified-class-name
3305 (ebrowse-ts-class (first info)))
3306 info alist)
3307 known-classes (cons (first info) known-classes)))))))
3308
3309
3310(defun ebrowse-choose-tree ()
3311 "Choose a class tree to use.
3312If there's more than one class tree loaded, let the user choose
3313the one he wants. Value is (TREE HEADER BUFFER), with TREE being
3314the class tree, HEADER the header structure of the tree, and BUFFER
3315being the tree or member buffer containing the tree."
3316 (let* ((buffer (ebrowse-choose-from-browser-buffers)))
3317 (if buffer (list (ebrowse-value-in-buffer 'ebrowse--tree buffer)
3318 (ebrowse-value-in-buffer 'ebrowse--header buffer)
3319 buffer))))
3320
3321
3322(defun ebrowse-tags-read-name (header prompt)
3323 "Read a C++ identifier from the minibuffer.
3324HEADER is the `ebrowse-hs' structure of the class tree.
3325Prompt with PROMPT. Insert into the minibuffer a C++ identifier read
3326from point as default. Value is a list (CLASS-NAME MEMBER-NAME)."
3327 (save-excursion
3328 (let* (start member-info (members (ebrowse-member-table header)))
3329 (multiple-value-bind (class-name member-name)
3330 (ebrowse-tags-read-member+class-name)
3331 (unless member-name
3332 (error "No member name at point"))
3333 (if members
47932cf8
SM
3334 (let* ((name (ebrowse-ignoring-completion-case
3335 (completing-read prompt members nil nil member-name)))
3336 (completion-result (try-completion name members)))
0ff9b955 3337 ;; Cannot rely on `try-completion' returning t for exact
110c171f 3338 ;; matches! It returns the name as a string.
be0dbdab
GM
3339 (unless (setq member-info (gethash name members))
3340 (if (y-or-n-p "No exact match found. Try substrings? ")
106ba1bb
JB
3341 (setq name
3342 (or (first (ebrowse-list-of-matching-members
be0dbdab
GM
3343 members (regexp-quote name) name))
3344 (error "Sorry, nothing found")))
3345 (error "Canceled")))
3346 (list class-name name))
3347 (list class-name (read-from-minibuffer prompt member-name)))))))
3348
3349
3350(defun ebrowse-tags-read-member+class-name ()
3351 "Read a C++ identifier from point.
3352Value is (CLASS-NAME MEMBER-NAME).
3353CLASS-NAME is the name of the class if the identifier was qualified.
3354It is nil otherwise.
3355MEMBER-NAME is the name of the member found."
3356 (save-excursion
3357 (skip-chars-backward "a-zA-Z0-9_")
3358 (let* ((start (point))
3359 (name (progn (skip-chars-forward "a-zA-Z0-9_")
3360 (buffer-substring start (point))))
3361 class)
3362 (list class name))))
3363
3364
3365(defun ebrowse-tags-choose-class (tree header name initial-class-name)
3366 "Read a class name for a member from the minibuffer.
3367TREE is the class tree we operate on.
3368HEADER is its header structure.
3369NAME is the name of the member.
3370INITIAL-CLASS-NAME is an initial class name to insert in the minibuffer.
3371Value is a list (TREE ACCESSOR MEMBER) for the member."
3372 (let ((alist (or (ebrowse-class-alist-for-member header name)
3373 (error "No classes with member `%s' found" name))))
3374 (ebrowse-ignoring-completion-case
3375 (if (null (second alist))
3376 (cdr (first alist))
3377 (push ?\? unread-command-events)
3378 (cdr (assoc (completing-read "In class: "
3379 alist nil t initial-class-name)
3380 alist))))))
3381
3382
3383(defun* ebrowse-tags-view/find-member-decl/defn
3384 (prefix &key view definition member-name)
3385 "If VIEW is t, view, else find an occurrence of MEMBER-NAME.
3386
3387If DEFINITION is t, find or view the member definition else its
3388declaration. This function reads the member's name from the
3389current buffer like FIND-TAG. It then prepares a completion list
3390of all classes containing a member with the given name and lets
3391the user choose the class to use. As a last step, a tags search
3392is performed that positions point on the member declaration or
3393definition."
3394 (multiple-value-bind
3395 (tree header tree-buffer) (ebrowse-choose-tree)
3396 (unless tree (error "No class tree"))
3397 (let* ((marker (point-marker))
3398 class-name
3399 (name member-name)
3400 info)
3401 (unless name
3402 (multiple-value-setq (class-name name)
3403 (ebrowse-tags-read-name
3404 header
3405 (concat (if view "View" "Find") " member "
3406 (if definition "definition" "declaration") ": "))))
3407 (setq info (ebrowse-tags-choose-class tree header name class-name))
3408 (ebrowse-push-position marker info)
3409 ;; Goto the occurrence of the member
3410 (ebrowse-view/find-member-declaration/definition
3411 prefix view definition info
3412 header
3413 (ebrowse-value-in-buffer 'ebrowse--tags-file-name tree-buffer))
3414 ;; Record position jumped to
3415 (ebrowse-push-position (point-marker) info t))))
3416
3417
8cbb7c61 3418;;;###autoload
be0dbdab
GM
3419(defun ebrowse-tags-view-declaration ()
3420 "View declaration of member at point."
3421 (interactive)
3422 (ebrowse-tags-view/find-member-decl/defn 0 :view t :definition nil))
3423
3424
8cbb7c61 3425;;;###autoload
be0dbdab
GM
3426(defun ebrowse-tags-find-declaration ()
3427 "Find declaration of member at point."
3428 (interactive)
3429 (ebrowse-tags-view/find-member-decl/defn 0 :view nil :definition nil))
3430
3431
8cbb7c61 3432;;;###autoload
be0dbdab
GM
3433(defun ebrowse-tags-view-definition ()
3434 "View definition of member at point."
3435 (interactive)
3436 (ebrowse-tags-view/find-member-decl/defn 0 :view t :definition t))
3437
3438
8cbb7c61 3439;;;###autoload
be0dbdab
GM
3440(defun ebrowse-tags-find-definition ()
3441 "Find definition of member at point."
3442 (interactive)
3443 (ebrowse-tags-view/find-member-decl/defn 0 :view nil :definition t))
3444
3445
3446(defun ebrowse-tags-view-declaration-other-window ()
3447 "View declaration of member at point in other window."
3448 (interactive)
3449 (ebrowse-tags-view/find-member-decl/defn 4 :view t :definition nil))
3450
3451
8cbb7c61 3452;;;###autoload
be0dbdab
GM
3453(defun ebrowse-tags-find-declaration-other-window ()
3454 "Find declaration of member at point in other window."
3455 (interactive)
3456 (ebrowse-tags-view/find-member-decl/defn 4 :view nil :definition nil))
3457
3458
8cbb7c61 3459;;;###autoload
be0dbdab
GM
3460(defun ebrowse-tags-view-definition-other-window ()
3461 "View definition of member at point in other window."
3462 (interactive)
3463 (ebrowse-tags-view/find-member-decl/defn 4 :view t :definition t))
3464
3465
8cbb7c61 3466;;;###autoload
be0dbdab
GM
3467(defun ebrowse-tags-find-definition-other-window ()
3468 "Find definition of member at point in other window."
3469 (interactive)
3470 (ebrowse-tags-view/find-member-decl/defn 4 :view nil :definition t))
3471
3472
3473(defun ebrowse-tags-view-declaration-other-frame ()
3474 "View definition of member at point in other frame."
3475 (interactive)
3476 (ebrowse-tags-view/find-member-decl/defn 5 :view t :definition nil))
3477
3478
8cbb7c61 3479;;;###autoload
be0dbdab
GM
3480(defun ebrowse-tags-find-declaration-other-frame ()
3481 "Find definition of member at point in other frame."
3482 (interactive)
3483 (ebrowse-tags-view/find-member-decl/defn 5 :view nil :definition nil))
3484
3485
8cbb7c61 3486;;;###autoload
be0dbdab
GM
3487(defun ebrowse-tags-view-definition-other-frame ()
3488 "View definition of member at point in other frame."
3489 (interactive)
3490 (ebrowse-tags-view/find-member-decl/defn 5 :view t :definition t))
3491
3492
8cbb7c61 3493;;;###autoload
be0dbdab
GM
3494(defun ebrowse-tags-find-definition-other-frame ()
3495 "Find definition of member at point in other frame."
3496 (interactive)
3497 (ebrowse-tags-view/find-member-decl/defn 5 :view nil :definition t))
3498
3499
3500(defun ebrowse-tags-select/create-member-buffer (tree-buffer info)
3501 "Select or create member buffer.
3502TREE-BUFFER specifies the tree to use. INFO describes the member.
3503It is a list (TREE ACCESSOR MEMBER)."
3504 (let ((buffer (get-buffer ebrowse-member-buffer-name)))
3505 (cond ((null buffer)
3506 (set-buffer tree-buffer)
3507 (switch-to-buffer (ebrowse-display-member-buffer
3508 (second info) nil (first info))))
3509 (t
3510 (switch-to-buffer buffer)
3511 (setq ebrowse--displayed-class (first info)
3512 ebrowse--accessor (second info)
3513 ebrowse--member-list (funcall ebrowse--accessor ebrowse--displayed-class))
3514 (ebrowse-redisplay-member-buffer)))
3515 (ebrowse-move-point-to-member (ebrowse-ms-name (third info)))))
3516
3517
3518(defun ebrowse-tags-display-member-buffer (&optional fix-name)
3519 "Display a member buffer for a member.
3520FIX-NAME non-nil means display the buffer for that member.
3521Otherwise read a member name from point."
3522 (interactive)
3523 (multiple-value-bind
3524 (tree header tree-buffer) (ebrowse-choose-tree)
3525 (unless tree (error "No class tree"))
3526 (let* ((marker (point-marker)) class-name (name fix-name) info)
3527 (unless name
3528 (multiple-value-setq (class-name name)
3529 (ebrowse-tags-read-name header
3530 (concat "Find member list of: "))))
3531 (setq info (ebrowse-tags-choose-class tree header name class-name))
3532 (ebrowse-push-position marker info)
3533 (ebrowse-tags-select/create-member-buffer tree-buffer info))))
3534
3535
3536(defun ebrowse-list-of-matching-members (members regexp &optional name)
3537 "Return a list of members in table MEMBERS matching REGEXP or NAME.
3538Both NAME and REGEXP may be nil in which case exact or regexp matches
3539are not performed."
3540 (let (list)
3541 (when (or name regexp)
3542 (maphash #'(lambda (member-name info)
3543 (when (or (and name (string= name member-name))
3544 (and regexp (string-match regexp member-name)))
3545 (setq list (cons member-name list))))
3546 members))
3547 list))
3548
3549
3550(defun ebrowse-tags-apropos ()
3551 "Display a list of members matching a regexp read from the minibuffer."
3552 (interactive)
3553 (let* ((buffer (or (ebrowse-choose-from-browser-buffers)
3554 (error "No tree buffer")))
3555 (header (ebrowse-value-in-buffer 'ebrowse--header buffer))
3556 (members (ebrowse-member-table header))
3557 temp-buffer-setup-hook
3558 (regexp (read-from-minibuffer "List members matching regexp: ")))
3559 (with-output-to-temp-buffer (concat "*Apropos Members*")
3560 (set-buffer standard-output)
3561 (erase-buffer)
3562 (insert "Members matching `" regexp "'\n\n")
3563 (loop for s in (ebrowse-list-of-matching-members members regexp) do
3564 (loop for info in (gethash s members) do
3565 (ebrowse-draw-file-member-info info))))))
3566
3567
3568(defun ebrowse-tags-list-members-in-file ()
3569 "Display a list of members found in a file.
3570The file name is read from the minibuffer."
3571 (interactive)
3572 (let* ((buffer (or (ebrowse-choose-from-browser-buffers)
3573 (error "No tree buffer")))
3574 (files (save-excursion (set-buffer buffer) (ebrowse-files-table)))
47932cf8 3575 (file (completing-read "List members in file: " files nil t))
be0dbdab
GM
3576 (header (ebrowse-value-in-buffer 'ebrowse--header buffer))
3577 temp-buffer-setup-hook
3578 (members (ebrowse-member-table header)))
3579 (with-output-to-temp-buffer (concat "*Members in file " file "*")
3580 (set-buffer standard-output)
3581 (maphash
3582 #'(lambda (member-name list)
3583 (loop for info in list
3584 as member = (third info)
3585 as class = (ebrowse-ts-class (first info))
3586 when (or (and (null (ebrowse-ms-file member))
3587 (string= (ebrowse-cs-file class) file))
3588 (string= file (ebrowse-ms-file member)))
3589 do (ebrowse-draw-file-member-info info "decl.")
3590 when (or (and (null (ebrowse-ms-definition-file member))
3591 (string= (ebrowse-cs-source-file class) file))
3592 (string= file (ebrowse-ms-definition-file member)))
3593 do (ebrowse-draw-file-member-info info "defn.")))
3594 members))))
3595
3596
3597(defun* ebrowse-draw-file-member-info (info &optional (kind ""))
3598 "Display a line in an the members per file info buffer.
3599INFO describes the member. It has the form (TREE ACCESSOR MEMBER).
3600TREE is the class of the member to display.
3601ACCESSOR is the accessor symbol of its member list.
3602MEMBER is the member structure.
106ba1bb 3603KIND is an additional string printed in the buffer."
be0dbdab
GM
3604 (let* ((tree (first info))
3605 (globals-p (ebrowse-globals-tree-p tree)))
3606 (unless globals-p
3607 (insert (ebrowse-cs-name (ebrowse-ts-class tree))))
3608 (insert "::" (ebrowse-ms-name (third info)))
3609 (indent-to 40)
3610 (insert kind)
3611 (indent-to 50)
3612 (insert (case (second info)
3613 ('ebrowse-ts-member-functions "member function")
3614 ('ebrowse-ts-member-variables "member variable")
3615 ('ebrowse-ts-static-functions "static function")
3616 ('ebrowse-ts-static-variables "static variable")
3617 ('ebrowse-ts-friends (if globals-p "define" "friend"))
3618 ('ebrowse-ts-types "type")
3619 (t "unknown"))
3620 "\n")))
3621
3622(defvar ebrowse-last-completion nil
3623 "Text inserted by the last completion operation.")
3624
3625
3626(defvar ebrowse-last-completion-start nil
3627 "String which was the basis for the last completion operation.")
3628
3629
3630(defvar ebrowse-last-completion-location nil
3631 "Buffer position at which the last completion operation was initiated.")
3632
3633
3634(defvar ebrowse-last-completion-obarray nil
3635 "Member used in last completion operation.")
3636
3637
3638(make-variable-buffer-local 'ebrowse-last-completion-obarray)
3639(make-variable-buffer-local 'ebrowse-last-completion-location)
3640(make-variable-buffer-local 'ebrowse-last-completion)
3641(make-variable-buffer-local 'ebrowse-last-completion-start)
3642
3643
3644\f
3645(defun ebrowse-some-member-table ()
32fda8c9 3646 "Return a hash table containing all members of a tree.
be0dbdab
GM
3647If there's only one tree loaded, use that. Otherwise let the
3648use choose a tree."
3649 (let* ((buffers (ebrowse-known-class-trees-buffer-list))
3650 (buffer (cond ((and (first buffers) (not (second buffers)))
3651 (first buffers))
3652 (t (or (ebrowse-electric-choose-tree)
3653 (error "No tree buffer")))))
3654 (header (ebrowse-value-in-buffer 'ebrowse--header buffer)))
3655 (ebrowse-member-table header)))
3656
3657
be0dbdab
GM
3658(defun ebrowse-cyclic-successor-in-string-list (string list)
3659 "Return the item following STRING in LIST.
3660If STRING is the last element, return the first element as successor."
3661 (or (nth (1+ (ebrowse-position string list 'string=)) list)
3662 (first list)))
3663
3664\f
3665;;; Symbol completion
3666
3667;;;###autoload
3668(defun* ebrowse-tags-complete-symbol (prefix)
3669 "Perform completion on the C++ symbol preceding point.
106ba1bb 3670A second call of this function without changing point inserts the next match.
be0dbdab
GM
3671A call with prefix PREFIX reads the symbol to insert from the minibuffer with
3672completion."
3673 (interactive "P")
3674 (let* ((end (point))
3675 (begin (save-excursion (skip-chars-backward "a-zA-Z_0-9") (point)))
3676 (pattern (buffer-substring begin end))
3677 list completion)
3678 (cond
3679 ;; With prefix, read name from minibuffer with completion.
3680 (prefix
3681 (let* ((members (ebrowse-some-member-table))
be0dbdab 3682 (completion (completing-read "Insert member: "
47932cf8 3683 members nil t pattern)))
be0dbdab
GM
3684 (when completion
3685 (setf ebrowse-last-completion-location nil)
3686 (delete-region begin end)
3687 (insert completion))))
3688 ;; If this function is called at the same point the last
3689 ;; expansion ended, insert the next expansion.
3690 ((eq (point) ebrowse-last-completion-location)
3691 (setf list (all-completions ebrowse-last-completion-start
3692 ebrowse-last-completion-obarray)
3693 completion (ebrowse-cyclic-successor-in-string-list
3694 ebrowse-last-completion list))
3695 (cond ((null completion)
3696 (error "No completion"))
3697 ((string= completion pattern)
3698 (error "No further completion"))
3699 (t
3700 (delete-region begin end)
3701 (insert completion)
3702 (setf ebrowse-last-completion completion
3703 ebrowse-last-completion-location (point)))))
3704 ;; First time the function is called at some position in the
3705 ;; buffer: Start new completion.
3706 (t
3707 (let* ((members (ebrowse-some-member-table))
3708 (completion (first (all-completions pattern members nil))))
3709 (cond ((eq completion t))
3710 ((null completion)
3711 (error "Can't find completion for `%s'" pattern))
3712 (t
3713 (delete-region begin end)
3714 (insert completion)
106ba1bb 3715
be0dbdab
GM
3716 (setf ebrowse-last-completion-location (point)
3717 ebrowse-last-completion-start pattern
3718 ebrowse-last-completion completion
3719 ebrowse-last-completion-obarray members))))))))
3720
3721\f
3722;;; Tags query replace & search
3723
3724(defvar ebrowse-tags-loop-form ()
3725 "Form for `ebrowse-loop-continue'.
3726Evaluated for each file in the tree. If it returns nil, proceed
3727with the next file.")
3728
3729(defvar ebrowse-tags-next-file-list ()
3730 "A list of files to be processed.")
3731
3732
3733(defvar ebrowse-tags-next-file-path nil
3734 "The path relative to which files have to be searched.")
3735
3736
3737(defvar ebrowse-tags-loop-last-file nil
3738 "The last file visited via `ebrowse-tags-loop'.")
3739
3740
3741(defun ebrowse-tags-next-file (&optional initialize tree-buffer)
3742 "Select next file among files in current tag table.
3743Non-nil argument INITIALIZE (prefix arg, if interactive) initializes
3744to the beginning of the list of files in the tag table.
3745TREE-BUFFER specifies the class tree we operate on."
3746 (interactive "P")
3747 ;; Call with INITIALIZE non-nil initializes the files list.
3748 ;; If more than one tree buffer is loaded, let the user choose
3749 ;; on which tree (s)he wants to operate.
3750 (when initialize
3751 (let ((buffer (or tree-buffer (ebrowse-choose-from-browser-buffers))))
3752 (save-excursion
3753 (set-buffer buffer)
3754 (setq ebrowse-tags-next-file-list
3755 (ebrowse-files-list (ebrowse-marked-classes-p))
3756 ebrowse-tags-loop-last-file
3757 nil
3758 ebrowse-tags-next-file-path
3759 (file-name-directory ebrowse--tags-file-name)))))
3760 ;; End of the loop if the stack of files is empty.
3761 (unless ebrowse-tags-next-file-list
3762 (error "All files processed"))
3763 ;; ebrowse-tags-loop-last-file is the last file that was visited due
3764 ;; to a call to BROWSE-LOOP (see below). If that file is still
3765 ;; in memory, and it wasn't modified, throw its buffer away to
3766 ;; prevent cluttering up the buffer list.
3767 (when ebrowse-tags-loop-last-file
3768 (let ((buffer (get-file-buffer ebrowse-tags-loop-last-file)))
3769 (when (and buffer
3770 (not (buffer-modified-p buffer)))
3771 (kill-buffer buffer))))
3772 ;; Remember this buffer file name for later deletion, if it
3773 ;; wasn't visited by other means.
3774 (let ((file (expand-file-name (car ebrowse-tags-next-file-list)
3775 ebrowse-tags-next-file-path)))
3776 (setq ebrowse-tags-loop-last-file (if (get-file-buffer file) nil file))
3777 ;; Find the file and pop the file list. Pop has to be done
3778 ;; before the file is loaded because FIND-FILE might encounter
3779 ;; an error, and we want to be able to proceed with the next
3780 ;; file in this case.
3781 (pop ebrowse-tags-next-file-list)
3782 (find-file file)))
3783
3784
3785;;;###autoload
3786(defun ebrowse-tags-loop-continue (&optional first-time tree-buffer)
3787 "Repeat last operation on files in tree.
3788FIRST-TIME non-nil means this is not a repetition, but the first time.
3789TREE-BUFFER if indirectly specifies which files to loop over."
3790 (interactive)
3791 (when first-time
3792 (ebrowse-tags-next-file first-time tree-buffer)
3793 (goto-char (point-min)))
3794 (while (not (eval ebrowse-tags-loop-form))
3795 (ebrowse-tags-next-file)
3796 (message "Scanning file `%s'..." buffer-file-name)
3797 (goto-char (point-min))))
3798
3799
8cbb7c61 3800;;;###autoload
be0dbdab
GM
3801(defun ebrowse-tags-search (regexp)
3802 "Search for REGEXP in all files in a tree.
3803If marked classes exist, process marked classes, only.
3804If regular expression is nil, repeat last search."
3805 (interactive "sTree search (regexp): ")
3806 (if (and (string= regexp "")
3807 (eq (car ebrowse-tags-loop-form) 're-search-forward))
3808 (ebrowse-tags-loop-continue)
3809 (setq ebrowse-tags-loop-form (list 're-search-forward regexp nil t))
3810 (ebrowse-tags-loop-continue 'first-time)))
3811
3812
3813;;;###autoload
3814(defun ebrowse-tags-query-replace (from to)
3815 "Query replace FROM with TO in all files of a class tree.
3816With prefix arg, process files of marked classes only."
106ba1bb 3817 (interactive
be0dbdab
GM
3818 "sTree query replace (regexp): \nsTree query replace %s by: ")
3819 (setq ebrowse-tags-loop-form
3820 (list 'and (list 'save-excursion
3821 (list 're-search-forward from nil t))
8c8f9bc1 3822 (list 'not (list 'perform-replace from to t t nil))))
be0dbdab
GM
3823 (ebrowse-tags-loop-continue 'first-time))
3824
3825
23b809c2 3826;;;###autoload
be0dbdab
GM
3827(defun ebrowse-tags-search-member-use (&optional fix-name)
3828 "Search for call sites of a member.
3829If FIX-NAME is specified, search uses of that member.
3830Otherwise, read a member name from the minibuffer.
3831Searches in all files mentioned in a class tree for something that
3832looks like a function call to the member."
3833 (interactive)
3834 ;; Choose the tree to use if there is more than one.
3835 (multiple-value-bind (tree header tree-buffer)
3836 (ebrowse-choose-tree)
3837 (unless tree
3838 (error "No class tree"))
3839 ;; Get the member name NAME (class-name is ignored).
3840 (let ((name fix-name) class-name regexp)
3841 (unless name
3842 (multiple-value-setq (class-name name)
3843 (ebrowse-tags-read-name header "Find calls of: ")))
3844 ;; Set tags loop form to search for member and begin loop.
3845 (setq regexp (concat "\\<" name "[ \t]*(")
3846 ebrowse-tags-loop-form (list 're-search-forward regexp nil t))
3847 (ebrowse-tags-loop-continue 'first-time tree-buffer))))
3848
3849
3850\f
3851;;; Tags position management
3852
3853;;; Structures of this kind are the elements of the position stack.
3854
3855(defstruct (ebrowse-position (:type vector) :named)
3856 file-name ; in which file
3857 point ; point in file
3858 target ; t if target of a jump
3859 info) ; (CLASS FUNC MEMBER) jumped to
3860
3861
3862(defvar ebrowse-position-stack ()
3863 "Stack of `ebrowse-position' structured.")
3864
3865
3866(defvar ebrowse-position-index 0
3867 "Current position in position stack.")
3868
3869
3870(defun ebrowse-position-name (position)
3871 "Return an identifying string for POSITION.
3872The string is printed in the electric position list buffer."
3873 (let ((info (ebrowse-position-info position)))
3874 (concat (if (ebrowse-position-target position) "at " "to ")
3875 (ebrowse-cs-name (ebrowse-ts-class (first info)))
3876 "::" (ebrowse-ms-name (third info)))))
3877
3878
3879(defun ebrowse-view/find-position (position &optional view)
3880 "Position point on POSITION.
3881If VIEW is non-nil, view the position, otherwise find it."
3882 (cond ((not view)
3883 (find-file (ebrowse-position-file-name position))
3884 (goto-char (ebrowse-position-point position)))
3885 (t
3886 (unwind-protect
3887 (progn
106ba1bb 3888 (push (function
be0dbdab
GM
3889 (lambda ()
3890 (goto-char (ebrowse-position-point position))))
3891 view-mode-hook)
3892 (view-file (ebrowse-position-file-name position)))
3893 (pop view-mode-hook)))))
3894
3895
3896(defun ebrowse-push-position (marker info &optional target)
3897 "Push current position on position stack.
3898MARKER is the marker to remember as position.
3899INFO is a list (CLASS FUNC MEMBER) specifying what we jumped to.
3900TARGET non-nil means we performed a jump.
3901Positions in buffers that have no file names are not saved."
3902 (when (buffer-file-name (marker-buffer marker))
3903 (let ((too-much (- (length ebrowse-position-stack)
3904 ebrowse-max-positions)))
3905 ;; Do not let the stack grow to infinity.
3906 (when (plusp too-much)
3907 (setq ebrowse-position-stack
3908 (butlast ebrowse-position-stack too-much)))
3909 ;; Push the position.
3910 (push (make-ebrowse-position
3911 :file-name (buffer-file-name (marker-buffer marker))
3912 :point (marker-position marker)
3913 :target target
106ba1bb 3914 :info info)
be0dbdab
GM
3915 ebrowse-position-stack))))
3916
3917
3918(defun ebrowse-move-in-position-stack (increment)
3919 "Move by INCREMENT in the position stack."
3920 (let ((length (length ebrowse-position-stack)))
3921 (when (zerop length)
3922 (error "No positions remembered"))
3923 (setq ebrowse-position-index
3924 (mod (+ increment ebrowse-position-index) length))
3925 (message "Position %d of %d " ebrowse-position-index length)
3926 (ebrowse-view/find-position (nth ebrowse-position-index
3927 ebrowse-position-stack))))
3928
3929
23b809c2 3930;;;###autoload
be0dbdab
GM
3931(defun ebrowse-back-in-position-stack (arg)
3932 "Move backward in the position stack.
3933Prefix arg ARG says how much."
3934 (interactive "p")
3935 (ebrowse-move-in-position-stack (max 1 arg)))
3936
3937
23b809c2 3938;;;###autoload
be0dbdab
GM
3939(defun ebrowse-forward-in-position-stack (arg)
3940 "Move forward in the position stack.
3941Prefix arg ARG says how much."
3942 (interactive "p")
3943 (ebrowse-move-in-position-stack (min -1 (- arg))))
3944
3945
3946\f
3947;;; Electric position list
3948
3949(defvar ebrowse-electric-position-mode-map ()
3950 "Keymap used in electric position stack window.")
3951
3952
3953(defvar ebrowse-electric-position-mode-hook nil
1c1d2dc8 3954 "If non-nil, its value is called by `ebrowse-electric-position-mode'.")
be0dbdab
GM
3955
3956
3957(unless ebrowse-electric-position-mode-map
3958 (let ((map (make-keymap))
3959 (submap (make-keymap)))
3960 (setq ebrowse-electric-position-mode-map map)
3961 (fillarray (car (cdr map)) 'ebrowse-electric-position-undefined)
3962 (fillarray (car (cdr submap)) 'ebrowse-electric-position-undefined)
3963 (define-key map "\e" submap)
3964 (define-key map "\C-z" 'suspend-emacs)
3965 (define-key map "\C-h" 'Helper-help)
3966 (define-key map "?" 'Helper-describe-bindings)
3967 (define-key map "\C-c" nil)
3968 (define-key map "\C-c\C-c" 'ebrowse-electric-position-quit)
3969 (define-key map "q" 'ebrowse-electric-position-quit)
3970 (define-key map " " 'ebrowse-electric-select-position)
3971 (define-key map "\C-l" 'recenter)
3972 (define-key map "\C-u" 'universal-argument)
3973 (define-key map "\C-p" 'previous-line)
3974 (define-key map "\C-n" 'next-line)
3975 (define-key map "p" 'previous-line)
3976 (define-key map "n" 'next-line)
3977 (define-key map "v" 'ebrowse-electric-view-position)
3978 (define-key map "\C-v" 'scroll-up)
3979 (define-key map "\ev" 'scroll-down)
3980 (define-key map "\e\C-v" 'scroll-other-window)
3981 (define-key map "\e>" 'end-of-buffer)
3982 (define-key map "\e<" 'beginning-of-buffer)
3983 (define-key map "\e>" 'end-of-buffer)))
3984
3985(put 'ebrowse-electric-position-mode 'mode-class 'special)
3986(put 'ebrowse-electric-position-undefined 'suppress-keymap t)
3987
3988
3989(defun ebrowse-electric-position-mode ()
3990 "Mode for electric position buffers.
3991Runs the hook `ebrowse-electric-position-mode-hook'."
3992 (kill-all-local-variables)
3993 (use-local-map ebrowse-electric-position-mode-map)
3994 (setq mode-name "Electric Position Menu"
3995 mode-line-buffer-identification "Electric Position Menu")
3996 (when (memq 'mode-name mode-line-format)
3997 (setq mode-line-format (copy-sequence mode-line-format))
3998 (setcar (memq 'mode-name mode-line-format) "Positions"))
3999 (make-local-variable 'Helper-return-blurb)
4000 (setq Helper-return-blurb "return to buffer editing"
4001 truncate-lines t
4002 buffer-read-only t
4003 major-mode 'ebrowse-electric-position-mode)
9a969196 4004 (run-mode-hooks 'ebrowse-electric-position-mode-hook))
be0dbdab
GM
4005
4006
4007(defun ebrowse-draw-position-buffer ()
4008 "Display positions in buffer *Positions*."
4009 (set-buffer (get-buffer-create "*Positions*"))
4010 (setq buffer-read-only nil)
4011 (erase-buffer)
4012 (insert "File Point Description\n"
4013 "---- ----- -----------\n")
4014 (dolist (position ebrowse-position-stack)
4015 (insert (file-name-nondirectory (ebrowse-position-file-name position)))
4016 (indent-to 15)
4017 (insert (int-to-string (ebrowse-position-point position)))
4018 (indent-to 22)
4019 (insert (ebrowse-position-name position) "\n"))
4020 (setq buffer-read-only t))
4021
4022
23b809c2 4023;;;###autoload
be0dbdab
GM
4024(defun ebrowse-electric-position-menu ()
4025 "List positions in the position stack in an electric buffer."
4026 (interactive)
4027 (unless ebrowse-position-stack
4028 (error "No positions remembered"))
4029 (let (select buffer window)
4030 (save-window-excursion
4031 (save-window-excursion (ebrowse-draw-position-buffer))
4032 (setq window (Electric-pop-up-window "*Positions*")
4033 buffer (window-buffer window))
4034 (shrink-window-if-larger-than-buffer window)
4035 (unwind-protect
4036 (progn
4037 (set-buffer buffer)
4038 (ebrowse-electric-position-mode)
4039 (setq select
4040 (catch 'ebrowse-electric-select-position
4041 (message "<<< Press Space to bury the list >>>")
4042 (let ((first (progn (goto-char (point-min))
4043 (forward-line 2)
4044 (point)))
4045 (last (progn (goto-char (point-max))
4046 (forward-line -1)
4047 (point)))
4048 (goal-column 0))
4049 (goto-char first)
4050 (Electric-command-loop 'ebrowse-electric-select-position
4051 nil t
4052 'ebrowse-electric-position-looper
4053 (cons first last))))))
4054 (set-buffer buffer)
4055 (bury-buffer buffer)
4056 (message nil)))
4057 (when select
4058 (set-buffer buffer)
4059 (ebrowse-electric-find-position select))
4060 (kill-buffer buffer)))
4061
4062
4063(defun ebrowse-electric-position-looper (state condition)
4064 "Prevent moving point on invalid lines.
4065Called from `Electric-command-loop'. See there for the meaning
4066of STATE and CONDITION."
4067 (cond ((and condition
4068 (not (memq (car condition) '(buffer-read-only
4069 end-of-buffer
4070 beginning-of-buffer))))
4071 (signal (car condition) (cdr condition)))
4072 ((< (point) (car state))
4073 (goto-char (point-min))
4074 (forward-line 2))
4075 ((> (point) (cdr state))
4076 (goto-char (point-max))
4077 (forward-line -1)
4078 (if (pos-visible-in-window-p (point-max))
4079 (recenter -1)))))
4080
4081
4082(defun ebrowse-electric-position-undefined ()
4083 "Function called for undefined keys."
4084 (interactive)
4085 (message "Type C-h for help, ? for commands, q to quit, Space to execute")
4086 (sit-for 4))
4087
4088
4089(defun ebrowse-electric-position-quit ()
4090 "Leave the electric position list."
4091 (interactive)
4092 (throw 'ebrowse-electric-select-position nil))
4093
4094
4095(defun ebrowse-electric-select-position ()
4096 "Select a position from the list."
4097 (interactive)
4098 (throw 'ebrowse-electric-select-position (point)))
4099
4100
4101(defun ebrowse-electric-find-position (point &optional view)
4102 "View/find what is described by the line at POINT.
4103If VIEW is non-nil, view else find source files."
4104 (let ((index (- (count-lines (point-min) point) 2)))
4105 (ebrowse-view/find-position (nth index
4106 ebrowse-position-stack) view)))
4107
4108
4109(defun ebrowse-electric-view-position ()
4110 "View the position described by the line point is in."
4111 (interactive)
4112 (ebrowse-electric-find-position (point) t))
4113
4114
4115\f
4116;;; Saving trees to disk
4117
4118(defun ebrowse-write-file-hook-fn ()
4119 "Write current buffer as a class tree.
4120Installed on `local-write-file-hooks'."
4121 (ebrowse-save-tree)
4122 t)
4123
4124
23b809c2 4125;;;###autoload
be0dbdab
GM
4126(defun ebrowse-save-tree ()
4127 "Save current tree in same file it was loaded from."
4128 (interactive)
4129 (ebrowse-save-tree-as (or buffer-file-name ebrowse--tags-file-name)))
4130
4131
4132;;;###autoload
4133(defun ebrowse-save-tree-as (&optional file-name)
4134 "Write the current tree data structure to a file.
4135Read the file name from the minibuffer if interactive.
4136Otherwise, FILE-NAME specifies the file to save the tree in."
4137 (interactive "FSave tree as: ")
4138 (let ((temp-buffer (get-buffer-create "*Tree Output"))
4139 (old-standard-output standard-output)
4140 (header (copy-ebrowse-hs ebrowse--header))
4141 (tree ebrowse--tree))
4142 (unwind-protect
4143 (save-excursion
4144 (set-buffer (setq standard-output temp-buffer))
4145 (erase-buffer)
4146 (setf (ebrowse-hs-member-table header) nil)
4147 (insert (prin1-to-string header) " ")
4148 (mapcar 'ebrowse-save-class tree)
4149 (write-file file-name)
4150 (message "Tree written to file `%s'" file-name))
4151 (kill-buffer temp-buffer)
4152 (set-buffer-modified-p nil)
4153 (ebrowse-update-tree-buffer-mode-line)
4154 (setq standard-output old-standard-output))))
4155
4156
4157(defun ebrowse-save-class (class)
4158 "Write single class CLASS to current buffer."
4159 (message "%s..." (ebrowse-cs-name (ebrowse-ts-class class)))
4160 (insert "[ebrowse-ts ")
4161 (prin1 (ebrowse-ts-class class)) ;class name
4162 (insert "(") ;list of subclasses
4163 (mapcar 'ebrowse-save-class (ebrowse-ts-subclasses class))
4164 (insert ")")
4165 (dolist (func ebrowse-member-list-accessors)
4166 (prin1 (funcall func class))
4167 (insert "\n"))
4168 (insert "()") ;base-classes slot
4169 (prin1 (ebrowse-ts-mark class))
4170 (insert "]\n"))
4171
4172
4173\f
4174;;; Statistics
4175
23b809c2 4176;;;###autoload
be0dbdab
GM
4177(defun ebrowse-statistics ()
4178 "Display statistics for a class tree."
4179 (interactive)
4180 (let ((tree-file (buffer-file-name))
4181 temp-buffer-setup-hook)
4182 (with-output-to-temp-buffer "*Tree Statistics*"
4183 (multiple-value-bind (classes member-functions member-variables
4184 static-functions static-variables)
4185 (ebrowse-gather-statistics)
4186 (set-buffer standard-output)
4187 (erase-buffer)
4188 (insert "STATISTICS FOR TREE " (or tree-file "unknown") ":\n\n")
4189 (ebrowse-print-statistics-line "Number of classes:" classes)
4190 (ebrowse-print-statistics-line "Number of member functions:"
4191 member-functions)
4192 (ebrowse-print-statistics-line "Number of member variables:"
4193 member-variables)
4194 (ebrowse-print-statistics-line "Number of static functions:"
4195 static-functions)
4196 (ebrowse-print-statistics-line "Number of static variables:"
4197 static-variables)))))
4198
4199
4200(defun ebrowse-print-statistics-line (title value)
4201 "Print a line in the statistics buffer.
1c1d2dc8 4202TITLE is the title of the line, VALUE is a number to be printed
be0dbdab
GM
4203after that."
4204 (insert title)
4205 (indent-to 40)
4206 (insert (format "%d\n" value)))
4207
4208
4209(defun ebrowse-gather-statistics ()
4210 "Return statistics for a class tree.
4211The result is a list (NUMBER-OF-CLASSES NUMBER-OF-MEMBER-FUNCTIONS
4212NUMBER-OF-INSTANCE-VARIABLES NUMBER-OF-STATIC-FUNCTIONS
4213NUMBER-OF-STATIC-VARIABLES:"
4214 (let ((classes 0) (member-functions 0) (member-variables 0)
4215 (static-functions 0) (static-variables 0))
4216 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
4217 (incf classes)
4218 (incf member-functions (length (ebrowse-ts-member-functions tree)))
4219 (incf member-variables (length (ebrowse-ts-member-variables tree)))
4220 (incf static-functions (length (ebrowse-ts-static-functions tree)))
4221 (incf static-variables (length (ebrowse-ts-static-variables tree))))
4222 (list classes member-functions member-variables
4223 static-functions static-variables)))
4224
4225
4226\f
4227;;; Global key bindings
4228
4229;;; The following can be used to bind key sequences starting with
4230;;; prefix `\C-cb' to browse commands.
4231
4232(defvar ebrowse-global-map nil
4233 "*Keymap for Ebrowse commands.")
4234
4235
4236(defvar ebrowse-global-prefix-key "\C-cb"
4237 "Prefix key for Ebrowse commands.")
4238
4239
4240(defvar ebrowse-global-submap-4 nil
4241 "Keymap used for `ebrowse-global-prefix' followed by `4'.")
4242
4243
4244(defvar ebrowse-global-submap-5 nil
4245 "Keymap used for `ebrowse-global-prefix' followed by `5'.")
4246
4247
4248(unless ebrowse-global-map
4249 (setq ebrowse-global-map (make-sparse-keymap))
4250 (setq ebrowse-global-submap-4 (make-sparse-keymap))
4251 (setq ebrowse-global-submap-5 (make-sparse-keymap))
4252 (define-key ebrowse-global-map "a" 'ebrowse-tags-apropos)
4253 (define-key ebrowse-global-map "b" 'ebrowse-pop-to-browser-buffer)
4254 (define-key ebrowse-global-map "-" 'ebrowse-back-in-position-stack)
4255 (define-key ebrowse-global-map "+" 'ebrowse-forward-in-position-stack)
4256 (define-key ebrowse-global-map "l" 'ebrowse-tags-list-members-in-file)
4257 (define-key ebrowse-global-map "m" 'ebrowse-tags-display-member-buffer)
4258 (define-key ebrowse-global-map "n" 'ebrowse-tags-next-file)
4259 (define-key ebrowse-global-map "p" 'ebrowse-electric-position-menu)
4260 (define-key ebrowse-global-map "s" 'ebrowse-tags-search)
4261 (define-key ebrowse-global-map "u" 'ebrowse-tags-search-member-use)
4262 (define-key ebrowse-global-map "v" 'ebrowse-tags-view-definition)
4263 (define-key ebrowse-global-map "V" 'ebrowse-tags-view-declaration)
4264 (define-key ebrowse-global-map "%" 'ebrowse-tags-query-replace)
4265 (define-key ebrowse-global-map "." 'ebrowse-tags-find-definition)
4266 (define-key ebrowse-global-map "f" 'ebrowse-tags-find-definition)
4267 (define-key ebrowse-global-map "F" 'ebrowse-tags-find-declaration)
4268 (define-key ebrowse-global-map "," 'ebrowse-tags-loop-continue)
4269 (define-key ebrowse-global-map " " 'ebrowse-electric-buffer-list)
4270 (define-key ebrowse-global-map "\t" 'ebrowse-tags-complete-symbol)
4271 (define-key ebrowse-global-map "4" ebrowse-global-submap-4)
4272 (define-key ebrowse-global-submap-4 "." 'ebrowse-tags-find-definition-other-window)
4273 (define-key ebrowse-global-submap-4 "f" 'ebrowse-tags-find-definition-other-window)
4274 (define-key ebrowse-global-submap-4 "v" 'ebrowse-tags-find-declaration-other-window)
4275 (define-key ebrowse-global-submap-4 "F" 'ebrowse-tags-view-definition-other-window)
4276 (define-key ebrowse-global-submap-4 "V" 'ebrowse-tags-view-declaration-other-window)
4277 (define-key ebrowse-global-map "5" ebrowse-global-submap-5)
4278 (define-key ebrowse-global-submap-5 "." 'ebrowse-tags-find-definition-other-frame)
4279 (define-key ebrowse-global-submap-5 "f" 'ebrowse-tags-find-definition-other-frame)
4280 (define-key ebrowse-global-submap-5 "v" 'ebrowse-tags-find-declaration-other-frame)
4281 (define-key ebrowse-global-submap-5 "F" 'ebrowse-tags-view-definition-other-frame)
4282 (define-key ebrowse-global-submap-5 "V" 'ebrowse-tags-view-declaration-other-frame)
4283 (define-key global-map ebrowse-global-prefix-key ebrowse-global-map))
4284
4285
4286\f
4287;;; Electric C++ browser buffer menu
4288
4289;;; Electric buffer menu customization to display only some buffers
4290;;; (in this case Tree buffers). There is only one problem with this:
4291;;; If the very first character typed in the buffer menu is a space,
4292;;; this will select the buffer from which the buffer menu was
4293;;; invoked. But this buffer is not displayed in the buffer list if
4294;;; it isn't a tree buffer. I therefore let the buffer menu command
4295;;; loop read the command `p' via `unread-command-char'. This command
4296;;; has no effect since we are on the first line of the buffer.
4297
4298(defvar electric-buffer-menu-mode-hook nil)
4299
4300
4301(defun ebrowse-hack-electric-buffer-menu ()
4302 "Hack the electric buffer menu to display browser buffers."
4303 (let (non-empty)
4304 (unwind-protect
4305 (save-excursion
4306 (setq buffer-read-only nil)
4307 (goto-char 1)
4308 (forward-line 2)
4309 (while (not (eobp))
4310 (let ((b (Buffer-menu-buffer nil)))
4311 (if (or (ebrowse-buffer-p b)
4312 (string= (buffer-name b) "*Apropos Members*"))
4313 (progn (forward-line 1)
4314 (setq non-empty t))
4315 (delete-region (point)
4316 (save-excursion (end-of-line)
4317 (min (point-max)
4318 (1+ (point)))))))))
4319 (unless non-empty
4320 (error "No tree buffers"))
4321 (setf unread-command-events (listify-key-sequence "p"))
4322 (shrink-window-if-larger-than-buffer (selected-window))
4323 (setq buffer-read-only t))))
4324
4325
4326(defun ebrowse-select-1st-to-9nth ()
4327 "Select the nth entry in the list by the keys 1..9."
4328 (interactive)
4329 (let* ((maxlin (count-lines (point-min) (point-max)))
027a4b6b 4330 (n (min maxlin (+ 2 (string-to-number (this-command-keys))))))
be0dbdab
GM
4331 (goto-line n)
4332 (throw 'electric-buffer-menu-select (point))))
4333
4334
4335(defun ebrowse-install-1-to-9-keys ()
1c1d2dc8 4336 "Define keys 1..9 to select the 1st to 9nth entry in the list."
be0dbdab
GM
4337 (dotimes (i 9)
4338 (define-key (current-local-map) (char-to-string (+ i ?1))
4339 'ebrowse-select-1st-to-9nth)))
4340
4341
4342(defun ebrowse-electric-buffer-list ()
4343 "Display an electric list of Ebrowse buffers."
4344 (interactive)
4345 (unwind-protect
4346 (progn
4347 (add-hook 'electric-buffer-menu-mode-hook
4348 'ebrowse-hack-electric-buffer-menu)
4349 (add-hook 'electric-buffer-menu-mode-hook
4350 'ebrowse-install-1-to-9-keys)
4351 (call-interactively 'electric-buffer-list))
4352 (remove-hook 'electric-buffer-menu-mode-hook
4353 'ebrowse-hack-electric-buffer-menu)))
4354
4355\f
4356;;; Mouse support
4357
4358(defun ebrowse-mouse-find-member (event)
4359 "Find the member clicked on in another frame.
4360EVENT is a mouse button event."
4361 (interactive "e")
4362 (mouse-set-point event)
4363 (let (start name)
4364 (save-excursion
4365 (skip-chars-backward "a-zA-Z0-9_")
4366 (setq start (point))
4367 (skip-chars-forward "a-zA-Z0-9_")
4368 (setq name (buffer-substring start (point))))
4369 (ebrowse-tags-view/find-member-decl/defn
4370 5 :view nil :definition t :member-name name)))
4371
4372
4373(defun ebrowse-popup-menu (menu event)
4374 "Pop up MENU and perform an action if something was selected.
4375EVENT is the mouse event."
4376 (save-selected-window
4377 (select-window (posn-window (event-start event)))
4378 (let ((selection (x-popup-menu event menu)) binding)
4379 (while selection
4380 (setq binding (lookup-key (or binding menu) (vector (car selection)))
4381 selection (cdr selection)))
4382 (when binding
4383 (call-interactively binding)))))
4384
4385
4386(easy-menu-define
106ba1bb 4387 ebrowse-tree-buffer-class-object-menu ebrowse-tree-mode-map
be0dbdab
GM
4388 "Object menu for classes in the tree buffer"
4389 '("Class"
4390 ["Functions" ebrowse-tree-command:show-member-functions
4391 :help "Display a list of member functions"
4392 :active t]
4393 ["Variables" ebrowse-tree-command:show-member-variables
4394 :help "Display a list of member variables"
4395 :active t]
4396 ["Static Functions" ebrowse-tree-command:show-static-member-functions
4397 :help "Display a list of static member functions"
4398 :active t]
4399 ["Static Variables" ebrowse-tree-command:show-static-member-variables
4400 :help "Display a list of static member variables"
4401 :active t]
4402 ["Friends/ Defines" ebrowse-tree-command:show-friends
4403 :help "Display a list of friends of a class"
4404 :active t]
4405 ["Types" ebrowse-tree-command:show-types
4406 :help "Display a list of types defined in a class"
4407 :active t]
4408 "-----------------"
4409 ["View" ebrowse-view-class-declaration
4410 :help "View class declaration"
4411 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4412 ["Find" ebrowse-find-class-declaration
4413 :help "Find class declaration in file"
4414 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4415 "-----------------"
4416 ["Mark" ebrowse-toggle-mark-at-point
4417 :help "Mark class point is on"
4418 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4419 "-----------------"
4420 ["Collapse" ebrowse-collapse-branch
4421 :help "Collapse subtree under class point is on"
4422 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4423 ["Expand" ebrowse-expand-branch
4424 :help "Expand subtree under class point is on"
4425 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]))
4426
4427
4428(easy-menu-define
106ba1bb 4429 ebrowse-tree-buffer-object-menu ebrowse-tree-mode-map
be0dbdab
GM
4430 "Object menu for tree buffers"
4431 '("Ebrowse"
4432 ["Filename Display" ebrowse-toggle-file-name-display
4433 :help "Toggle display of source files names"
4434 :style toggle
4435 :selected ebrowse--show-file-names-flag
4436 :active t]
4437 ["Tree Indentation" ebrowse-set-tree-indentation
4438 :help "Set the tree's indentation"
4439 :active t]
4440 ["Unmark All Classes" ebrowse-mark-all-classes
4441 :help "Unmark all classes in the class tree"
4442 :active t]
4443 ["Expand All" ebrowse-expand-all
4444 :help "Expand all subtrees in the class tree"
4445 :active t]
4446 ["Statistics" ebrowse-statistics
4447 :help "Show a buffer with class hierarchy statistics"
4448 :active t]
4449 ["Find Class" ebrowse-read-class-name-and-go
4450 :help "Find a class in the tree"
4451 :active t]
4452 ["Member Buffer" ebrowse-pop/switch-to-member-buffer-for-same-tree
4453 :help "Show a member buffer for this class tree"
4454 :active t]))
4455
4456
4457(defun ebrowse-mouse-3-in-tree-buffer (event)
4458 "Perform mouse actions in tree buffers.
4459EVENT is the mouse event."
4460 (interactive "e")
4461 (mouse-set-point event)
4462 (let* ((where (posn-point (event-start event)))
4463 (property (get-text-property where 'ebrowse-what)))
4464 (case (event-click-count event)
4465 (1
4466 (case property
4467 (class-name
4468 (ebrowse-popup-menu ebrowse-tree-buffer-class-object-menu event))
4469 (t
4470 (ebrowse-popup-menu ebrowse-tree-buffer-object-menu event)))))))
4471
4472
4473(defun ebrowse-mouse-2-in-tree-buffer (event)
4474 "Perform mouse actions in tree buffers.
4475EVENT is the mouse event."
4476 (interactive "e")
4477 (mouse-set-point event)
4478 (let* ((where (posn-point (event-start event)))
4479 (property (get-text-property where 'ebrowse-what)))
4480 (case (event-click-count event)
4481 (1 (case property
4482 (class-name
4483 (ebrowse-tree-command:show-member-functions)))))))
4484
4485
4486(defun ebrowse-mouse-1-in-tree-buffer (event)
4487 "Perform mouse actions in tree buffers.
4488EVENT is the mouse event."
4489 (interactive "e")
4490 (mouse-set-point event)
4491 (let* ((where (posn-point (event-start event)))
4492 (property (get-text-property where 'ebrowse-what)))
4493 (case (event-click-count event)
4494 (2 (case property
4495 (class-name
4496 (let ((collapsed (save-excursion (skip-chars-forward "^\r\n")
4497 (looking-at "\r"))))
4498 (ebrowse-collapse-fn (not collapsed))))
4499 (mark
4500 (ebrowse-toggle-mark-at-point 1)))))))
4501
4502
4503\f
be0dbdab
GM
4504(provide 'ebrowse)
4505
4506;;; Local variables:
4507;;; eval:(put 'ebrowse-output 'lisp-indent-hook 0)
4508;;; eval:(put 'ebrowse-ignoring-completion-case 'lisp-indent-hook 0)
4509;;; eval:(put 'ebrowse-save-selective 'lisp-indent-hook 0)
4510;;; eval:(put 'ebrowse-for-all-trees 'lisp-indent-hook 1)
4511;;; End:
4512
ab5796a9 4513;;; arch-tag: 4fa3c8bf-1771-479b-bcd7-b029c7c9677b
55535639 4514;;; ebrowse.el ends here