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