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