(sgml-quote): Use narrowing. Improve the regexp used when unquoting.
[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)
1702 do (setf (substring regexp (match-beginning 0) (match-end 0))
1703 "[ \t]*"
1704 start (+ (match-beginning 0) 5))))
1705
1706
1707(defun ebrowse-class-declaration-regexp (name)
1708 "Construct a regexp for a declaration of class NAME."
1709 (concat "^[ \t]*\\(template[ \t\n]*<.*>\\)?"
1710 "[ \t\n]*\\(class\\|struct\\|union\\).*\\S_"
1711 (ebrowse-symbol-regexp name)
1712 "\\S_"))
1713
1714
1715(defun ebrowse-variable-declaration-regexp (name)
1716 "Construct a regexp for matching a variable NAME."
1717 (concat "\\S_" (ebrowse-symbol-regexp name) "\\S_"))
1718
1719
1720(defun ebrowse-function-declaration/definition-regexp (name)
1721 "Construct a regexp for matching a function NAME."
1722 (concat "^[a-zA-Z0-9_:*&<>, \t]*\\S_"
1723 (ebrowse-symbol-regexp name)
1724 "[ \t\n]*("))
1725
1726
1727(defun ebrowse-pp-define-regexp (name)
1728 "Construct a regexp matching a define of NAME."
1729 (concat "^[ \t]*#[ \t]*define[ \t]+" (regexp-quote name)))
1730
1731
1732(defun* ebrowse-find-pattern (&optional position info &aux viewing)
1733 "Find a pattern.
1734
1735This is a kluge: Ebrowse allows you to find or view a file containing
1736a pattern. To be able to do a search in a viewed buffer,
1737`view-mode-hook' is temporarily set to this function;
1738`ebrowse-temp-position-to-view' holds what to search for.
1739
1740INFO is a list (TREE-HEADER TREE-OR-MEMBER MEMBER-LIST)."
1741 (unless position
1742 (pop view-mode-hook)
1743 (setf viewing t
1744 position ebrowse-temp-position-to-view
1745 info ebrowse-temp-info-to-view))
1746 (widen)
1747 (let* ((pattern (ebrowse-bs-pattern position))
1748 (start (ebrowse-bs-point position))
1749 (offset 100)
1750 found)
1751 (destructuring-bind (header class-or-member member-list) info
1752 ;; If no pattern is specified, construct one from the member name.
1753 (when (stringp pattern)
1754 (setq pattern (concat "^.*" (regexp-quote pattern))))
1755 ;; Construct a regular expression if none given.
1756 (unless pattern
1757 (typecase class-or-member
1758 (ebrowse-ms
1759 (case member-list
1760 ((ebrowse-ts-member-variables
1761 ebrowse-ts-static-variables
1762 ebrowse-ts-types)
1763 (setf pattern (ebrowse-variable-declaration-regexp
1764 (ebrowse-bs-name position))))
1765 (otherwise
1766 (if (ebrowse-define-p class-or-member)
1767 (setf pattern (ebrowse-pp-define-regexp (ebrowse-bs-name position)))
1768 (setf pattern (ebrowse-function-declaration/definition-regexp
1769 (ebrowse-bs-name position)))))))
1770 (ebrowse-cs
1771 (setf pattern (ebrowse-class-declaration-regexp
1772 (ebrowse-bs-name position))))))
1773 ;; Begin searching some OFFSET from the original point where the
1774 ;; regular expression was found by the parse, and step forward.
1775 ;; When there is no regular expression in the database and a
1776 ;; member definition/declaration was not seen by the parser,
1777 ;; START will be 0.
1778 (when (and (boundp 'ebrowse-debug)
1779 (symbol-value 'ebrowse-debug))
1780 (y-or-n-p (format "start = %d" start))
1781 (y-or-n-p pattern))
1782 (setf found
1783 (loop do (goto-char (max (point-min) (- start offset)))
1784 when (re-search-forward pattern (+ start offset) t) return t
1785 never (bobp)
1786 do (incf offset offset)))
1787 (cond (found
1788 (beginning-of-line)
1789 (run-hooks 'ebrowse-view/find-hook))
1790 ((numberp (ebrowse-bs-pattern position))
1791 (goto-char start)
1792 (if ebrowse-not-found-hook
1793 (run-hooks 'ebrowse-not-found-hook)
1794 (message "Not found")
1795 (sit-for 2)))
1796 (t
1797 (if ebrowse-not-found-hook
1798 (run-hooks 'ebrowse-not-found-hook)
1799 (unless viewing
1800 (error "Not found"))
1801 (message "Not found")
1802 (sit-for 2)))))))
1803
1804\f
1805;;; Drawing the tree
1806
1807(defun ebrowse-redraw-tree (&optional quietly)
1808 "Redisplay the complete tree.
1809QUIETLY non-nil means don't display progress messages."
1810 (interactive)
1811 (or quietly (message "Displaying..."))
1812 (save-excursion
1813 (ebrowse-output
1814 (erase-buffer)
1815 (ebrowse-draw-tree-fn)))
1816 (ebrowse-update-tree-buffer-mode-line)
1817 (or quietly (message nil)))
1818
1819
1820(defun ebrowse-set-mark-props (start end tree)
1821 "Set text properties for class marker signs between START and END.
1822TREE denotes the class shown."
1823 (add-text-properties
1824 start end
1825 `(mouse-face highlight ebrowse-what mark ebrowse-tree ,tree
1826 help-echo "double-mouse-1: mark/unmark"))
1827 (ebrowse-set-face start end 'ebrowse-tree-mark-face))
1828
1829
1830(defun* ebrowse-draw-tree-fn (&aux stack1 stack2 start)
1831 "Display a single class and recursively it's subclasses.
1832This function may look weird, but this is faster than recursion."
1833 (setq stack1 (make-list (length ebrowse--tree) 0)
658397fb 1834 stack2 (copy-sequence ebrowse--tree))
be0dbdab
GM
1835 (loop while stack2
1836 as level = (pop stack1)
1837 as tree = (pop stack2)
1838 as class = (ebrowse-ts-class tree) do
1839 (let ((start-of-line (point))
1840 start-of-class-name end-of-class-name)
1841 ;; Insert mark
1842 (insert (if (ebrowse-ts-mark tree) ">" " "))
1843
1844 ;; Indent and insert class name
1845 (indent-to (+ (* level ebrowse--indentation)
1846 ebrowse-tree-left-margin))
1847 (setq start (point))
1848 (insert (ebrowse-qualified-class-name class))
1849
1850 ;; If template class, add <>
1851 (when (ebrowse-template-p class)
1852 (insert "<>"))
1853 (ebrowse-set-face start (point) (if (zerop level)
1854 'ebrowse-root-class-face
1855 'ebrowse-default-face))
1856 (setf start-of-class-name start
1857 end-of-class-name (point))
1858 ;; If filenames are to be displayed...
1859 (when ebrowse--show-file-names-flag
1860 (indent-to ebrowse-source-file-column)
1861 (setq start (point))
1862 (insert "("
1863 (or (ebrowse-cs-file class)
1864 "unknown")
1865 ")")
1866 (ebrowse-set-face start (point) 'ebrowse-file-name-face))
1867 (ebrowse-set-mark-props start-of-line (1+ start-of-line) tree)
1868 (add-text-properties
1869 start-of-class-name end-of-class-name
1870 `(mouse-face highlight ebrowse-what class-name
1871 ebrowse-tree ,tree
1872 help-echo "double-mouse-1: (un)expand tree; mouse-2: member functions, mouse-3: menu"))
1873 (insert "\n"))
1874 ;; Push subclasses, if any.
1875 (when (ebrowse-ts-subclasses tree)
1876 (setq stack2
658397fb 1877 (nconc (copy-sequence (ebrowse-ts-subclasses tree)) stack2)
be0dbdab
GM
1878 stack1
1879 (nconc (make-list (length (ebrowse-ts-subclasses tree))
1880 (1+ level)) stack1)))))
1881
1882
1883\f
1884;;; Expanding/ collapsing tree branches
1885
1886(defun ebrowse-expand-branch (arg)
1887 "Expand a sub-tree that has been previously collapsed.
1888With prefix ARG, expand all sub-trees."
1889 (interactive "P")
1890 (if arg
1891 (ebrowse-expand-all arg)
1892 (ebrowse-collapse-fn nil)))
1893
1894
1895(defun ebrowse-collapse-branch (arg)
1896 "Fold (do no longer display) the subclasses of the current class.
1897\(The class cursor is on.) With prefix ARG, fold all trees in the buffer."
1898 (interactive "P")
1899 (if arg
1900 (ebrowse-expand-all (not arg))
1901 (ebrowse-collapse-fn t)))
1902
1903
1904(defun ebrowse-expand-all (collapse)
1905 "Expand or fold all trees in the buffer.
1906COLLAPSE non-nil means fold them."
1907 (interactive "P")
1908 (let ((line-end (if collapse "^\n" "^\r"))
1909 (insertion (if collapse "\r" "\n")))
1910 (ebrowse-output
1911 (save-excursion
1912 (goto-char (point-min))
1913 (while (not (progn (skip-chars-forward line-end) (eobp)))
1914 (when (or (not collapse)
1915 (looking-at "\n "))
1916 (delete-char 1)
1917 (insert insertion))
1918 (when collapse
1919 (skip-chars-forward "\n ")))))))
1920
1921
1922(defun ebrowse-unhide-base-classes ()
1923 "Unhide the line the cursor is on and all base classes."
1924 (ebrowse-output
1925 (save-excursion
1926 (let (indent last-indent)
1927 (skip-chars-backward "^\r\n")
1928 (when (not (looking-at "[\r\n][^ \t]"))
1929 (skip-chars-forward "\r\n \t")
1930 (while (and (or (null last-indent) ;first time
1931 (> indent 1)) ;not root class
1932 (re-search-backward "[\r\n][ \t]*" nil t))
1933 (setf indent (- (match-end 0)
1934 (match-beginning 0)))
1935 (when (or (null last-indent)
1936 (< indent last-indent))
1937 (setf last-indent indent)
1938 (when (looking-at "\r")
1939 (delete-char 1)
1940 (insert 10)))
1941 (backward-char 1)))))))
1942
1943
1944(defun ebrowse-hide-line (collapse)
1945 "Hide/show a single line in the tree.
1946COLLAPSE non-nil means hide."
1947 (save-excursion
1948 (ebrowse-output
1949 (skip-chars-forward "^\r\n")
1950 (delete-char 1)
1951 (insert (if collapse 13 10)))))
1952
1953
1954(defun ebrowse-collapse-fn (collapse)
1955 "Collapse or expand a branch of the tree.
1956COLLAPSE non-nil means collapse the branch."
1957 (ebrowse-output
1958 (save-excursion
1959 (beginning-of-line)
1960 (skip-chars-forward "> \t")
1961 (let ((indentation (current-column)))
1962 (while (and (not (eobp))
1963 (save-excursion
1964 (skip-chars-forward "^\r\n")
1965 (goto-char (1+ (point)))
1966 (skip-chars-forward "> \t")
1967 (> (current-column) indentation)))
1968 (ebrowse-hide-line collapse)
1969 (skip-chars-forward "^\r\n")
1970 (goto-char (1+ (point))))))))
1971
1972\f
1973;;; Electric tree selection
1974
1975(defvar ebrowse-electric-list-mode-map ()
1976 "Keymap used in electric Ebrowse buffer list window.")
1977
1978
1979(unless ebrowse-electric-list-mode-map
1980 (let ((map (make-keymap))
1981 (submap (make-keymap)))
1982 (setq ebrowse-electric-list-mode-map map)
1983 (fillarray (car (cdr map)) 'ebrowse-electric-list-undefined)
1984 (fillarray (car (cdr submap)) 'ebrowse-electric-list-undefined)
1985 (define-key map "\e" submap)
1986 (define-key map "\C-z" 'suspend-emacs)
1987 (define-key map "\C-h" 'Helper-help)
1988 (define-key map "?" 'Helper-describe-bindings)
1989 (define-key map "\C-c" nil)
1990 (define-key map "\C-c\C-c" 'ebrowse-electric-list-quit)
1991 (define-key map "q" 'ebrowse-electric-list-quit)
1992 (define-key map " " 'ebrowse-electric-list-select)
1993 (define-key map "\C-l" 'recenter)
1994 (define-key map "\C-u" 'universal-argument)
1995 (define-key map "\C-p" 'previous-line)
1996 (define-key map "\C-n" 'next-line)
1997 (define-key map "p" 'previous-line)
1998 (define-key map "n" 'next-line)
1999 (define-key map "v" 'ebrowse-electric-view-buffer)
2000 (define-key map "\C-v" 'scroll-up)
2001 (define-key map "\ev" 'scroll-down)
2002 (define-key map "\e\C-v" 'scroll-other-window)
2003 (define-key map "\e>" 'end-of-buffer)
2004 (define-key map "\e<" 'beginning-of-buffer)
2005 (define-key map "\e>" 'end-of-buffer)))
2006
2007(put 'ebrowse-electric-list-mode 'mode-class 'special)
2008(put 'ebrowse-electric-list-undefined 'suppress-keymap t)
2009
2010
2011(defun ebrowse-electric-list-mode ()
2012 "Mode for electric tree list mode."
2013 (kill-all-local-variables)
2014 (use-local-map ebrowse-electric-list-mode-map)
2015 (setq mode-name "Electric Position Menu"
2016 mode-line-buffer-identification "Electric Tree Menu")
2017 (when (memq 'mode-name mode-line-format)
2018 (setq mode-line-format (copy-sequence mode-line-format))
2019 (setcar (memq 'mode-name mode-line-format) "Tree Buffers"))
2020 (make-local-variable 'Helper-return-blurb)
2021 (setq Helper-return-blurb "return to buffer editing"
2022 truncate-lines t
2023 buffer-read-only t
2024 major-mode 'ebrowse-electric-list-mode)
2025 (run-hooks 'ebrowse-electric-list-mode-hook))
2026
2027
2028(defun ebrowse-list-tree-buffers ()
2029 "Display a list of all tree buffers."
2030 (set-buffer (get-buffer-create "*Tree Buffers*"))
2031 (setq buffer-read-only nil)
2032 (erase-buffer)
2033 (insert "Tree\n" "----\n")
2034 (dolist (buffer (ebrowse-known-class-trees-buffer-list))
2035 (insert (buffer-name buffer) "\n"))
2036 (setq buffer-read-only t))
2037
2038
2039;;;###autoload
2040(defun ebrowse-electric-choose-tree ()
2041 "Return a buffer containing a tree or nil if no tree found or canceled."
2042 (interactive)
2043 (unless (car (ebrowse-known-class-trees-buffer-list))
2044 (error "No tree buffers"))
2045 (let (select buffer window)
2046 (save-window-excursion
2047 (save-window-excursion (ebrowse-list-tree-buffers))
2048 (setq window (Electric-pop-up-window "*Tree Buffers*")
2049 buffer (window-buffer window))
2050 (shrink-window-if-larger-than-buffer window)
2051 (unwind-protect
2052 (progn
2053 (set-buffer buffer)
2054 (ebrowse-electric-list-mode)
2055 (setq select
2056 (catch 'ebrowse-electric-list-select
2057 (message "<<< Press Space to bury the list >>>")
2058 (let ((first (progn (goto-char (point-min))
2059 (forward-line 2)
2060 (point)))
2061 (last (progn (goto-char (point-max))
2062 (forward-line -1)
2063 (point)))
2064 (goal-column 0))
2065 (goto-char first)
2066 (Electric-command-loop 'ebrowse-electric-list-select
2067 nil
2068 t
2069 'ebrowse-electric-list-looper
2070 (cons first last))))))
2071 (set-buffer buffer)
2072 (bury-buffer buffer)
2073 (message nil)))
2074 (when select
2075 (set-buffer buffer)
2076 (setq select (ebrowse-electric-get-buffer select)))
2077 (kill-buffer buffer)
2078 select))
2079
2080
2081(defun ebrowse-electric-list-looper (state condition)
2082 "Prevent cursor from moving beyond the buffer end.
2083Don't let it move into the title lines.
2084See 'Electric-command-loop' for a description of STATE and CONDITION."
2085 (cond ((and condition
2086 (not (memq (car condition)
2087 '(buffer-read-only end-of-buffer
2088 beginning-of-buffer))))
2089 (signal (car condition) (cdr condition)))
2090 ((< (point) (car state))
2091 (goto-char (point-min))
2092 (forward-line 2))
2093 ((> (point) (cdr state))
2094 (goto-char (point-max))
2095 (forward-line -1)
2096 (if (pos-visible-in-window-p (point-max))
2097 (recenter -1)))))
2098
2099
2100(defun ebrowse-electric-list-undefined ()
2101 "Function called for keys that are undefined."
2102 (interactive)
2103 (message "Type C-h for help, ? for commands, q to quit, Space to select.")
2104 (sit-for 4))
2105
2106
2107(defun ebrowse-electric-list-quit ()
2108 "Discard the buffer list."
2109 (interactive)
2110 (throw 'ebrowse-electric-list-select nil))
2111
2112
2113(defun ebrowse-electric-list-select ()
2114 "Select a buffer from the buffer list."
2115 (interactive)
2116 (throw 'ebrowse-electric-list-select (point)))
2117
2118
2119(defun ebrowse-electric-get-buffer (point)
2120 "Get a buffer corresponding to the line POINT is in."
2121 (let ((index (- (count-lines (point-min) point) 2)))
2122 (nth index (ebrowse-known-class-trees-buffer-list))))
2123
2124
2125;;; View a buffer for a tree.
2126
2127(defun ebrowse-electric-view-buffer ()
2128 "View buffer point is on."
2129 (interactive)
2130 (let ((buffer (ebrowse-electric-get-buffer (point))))
2131 (cond (buffer
2132 (view-buffer buffer))
2133 (t
2134 (error "Buffer no longer exists")))))
2135
2136
2137(defun ebrowse-choose-from-browser-buffers ()
2138 "Read a browser buffer name from the minibuffer and return that buffer."
2139 (let* ((buffers (ebrowse-known-class-trees-buffer-list)))
2140 (if buffers
2141 (if (not (second buffers))
2142 (first buffers)
2143 (or (ebrowse-electric-choose-tree) (error "No tree buffer")))
2144 (let* ((insert-default-directory t)
2145 (file (read-file-name "Find tree: " nil nil t)))
2146 (save-excursion
2147 (find-file file))
2148 (find-buffer-visiting file)))))
2149
2150\f
2151;;; Member buffers
2152
2153(unless ebrowse-member-mode-map
2154 (let ((map (make-keymap)))
2155 (setf ebrowse-member-mode-map map)
2156 (suppress-keymap map)
2157
f4a2b0a4 2158 (when (display-mouse-p)
be0dbdab
GM
2159 (define-key map [down-mouse-3] 'ebrowse-member-mouse-3)
2160 (define-key map [mouse-2] 'ebrowse-member-mouse-2))
2161
2162 (let ((map1 (make-sparse-keymap)))
2163 (suppress-keymap map1 t)
2164 (define-key map "C" map1)
2165 (define-key map1 "b" 'ebrowse-switch-member-buffer-to-base-class)
2166 (define-key map1 "c" 'ebrowse-switch-member-buffer-to-any-class)
2167 (define-key map1 "d" 'ebrowse-switch-member-buffer-to-derived-class)
2168 (define-key map1 "n" 'ebrowse-switch-member-buffer-to-next-sibling-class)
2169 (define-key map1 "p" 'ebrowse-switch-member-buffer-to-previous-sibling-class))
2170
2171 (let ((map1 (make-sparse-keymap)))
2172 (suppress-keymap map1 t)
2173 (define-key map "D" map1)
2174 (define-key map1 "a" 'ebrowse-toggle-member-attributes-display)
2175 (define-key map1 "b" 'ebrowse-toggle-base-class-display)
2176 (define-key map1 "f" 'ebrowse-freeze-member-buffer)
2177 (define-key map1 "l" 'ebrowse-toggle-long-short-display)
2178 (define-key map1 "r" 'ebrowse-toggle-regexp-display)
2179 (define-key map1 "w" 'ebrowse-set-member-buffer-column-width))
2180
2181 (let ((map1 (make-sparse-keymap)))
2182 (suppress-keymap map1 t)
2183 (define-key map "F" map1)
2184 (let ((map2 (make-sparse-keymap)))
2185 (suppress-keymap map2 t)
2186 (define-key map1 "a" map2)
2187 (define-key map2 "i" 'ebrowse-toggle-private-member-filter)
2188 (define-key map2 "o" 'ebrowse-toggle-protected-member-filter)
2189 (define-key map2 "u" 'ebrowse-toggle-public-member-filter))
2190 (define-key map1 "c" 'ebrowse-toggle-const-member-filter)
2191 (define-key map1 "i" 'ebrowse-toggle-inline-member-filter)
2192 (define-key map1 "p" 'ebrowse-toggle-pure-member-filter)
2193 (define-key map1 "r" 'ebrowse-remove-all-member-filters)
2194 (define-key map1 "v" 'ebrowse-toggle-virtual-member-filter))
2195
2196 (let ((map1 (make-sparse-keymap)))
2197 (suppress-keymap map1 t)
2198 (define-key map "L" map1)
2199 (define-key map1 "d" 'ebrowse-display-friends-member-list)
2200 (define-key map1 "f" 'ebrowse-display-function-member-list)
2201 (define-key map1 "F" 'ebrowse-display-static-functions-member-list)
2202 (define-key map1 "n" 'ebrowse-display-next-member-list)
2203 (define-key map1 "p" 'ebrowse-display-previous-member-list)
2204 (define-key map1 "t" 'ebrowse-display-types-member-list)
2205 (define-key map1 "v" 'ebrowse-display-variables-member-list)
2206 (define-key map1 "V" 'ebrowse-display-static-variables-member-list))
2207
2208 (let ((map1 (make-sparse-keymap)))
2209 (suppress-keymap map1 t)
2210 (define-key map "G" map1)
2211 (define-key map1 "m" 'ebrowse-goto-visible-member/all-member-lists)
2212 (define-key map1 "n" 'ebrowse-repeat-member-search)
2213 (define-key map1 "v" 'ebrowse-goto-visible-member))
2214
2215 (define-key map "f" 'ebrowse-find-member-declaration)
2216 (define-key map "m" 'ebrowse-switch-to-next-member-buffer)
2217 (define-key map "q" 'bury-buffer)
2218 (define-key map "t" 'ebrowse-show-displayed-class-in-tree)
2219 (define-key map "v" 'ebrowse-view-member-declaration)
2220 (define-key map " " 'ebrowse-view-member-definition)
2221 (define-key map "?" 'describe-mode)
2222 (define-key map "\C-i" 'ebrowse-pop-from-member-to-tree-buffer)
2223 (define-key map "\C-l" 'ebrowse-redisplay-member-buffer)
2224 (define-key map "\C-m" 'ebrowse-find-member-definition)))
2225
2226
2227\f
2228;;; Member mode
2229
2230;;###autoload
2231(defun ebrowse-member-mode ()
2232 "Major mode for Ebrowse member buffers.
2233
2234\\{ebrowse-member-mode-map}"
2235 (kill-all-local-variables)
2236 (use-local-map ebrowse-member-mode-map)
2237 (setq major-mode 'ebrowse-member-mode)
2238 (mapcar 'make-local-variable
2239 '(ebrowse--decl-column ;display column
2240 ebrowse--n-columns ;number of short columns
2241 ebrowse--column-width ;width of columns above
2242 ebrowse--show-inherited-flag ;include inherited members?
2243 ebrowse--filters ;public, protected, private
2244 ebrowse--accessor ;vars, functions, friends
2245 ebrowse--displayed-class ;class displayed
2246 ebrowse--long-display-flag ;display with regexps?
2247 ebrowse--source-regexp-flag ;show source regexp?
2248 ebrowse--attributes-flag ;show `virtual' and `inline'
2249 ebrowse--member-list ;list of members displayed
2250 ebrowse--tree ;the class tree
2251 ebrowse--member-mode-strings ;part of mode line
2252 ebrowse--tags-file-name ;
2253 ebrowse--header
2254 ebrowse--tree-obarray
2255 ebrowse--virtual-display-flag
2256 ebrowse--inline-display-flag
2257 ebrowse--const-display-flag
2258 ebrowse--pure-display-flag
be0dbdab 2259 ebrowse--frozen-flag)) ;buffer not automagically reused
8b2affc5
GM
2260 (setq mode-name "Ebrowse-Members"
2261 mode-line-buffer-identification
2262 (propertized-buffer-identification "C++ Members")
be0dbdab
GM
2263 buffer-read-only t
2264 ebrowse--long-display-flag nil
2265 ebrowse--attributes-flag t
2266 ebrowse--show-inherited-flag t
2267 ebrowse--source-regexp-flag nil
2268 ebrowse--filters [0 1 2]
2269 ebrowse--decl-column ebrowse-default-declaration-column
2270 ebrowse--column-width ebrowse-default-column-width
2271 ebrowse--virtual-display-flag nil
2272 ebrowse--inline-display-flag nil
2273 ebrowse--const-display-flag nil
2274 ebrowse--pure-display-flag nil)
2275 (modify-syntax-entry ?_ (char-to-string (char-syntax ?a)))
2276 (run-hooks 'ebrowse-member-mode-hook))
2277
2278
2279\f
2280;;; Member mode mode line
2281
2282(defsubst ebrowse-class-name-displayed-in-member-buffer ()
2283 "Return the name of the class displayed in the member buffer."
2284 (ebrowse-cs-name (ebrowse-ts-class ebrowse--displayed-class)))
2285
2286
2287(defsubst ebrowse-member-list-name ()
2288 "Return a string describing what is displayed in the member buffer."
2289 (get ebrowse--accessor (if (ebrowse-globals-tree-p ebrowse--displayed-class)
2290 'ebrowse-global-title
2291 'ebrowse-title)))
2292
2293
2294(defun ebrowse-update-member-buffer-mode-line ()
2295 "Update the mode line of member buffers."
2296 (let* ((name (when ebrowse--frozen-flag
2297 (concat (ebrowse-class-name-displayed-in-member-buffer)
2298 " ")))
2299 (ident (concat name (ebrowse-member-list-name))))
8b2affc5
GM
2300 (setq mode-line-buffer-identification
2301 (propertized-buffer-identification ident))
be0dbdab
GM
2302 (ebrowse-rename-buffer (if name ident ebrowse-member-buffer-name))
2303 (force-mode-line-update)))
2304
2305
2306;;; Misc member buffer commands
2307
2308(defun ebrowse-freeze-member-buffer ()
2309 "Toggle frozen status of current buffer."
2310 (interactive)
2311 (setq ebrowse--frozen-flag (not ebrowse--frozen-flag))
2312 (ebrowse-redisplay-member-buffer))
2313
2314
2315(defun ebrowse-show-displayed-class-in-tree (arg)
2316 "Show the currently displayed class in the tree window.
2317With prefix ARG, switch to the tree buffer else pop to it."
2318 (interactive "P")
2319 (let ((class-name (ebrowse-class-name-displayed-in-member-buffer)))
2320 (when (ebrowse-pop-from-member-to-tree-buffer arg)
2321 (ebrowse-read-class-name-and-go class-name))))
2322
2323
2324(defun ebrowse-set-member-buffer-column-width ()
2325 "Set the column width of the member display.
2326The new width is read from the minibuffer."
2327 (interactive)
2328 (let ((width (string-to-int
2329 (read-from-minibuffer
2330 (concat "Column width ("
2331 (int-to-string (if ebrowse--long-display-flag
2332 ebrowse--decl-column
2333 ebrowse--column-width))
2334 "): ")))))
2335 (when (plusp width)
2336 (if ebrowse--long-display-flag
2337 (setq ebrowse--decl-column width)
2338 (setq ebrowse--column-width width))
2339 (ebrowse-redisplay-member-buffer))))
2340
2341
2342(defun ebrowse-pop-from-member-to-tree-buffer (arg)
2343 "Pop from a member buffer to the matching tree buffer.
2344Switch to the buffer if prefix ARG. If no tree buffer exists,
2345make one."
2346 (interactive "P")
2347 (let ((buf (or (get-buffer (ebrowse-frozen-tree-buffer-name
2348 ebrowse--tags-file-name))
2349 (get-buffer ebrowse-tree-buffer-name)
2350 (ebrowse-create-tree-buffer ebrowse--tree
2351 ebrowse--tags-file-name
2352 ebrowse--header
2353 ebrowse--tree-obarray
2354 'pop))))
2355 (and buf
2356 (funcall (if arg 'switch-to-buffer 'pop-to-buffer) buf))
2357 buf))
2358
2359
2360\f
2361;;; Switching between member lists
2362
2363(defun ebrowse-display-member-list-for-accessor (accessor)
2364 "Switch the member buffer to display the member list for ACCESSOR."
2365 (setf ebrowse--accessor accessor
2366 ebrowse--member-list (funcall accessor ebrowse--displayed-class))
2367 (ebrowse-redisplay-member-buffer))
2368
2369
2370(defun ebrowse-cyclic-display-next/previous-member-list (incr)
2371 "Switch buffer to INCR'th next/previous list of members."
2372 (let ((index (ebrowse-position ebrowse--accessor
2373 ebrowse-member-list-accessors)))
2374 (setf ebrowse--accessor
2375 (cond ((plusp incr)
2376 (or (nth (1+ index)
2377 ebrowse-member-list-accessors)
2378 (first ebrowse-member-list-accessors)))
2379 ((minusp incr)
2380 (or (and (>= (decf index) 0)
2381 (nth index
2382 ebrowse-member-list-accessors))
2383 (first (last ebrowse-member-list-accessors))))))
2384 (ebrowse-display-member-list-for-accessor ebrowse--accessor)))
2385
2386
2387(defun ebrowse-display-next-member-list ()
2388 "Switch buffer to next member list."
2389 (interactive)
2390 (ebrowse-cyclic-display-next/previous-member-list 1))
2391
2392
2393(defun ebrowse-display-previous-member-list ()
2394 "Switch buffer to previous member list."
2395 (interactive)
2396 (ebrowse-cyclic-display-next/previous-member-list -1))
2397
2398
2399(defun ebrowse-display-function-member-list ()
2400 "Display the list of member functions."
2401 (interactive)
2402 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-member-functions))
2403
2404
2405(defun ebrowse-display-variables-member-list ()
2406 "Display the list of member variables."
2407 (interactive)
2408 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-member-variables))
2409
2410
2411(defun ebrowse-display-static-variables-member-list ()
2412 "Display the list of static member variables."
2413 (interactive)
2414 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-static-variables))
2415
2416
2417(defun ebrowse-display-static-functions-member-list ()
2418 "Display the list of static member functions."
2419 (interactive)
2420 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-static-functions))
2421
2422
2423(defun ebrowse-display-friends-member-list ()
2424 "Display the list of friends."
2425 (interactive)
2426 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-friends))
2427
2428
2429(defun ebrowse-display-types-member-list ()
2430 "Display the list of types."
2431 (interactive)
2432 (ebrowse-display-member-list-for-accessor 'ebrowse-ts-types))
2433
2434
2435\f
2436;;; Filters and other display attributes
2437
2438(defun ebrowse-toggle-member-attributes-display ()
2439 "Toggle display of `virtual', `inline', `const' etc."
2440 (interactive)
2441 (setq ebrowse--attributes-flag (not ebrowse--attributes-flag))
2442 (ebrowse-redisplay-member-buffer))
2443
2444
2445(defun ebrowse-toggle-base-class-display ()
2446 "Toggle the display of members inherited from base classes."
2447 (interactive)
2448 (setf ebrowse--show-inherited-flag (not ebrowse--show-inherited-flag))
2449 (ebrowse-redisplay-member-buffer))
2450
2451
2452(defun ebrowse-toggle-pure-member-filter ()
2453 "Toggle display of pure virtual members."
2454 (interactive)
2455 (setf ebrowse--pure-display-flag (not ebrowse--pure-display-flag))
2456 (ebrowse-redisplay-member-buffer))
2457
2458
2459(defun ebrowse-toggle-const-member-filter ()
2460 "Toggle display of const members."
2461 (interactive)
2462 (setf ebrowse--const-display-flag (not ebrowse--const-display-flag))
2463 (ebrowse-redisplay-member-buffer))
2464
2465
2466(defun ebrowse-toggle-inline-member-filter ()
2467 "Toggle display of inline members."
2468 (interactive)
2469 (setf ebrowse--inline-display-flag (not ebrowse--inline-display-flag))
2470 (ebrowse-redisplay-member-buffer))
2471
2472
2473(defun ebrowse-toggle-virtual-member-filter ()
2474 "Toggle display of virtual members."
2475 (interactive)
2476 (setf ebrowse--virtual-display-flag (not ebrowse--virtual-display-flag))
2477 (ebrowse-redisplay-member-buffer))
2478
2479
2480(defun ebrowse-remove-all-member-filters ()
2481 "Remove all filters."
2482 (interactive)
2483 (dotimes (i 3)
2484 (aset ebrowse--filters i i))
2485 (setq ebrowse--pure-display-flag nil
2486 ebrowse--const-display-flag nil
2487 ebrowse--virtual-display-flag nil
2488 ebrowse--inline-display-flag nil)
2489 (ebrowse-redisplay-member-buffer))
2490
2491
2492(defun ebrowse-toggle-public-member-filter ()
2493 "Toggle visibility of public members."
2494 (interactive)
2495 (ebrowse-set-member-access-visibility 0)
2496 (ebrowse-redisplay-member-buffer))
2497
2498
2499(defun ebrowse-toggle-protected-member-filter ()
2500 "Toggle visibility of protected members."
2501 (interactive)
2502 (ebrowse-set-member-access-visibility 1)
2503 (ebrowse-redisplay-member-buffer))
2504
2505
2506(defun ebrowse-toggle-private-member-filter ()
2507 "Toggle visibility of private members."
2508 (interactive)
2509 (ebrowse-set-member-access-visibility 2)
2510 (ebrowse-redisplay-member-buffer))
2511
2512
2513(defun ebrowse-set-member-access-visibility (vis)
2514 (setf (aref ebrowse--filters vis)
2515 (if (aref ebrowse--filters vis) nil vis)))
2516
2517
2518(defun ebrowse-toggle-long-short-display ()
2519 "Toggle between long and short display form of member buffers."
2520 (interactive)
2521 (setf ebrowse--long-display-flag (not ebrowse--long-display-flag))
2522 (ebrowse-redisplay-member-buffer))
2523
2524
2525(defun ebrowse-toggle-regexp-display ()
2526 "Toggle declaration/definition regular expression display.
2527Used in member buffers showing the long display form."
2528 (interactive)
2529 (setf ebrowse--source-regexp-flag (not ebrowse--source-regexp-flag))
2530 (ebrowse-redisplay-member-buffer))
2531
2532
2533\f
2534;;; Viewing/finding members
2535
2536(defun ebrowse-find-member-definition (&optional prefix)
2537 "Find the file containing a member definition.
2538With PREFIX 4. find file in another window, with prefix 5
2539find file in another frame."
2540 (interactive "p")
2541 (ebrowse-view/find-member-declaration/definition prefix nil t))
2542
2543
2544(defun ebrowse-view-member-definition (prefix)
2545 "View the file containing a member definition.
2546With PREFIX 4. find file in another window, with prefix 5
2547find file in another frame."
2548 (interactive "p")
2549 (ebrowse-view/find-member-declaration/definition prefix t t))
2550
2551
2552(defun ebrowse-find-member-declaration (prefix)
2553 "Find the file containing a member's declaration.
2554With PREFIX 4. find file in another window, with prefix 5
2555find file in another frame."
2556 (interactive "p")
2557 (ebrowse-view/find-member-declaration/definition prefix nil))
2558
2559
2560(defun ebrowse-view-member-declaration (prefix)
2561 "View the file containing a member's declaration.
2562With PREFIX 4. find file in another window, with prefix 5
2563find file in another frame."
2564 (interactive "p")
2565 (ebrowse-view/find-member-declaration/definition prefix t))
2566
2567
2568(defun* ebrowse-view/find-member-declaration/definition
2569 (prefix view &optional definition info header tags-file-name)
2570 "Find or view a member declaration or definition.
2571With PREFIX 4. find file in another window, with prefix 5
2572find file in another frame.
2573DEFINITION non-nil means find the definition, otherwise find the
2574declaration.
2575INFO is a list (TREE ACCESSOR MEMBER) describing the member to
2576search.
183c2d42 2577TAGS-FILE-NAME is the file name of the BROWSE file."
be0dbdab
GM
2578 (unless header
2579 (setq header ebrowse--header))
2580 (unless tags-file-name
2581 (setq tags-file-name ebrowse--tags-file-name))
2582 (let (tree member accessor file on-class
2583 (where (if (= prefix 4) 'other-window
2584 (if (= prefix 5) 'other-frame 'this-window))))
2585 ;; If not given as parameters, get the necessary information
2586 ;; out of the member buffer.
2587 (if info
2588 (setq tree (first info)
2589 accessor (second info)
2590 member (third info))
2591 (multiple-value-setq (tree member on-class)
2592 (ebrowse-member-info-from-point))
2593 (setq accessor ebrowse--accessor))
2594 ;; View/find class if on a line containing a class name.
2595 (when on-class
2596 (return-from ebrowse-view/find-member-declaration/definition
2597 (ebrowse-view/find-file-and-search-pattern
2598 (ebrowse-ts-class tree)
2599 (list ebrowse--header (ebrowse-ts-class tree) nil)
2600 (ebrowse-cs-file (ebrowse-ts-class tree))
2601 tags-file-name view where)))
2602 ;; For some member lists, it doesn't make sense to search for
2603 ;; a definition. If this is requested, silently search for the
2604 ;; declaration.
2605 (when (and definition
2606 (eq accessor 'ebrowse-ts-member-variables))
2607 (setq definition nil))
2608 ;; Construct a suitable `browse' struct for definitions.
2609 (when definition
2610 (setf member (make-ebrowse-ms
2611 :name (ebrowse-ms-name member)
2612 :file (ebrowse-ms-definition-file member)
2613 :pattern (ebrowse-ms-definition-pattern
2614 member)
2615 :flags (ebrowse-ms-flags member)
2616 :point (ebrowse-ms-definition-point
2617 member))))
2618 ;; When no file information in member, use that of the class
2619 (setf file (or (ebrowse-ms-file member)
2620 (if definition
2621 (ebrowse-cs-source-file (ebrowse-ts-class tree))
2622 (ebrowse-cs-file (ebrowse-ts-class tree)))))
2623 ;; When we have no regular expressions in the database the only
2624 ;; indication that the parser hasn't seen a definition/declaration
2625 ;; is that the search start point will be zero.
2626 (if (or (null file) (zerop (ebrowse-ms-point member)))
2627 (if (y-or-n-p (concat "No information about "
2628 (if definition "definition" "declaration")
2629 ". Search for "
2630 (if definition "declaration" "definition")
2631 " of `"
2632 (ebrowse-ms-name member)
2633 "'? "))
2634 (progn
2635 (message nil)
2636 ;; Recurse with new info.
2637 (ebrowse-view/find-member-declaration/definition
2638 prefix view (not definition) info header tags-file-name))
2639 (error "Search canceled"))
2640 ;; Find that thing.
2641 (ebrowse-view/find-file-and-search-pattern
2642 (make-ebrowse-bs :name (ebrowse-ms-name member)
2643 :pattern (ebrowse-ms-pattern member)
2644 :file (ebrowse-ms-file member)
2645 :flags (ebrowse-ms-flags member)
2646 :point (ebrowse-ms-point member))
2647 (list header member accessor)
2648 file
2649 tags-file-name
2650 view
2651 where))))
2652
2653
2654\f
2655;;; Drawing the member buffer
2656
2657(defun ebrowse-redisplay-member-buffer ()
2658 "Force buffer redisplay."
2659 (interactive)
2660 (let ((display-fn (if ebrowse--long-display-flag
2661 'ebrowse-draw-member-long-fn
2662 'ebrowse-draw-member-short-fn)))
2663 (ebrowse-output
2664 (erase-buffer)
2665 ;; Show this class
2666 (ebrowse-draw-member-buffer-class-line)
2667 (funcall display-fn ebrowse--member-list ebrowse--displayed-class)
2668 ;; Show inherited members if corresponding switch is on
2669 (when ebrowse--show-inherited-flag
2670 (dolist (super (ebrowse-base-classes ebrowse--displayed-class))
2671 (goto-char (point-max))
2672 (insert (if (bolp) "\n\n" "\n"))
2673 (ebrowse-draw-member-buffer-class-line super)
2674 (funcall display-fn (funcall ebrowse--accessor super) super)))
2675 (ebrowse-update-member-buffer-mode-line))))
2676
2677
2678(defun ebrowse-draw-member-buffer-class-line (&optional class)
2679 "Display the title line for a class section in the member buffer.
2680CLASS non-nil means display that class' title. Otherwise use
2681the class cursor is on."
2682 (let ((start (point))
2683 (tree (or class ebrowse--displayed-class))
2684 class-name-start
2685 class-name-end)
2686 (insert "class ")
2687 (setq class-name-start (point))
2688 (insert (ebrowse-qualified-class-name (ebrowse-ts-class tree)))
2689 (when (ebrowse-template-p (ebrowse-ts-class tree))
2690 (insert "<>"))
2691 (setq class-name-end (point))
2692 (insert ":\n\n")
2693 (ebrowse-set-face start (point) 'ebrowse-member-class-face)
2694 (add-text-properties
2695 class-name-start class-name-end
2696 '(ebrowse-what class-name
2697 mouse-face highlight
2698 help-echo "mouse-3: menu"))
2699 (put-text-property start class-name-end 'ebrowse-tree tree)))
2700
2701
2702(defun ebrowse-display-member-buffer (list &optional stand-alone class)
2703 "Start point for member buffer creation.
2704LIST is the member list to display. STAND-ALONE non-nil
2705means the member buffer is standalone. CLASS is its class."
2706 (let* ((classes ebrowse--tree-obarray)
2707 (tree ebrowse--tree)
2708 (tags-file-name ebrowse--tags-file-name)
2709 (header ebrowse--header)
2710 temp-buffer-setup-hook
2711 (temp-buffer (get-buffer ebrowse-member-buffer-name)))
2712 ;; Get the class description from the name the cursor
2713 ;; is on if not specified as an argument.
2714 (unless class
2715 (setq class (ebrowse-tree-at-point)))
2716 (with-output-to-temp-buffer ebrowse-member-buffer-name
2717 (save-excursion
2718 (set-buffer standard-output)
2719 ;; If new buffer, set the mode and initial values of locals
2720 (unless temp-buffer
2721 (ebrowse-member-mode))
2722 ;; Set local variables
2723 (setq ebrowse--member-list (funcall list class)
2724 ebrowse--displayed-class class
2725 ebrowse--accessor list
2726 ebrowse--tree-obarray classes
2727 ebrowse--frozen-flag stand-alone
2728 ebrowse--tags-file-name tags-file-name
2729 ebrowse--header header
2730 ebrowse--tree tree
2731 buffer-read-only t)
2732 (ebrowse-redisplay-member-buffer)
2733 (current-buffer)))))
2734
2735
2736(defun ebrowse-member-display-p (member)
2737 "Return t if MEMBER must be displayed under the current filter settings."
2738 (if (and (aref ebrowse--filters (ebrowse-ms-visibility member))
2739 (or (null ebrowse--const-display-flag)
2740 (ebrowse-const-p member))
2741 (or (null ebrowse--inline-display-flag)
2742 (ebrowse-inline-p member))
2743 (or (null ebrowse--pure-display-flag)
2744 (ebrowse-bs-p member))
2745 (or (null ebrowse--virtual-display-flag)
2746 (ebrowse-virtual-p member)))
2747 member))
2748
2749
2750(defun ebrowse-draw-member-attributes (member)
2751 "Insert a string for the attributes of MEMBER."
2752 (insert (if (ebrowse-template-p member) "T" "-")
2753 (if (ebrowse-extern-c-p member) "C" "-")
2754 (if (ebrowse-virtual-p member) "v" "-")
2755 (if (ebrowse-inline-p member) "i" "-")
2756 (if (ebrowse-const-p member) "c" "-")
2757 (if (ebrowse-pure-virtual-p member) "0" "-")
2758 (if (ebrowse-mutable-p member) "m" "-")
2759 (if (ebrowse-explicit-p member) "e" "-")
2760 (if (ebrowse-throw-list-p member) "t" "-")))
2761
2762
2763(defun ebrowse-draw-member-regexp (member-struc)
2764 "Insert a string for the regular expression matching MEMBER-STRUC."
2765 (let ((pattern (if ebrowse--source-regexp-flag
2766 (ebrowse-ms-definition-pattern
2767 member-struc)
2768 (ebrowse-ms-pattern member-struc))))
2769 (cond ((stringp pattern)
2770 (insert (ebrowse-trim-string pattern) "...\n")
2771 (beginning-of-line 0)
2772 (move-to-column (+ 4 ebrowse--decl-column))
2773 (while (re-search-forward "[ \t]+" nil t)
2774 (delete-region (match-beginning 0) (match-end 0))
2775 (insert " "))
2776 (beginning-of-line 2))
2777 (t
2778 (insert "[not recorded or unknown]\n")))))
2779
2780
2781(defun ebrowse-draw-member-long-fn (member-list tree)
2782 "Display member buffer for MEMBER-LIST in long form.
2783TREE is the class tree of MEMBER-LIST."
2784 (dolist (member-struc (mapcar 'ebrowse-member-display-p member-list))
2785 (when member-struc
2786 (let ((name (ebrowse-ms-name member-struc))
2787 (start (point)))
2788 ;; Insert member name truncated to the right length
2789 (insert (substring name
2790 0
2791 (min (length name)
2792 (1- ebrowse--decl-column))))
2793 (add-text-properties
2794 start (point)
2795 `(mouse-face highlight ebrowse-what member-name
2796 ebrowse-member ,member-struc
2797 ebrowse-tree ,tree
2798 help-echo "mouse-2: view definition; mouse-3: menu"))
2799 ;; Display virtual, inline, and const status
2800 (setf start (point))
2801 (indent-to ebrowse--decl-column)
2802 (put-text-property start (point) 'mouse-face nil)
2803 (when ebrowse--attributes-flag
2804 (let ((start (point)))
2805 (insert "<")
2806 (ebrowse-draw-member-attributes member-struc)
2807 (insert ">")
2808 (ebrowse-set-face start (point)
2809 'ebrowse-member-attribute-face)))
2810 (insert " ")
2811 (ebrowse-draw-member-regexp member-struc))))
2812 (insert "\n")
2813 (goto-char (point-min)))
2814
2815
2816(defun ebrowse-draw-member-short-fn (member-list tree)
2817 "Display MEMBER-LIST in short form.
2818TREE is the class tree in which the members are found."
2819 (let ((i 0)
2820 (column-width (+ ebrowse--column-width
2821 (if ebrowse--attributes-flag 12 0))))
2822 ;; Get the number of columns to draw.
2823 (setq ebrowse--n-columns
2824 (max 1 (/ (ebrowse-width-of-drawable-area) column-width)))
2825 (dolist (member (mapcar #'ebrowse-member-display-p member-list))
2826 (when member
2827 (let ((name (ebrowse-ms-name member))
2828 start-of-entry
2829 (start-of-column (point))
2830 start-of-name)
2831 (indent-to (* i column-width))
2832 (put-text-property start-of-column (point) 'mouse-face nil)
2833 (setq start-of-entry (point))
2834 ;; Show various attributes
2835 (when ebrowse--attributes-flag
2836 (insert "<")
2837 (ebrowse-draw-member-attributes member)
2838 (insert "> ")
2839 (ebrowse-set-face start-of-entry (point)
2840 'ebrowse-member-attribute-face))
2841 ;; insert member name truncated to column width
2842 (setq start-of-name (point))
2843 (insert (substring name 0
2844 (min (length name)
2845 (1- ebrowse--column-width))))
2846 ;; set text properties
2847 (add-text-properties
2848 start-of-name (point)
2849 `(ebrowse-what member-name
2850 ebrowse-member ,member
2851 mouse-face highlight
2852 ebrowse-tree ,tree
2853 help-echo "mouse-2: view definition; mouse-3: menu"))
2854 (incf i)
2855 (when (>= i ebrowse--n-columns)
2856 (setf i 0)
2857 (insert "\n")))))
2858 (when (plusp i)
2859 (insert "\n"))
2860 (goto-char (point-min))))
2861
2862
2863\f
2864;;; Killing members from tree
2865
2866(defun ebrowse-member-info-from-point ()
2867 "Ger information about the member at point.
2868The result has the form (TREE MEMBER NULL-P). TREE is the tree
2869we're in, MEMBER is the member we're on. NULL-P is t if MEMBER
2870is nil."
2871 (let ((tree (or (get-text-property (point) 'ebrowse-tree)
2872 (error "No information at point")))
2873 (member (get-text-property (point) 'ebrowse-member)))
2874 (list tree member (null member))))
2875
2876
2877\f
2878;;; Switching member buffer to display a selected member
2879
2880(defun ebrowse-goto-visible-member/all-member-lists (prefix)
2881 "Position cursor on a member read from the minibuffer.
2882With PREFIX, search all members in the tree. Otherwise consider
2883only members visible in the buffer."
2884 (interactive "p")
2885 (ebrowse-ignoring-completion-case
2886 (let* ((completion-list (ebrowse-name/accessor-alist-for-class-members))
2887 (member (completing-read "Goto member: " completion-list nil t))
2888 (accessor (cdr (assoc member completion-list))))
2889 (unless accessor
2890 (error "`%s' not found" member))
2891 (unless (eq accessor ebrowse--accessor)
2892 (setf ebrowse--accessor accessor
2893 ebrowse--member-list (funcall accessor ebrowse--displayed-class))
2894 (ebrowse-redisplay-member-buffer))
2895 (ebrowse-move-point-to-member member))))
2896
2897
2898(defun ebrowse-goto-visible-member (repeat)
2899 "Position point on a member.
2900Read the member's name from the minibuffer. Consider only members
2901visible in the member buffer.
2902REPEAT non-nil means repeat the search that number of times."
2903 (interactive "p")
2904 (ebrowse-ignoring-completion-case
2905 ;; Read member name
2906 (let* ((completion-list (ebrowse-name/accessor-alist-for-visible-members))
2907 (member (completing-read "Goto member: " completion-list nil t)))
2908 (ebrowse-move-point-to-member member repeat))))
2909
2910
2911\f
2912;;; Searching a member in the member buffer
2913
2914(defun ebrowse-repeat-member-search (repeat)
2915 "Repeat the last regular expression search.
2916REPEAT, if specified, says repeat the search REPEAT times."
2917 (interactive "p")
2918 (unless ebrowse--last-regexp
2919 (error "No regular expression remembered"))
2920 ;; Skip over word the point is on
2921 (skip-chars-forward "^ \t\n")
2922 ;; Search for regexp from point
2923 (if (re-search-forward ebrowse--last-regexp nil t repeat)
2924 (progn
2925 (goto-char (match-beginning 0))
2926 (skip-chars-forward " \t\n"))
2927 ;; If not found above, repeat search from buffer start
2928 (goto-char (point-min))
2929 (if (re-search-forward ebrowse--last-regexp nil t)
2930 (progn
2931 (goto-char (match-beginning 0))
2932 (skip-chars-forward " \t\n"))
2933 (error "Not found"))))
2934
2935
2936(defun* ebrowse-move-point-to-member (name &optional count &aux member)
2937 "Set point on member NAME in the member buffer
2938COUNT, if specified, says search the COUNT'th member with the same name."
2939 (goto-char (point-min))
2940 (widen)
2941 (setq member
2942 (substring name 0 (min (length name) (1- ebrowse--column-width)))
2943 ebrowse--last-regexp
2944 (concat "[ \t\n]" (regexp-quote member) "[ \n\t]"))
2945 (if (re-search-forward ebrowse--last-regexp nil t count)
2946 (goto-char (1+ (match-beginning 0)))
2947 (error "Not found")))
2948
2949
2950\f
2951;;; Switching member buffer to another class.
2952
2953(defun ebrowse-switch-member-buffer-to-other-class (title compl-list)
2954 "Switch member buffer to a class read from the minibuffer.
2955Use TITLE as minibuffer prompt.
2956COMPL-LIST is a completion list to use."
2957 (let* ((initial (unless (second compl-list)
2958 (first (first compl-list))))
2959 (class (or (ebrowse-completing-read-value title compl-list initial)
2960 (error "Not found"))))
2961 (setf ebrowse--displayed-class class
2962 ebrowse--member-list (funcall ebrowse--accessor ebrowse--displayed-class))
2963 (ebrowse-redisplay-member-buffer)))
2964
2965
2966(defun ebrowse-switch-member-buffer-to-any-class ()
2967 "Switch member buffer to a class read from the minibuffer."
2968 (interactive)
2969 (ebrowse-switch-member-buffer-to-other-class
2970 "Goto class: " (ebrowse-tree-obarray-as-alist)))
2971
2972
2973(defun ebrowse-switch-member-buffer-to-base-class (arg)
2974 "Switch buffer to ARG'th base class."
2975 (interactive "P")
2976 (let ((supers (or (ebrowse-direct-base-classes ebrowse--displayed-class)
2977 (error "No base classes"))))
2978 (if (and arg (second supers))
2979 (let ((alist (loop for s in supers
2980 collect (cons (ebrowse-qualified-class-name
2981 (ebrowse-ts-class s))
2982 s))))
2983 (ebrowse-switch-member-buffer-to-other-class
2984 "Goto base class: " alist))
2985 (setq ebrowse--displayed-class (first supers)
2986 ebrowse--member-list
2987 (funcall ebrowse--accessor ebrowse--displayed-class))
2988 (ebrowse-redisplay-member-buffer))))
2989
2990(defun ebrowse-switch-member-buffer-to-next-sibling-class (arg)
2991 "Move to ARG'th next sibling."
2992 (interactive "p")
2993 (ebrowse-switch-member-buffer-to-sibling-class arg))
2994
2995
2996(defun ebrowse-switch-member-buffer-to-previous-sibling-class (arg)
2997 "Move to ARG'th previous sibling."
2998 (interactive "p")
2999 (ebrowse-switch-member-buffer-to-sibling-class (- arg)))
3000
3001
3002(defun ebrowse-switch-member-buffer-to-sibling-class (inc)
3003 "Switch member display to nth sibling class.
3004Prefix arg INC specifies which one."
3005 (interactive "p")
3006 (let ((containing-list ebrowse--tree)
3007 index cls
3008 (supers (ebrowse-direct-base-classes ebrowse--displayed-class)))
3009 (flet ((trees-alist (trees)
3010 (loop for tr in trees
3011 collect (cons (ebrowse-cs-name
3012 (ebrowse-ts-class tr)) tr))))
3013 (when supers
3014 (let ((tree (if (second supers)
3015 (ebrowse-completing-read-value
3016 "Relative to base class: "
3017 (trees-alist supers) nil)
3018 (first supers))))
3019 (unless tree (error "Not found"))
3020 (setq containing-list (ebrowse-ts-subclasses tree)))))
3021 (setq index (+ inc (ebrowse-position ebrowse--displayed-class
3022 containing-list)))
3023 (cond ((minusp index) (message "No previous class"))
3024 ((null (nth index containing-list)) (message "No next class")))
3025 (setq index (max 0 (min index (1- (length containing-list)))))
3026 (setq cls (nth index containing-list))
3027 (setf ebrowse--displayed-class cls
3028 ebrowse--member-list (funcall ebrowse--accessor cls))
3029 (ebrowse-redisplay-member-buffer)))
3030
3031
3032(defun ebrowse-switch-member-buffer-to-derived-class (arg)
3033 "Switch member display to nth derived class.
3034Prefix arg ARG says which class should be displayed. Default is
3035the first derived class."
3036 (interactive "P")
3037 (flet ((ebrowse-tree-obarray-as-alist ()
3038 (loop for s in (ebrowse-ts-subclasses
3039 ebrowse--displayed-class)
3040 collect (cons (ebrowse-cs-name
3041 (ebrowse-ts-class s)) s))))
3042 (let ((subs (or (ebrowse-ts-subclasses ebrowse--displayed-class)
3043 (error "No derived classes"))))
3044 (if (and arg (second subs))
3045 (ebrowse-switch-member-buffer-to-other-class
3046 "Goto derived class: " (ebrowse-tree-obarray-as-alist))
3047 (setq ebrowse--displayed-class (first subs)
3048 ebrowse--member-list
3049 (funcall ebrowse--accessor ebrowse--displayed-class))
3050 (ebrowse-redisplay-member-buffer)))))
3051
3052
3053\f
3054;;; Member buffer mouse functions
3055
3056(defun ebrowse-displaying-functions ()
3057 (eq ebrowse--accessor 'ebrowse-ts-member-functions))
3058(defun ebrowse-displaying-variables ()
3059 (eq ebrowse--accessor 'ebrowse-ts-member-variables))
3060(defun ebrowse-displaying-static-functions ()
3061 )
3062(defun ebrowse-displaying-static-variables ()
3063 )
3064(defun ebrowse-displaying-types ()
3065 (eq ebrowse--accessor 'ebrowse-ts-types))
3066(defun ebrowse-displaying-friends ()
3067 (eq ebrowse--accessor 'ebrowse-ts-friends))
3068
3069(easy-menu-define
3070 ebrowse-member-buffer-object-menu ebrowse-member-mode-map
3071 "Object menu for the member buffer itself."
3072 '("Members"
3073 ("Members List"
3074 ["Functions" ebrowse-display-function-member-list
3075 :help "Show the list of member functions"
3076 :style radio
3077 :selected (eq ebrowse--accessor 'ebrowse-ts-member-functions)
3078 :active t]
3079 ["Variables" ebrowse-display-variables-member-list
3080 :help "Show the list of member variables"
3081 :style radio
3082 :selected (eq ebrowse--accessor 'ebrowse-ts-member-variables)
3083 :active t]
3084 ["Static Functions" ebrowse-display-static-functions-member-list
3085 :help "Show the list of static member functions"
3086 :style radio
3087 :selected (eq ebrowse--accessor 'ebrowse-ts-static-functions)
3088 :active t]
3089 ["Static Variables" ebrowse-display-static-variables-member-list
3090 :help "Show the list of static member variables"
3091 :style radio
3092 :selected (eq ebrowse--accessor 'ebrowse-ts-static-variables)
3093 :active t]
3094 ["Types" ebrowse-display-types-member-list
3095 :help "Show the list of nested types"
3096 :style radio
3097 :selected (eq ebrowse--accessor 'ebrowse-ts-types)
3098 :active t]
3099 ["Friends/Defines" ebrowse-display-friends-member-list
3100 :help "Show the list of friends or defines"
3101 :style radio
3102 :selected (eq ebrowse--accessor 'ebrowse-ts-friends)
3103 :active t])
3104 ("Class"
3105 ["Up" ebrowse-switch-member-buffer-to-base-class
3106 :help "Show the base class of this class"
3107 :active t]
3108 ["Down" ebrowse-switch-member-buffer-to-derived-class
3109 :help "Show a derived class class of this class"
3110 :active t]
3111 ["Next Sibling" ebrowse-switch-member-buffer-to-next-sibling-class
3112 :help "Show the next sibling class"
3113 :active t]
3114 ["Previous Sibling" ebrowse-switch-member-buffer-to-previous-sibling-class
3115 :help "Show the previous sibling class"
3116 :active t])
3117 ("Member"
3118 ["Show in Tree" ebrowse-show-displayed-class-in-tree
3119 :help "Show this class in the class tree"
3120 :active t]
3121 ["Find in this Class" ebrowse-goto-visible-member
3122 :help "Search for a member of this class"
3123 :active t]
3124 ["Find in Tree" ebrowse-goto-visible-member/all-member-lists
3125 :help "Search for a member in any class"
3126 :active t])
3127 ("Display"
3128 ["Inherited" ebrowse-toggle-base-class-display
3129 :help "Toggle display of inherited members"
3130 :style toggle
3131 :selected ebrowse--show-inherited-flag
3132 :active t]
3133 ["Attributes" ebrowse-toggle-member-attributes-display
3134 :help "Show member attributes"
3135 :style toggle
3136 :selected ebrowse--attributes-flag
3137 :active t]
3138 ["Long Display" ebrowse-toggle-long-short-display
3139 :help "Toggle the member display format"
3140 :style toggle
3141 :selected ebrowse--long-display-flag
3142 :active t]
3143 ["Column Width" ebrowse-set-member-buffer-column-width
3144 :help "Set the display's column width"
3145 :active t])
3146 ("Filter"
3147 ["Public" ebrowse-toggle-public-member-filter
3148 :help "Toggle the visibility of public members"
3149 :style toggle
3150 :selected (not (aref ebrowse--filters 0))
3151 :active t]
3152 ["Protected" ebrowse-toggle-protected-member-filter
3153 :help "Toggle the visibility of protected members"
3154 :style toggle
3155 :selected (not (aref ebrowse--filters 1))
3156 :active t]
3157 ["Private" ebrowse-toggle-private-member-filter
3158 :help "Toggle the visibility of private members"
3159 :style toggle
3160 :selected (not (aref ebrowse--filters 2))
3161 :active t]
3162 ["Virtual" ebrowse-toggle-virtual-member-filter
3163 :help "Toggle the visibility of virtual members"
3164 :style toggle
3165 :selected ebrowse--virtual-display-flag
3166 :active t]
3167 ["Inline" ebrowse-toggle-inline-member-filter
3168 :help "Toggle the visibility of inline members"
3169 :style toggle
3170 :selected ebrowse--inline-display-flag
3171 :active t]
3172 ["Const" ebrowse-toggle-const-member-filter
3173 :help "Toggle the visibility of const members"
3174 :style toggle
3175 :selected ebrowse--const-display-flag
3176 :active t]
3177 ["Pure" ebrowse-toggle-pure-member-filter
3178 :help "Toggle the visibility of pure virtual members"
3179 :style toggle
3180 :selected ebrowse--pure-display-flag
3181 :active t]
3182 "-----------------"
3183 ["Show all" ebrowse-remove-all-member-filters
3184 :help "Remove any display filters"
3185 :active t])
3186 ("Buffer"
3187 ["Tree" ebrowse-pop-from-member-to-tree-buffer
3188 :help "Pop to the class tree buffer"
3189 :active t]
3190 ["Next Member Buffer" ebrowse-switch-to-next-member-buffer
3191 :help "Switch to the next member buffer of this class tree"
3192 :active t]
3193 ["Freeze" ebrowse-freeze-member-buffer
3194 :help "Freeze (do not reuse) this member buffer"
3195 :active t])))
3196
3197
3198(defun ebrowse-on-class-name ()
3199 "Value is non-nil if point is on a class name."
3200 (eq (get-text-property (point) 'ebrowse-what) 'class-name))
3201
3202
3203(defun ebrowse-on-member-name ()
3204 "Value is non-nil if point is on a member name."
3205 (eq (get-text-property (point) 'ebrowse-what) 'member-name))
3206
3207
3208(easy-menu-define
3209 ebrowse-member-class-name-object-menu ebrowse-member-mode-map
3210 "Object menu for class names in member buffer."
3211 '("Class"
3212 ["Find" ebrowse-find-member-definition
3213 :help "Find this class in the source files"
3214 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
3215 ["View" ebrowse-view-member-definition
3216 :help "View this class in the source files"
3217 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]))
3218
3219
3220(easy-menu-define
3221 ebrowse-member-name-object-menu ebrowse-member-mode-map
3222 "Object menu for member names"
3223 '("Ebrowse"
3224 ["Find Definition" ebrowse-find-member-definition
3225 :help "Find this member's definition in the source files"
3226 :active (ebrowse-on-member-name)]
3227 ["Find Declaration" ebrowse-find-member-declaration
3228 :help "Find this member's declaration in the source files"
3229 :active (ebrowse-on-member-name)]
3230 ["View Definition" ebrowse-view-member-definition
3231 :help "View this member's definition in the source files"
3232 :active (ebrowse-on-member-name)]
3233 ["View Declaration" ebrowse-view-member-declaration
3234 :help "View this member's declaration in the source files"
3235 :active (ebrowse-on-member-name)]))
3236
3237
3238(defun ebrowse-member-mouse-3 (event)
3239 "Handle `mouse-3' events in member buffers.
3240EVENT is the mouse event."
3241 (interactive "e")
3242 (mouse-set-point event)
3243 (case (event-click-count event)
3244 (2 (ebrowse-find-member-definition))
3245 (1 (case (get-text-property (posn-point (event-start event))
3246 'ebrowse-what)
3247 (member-name
3248 (ebrowse-popup-menu ebrowse-member-name-object-menu event))
3249 (class-name
3250 (ebrowse-popup-menu ebrowse-member-class-name-object-menu event))
3251 (t
3252 (ebrowse-popup-menu ebrowse-member-buffer-object-menu event))))))
3253
3254
3255(defun ebrowse-member-mouse-2 (event)
3256 "Handle `mouse-2' events in member buffers.
3257EVENT is the mouse event."
3258 (interactive "e")
3259 (mouse-set-point event)
3260 (case (event-click-count event)
3261 (2 (ebrowse-find-member-definition))
3262 (1 (case (get-text-property (posn-point (event-start event))
3263 'ebrowse-what)
3264 (member-name
3265 (ebrowse-view-member-definition 0))))))
3266
3267
3268\f
3269;;; Tags view/find
3270
3271(defun ebrowse-class-alist-for-member (tree-header name)
3272 "Return information about a member in a class tree.
3273TREE-HEADER is the header structure of the class tree.
3274NAME is the name of the member.
3275Value is an alist of elements (CLASS-NAME . (CLASS LIST NAME)),
3276where each element describes one occurrence of member NAME in the tree.
3277CLASS-NAME is the qualified name of the class in which the
3278member was found. The CDR of the acons is described in function
3279`ebrowse-class/index/member-for-member'."
3280 (let ((table (ebrowse-member-table tree-header))
3281 known-classes
3282 alist)
3283 (when name
3284 (dolist (info (gethash name table) alist)
3285 (unless (memq (first info) known-classes)
3286 (setf alist (acons (ebrowse-qualified-class-name
3287 (ebrowse-ts-class (first info)))
3288 info alist)
3289 known-classes (cons (first info) known-classes)))))))
3290
3291
3292(defun ebrowse-choose-tree ()
3293 "Choose a class tree to use.
3294If there's more than one class tree loaded, let the user choose
3295the one he wants. Value is (TREE HEADER BUFFER), with TREE being
3296the class tree, HEADER the header structure of the tree, and BUFFER
3297being the tree or member buffer containing the tree."
3298 (let* ((buffer (ebrowse-choose-from-browser-buffers)))
3299 (if buffer (list (ebrowse-value-in-buffer 'ebrowse--tree buffer)
3300 (ebrowse-value-in-buffer 'ebrowse--header buffer)
3301 buffer))))
3302
3303
3304(defun ebrowse-tags-read-name (header prompt)
3305 "Read a C++ identifier from the minibuffer.
3306HEADER is the `ebrowse-hs' structure of the class tree.
3307Prompt with PROMPT. Insert into the minibuffer a C++ identifier read
3308from point as default. Value is a list (CLASS-NAME MEMBER-NAME)."
3309 (save-excursion
3310 (let* (start member-info (members (ebrowse-member-table header)))
3311 (multiple-value-bind (class-name member-name)
3312 (ebrowse-tags-read-member+class-name)
3313 (unless member-name
3314 (error "No member name at point"))
3315 (if members
3316 (let* ((alist (ebrowse-hash-table-to-alist members))
3317 (name (ebrowse-ignoring-completion-case
3318 (completing-read prompt alist nil nil member-name)))
3319 (completion-result (try-completion name alist)))
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)))
3558 (alist (ebrowse-hash-table-to-alist files))
3559 (file (completing-read "List members in file: " alist nil t))
3560 (header (ebrowse-value-in-buffer 'ebrowse--header buffer))
3561 temp-buffer-setup-hook
3562 (members (ebrowse-member-table header)))
3563 (with-output-to-temp-buffer (concat "*Members in file " file "*")
3564 (set-buffer standard-output)
3565 (maphash
3566 #'(lambda (member-name list)
3567 (loop for info in list
3568 as member = (third info)
3569 as class = (ebrowse-ts-class (first info))
3570 when (or (and (null (ebrowse-ms-file member))
3571 (string= (ebrowse-cs-file class) file))
3572 (string= file (ebrowse-ms-file member)))
3573 do (ebrowse-draw-file-member-info info "decl.")
3574 when (or (and (null (ebrowse-ms-definition-file member))
3575 (string= (ebrowse-cs-source-file class) file))
3576 (string= file (ebrowse-ms-definition-file member)))
3577 do (ebrowse-draw-file-member-info info "defn.")))
3578 members))))
3579
3580
3581(defun* ebrowse-draw-file-member-info (info &optional (kind ""))
3582 "Display a line in an the members per file info buffer.
3583INFO describes the member. It has the form (TREE ACCESSOR MEMBER).
3584TREE is the class of the member to display.
3585ACCESSOR is the accessor symbol of its member list.
3586MEMBER is the member structure.
3587KIND is a an additional string printed in the buffer."
3588 (let* ((tree (first info))
3589 (globals-p (ebrowse-globals-tree-p tree)))
3590 (unless globals-p
3591 (insert (ebrowse-cs-name (ebrowse-ts-class tree))))
3592 (insert "::" (ebrowse-ms-name (third info)))
3593 (indent-to 40)
3594 (insert kind)
3595 (indent-to 50)
3596 (insert (case (second info)
3597 ('ebrowse-ts-member-functions "member function")
3598 ('ebrowse-ts-member-variables "member variable")
3599 ('ebrowse-ts-static-functions "static function")
3600 ('ebrowse-ts-static-variables "static variable")
3601 ('ebrowse-ts-friends (if globals-p "define" "friend"))
3602 ('ebrowse-ts-types "type")
3603 (t "unknown"))
3604 "\n")))
3605
3606(defvar ebrowse-last-completion nil
3607 "Text inserted by the last completion operation.")
3608
3609
3610(defvar ebrowse-last-completion-start nil
3611 "String which was the basis for the last completion operation.")
3612
3613
3614(defvar ebrowse-last-completion-location nil
3615 "Buffer position at which the last completion operation was initiated.")
3616
3617
3618(defvar ebrowse-last-completion-obarray nil
3619 "Member used in last completion operation.")
3620
3621
3622(make-variable-buffer-local 'ebrowse-last-completion-obarray)
3623(make-variable-buffer-local 'ebrowse-last-completion-location)
3624(make-variable-buffer-local 'ebrowse-last-completion)
3625(make-variable-buffer-local 'ebrowse-last-completion-start)
3626
3627
3628\f
3629(defun ebrowse-some-member-table ()
3630 "Return a hash table containing all member of a tree.
3631If there's only one tree loaded, use that. Otherwise let the
3632use choose a tree."
3633 (let* ((buffers (ebrowse-known-class-trees-buffer-list))
3634 (buffer (cond ((and (first buffers) (not (second buffers)))
3635 (first buffers))
3636 (t (or (ebrowse-electric-choose-tree)
3637 (error "No tree buffer")))))
3638 (header (ebrowse-value-in-buffer 'ebrowse--header buffer)))
3639 (ebrowse-member-table header)))
3640
3641
3642(defun ebrowse-hash-table-to-alist (table)
3643 "Return an alist holding all key/value pairs of hash table TABLE."
3644 (let ((list))
3645 (maphash #'(lambda (key value)
3646 (setq list (cons (cons key value) list)))
3647 table)
3648 list))
3649
3650
3651(defun ebrowse-cyclic-successor-in-string-list (string list)
3652 "Return the item following STRING in LIST.
3653If STRING is the last element, return the first element as successor."
3654 (or (nth (1+ (ebrowse-position string list 'string=)) list)
3655 (first list)))
3656
3657\f
3658;;; Symbol completion
3659
3660;;;###autoload
3661(defun* ebrowse-tags-complete-symbol (prefix)
3662 "Perform completion on the C++ symbol preceding point.
3663A second call of this function without changing point inserts the next match.
3664A call with prefix PREFIX reads the symbol to insert from the minibuffer with
3665completion."
3666 (interactive "P")
3667 (let* ((end (point))
3668 (begin (save-excursion (skip-chars-backward "a-zA-Z_0-9") (point)))
3669 (pattern (buffer-substring begin end))
3670 list completion)
3671 (cond
3672 ;; With prefix, read name from minibuffer with completion.
3673 (prefix
3674 (let* ((members (ebrowse-some-member-table))
3675 (alist (ebrowse-hash-table-to-alist members))
3676 (completion (completing-read "Insert member: "
3677 alist nil t pattern)))
3678 (when completion
3679 (setf ebrowse-last-completion-location nil)
3680 (delete-region begin end)
3681 (insert completion))))
3682 ;; If this function is called at the same point the last
3683 ;; expansion ended, insert the next expansion.
3684 ((eq (point) ebrowse-last-completion-location)
3685 (setf list (all-completions ebrowse-last-completion-start
3686 ebrowse-last-completion-obarray)
3687 completion (ebrowse-cyclic-successor-in-string-list
3688 ebrowse-last-completion list))
3689 (cond ((null completion)
3690 (error "No completion"))
3691 ((string= completion pattern)
3692 (error "No further completion"))
3693 (t
3694 (delete-region begin end)
3695 (insert completion)
3696 (setf ebrowse-last-completion completion
3697 ebrowse-last-completion-location (point)))))
3698 ;; First time the function is called at some position in the
3699 ;; buffer: Start new completion.
3700 (t
3701 (let* ((members (ebrowse-some-member-table))
3702 (completion (first (all-completions pattern members nil))))
3703 (cond ((eq completion t))
3704 ((null completion)
3705 (error "Can't find completion for `%s'" pattern))
3706 (t
3707 (delete-region begin end)
3708 (insert completion)
3709
3710 (setf ebrowse-last-completion-location (point)
3711 ebrowse-last-completion-start pattern
3712 ebrowse-last-completion completion
3713 ebrowse-last-completion-obarray members))))))))
3714
3715\f
3716;;; Tags query replace & search
3717
3718(defvar ebrowse-tags-loop-form ()
3719 "Form for `ebrowse-loop-continue'.
3720Evaluated for each file in the tree. If it returns nil, proceed
3721with the next file.")
3722
3723(defvar ebrowse-tags-next-file-list ()
3724 "A list of files to be processed.")
3725
3726
3727(defvar ebrowse-tags-next-file-path nil
3728 "The path relative to which files have to be searched.")
3729
3730
3731(defvar ebrowse-tags-loop-last-file nil
3732 "The last file visited via `ebrowse-tags-loop'.")
3733
3734
3735(defun ebrowse-tags-next-file (&optional initialize tree-buffer)
3736 "Select next file among files in current tag table.
3737Non-nil argument INITIALIZE (prefix arg, if interactive) initializes
3738to the beginning of the list of files in the tag table.
3739TREE-BUFFER specifies the class tree we operate on."
3740 (interactive "P")
3741 ;; Call with INITIALIZE non-nil initializes the files list.
3742 ;; If more than one tree buffer is loaded, let the user choose
3743 ;; on which tree (s)he wants to operate.
3744 (when initialize
3745 (let ((buffer (or tree-buffer (ebrowse-choose-from-browser-buffers))))
3746 (save-excursion
3747 (set-buffer buffer)
3748 (setq ebrowse-tags-next-file-list
3749 (ebrowse-files-list (ebrowse-marked-classes-p))
3750 ebrowse-tags-loop-last-file
3751 nil
3752 ebrowse-tags-next-file-path
3753 (file-name-directory ebrowse--tags-file-name)))))
3754 ;; End of the loop if the stack of files is empty.
3755 (unless ebrowse-tags-next-file-list
3756 (error "All files processed"))
3757 ;; ebrowse-tags-loop-last-file is the last file that was visited due
3758 ;; to a call to BROWSE-LOOP (see below). If that file is still
3759 ;; in memory, and it wasn't modified, throw its buffer away to
3760 ;; prevent cluttering up the buffer list.
3761 (when ebrowse-tags-loop-last-file
3762 (let ((buffer (get-file-buffer ebrowse-tags-loop-last-file)))
3763 (when (and buffer
3764 (not (buffer-modified-p buffer)))
3765 (kill-buffer buffer))))
3766 ;; Remember this buffer file name for later deletion, if it
3767 ;; wasn't visited by other means.
3768 (let ((file (expand-file-name (car ebrowse-tags-next-file-list)
3769 ebrowse-tags-next-file-path)))
3770 (setq ebrowse-tags-loop-last-file (if (get-file-buffer file) nil file))
3771 ;; Find the file and pop the file list. Pop has to be done
3772 ;; before the file is loaded because FIND-FILE might encounter
3773 ;; an error, and we want to be able to proceed with the next
3774 ;; file in this case.
3775 (pop ebrowse-tags-next-file-list)
3776 (find-file file)))
3777
3778
3779;;;###autoload
3780(defun ebrowse-tags-loop-continue (&optional first-time tree-buffer)
3781 "Repeat last operation on files in tree.
3782FIRST-TIME non-nil means this is not a repetition, but the first time.
3783TREE-BUFFER if indirectly specifies which files to loop over."
3784 (interactive)
3785 (when first-time
3786 (ebrowse-tags-next-file first-time tree-buffer)
3787 (goto-char (point-min)))
3788 (while (not (eval ebrowse-tags-loop-form))
3789 (ebrowse-tags-next-file)
3790 (message "Scanning file `%s'..." buffer-file-name)
3791 (goto-char (point-min))))
3792
3793
3794;;###autoload
3795(defun ebrowse-tags-search (regexp)
3796 "Search for REGEXP in all files in a tree.
3797If marked classes exist, process marked classes, only.
3798If regular expression is nil, repeat last search."
3799 (interactive "sTree search (regexp): ")
3800 (if (and (string= regexp "")
3801 (eq (car ebrowse-tags-loop-form) 're-search-forward))
3802 (ebrowse-tags-loop-continue)
3803 (setq ebrowse-tags-loop-form (list 're-search-forward regexp nil t))
3804 (ebrowse-tags-loop-continue 'first-time)))
3805
3806
3807;;;###autoload
3808(defun ebrowse-tags-query-replace (from to)
3809 "Query replace FROM with TO in all files of a class tree.
3810With prefix arg, process files of marked classes only."
3811 (interactive
3812 "sTree query replace (regexp): \nsTree query replace %s by: ")
3813 (setq ebrowse-tags-loop-form
3814 (list 'and (list 'save-excursion
3815 (list 're-search-forward from nil t))
8c8f9bc1 3816 (list 'not (list 'perform-replace from to t t nil))))
be0dbdab
GM
3817 (ebrowse-tags-loop-continue 'first-time))
3818
3819
23b809c2 3820;;;###autoload
be0dbdab
GM
3821(defun ebrowse-tags-search-member-use (&optional fix-name)
3822 "Search for call sites of a member.
3823If FIX-NAME is specified, search uses of that member.
3824Otherwise, read a member name from the minibuffer.
3825Searches in all files mentioned in a class tree for something that
3826looks like a function call to the member."
3827 (interactive)
3828 ;; Choose the tree to use if there is more than one.
3829 (multiple-value-bind (tree header tree-buffer)
3830 (ebrowse-choose-tree)
3831 (unless tree
3832 (error "No class tree"))
3833 ;; Get the member name NAME (class-name is ignored).
3834 (let ((name fix-name) class-name regexp)
3835 (unless name
3836 (multiple-value-setq (class-name name)
3837 (ebrowse-tags-read-name header "Find calls of: ")))
3838 ;; Set tags loop form to search for member and begin loop.
3839 (setq regexp (concat "\\<" name "[ \t]*(")
3840 ebrowse-tags-loop-form (list 're-search-forward regexp nil t))
3841 (ebrowse-tags-loop-continue 'first-time tree-buffer))))
3842
3843
3844\f
3845;;; Tags position management
3846
3847;;; Structures of this kind are the elements of the position stack.
3848
3849(defstruct (ebrowse-position (:type vector) :named)
3850 file-name ; in which file
3851 point ; point in file
3852 target ; t if target of a jump
3853 info) ; (CLASS FUNC MEMBER) jumped to
3854
3855
3856(defvar ebrowse-position-stack ()
3857 "Stack of `ebrowse-position' structured.")
3858
3859
3860(defvar ebrowse-position-index 0
3861 "Current position in position stack.")
3862
3863
3864(defun ebrowse-position-name (position)
3865 "Return an identifying string for POSITION.
3866The string is printed in the electric position list buffer."
3867 (let ((info (ebrowse-position-info position)))
3868 (concat (if (ebrowse-position-target position) "at " "to ")
3869 (ebrowse-cs-name (ebrowse-ts-class (first info)))
3870 "::" (ebrowse-ms-name (third info)))))
3871
3872
3873(defun ebrowse-view/find-position (position &optional view)
3874 "Position point on POSITION.
3875If VIEW is non-nil, view the position, otherwise find it."
3876 (cond ((not view)
3877 (find-file (ebrowse-position-file-name position))
3878 (goto-char (ebrowse-position-point position)))
3879 (t
3880 (unwind-protect
3881 (progn
3882 (push (function
3883 (lambda ()
3884 (goto-char (ebrowse-position-point position))))
3885 view-mode-hook)
3886 (view-file (ebrowse-position-file-name position)))
3887 (pop view-mode-hook)))))
3888
3889
3890(defun ebrowse-push-position (marker info &optional target)
3891 "Push current position on position stack.
3892MARKER is the marker to remember as position.
3893INFO is a list (CLASS FUNC MEMBER) specifying what we jumped to.
3894TARGET non-nil means we performed a jump.
3895Positions in buffers that have no file names are not saved."
3896 (when (buffer-file-name (marker-buffer marker))
3897 (let ((too-much (- (length ebrowse-position-stack)
3898 ebrowse-max-positions)))
3899 ;; Do not let the stack grow to infinity.
3900 (when (plusp too-much)
3901 (setq ebrowse-position-stack
3902 (butlast ebrowse-position-stack too-much)))
3903 ;; Push the position.
3904 (push (make-ebrowse-position
3905 :file-name (buffer-file-name (marker-buffer marker))
3906 :point (marker-position marker)
3907 :target target
3908 :info info)
3909 ebrowse-position-stack))))
3910
3911
3912(defun ebrowse-move-in-position-stack (increment)
3913 "Move by INCREMENT in the position stack."
3914 (let ((length (length ebrowse-position-stack)))
3915 (when (zerop length)
3916 (error "No positions remembered"))
3917 (setq ebrowse-position-index
3918 (mod (+ increment ebrowse-position-index) length))
3919 (message "Position %d of %d " ebrowse-position-index length)
3920 (ebrowse-view/find-position (nth ebrowse-position-index
3921 ebrowse-position-stack))))
3922
3923
23b809c2 3924;;;###autoload
be0dbdab
GM
3925(defun ebrowse-back-in-position-stack (arg)
3926 "Move backward in the position stack.
3927Prefix arg ARG says how much."
3928 (interactive "p")
3929 (ebrowse-move-in-position-stack (max 1 arg)))
3930
3931
23b809c2 3932;;;###autoload
be0dbdab
GM
3933(defun ebrowse-forward-in-position-stack (arg)
3934 "Move forward in the position stack.
3935Prefix arg ARG says how much."
3936 (interactive "p")
3937 (ebrowse-move-in-position-stack (min -1 (- arg))))
3938
3939
3940\f
3941;;; Electric position list
3942
3943(defvar ebrowse-electric-position-mode-map ()
3944 "Keymap used in electric position stack window.")
3945
3946
3947(defvar ebrowse-electric-position-mode-hook nil
3948 "If non-nil, its value is called by ebrowse-electric-position-mode.")
3949
3950
3951(unless ebrowse-electric-position-mode-map
3952 (let ((map (make-keymap))
3953 (submap (make-keymap)))
3954 (setq ebrowse-electric-position-mode-map map)
3955 (fillarray (car (cdr map)) 'ebrowse-electric-position-undefined)
3956 (fillarray (car (cdr submap)) 'ebrowse-electric-position-undefined)
3957 (define-key map "\e" submap)
3958 (define-key map "\C-z" 'suspend-emacs)
3959 (define-key map "\C-h" 'Helper-help)
3960 (define-key map "?" 'Helper-describe-bindings)
3961 (define-key map "\C-c" nil)
3962 (define-key map "\C-c\C-c" 'ebrowse-electric-position-quit)
3963 (define-key map "q" 'ebrowse-electric-position-quit)
3964 (define-key map " " 'ebrowse-electric-select-position)
3965 (define-key map "\C-l" 'recenter)
3966 (define-key map "\C-u" 'universal-argument)
3967 (define-key map "\C-p" 'previous-line)
3968 (define-key map "\C-n" 'next-line)
3969 (define-key map "p" 'previous-line)
3970 (define-key map "n" 'next-line)
3971 (define-key map "v" 'ebrowse-electric-view-position)
3972 (define-key map "\C-v" 'scroll-up)
3973 (define-key map "\ev" 'scroll-down)
3974 (define-key map "\e\C-v" 'scroll-other-window)
3975 (define-key map "\e>" 'end-of-buffer)
3976 (define-key map "\e<" 'beginning-of-buffer)
3977 (define-key map "\e>" 'end-of-buffer)))
3978
3979(put 'ebrowse-electric-position-mode 'mode-class 'special)
3980(put 'ebrowse-electric-position-undefined 'suppress-keymap t)
3981
3982
3983(defun ebrowse-electric-position-mode ()
3984 "Mode for electric position buffers.
3985Runs the hook `ebrowse-electric-position-mode-hook'."
3986 (kill-all-local-variables)
3987 (use-local-map ebrowse-electric-position-mode-map)
3988 (setq mode-name "Electric Position Menu"
3989 mode-line-buffer-identification "Electric Position Menu")
3990 (when (memq 'mode-name mode-line-format)
3991 (setq mode-line-format (copy-sequence mode-line-format))
3992 (setcar (memq 'mode-name mode-line-format) "Positions"))
3993 (make-local-variable 'Helper-return-blurb)
3994 (setq Helper-return-blurb "return to buffer editing"
3995 truncate-lines t
3996 buffer-read-only t
3997 major-mode 'ebrowse-electric-position-mode)
3998 (run-hooks 'ebrowse-electric-position-mode-hook))
3999
4000
4001(defun ebrowse-draw-position-buffer ()
4002 "Display positions in buffer *Positions*."
4003 (set-buffer (get-buffer-create "*Positions*"))
4004 (setq buffer-read-only nil)
4005 (erase-buffer)
4006 (insert "File Point Description\n"
4007 "---- ----- -----------\n")
4008 (dolist (position ebrowse-position-stack)
4009 (insert (file-name-nondirectory (ebrowse-position-file-name position)))
4010 (indent-to 15)
4011 (insert (int-to-string (ebrowse-position-point position)))
4012 (indent-to 22)
4013 (insert (ebrowse-position-name position) "\n"))
4014 (setq buffer-read-only t))
4015
4016
23b809c2 4017;;;###autoload
be0dbdab
GM
4018(defun ebrowse-electric-position-menu ()
4019 "List positions in the position stack in an electric buffer."
4020 (interactive)
4021 (unless ebrowse-position-stack
4022 (error "No positions remembered"))
4023 (let (select buffer window)
4024 (save-window-excursion
4025 (save-window-excursion (ebrowse-draw-position-buffer))
4026 (setq window (Electric-pop-up-window "*Positions*")
4027 buffer (window-buffer window))
4028 (shrink-window-if-larger-than-buffer window)
4029 (unwind-protect
4030 (progn
4031 (set-buffer buffer)
4032 (ebrowse-electric-position-mode)
4033 (setq select
4034 (catch 'ebrowse-electric-select-position
4035 (message "<<< Press Space to bury the list >>>")
4036 (let ((first (progn (goto-char (point-min))
4037 (forward-line 2)
4038 (point)))
4039 (last (progn (goto-char (point-max))
4040 (forward-line -1)
4041 (point)))
4042 (goal-column 0))
4043 (goto-char first)
4044 (Electric-command-loop 'ebrowse-electric-select-position
4045 nil t
4046 'ebrowse-electric-position-looper
4047 (cons first last))))))
4048 (set-buffer buffer)
4049 (bury-buffer buffer)
4050 (message nil)))
4051 (when select
4052 (set-buffer buffer)
4053 (ebrowse-electric-find-position select))
4054 (kill-buffer buffer)))
4055
4056
4057(defun ebrowse-electric-position-looper (state condition)
4058 "Prevent moving point on invalid lines.
4059Called from `Electric-command-loop'. See there for the meaning
4060of STATE and CONDITION."
4061 (cond ((and condition
4062 (not (memq (car condition) '(buffer-read-only
4063 end-of-buffer
4064 beginning-of-buffer))))
4065 (signal (car condition) (cdr condition)))
4066 ((< (point) (car state))
4067 (goto-char (point-min))
4068 (forward-line 2))
4069 ((> (point) (cdr state))
4070 (goto-char (point-max))
4071 (forward-line -1)
4072 (if (pos-visible-in-window-p (point-max))
4073 (recenter -1)))))
4074
4075
4076(defun ebrowse-electric-position-undefined ()
4077 "Function called for undefined keys."
4078 (interactive)
4079 (message "Type C-h for help, ? for commands, q to quit, Space to execute")
4080 (sit-for 4))
4081
4082
4083(defun ebrowse-electric-position-quit ()
4084 "Leave the electric position list."
4085 (interactive)
4086 (throw 'ebrowse-electric-select-position nil))
4087
4088
4089(defun ebrowse-electric-select-position ()
4090 "Select a position from the list."
4091 (interactive)
4092 (throw 'ebrowse-electric-select-position (point)))
4093
4094
4095(defun ebrowse-electric-find-position (point &optional view)
4096 "View/find what is described by the line at POINT.
4097If VIEW is non-nil, view else find source files."
4098 (let ((index (- (count-lines (point-min) point) 2)))
4099 (ebrowse-view/find-position (nth index
4100 ebrowse-position-stack) view)))
4101
4102
4103(defun ebrowse-electric-view-position ()
4104 "View the position described by the line point is in."
4105 (interactive)
4106 (ebrowse-electric-find-position (point) t))
4107
4108
4109\f
4110;;; Saving trees to disk
4111
4112(defun ebrowse-write-file-hook-fn ()
4113 "Write current buffer as a class tree.
4114Installed on `local-write-file-hooks'."
4115 (ebrowse-save-tree)
4116 t)
4117
4118
23b809c2 4119;;;###autoload
be0dbdab
GM
4120(defun ebrowse-save-tree ()
4121 "Save current tree in same file it was loaded from."
4122 (interactive)
4123 (ebrowse-save-tree-as (or buffer-file-name ebrowse--tags-file-name)))
4124
4125
4126;;;###autoload
4127(defun ebrowse-save-tree-as (&optional file-name)
4128 "Write the current tree data structure to a file.
4129Read the file name from the minibuffer if interactive.
4130Otherwise, FILE-NAME specifies the file to save the tree in."
4131 (interactive "FSave tree as: ")
4132 (let ((temp-buffer (get-buffer-create "*Tree Output"))
4133 (old-standard-output standard-output)
4134 (header (copy-ebrowse-hs ebrowse--header))
4135 (tree ebrowse--tree))
4136 (unwind-protect
4137 (save-excursion
4138 (set-buffer (setq standard-output temp-buffer))
4139 (erase-buffer)
4140 (setf (ebrowse-hs-member-table header) nil)
4141 (insert (prin1-to-string header) " ")
4142 (mapcar 'ebrowse-save-class tree)
4143 (write-file file-name)
4144 (message "Tree written to file `%s'" file-name))
4145 (kill-buffer temp-buffer)
4146 (set-buffer-modified-p nil)
4147 (ebrowse-update-tree-buffer-mode-line)
4148 (setq standard-output old-standard-output))))
4149
4150
4151(defun ebrowse-save-class (class)
4152 "Write single class CLASS to current buffer."
4153 (message "%s..." (ebrowse-cs-name (ebrowse-ts-class class)))
4154 (insert "[ebrowse-ts ")
4155 (prin1 (ebrowse-ts-class class)) ;class name
4156 (insert "(") ;list of subclasses
4157 (mapcar 'ebrowse-save-class (ebrowse-ts-subclasses class))
4158 (insert ")")
4159 (dolist (func ebrowse-member-list-accessors)
4160 (prin1 (funcall func class))
4161 (insert "\n"))
4162 (insert "()") ;base-classes slot
4163 (prin1 (ebrowse-ts-mark class))
4164 (insert "]\n"))
4165
4166
4167\f
4168;;; Statistics
4169
23b809c2 4170;;;###autoload
be0dbdab
GM
4171(defun ebrowse-statistics ()
4172 "Display statistics for a class tree."
4173 (interactive)
4174 (let ((tree-file (buffer-file-name))
4175 temp-buffer-setup-hook)
4176 (with-output-to-temp-buffer "*Tree Statistics*"
4177 (multiple-value-bind (classes member-functions member-variables
4178 static-functions static-variables)
4179 (ebrowse-gather-statistics)
4180 (set-buffer standard-output)
4181 (erase-buffer)
4182 (insert "STATISTICS FOR TREE " (or tree-file "unknown") ":\n\n")
4183 (ebrowse-print-statistics-line "Number of classes:" classes)
4184 (ebrowse-print-statistics-line "Number of member functions:"
4185 member-functions)
4186 (ebrowse-print-statistics-line "Number of member variables:"
4187 member-variables)
4188 (ebrowse-print-statistics-line "Number of static functions:"
4189 static-functions)
4190 (ebrowse-print-statistics-line "Number of static variables:"
4191 static-variables)))))
4192
4193
4194(defun ebrowse-print-statistics-line (title value)
4195 "Print a line in the statistics buffer.
4196TITLE is the title of the line, VALUE is number to be printed
4197after that."
4198 (insert title)
4199 (indent-to 40)
4200 (insert (format "%d\n" value)))
4201
4202
4203(defun ebrowse-gather-statistics ()
4204 "Return statistics for a class tree.
4205The result is a list (NUMBER-OF-CLASSES NUMBER-OF-MEMBER-FUNCTIONS
4206NUMBER-OF-INSTANCE-VARIABLES NUMBER-OF-STATIC-FUNCTIONS
4207NUMBER-OF-STATIC-VARIABLES:"
4208 (let ((classes 0) (member-functions 0) (member-variables 0)
4209 (static-functions 0) (static-variables 0))
4210 (ebrowse-for-all-trees (tree ebrowse--tree-obarray)
4211 (incf classes)
4212 (incf member-functions (length (ebrowse-ts-member-functions tree)))
4213 (incf member-variables (length (ebrowse-ts-member-variables tree)))
4214 (incf static-functions (length (ebrowse-ts-static-functions tree)))
4215 (incf static-variables (length (ebrowse-ts-static-variables tree))))
4216 (list classes member-functions member-variables
4217 static-functions static-variables)))
4218
4219
4220\f
4221;;; Global key bindings
4222
4223;;; The following can be used to bind key sequences starting with
4224;;; prefix `\C-cb' to browse commands.
4225
4226(defvar ebrowse-global-map nil
4227 "*Keymap for Ebrowse commands.")
4228
4229
4230(defvar ebrowse-global-prefix-key "\C-cb"
4231 "Prefix key for Ebrowse commands.")
4232
4233
4234(defvar ebrowse-global-submap-4 nil
4235 "Keymap used for `ebrowse-global-prefix' followed by `4'.")
4236
4237
4238(defvar ebrowse-global-submap-5 nil
4239 "Keymap used for `ebrowse-global-prefix' followed by `5'.")
4240
4241
4242(unless ebrowse-global-map
4243 (setq ebrowse-global-map (make-sparse-keymap))
4244 (setq ebrowse-global-submap-4 (make-sparse-keymap))
4245 (setq ebrowse-global-submap-5 (make-sparse-keymap))
4246 (define-key ebrowse-global-map "a" 'ebrowse-tags-apropos)
4247 (define-key ebrowse-global-map "b" 'ebrowse-pop-to-browser-buffer)
4248 (define-key ebrowse-global-map "-" 'ebrowse-back-in-position-stack)
4249 (define-key ebrowse-global-map "+" 'ebrowse-forward-in-position-stack)
4250 (define-key ebrowse-global-map "l" 'ebrowse-tags-list-members-in-file)
4251 (define-key ebrowse-global-map "m" 'ebrowse-tags-display-member-buffer)
4252 (define-key ebrowse-global-map "n" 'ebrowse-tags-next-file)
4253 (define-key ebrowse-global-map "p" 'ebrowse-electric-position-menu)
4254 (define-key ebrowse-global-map "s" 'ebrowse-tags-search)
4255 (define-key ebrowse-global-map "u" 'ebrowse-tags-search-member-use)
4256 (define-key ebrowse-global-map "v" 'ebrowse-tags-view-definition)
4257 (define-key ebrowse-global-map "V" 'ebrowse-tags-view-declaration)
4258 (define-key ebrowse-global-map "%" 'ebrowse-tags-query-replace)
4259 (define-key ebrowse-global-map "." 'ebrowse-tags-find-definition)
4260 (define-key ebrowse-global-map "f" 'ebrowse-tags-find-definition)
4261 (define-key ebrowse-global-map "F" 'ebrowse-tags-find-declaration)
4262 (define-key ebrowse-global-map "," 'ebrowse-tags-loop-continue)
4263 (define-key ebrowse-global-map " " 'ebrowse-electric-buffer-list)
4264 (define-key ebrowse-global-map "\t" 'ebrowse-tags-complete-symbol)
4265 (define-key ebrowse-global-map "4" ebrowse-global-submap-4)
4266 (define-key ebrowse-global-submap-4 "." 'ebrowse-tags-find-definition-other-window)
4267 (define-key ebrowse-global-submap-4 "f" 'ebrowse-tags-find-definition-other-window)
4268 (define-key ebrowse-global-submap-4 "v" 'ebrowse-tags-find-declaration-other-window)
4269 (define-key ebrowse-global-submap-4 "F" 'ebrowse-tags-view-definition-other-window)
4270 (define-key ebrowse-global-submap-4 "V" 'ebrowse-tags-view-declaration-other-window)
4271 (define-key ebrowse-global-map "5" ebrowse-global-submap-5)
4272 (define-key ebrowse-global-submap-5 "." 'ebrowse-tags-find-definition-other-frame)
4273 (define-key ebrowse-global-submap-5 "f" 'ebrowse-tags-find-definition-other-frame)
4274 (define-key ebrowse-global-submap-5 "v" 'ebrowse-tags-find-declaration-other-frame)
4275 (define-key ebrowse-global-submap-5 "F" 'ebrowse-tags-view-definition-other-frame)
4276 (define-key ebrowse-global-submap-5 "V" 'ebrowse-tags-view-declaration-other-frame)
4277 (define-key global-map ebrowse-global-prefix-key ebrowse-global-map))
4278
4279
4280\f
4281;;; Electric C++ browser buffer menu
4282
4283;;; Electric buffer menu customization to display only some buffers
4284;;; (in this case Tree buffers). There is only one problem with this:
4285;;; If the very first character typed in the buffer menu is a space,
4286;;; this will select the buffer from which the buffer menu was
4287;;; invoked. But this buffer is not displayed in the buffer list if
4288;;; it isn't a tree buffer. I therefore let the buffer menu command
4289;;; loop read the command `p' via `unread-command-char'. This command
4290;;; has no effect since we are on the first line of the buffer.
4291
4292(defvar electric-buffer-menu-mode-hook nil)
4293
4294
4295(defun ebrowse-hack-electric-buffer-menu ()
4296 "Hack the electric buffer menu to display browser buffers."
4297 (let (non-empty)
4298 (unwind-protect
4299 (save-excursion
4300 (setq buffer-read-only nil)
4301 (goto-char 1)
4302 (forward-line 2)
4303 (while (not (eobp))
4304 (let ((b (Buffer-menu-buffer nil)))
4305 (if (or (ebrowse-buffer-p b)
4306 (string= (buffer-name b) "*Apropos Members*"))
4307 (progn (forward-line 1)
4308 (setq non-empty t))
4309 (delete-region (point)
4310 (save-excursion (end-of-line)
4311 (min (point-max)
4312 (1+ (point)))))))))
4313 (unless non-empty
4314 (error "No tree buffers"))
4315 (setf unread-command-events (listify-key-sequence "p"))
4316 (shrink-window-if-larger-than-buffer (selected-window))
4317 (setq buffer-read-only t))))
4318
4319
4320(defun ebrowse-select-1st-to-9nth ()
4321 "Select the nth entry in the list by the keys 1..9."
4322 (interactive)
4323 (let* ((maxlin (count-lines (point-min) (point-max)))
4324 (n (min maxlin (+ 2 (string-to-int (this-command-keys))))))
4325 (goto-line n)
4326 (throw 'electric-buffer-menu-select (point))))
4327
4328
4329(defun ebrowse-install-1-to-9-keys ()
4330 "Define keys 1..9 to select the 1st to 0nth entry in the list."
4331 (dotimes (i 9)
4332 (define-key (current-local-map) (char-to-string (+ i ?1))
4333 'ebrowse-select-1st-to-9nth)))
4334
4335
4336(defun ebrowse-electric-buffer-list ()
4337 "Display an electric list of Ebrowse buffers."
4338 (interactive)
4339 (unwind-protect
4340 (progn
4341 (add-hook 'electric-buffer-menu-mode-hook
4342 'ebrowse-hack-electric-buffer-menu)
4343 (add-hook 'electric-buffer-menu-mode-hook
4344 'ebrowse-install-1-to-9-keys)
4345 (call-interactively 'electric-buffer-list))
4346 (remove-hook 'electric-buffer-menu-mode-hook
4347 'ebrowse-hack-electric-buffer-menu)))
4348
4349\f
4350;;; Mouse support
4351
4352(defun ebrowse-mouse-find-member (event)
4353 "Find the member clicked on in another frame.
4354EVENT is a mouse button event."
4355 (interactive "e")
4356 (mouse-set-point event)
4357 (let (start name)
4358 (save-excursion
4359 (skip-chars-backward "a-zA-Z0-9_")
4360 (setq start (point))
4361 (skip-chars-forward "a-zA-Z0-9_")
4362 (setq name (buffer-substring start (point))))
4363 (ebrowse-tags-view/find-member-decl/defn
4364 5 :view nil :definition t :member-name name)))
4365
4366
4367(defun ebrowse-popup-menu (menu event)
4368 "Pop up MENU and perform an action if something was selected.
4369EVENT is the mouse event."
4370 (save-selected-window
4371 (select-window (posn-window (event-start event)))
4372 (let ((selection (x-popup-menu event menu)) binding)
4373 (while selection
4374 (setq binding (lookup-key (or binding menu) (vector (car selection)))
4375 selection (cdr selection)))
4376 (when binding
4377 (call-interactively binding)))))
4378
4379
4380(easy-menu-define
4381 ebrowse-tree-buffer-class-object-menu ebrowse-tree-mode-map
4382 "Object menu for classes in the tree buffer"
4383 '("Class"
4384 ["Functions" ebrowse-tree-command:show-member-functions
4385 :help "Display a list of member functions"
4386 :active t]
4387 ["Variables" ebrowse-tree-command:show-member-variables
4388 :help "Display a list of member variables"
4389 :active t]
4390 ["Static Functions" ebrowse-tree-command:show-static-member-functions
4391 :help "Display a list of static member functions"
4392 :active t]
4393 ["Static Variables" ebrowse-tree-command:show-static-member-variables
4394 :help "Display a list of static member variables"
4395 :active t]
4396 ["Friends/ Defines" ebrowse-tree-command:show-friends
4397 :help "Display a list of friends of a class"
4398 :active t]
4399 ["Types" ebrowse-tree-command:show-types
4400 :help "Display a list of types defined in a class"
4401 :active t]
4402 "-----------------"
4403 ["View" ebrowse-view-class-declaration
4404 :help "View class declaration"
4405 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4406 ["Find" ebrowse-find-class-declaration
4407 :help "Find class declaration in file"
4408 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4409 "-----------------"
4410 ["Mark" ebrowse-toggle-mark-at-point
4411 :help "Mark class point is on"
4412 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4413 "-----------------"
4414 ["Collapse" ebrowse-collapse-branch
4415 :help "Collapse subtree under class point is on"
4416 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]
4417 ["Expand" ebrowse-expand-branch
4418 :help "Expand subtree under class point is on"
4419 :active (eq (get-text-property (point) 'ebrowse-what) 'class-name)]))
4420
4421
4422(easy-menu-define
4423 ebrowse-tree-buffer-object-menu ebrowse-tree-mode-map
4424 "Object menu for tree buffers"
4425 '("Ebrowse"
4426 ["Filename Display" ebrowse-toggle-file-name-display
4427 :help "Toggle display of source files names"
4428 :style toggle
4429 :selected ebrowse--show-file-names-flag
4430 :active t]
4431 ["Tree Indentation" ebrowse-set-tree-indentation
4432 :help "Set the tree's indentation"
4433 :active t]
4434 ["Unmark All Classes" ebrowse-mark-all-classes
4435 :help "Unmark all classes in the class tree"
4436 :active t]
4437 ["Expand All" ebrowse-expand-all
4438 :help "Expand all subtrees in the class tree"
4439 :active t]
4440 ["Statistics" ebrowse-statistics
4441 :help "Show a buffer with class hierarchy statistics"
4442 :active t]
4443 ["Find Class" ebrowse-read-class-name-and-go
4444 :help "Find a class in the tree"
4445 :active t]
4446 ["Member Buffer" ebrowse-pop/switch-to-member-buffer-for-same-tree
4447 :help "Show a member buffer for this class tree"
4448 :active t]))
4449
4450
4451(defun ebrowse-mouse-3-in-tree-buffer (event)
4452 "Perform mouse actions in tree buffers.
4453EVENT is the mouse event."
4454 (interactive "e")
4455 (mouse-set-point event)
4456 (let* ((where (posn-point (event-start event)))
4457 (property (get-text-property where 'ebrowse-what)))
4458 (case (event-click-count event)
4459 (1
4460 (case property
4461 (class-name
4462 (ebrowse-popup-menu ebrowse-tree-buffer-class-object-menu event))
4463 (t
4464 (ebrowse-popup-menu ebrowse-tree-buffer-object-menu event)))))))
4465
4466
4467(defun ebrowse-mouse-2-in-tree-buffer (event)
4468 "Perform mouse actions in tree buffers.
4469EVENT is the mouse event."
4470 (interactive "e")
4471 (mouse-set-point event)
4472 (let* ((where (posn-point (event-start event)))
4473 (property (get-text-property where 'ebrowse-what)))
4474 (case (event-click-count event)
4475 (1 (case property
4476 (class-name
4477 (ebrowse-tree-command:show-member-functions)))))))
4478
4479
4480(defun ebrowse-mouse-1-in-tree-buffer (event)
4481 "Perform mouse actions in tree buffers.
4482EVENT is the mouse event."
4483 (interactive "e")
4484 (mouse-set-point event)
4485 (let* ((where (posn-point (event-start event)))
4486 (property (get-text-property where 'ebrowse-what)))
4487 (case (event-click-count event)
4488 (2 (case property
4489 (class-name
4490 (let ((collapsed (save-excursion (skip-chars-forward "^\r\n")
4491 (looking-at "\r"))))
4492 (ebrowse-collapse-fn (not collapsed))))
4493 (mark
4494 (ebrowse-toggle-mark-at-point 1)))))))
4495
4496
4497\f
be0dbdab
GM
4498(provide 'ebrowse)
4499
4500;;; Local variables:
4501;;; eval:(put 'ebrowse-output 'lisp-indent-hook 0)
4502;;; eval:(put 'ebrowse-ignoring-completion-case 'lisp-indent-hook 0)
4503;;; eval:(put 'ebrowse-save-selective 'lisp-indent-hook 0)
4504;;; eval:(put 'ebrowse-for-all-trees 'lisp-indent-hook 1)
4505;;; End:
4506
55535639 4507;;; ebrowse.el ends here