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