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