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