comparison lisp/oobr/br.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 4103f0995bd7
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;!emacs
2 ;;
3 ;; FILE: br.el
4 ;; SUMMARY: Browse object-oriented code.
5 ;; USAGE: GNU Emacs Lisp Library
6 ;; KEYWORDS: matching, oop, tools
7 ;;
8 ;; AUTHOR: Bob Weiner
9 ;; ORG: Motorola Inc.
10 ;;
11 ;; ORIG-DATE: 12-Dec-89
12 ;; LAST-MOD: 21-Sep-95 at 12:39:17 by Bob Weiner
13 ;;
14 ;; Copyright (C) 1989-1995 Free Software Foundation, Inc.
15 ;; See the file BR-COPY for license information.
16 ;;
17 ;; This file is part of the OO-Browser.
18 ;;
19 ;; DESCRIPTION:
20 ;; DESCRIP-END.
21
22 ;;; ************************************************************************
23 ;;; Other required Elisp libraries
24 ;;; ************************************************************************
25
26 (require 'br-lib)
27
28 ;;; ************************************************************************
29 ;;; Public variables
30 ;;; ************************************************************************
31
32 (defvar br-c-tags-flag t
33 "*Non-nil means add C constructs when building C-based language Environments.")
34
35 (defvar br-directory nil
36 "Directory in which OO-Browser executable and help files are kept.")
37
38 (defconst br-feature-signature-regexp "[:|,]"
39 "Regular expression that matches a feature signature but not a class name.")
40
41 (defvar br-inherited-features-flag t
42 "*If non-nil (the default), feature/element listings include all inherited features.
43 If nil, only those features lexically included within a class are shown.")
44
45 (defvar br-inhibit-version nil
46 "*Personal setting which if non-nil, skips version/credit information upon startup.
47 The default should be left as nil, since new users may find this helpful.")
48
49 (defvar br-invert-ancestors nil
50 "*Personal setting which if non-nil makes ancestors appear as do other inheritance listings.
51 That is, parents appear above children, rather than the default, which is the
52 reverse.")
53
54 (defvar br-keep-viewed-classes nil
55 "*Personal setting which if non-nil means leave all viewed classes around for later selection.
56 Non-nil deletes last viewed class when a new one is displayed. Note this
57 does not affect classes displayed for editing, all such classes are left
58 around.")
59
60 (defconst br-min-width-window 25
61 "*Minimum width of a browser class list window.
62 This together with the frame width determines the number of such windows.")
63
64 ;; -f treats upper and lower case the same in sorting, also makes 'a' sort
65 ;; list before '[a]', so default classes appear at the end of the list,
66 ;; typically.
67 ;; -u leaves only unique elements in the sorted list
68 (defvar br-sort-options "-fu"
69 "*String of options to send to the operating system `sort' command.
70 Use nil for none. This is used by the OO-Browser (br-order) command only
71 under Emacs 18.")
72
73 ;;; ************************************************************************
74 ;;; Public macros
75 ;;; ************************************************************************
76
77 (if (fboundp 'window-highest-p)
78 (defun br-non-listing-window-p ()
79 "Is the selected window a non-OO-Browser listing window?"
80 ;; Top of window is not at top of frame.
81 (not (window-highest-p (selected-window))))
82 (defun br-non-listing-window-p ()
83 "Is the selected window a non-OO-Browser listing window?"
84 ;; Top of window is not at top of frame.
85 (/= (nth 1 (window-edges)) br-top-of-frame)))
86
87 (if (fboundp 'window-highest-p)
88 (defun br-listing-window-p ()
89 "Is the selected window an OO-Browser listing window?"
90 (window-highest-p (selected-window)))
91 (defun br-listing-window-p ()
92 "Is the selected window an OO-Browser listing window?"
93 ;; Top of window is at top of frame.
94 (= (nth 1 (window-edges)) br-top-of-frame)))
95
96 ;;; ************************************************************************
97 ;;; Public functions
98 ;;; ************************************************************************
99
100 (defun br-browse ()
101 "Internally invoke the OO-Browser, for browsing class hierarchies.
102 Use \\[br-help] and \\[br-help-ms] for help on browser usage."
103 (interactive)
104 ;; If not already in the browser, save window config.
105 (if (br-in-browser)
106 nil
107 (setq *br-prev-wconfig* (current-window-configuration)
108 br-in-browser (selected-frame))
109 ;; If were previously in the browser, restore its saved window config,
110 ;; otherwise, set up from scratch.
111 (if *br-save-wconfig*
112 (set-window-configuration *br-save-wconfig*)
113 (br-window-setup)
114 (if br-inhibit-version
115 (br-top-classes t)
116 (br-version)
117 (message "Press {h} for for help.")
118 ;; Display all classes.
119 (br-top-classes t)
120 (message "Press {h} for for help.")
121 ;; Wait for 60 seconds or until a single key sequence is given.
122 (sit-for 60)
123 (message ""))
124 (br-help))
125 (run-hooks 'br-mode-hook
126 (intern (concat "br-" br-lang-prefix "mode-hook")))))
127
128 ;;;###autoload
129 (defun br-add-class-file (&optional class-path lib-table-p save-file)
130 "Add a file of classes to the current Environment.
131 Interactively or when optional CLASS-PATH is nil, CLASS-PATH defaults to the
132 current buffer file pathname. If optional LIB-TABLE-P is non-nil, add to
133 Library Environment, otherwise add to System Environment. If optional
134 SAVE-FILE is t, the Environment is then stored to the filename given by
135 'br-env-file'. If SAVE-FILE is non-nil and not t, its string value is used
136 as the file to which to save the Environment."
137 (interactive
138 (list (read-file-name (concat "Class file name to add"
139 (if buffer-file-name
140 (concat " (default \""
141 (file-name-nondirectory
142 buffer-file-name)
143 "\")"))
144 ": ")
145 nil buffer-file-name t)
146 (y-or-n-p "Add to Library, rather than System tables? ")
147 (y-or-n-p
148 (concat "Save tables after addition to " br-env-file "? "))))
149 (or class-path (setq class-path buffer-file-name))
150 (if (not (if class-path (file-readable-p class-path)))
151 (error "(br-add-class-file): %s is not readable" class-path))
152 (let* ((paths-parents-cons
153 (let ((br-view-file-function 'br-insert-file-contents))
154 (br-get-classes-from-source class-path)))
155 (classes (car paths-parents-cons))
156 (parents (cdr paths-parents-cons))
157 (paths-key class-path)
158 (path-htable (br-get-htable (if lib-table-p "lib-paths" "sys-paths")))
159 (par-htable (br-get-htable
160 (if lib-table-p "lib-parents" "sys-parents")))
161 (child-htable (br-get-children-htable)))
162 (mapcar
163 (function
164 (lambda (class)
165 (br-add-to-paths-htable class paths-key path-htable)))
166 classes)
167 (mapcar
168 (function
169 (lambda (parent-cons)
170 (hash-add (car parent-cons) (cdr parent-cons) par-htable)))
171 parents)
172 (br-env-set-htables)
173 (let ((child) (par-list) children)
174 (mapcar
175 (function
176 (lambda (parent-cons)
177 (setq child (cdr parent-cons)
178 par-list (car parent-cons))
179 (mapcar
180 (function
181 (lambda (parent)
182 (setq children (hash-get parent child-htable))
183 (or (br-member child children)
184 (hash-add (cons child children) parent child-htable))))
185 par-list)))
186 parents)))
187 (cond ((eq save-file nil))
188 ((eq save-file t) (br-env-save))
189 ((br-env-save save-file))))
190
191 (defun br-ancestors (&optional arg features-flag)
192 "Display ancestor tree whose root is the current class.
193 With optional prefix ARG, display all ancestor trees whose roots are in the
194 current listing. If ARG = -1 or 'br-invert-ancestors' is t, the current
195 class ancestry tree is inverted. That is, it shows branches going down
196 towards the root class, so that parents appear above children. If ARG < -1 or
197 'br-invert-ancestors' is t and ARG > 1, then the ancestry trees of all
198 classes in the current listing are inverted.
199
200 Optional second argument, FEATURES-FLAG non-nil means display features under
201 each ancestor class."
202 (interactive "p")
203 (or arg (setq arg 1))
204 (if br-invert-ancestors (setq arg (- arg)))
205 (let* ((class-list
206 (if (and (/= arg 1) (/= arg -1))
207 (br-this-level-classes)
208 (list (br-find-class-name))))
209 (parents (delq nil (mapcar (function
210 (lambda (c) (br-get-parents c)))
211 class-list))))
212 (cond ((or parents
213 (and features-flag
214 (if (/= 1 (length class-list))
215 t ;; Assume some class will have features.
216 ;; This class must have features.
217 (br-list-features (car class-list)))))
218 (if (and (/= arg 1) (/= arg -1))
219 (message "Computing %s..."
220 (if features-flag "features" "ancestors")))
221 (if features-flag
222 (progn
223 (br-add-level-hist)
224 (br-next-buffer))
225 (let ((child-level (br-buffer-level)))
226 (br-add-level-hist)
227 (br-next-listing-window -1)
228 (br-next-buffer (concat "p" child-level))))
229 (let (buffer-read-only)
230 (cond ((>= arg 0)
231 (br-ancestor-trees-inverted class-list))
232 (t
233 (br-ancestor-trees class-list))))
234 (goto-char (point-min))
235 (if (and (/= arg 1) (/= arg -1))
236 (message "Computing %s...Done"
237 (if features-flag "features" "ancestors")))
238 t)
239 (t
240 (message "No %s." (if features-flag "features" "ancestors"))
241 (beep)))))
242
243 (defun br-at (&optional arg)
244 "Display current class location in the inheritance graph.
245 The class is displayed among both its ancestors and descendants.
246 With optional prefix ARG, display location for all classes in the current
247 listing."
248 (interactive "P")
249 (let* ((parent)
250 (parent-list
251 (if arg
252 (br-this-level-classes)
253 (list (setq parent (br-find-class-name))))))
254 (if arg
255 (message "Computing class locations...")
256 (br-narrow-to-class))
257 (br-add-level-hist)
258 (br-next-buffer)
259 (let (buffer-read-only)
260 (br-descendant-trees (br-ancestor-roots parent-list))
261 (goto-char (point-min))
262 (if arg
263 (message "Computing class locations...Done")
264 (re-search-forward (concat "\\(^\\|[ \t]+\\)" parent "$"))
265 (goto-char (match-end 1))
266 (recenter '(4))))))
267
268 (defun br-categories (&optional arg)
269 "Display categories directly associated with the current class.
270 This does not include any categories which the class inherits.
271 With optional prefix ARG, display categories of all classes in the current
272 listing."
273 (interactive "P")
274 (let ((has-categories)
275 class-list categories class-and-categories)
276 (setq class-list (cond (arg
277 (message "Computing class categories...")
278 (br-this-level-classes))
279 (t
280 (list (br-find-class-name))))
281 categories
282 (delq nil (mapcar
283 (function
284 (lambda (class)
285 (setq class-and-categories (br-list-categories class)
286 has-categories (or has-categories
287 class-and-categories))
288 (cons class class-and-categories)))
289 class-list)))
290 (cond ((not class-list)
291 (message "(OO-Browser): Apply 'br-categories' to a class.") (beep))
292 ((not has-categories)
293 (message "No class categories.") (beep))
294 (t
295 (br-add-level-hist)
296 (br-next-buffer nil)
297 (let (buffer-read-only done-set class)
298 (mapcar
299 (function
300 (lambda (class-and-categories)
301 (setq class (car class-and-categories))
302 (if (not (br-set-cons done-set class))
303 (insert class " ...\n")
304 ;; Class successfully added to set, so it has not been
305 ;; listed before.
306 (insert class "\n")
307 (br-insert-features (cdr class-and-categories) 2))))
308 categories))
309 (message "Computing class categories...Done")
310 (goto-char (point-min))
311 t))))
312
313 (defun br-children (&optional arg)
314 "Display children of current class.
315 With optional prefix ARG, display children of all the classes in the current
316 listing."
317 (interactive "P")
318 (let ((class-list (cond (arg
319 (message "Computing children...")
320 (br-this-level-classes))
321 (t
322 (list (br-find-class-name)))))
323 (has-children)
324 children children-list)
325 (setq children-list (delq nil (mapcar
326 (function
327 (lambda (parent)
328 (setq children
329 (br-get-children parent)
330 has-children
331 (or has-children children))
332 (cons parent children)))
333 class-list)))
334 (cond ((not children-list)
335 (message "(OO-Browser): Apply 'br-children' to a class.")
336 (beep))
337 ((not has-children)
338 (message "No children.") (beep))
339 (t
340 (br-add-level-hist)
341 (br-next-buffer nil)
342 (let (buffer-read-only done-set parent)
343 (mapcar
344 (function
345 (lambda (parent-children-cons)
346 (setq parent (car parent-children-cons))
347 (if (not (br-set-cons done-set parent))
348 (insert parent " ...\n")
349 ;; Class successfully added to set, so it has not been
350 ;; listed before.
351 (insert parent "\n")
352 (br-insert-classes (cdr parent-children-cons) 2))))
353 children-list))
354 (if arg (message "Computing children...Done"))
355 (goto-char (point-min))
356 t))))
357
358 (defun br-class-stats (&optional prompt)
359 "Display statistics summary for current class.
360 Optional prefix arg PROMPT means prompt for class name."
361 (interactive "P")
362 (let ((class-name (if prompt (br-complete-class-name) (br-find-class-name))))
363 (if class-name
364 (message "Class %s: Parents: %d; Children: %d"
365 class-name (length (br-get-parents class-name))
366 (length (br-get-children class-name)))
367 (error "No class name at point."))))
368
369 (defun br-cmd-help (key &optional full)
370 "Show first line of doc for OO-Browser KEY in minibuffer.
371 With optional FULL, display full documentation for command."
372 (interactive "kOO-Browser key binding: \nP")
373 (let* ((cmd (let ((cmd (if (eq major-mode 'br-mode)
374 (lookup-key br-mode-map key)
375 (key-binding key))))
376 (if (not (integerp cmd)) cmd)))
377 (doc (and cmd (documentation cmd)))
378 (end-line))
379 (if doc
380 (or full
381 (setq end-line (string-match "[\n]" doc)
382 doc (substitute-command-keys (substring doc 0 end-line))))
383 (setq doc (format "No documentation for {%s} %s" key (or cmd ""))))
384 (if (and cmd doc)
385 (if full
386 (progn (br-to-view-window)
387 (other-window -1)
388 (describe-function cmd))
389 (message doc)))))
390
391 (defun br-count ()
392 "Count number of entries visible in current listing buffer.
393 Print text result in minibuffer when called interactively."
394 (interactive)
395 (let ((cnt (count-lines (point-min) (point-max))))
396 (if (interactive-p)
397 (message "%s contains %d entries." (buffer-name) cnt)
398 cnt)))
399
400 (defun br-copyright ()
401 "Display browser copyright information in viewer window."
402 (interactive)
403 (br-file-to-viewer "BR-COPY"))
404
405 (defun br-delete (&optional prompt)
406 "Delete class from current Environment.
407 Does not alter descendency relations.
408 Optional prefix arg PROMPT means prompt for class name."
409 (interactive "P")
410 (let ((class (if prompt (br-complete-class-name) (br-find-class-name))))
411 (and class
412 (if (interactive-p)
413 (y-or-n-p (concat "Delete class " class " from Environment? "))
414 t)
415 (progn (br-real-delete-class class)
416 ;; Delete class name at point in listing window
417 (or prompt (let (buffer-read-only)
418 (progn (beginning-of-line)
419 (delete-region
420 (point) (progn (forward-line 1)
421 (point))))))
422 (message "Class " class " deleted.")))))
423
424 (defun br-descendants (&optional arg)
425 "Display descendant tree whose root is the current class.
426 With optional prefix ARG, display all descendant trees whose roots are
427 the classes in the current listing."
428 (interactive "P")
429 (let ((parent-list
430 (if arg
431 (br-this-level-classes)
432 (list (br-find-class-name)))))
433 (cond ((delq nil (mapcar
434 (function (lambda (parent)
435 (br-get-children parent)))
436 parent-list))
437 (if arg (message "Computing descendants..."))
438 (br-add-level-hist)
439 (br-next-buffer)
440 (let (buffer-read-only)
441 (br-descendant-trees parent-list))
442 (goto-char (point-min))
443 (if arg (message "Computing descendants...Done"))
444 t)
445 (t
446 (message "No descendants.") (beep)))))
447
448 (defun br-edit-entry (&optional prompt)
449 "Edits source for any browser listing entry, such as a class or a feature.
450 Optional prefix arg PROMPT means prompt for entry name."
451 (interactive "P")
452 (let ((entry) (sig))
453 (if prompt
454 (cond ((and (setq entry (br-complete-entry))
455 (string-match br-feature-signature-regexp entry))
456 (if (setq sig (car (br-feature-signature-and-file entry)))
457 (br-feature nil nil sig)
458 (error "(br-feature-signature-and-file): Couldn't find match for: '%s'" entry)))
459 (entry ;; class name
460 (br-edit nil entry))
461 (t (error "(br-complete-entry): Exited without selecting a match")))
462 (cond ((br-find-feature-entry)
463 (br-feature))
464 ((and (setq entry (br-find-class-name))
465 (br-class-in-table-p entry))
466 (br-edit nil entry))
467 (t (error "(OO-Browser): No entry for current line in current Environment"))))))
468
469 (defun br-edit (&optional prompt class)
470 "Edit a class in the viewer window.
471 Select viewer window. With optional prefix arg PROMPT, prompt for class
472 name. Optional CLASS is the one to edit."
473 (interactive "P")
474 (or br-editor-cmd
475 (br-in-view-window-p)
476 (setq *br-prev-listing-window* (selected-window)))
477 (br-view prompt t class))
478
479 (defun br-edit-ext (editor-cmd file)
480 "Invoke a non-standard EDITOR-CMD on FILE.
481 See also 'br-editor-cmd'."
482 (interactive "fFile to edit: ")
483 (or editor-cmd (setq editor-cmd br-editor-cmd))
484 (if (not (stringp editor-cmd)) ;; must be a Lisp function that takes a
485 ;; single, file arg
486 (funcall editor-cmd file)
487 (setq delete-exited-processes t)
488 (let ((proc)
489 (name (concat br-ed-name br-ed-num))
490 )
491 (setq br-ed-num (1+ br-ed-num)
492 proc (br-edit-ext-start editor-cmd name file))
493 (if proc
494 (process-kill-without-query proc)
495 (beep)
496 (message "(OO-Browser): Could not start external edit process: %s"
497 editor-cmd)))))
498
499 (defun br-editor-kill ()
500 "Kill all current external editor sub-processes."
501 (interactive)
502 (if (br-kill-process-group br-ed-name br-ed-num "external editors")
503 (setq br-ed-num 0)))
504
505 (defun br-entry-info ()
506 "Display attributes of the current entry in the viewer window."
507 (interactive)
508 (if (fboundp 'br-insert-class-info)
509 (let ((class-name (br-find-class-name)))
510 (if class-name
511 (progn
512 (message "Building '%s' class info..." class-name)
513 ; (sit-for 2) ; Why should we pause here?
514 (br-store-class-info class-name)
515 (message "Building '%s' class info...Done" class-name)
516 (br-funcall-in-view-window
517 (concat br-buffer-prefix-info "Info")
518 'br-insert-class-info))
519 (error "Move point to a class name line.")))
520 (beep)
521 (message "No class information function for this language.")))
522
523 (defun br-exit-level (arg)
524 "Return to prefix ARGth previous inheritance level listing.
525 The command is ignored with ARG < 1."
526 (interactive "p")
527 (setq arg (or arg 1))
528 (let ((prev-wind-buf-line))
529 (if (null *br-level-hist*)
530 (and (> arg 0)
531 (message "No previous level to which to exit.")
532 (beep))
533 (while (and (> arg 0) *br-level-hist*)
534 (br-next-buffer (br-listing-window-num) br-buffer-prefix-blank)
535 (setq prev-wind-buf-line (car *br-level-hist*)
536 *br-level-hist* (cdr *br-level-hist*)
537 arg (1- arg))
538 (select-window (car prev-wind-buf-line))
539 (switch-to-buffer (car (cdr prev-wind-buf-line))))
540 (widen)
541 ;; Position window lines exactly as before.
542 (recenter (car (cdr (cdr prev-wind-buf-line)))))))
543
544 (defun br-feature (&optional arg view-only ftr-sig)
545 "Edit a feature in the viewer window. Select viewer window.
546 With optional prefix ARG, prompt for feature name.
547 Optional VIEW-ONLY non-nil means view rather than edit feature.
548 Optional FTR-SIG is signature of feature to edit."
549 (interactive "P")
550 (or ftr-sig
551 (setq ftr-sig (if arg
552 (br-feature-complete 'must-match)
553 ;; Get current feature signature
554 (br-feature-get-signature))))
555 (if (null ftr-sig)
556 (error "(br-feature): No definition for this entry")
557 (br-to-view-window)
558 (if (br-feature-found-p (br-feature-file ftr-sig) ftr-sig)
559 (if view-only
560 (progn (setq buffer-read-only t)
561 (br-to-from-viewer))
562 (if (file-writable-p (buffer-file-name))
563 (setq buffer-read-only nil)))
564 ;; Feature not found. Return to original window and signal an error.
565 (br-to-from-viewer)
566 (error "(br-feature): Can't find definition of: '%s'" ftr-sig))))
567
568 (defun br-features (arg)
569 "Display features/elements of the current class (prefix ARG = 1) or of the current listing if ARG is other than 0 or 1.
570
571 With ARG = 0, the value of the variable, 'br-inherited-features-flag', is
572 toggled and no other action is taken.
573
574 If 'br-inherited-features-flag' is t, all features of each class are shown.
575 If nil, only lexically included features are shown and if the features of a
576 single class are requested and none are defined, the class definition is
577 displayed so that its feature declarations may be browsed."
578 (interactive "p")
579 (cond ((and (integerp arg) (= arg 0))
580 (setq br-inherited-features-flag
581 (not br-inherited-features-flag))
582 (message "Inherited features/elements will %sbe shown."
583 (if br-inherited-features-flag "" "not ")))
584 (br-inherited-features-flag
585 (br-inherited-features arg))
586 (t (br-lexical-features arg))))
587
588 (defun br-find (element)
589 "Interactively complete class or ELEMENT name and jump to its definition.
590 Return ELEMENT or signal an error."
591 (interactive (list (br-complete-entry)))
592 (if (and element
593 (progn
594 (if (not (br-in-view-window-p)) (br-to-from-viewer))
595 (if (string-match br-feature-signature-regexp element)
596 (br-find-feature element)
597 (br-find-class element))))
598 element
599 (error "(OO-Browser): '%s' definition not found." element)))
600
601 (defun br-help (&optional file)
602 "Display browser operation help information in viewer window."
603 (interactive)
604 (or file (setq file "br-help"))
605 (br-file-to-viewer file)
606 (save-window-excursion
607 (br-to-view-window)
608 (br-mode)
609 (use-local-map nil))
610 (message ""))
611
612 (defun br-help-ms ()
613 "Display browser mouse usage help information in viewer window."
614 (interactive)
615 (br-help "br-help-ms"))
616
617 (defun br-implementors (&optional arg)
618 "Display hierarchy of classes that define current element.
619 Ignore inherited elements. With optional prefix ARG, display implementors of
620 all elements in the current listing."
621 (interactive "P")
622 (let
623 ((child-level (br-buffer-level))
624 (ftr-list (if arg (br-set-of-strings
625 (sort (br-this-level-features) 'string-lessp))
626 ;; Need this check to avoid trying to find implementors of
627 ;; a class which happens to have an attached element tag,
628 ;; e.g. in an implementors listing buffer.
629 (save-excursion
630 (beginning-of-line)
631 (skip-chars-forward " \t")
632 (if (looking-at br-feature-entry)
633 (list (br-find-feature-entry)))))))
634 (if (or (null ftr-list) (null (car ftr-list)))
635 (error
636 "(OO-Browser): 'br-implementors' must be applied to a feature.")
637 (message "Computing implementors...")
638 (br-add-level-hist)
639 (br-next-listing-window -1)
640 (br-next-buffer (concat "p" child-level))
641 (let ((buffer-read-only) (implementor-tags) (classes)
642 start)
643 (widen)
644 (erase-buffer)
645 (mapcar (function
646 (lambda (ftr-entry)
647 (setq implementor-tags
648 (sort
649 (br-feature-implementors
650 (br-feature-name ftr-entry))
651 'string-lessp)
652 classes (mapcar 'br-feature-tag-class
653 implementor-tags))
654 (insert ftr-entry "\n")
655 (setq start (point))
656 (br-insert-classes classes 4)
657 (save-excursion
658 (goto-char start)
659 (br-feature-put-signatures implementor-tags))))
660 ftr-list))
661 (goto-char 1)
662 (message "Computing implementors...Done"))))
663
664 (defun br-inherited-features (arg)
665 "Display class features, including those from ancestors.
666 With optional prefix ARG, display features of all classes in the current
667 listing."
668 (interactive "p")
669 (let ((br-ancestor-function
670 (function
671 (lambda (class repeated-class indent)
672 (if repeated-class
673 nil
674 (br-insert-features (br-list-features class indent) indent))))))
675 (br-ancestors arg t)))
676
677 (defun br-kill ()
678 "Kill buffer in viewer window and redisplay help text."
679 (interactive)
680 (br-do-in-view-window '(progn (kill-buffer nil) (br-help))))
681
682 (defun br-lexical-features (arg)
683 "Display class features lexically defined within current class.
684 With numeric prefix ARG, display features of all classes in the current
685 listing.
686
687 If the features of a single class are requested and there are no feature
688 definitions for the class, display the class definition so that its feature
689 declarations may be browsed."
690 (interactive "p")
691 (let ((has-features)
692 class-list features class-and-features)
693 (setq class-list (cond ((and (integerp arg) (/= arg 1))
694 (message "Computing class features...")
695 (br-this-level-classes))
696 (t
697 (list (br-find-class-name))))
698 features
699 (delq nil (mapcar
700 (function
701 (lambda (class)
702 (setq class-and-features (br-list-features class)
703 has-features (or has-features
704 class-and-features))
705 (cons class class-and-features)))
706 class-list)))
707 (cond ((not class-list)
708 (beep)
709 (message "(OO-Browser): Apply 'br-features' to a class."))
710 ((not has-features)
711 (if (and (= (length class-list) 1)
712 (br-class-path (car class-list)))
713 (if (br-view nil nil (car class-list))
714 (message
715 "No feature definitions, browse declarations instead."))
716 (message "No class features.") (beep)))
717 (t
718 (br-add-level-hist)
719 (br-next-buffer nil)
720 (let (buffer-read-only done-set class)
721 (mapcar
722 (function
723 (lambda (class-and-features)
724 (setq class (car class-and-features))
725 (if (not (br-set-cons done-set class))
726 (insert class " ...\n")
727 ;; Class successfully added to set, so it has not been
728 ;; listed before.
729 (insert class "\n")
730 (br-insert-features (cdr class-and-features) 2))))
731 features)
732 (message "Computing class features...Done")
733 (goto-char (point-min)))))))
734
735 (defun br-lib-rebuild ()
736 "Rescan Library components of the current Environment."
737 (interactive)
738 (if (call-interactively 'br-build-lib-htable)
739 (br-top-classes t)))
740
741 (defun br-lib-top-classes (&optional arg)
742 "Display list of top level Library classes.
743 With prefix ARG, display all Library classes."
744 (interactive "P")
745 (and (or (not (interactive-p))
746 (br-in-top-buffer-p)
747 (y-or-n-p "Exit to top-level class listing buffer? "))
748 (cond (arg
749 (br-show-top-classes
750 (function (lambda () (br-all-classes "lib")))
751 'uniq)
752 (message "Listing of all Library classes"))
753 (t
754 (br-show-top-classes 'br-get-lib-top-classes 'uniq)
755 (message "Listing of top-level Library classes")))
756 (setq *br-level-hist* nil)))
757
758 (defun br-match (&optional expr arg again matched)
759 "Show all class names in current Environment that contain optional EXPR.
760 Nil value of EXPR means prompt for a value. With optional prefix ARG, EXPR
761 is treated as a string. By default, it is treated as a regular expresion.
762 AGAIN non-nil shows the number of classes MATCHED from the last search,
763 allowing repeated narrowing of the search set. Empty EXPR when AGAIN is nil
764 matches to all classes in the Environment."
765 (interactive (list nil current-prefix-arg))
766 (or expr (setq expr (read-string
767 (concat (if again (format "(%s matches) " matched))
768 (if arg
769 "Find Environment class string matches"
770 "Find Environment class regular expression matches")
771 (if again " (RTN to end): " ": ")))))
772 (if (and again (equal expr ""))
773 nil
774 (let* ((match-expr (if arg (regexp-quote expr) expr))
775 (classes
776 (delq nil (mapcar
777 (function
778 (lambda (cl)
779 (if (string-match match-expr cl) cl)))
780 (if again
781 (sort (br-this-level-classes) 'string-lessp)
782 (br-all-classes))))))
783 (setq classes (br-class-list-filter classes))
784 (if classes
785 (progn (let (buffer-read-only)
786 (br-feature-clear-signatures)
787 (erase-buffer)
788 (br-insert-classes classes 0))
789 (goto-char (point-min))
790 (br-match nil arg t (br-count)))
791 (beep)
792 (message "No matches for \"%s\"." expr)))))
793
794 (defun br-match-entries (&optional expr arg again matched)
795 "Show all entries in current listing that contain optional EXPR.
796 Nil value of EXPR means prompt for a value. With optional prefix ARG, EXPR
797 is treated as a string. By default, it is treated as a regular expresion.
798 AGAIN non-nil means show the number of entries MATCHED from last search,
799 allowing repeated narrowing of the search set. Empty EXPR when AGAIN is nil
800 matches to all entries in the listing."
801 (interactive (list nil current-prefix-arg))
802 (or expr (setq expr (read-string
803 (concat (if again (format "(%s matches) " matched))
804 (if arg
805 "Find string matches in listing"
806 "Find regular expression matches in listing")
807 (if again " (RTN to end): " ": ")))))
808 (if (and again (equal expr ""))
809 nil
810 (let* ((match-expr (if arg (regexp-quote expr) expr))
811 (buffer-read-only))
812 (goto-char (point-min))
813 (if (not (re-search-forward match-expr nil t))
814 (progn (beep)
815 (message "No matches for \"%s\"." expr))
816 (goto-char (point-min))
817 (delete-non-matching-lines match-expr)
818 (goto-char (point-min))
819 (br-match-entries nil arg t (br-count))))))
820
821 (defun br-next-entry (arg)
822 "Move point vertically down prefix ARG number of lines in listing buffer."
823 (interactive "p")
824 (let ((end))
825 (setq end (= (forward-line arg) arg))
826 (and (looking-at "^$") (forward-line -1) (setq end t))
827 (and end (message "No next entry.") (beep))))
828
829 (defun br-order (arg)
830 "Order current browser listing window entries.
831 With prefix ARG other than 1 (the default), don't remove leading space from
832 entry lines before ordering. Negative ARG means order in descending Ascii
833 sequence, otherwise order in ascending sequence."
834 (interactive "p")
835 (setq arg (or arg 1))
836 (message "Ordering entries...")
837 (let ((buffer-read-only)
838 sort-args)
839 (and (= arg 1) (progn (goto-char (point-min))
840 (while (re-search-forward "^[ \t]+" nil t)
841 (replace-match ""))))
842 (if (string-match "^19\\." emacs-version)
843 (progn
844 ;; Emacs 19: This slower than calling an external sort but it
845 ;; maintains the element tags in a listing, allowing further browsing
846 ;; from this buffer.
847 (sort-lines (< arg 0) (point-min) (point-max))
848 ;; Move [default] classes to the end of the sorted list.
849 (goto-char (point-min))
850 (if (re-search-forward "^[ \t]*\\[" nil t)
851 (let (start end)
852 (beginning-of-line)
853 (setq start (point))
854 (goto-char (point-max))
855 (re-search-backward "^[ \t]*\\[" nil t)
856 (forward-line 1)
857 (setq end (point))
858 (goto-char (point-max))
859 (append-to-buffer (current-buffer) start end)
860 (delete-region start end))))
861 ;;
862 ;; Emacs 18: We can't maintain the buffer tags, so we just use a fast
863 ;; external sort.
864 (setq sort-args (list (point-min) (point-max) "sort" t t nil)
865 sort-args (if (< arg 0)
866 (if (stringp br-sort-options)
867 (nconc sort-args (list "-r" br-sort-options))
868 (nconc sort-args (list "-r")))
869 (if (stringp br-sort-options)
870 (nconc sort-args (list br-sort-options))
871 sort-args)))
872 (apply 'call-process-region sort-args)))
873 (goto-char (point-min))
874 (message "Ordering entries...Done"))
875
876 (defun br-parents (&optional arg)
877 "Display parents of current class.
878 With optional prefix ARG, display parents of all the classes in the current
879 listing."
880 (interactive "P")
881 (let ((class-list (cond (arg
882 (message "Computing parents...")
883 (br-this-level-classes))
884 (t
885 (list (br-find-class-name)))))
886 (has-parents)
887 parents parents-list)
888 (setq parents-list
889 (delq nil (mapcar (function
890 (lambda (class)
891 (setq parents (br-get-parents class)
892 has-parents (or has-parents parents))
893 (cons class parents)))
894 class-list)))
895 (cond ((not parents-list)
896 (message "(OO-Browser): Apply 'br-parents' to a class.") (beep))
897 ((not has-parents)
898 (message "No parents.") (beep))
899 (t
900 (let ((child-level (br-buffer-level)))
901 (br-add-level-hist)
902 (br-next-listing-window -1)
903 (br-next-buffer (concat "p" child-level)))
904 (let (buffer-read-only done-set class)
905 (mapcar
906 (function
907 (lambda (class-parents-cons)
908 (setq class (car class-parents-cons))
909 (if (not (br-set-cons done-set class))
910 (insert class " ...\n")
911 ;; Class successfully added to set, so it has not been
912 ;; listed before.
913 (insert class "\n")
914 (br-insert-classes (cdr class-parents-cons) 2))))
915 parents-list))
916 (if arg (message "Computing parents...Done"))
917 (goto-char (point-min))
918 t))))
919
920 (defun br-prev-entry (arg)
921 "Move point vertically up prefix ARG number of lines in listing buffer."
922 (interactive "p")
923 (setq arg (- arg))
924 (and (= (forward-line arg) arg)
925 (message "No previous entry.")
926 (beep)))
927
928 (defun br-protocols (&optional arg)
929 "Display protocols to which the current class conforms.
930 This does not include any protocols which the class inherits from its
931 ancestors but it does include protocols which conform to other protocols.
932 With optional prefix ARG, display protocols of all classes in the current
933 listing."
934 (interactive "P")
935 (let ((has-protocols)
936 class-list protocols class-and-protocols)
937 (setq class-list (cond (arg
938 (message "Computing class protocols...")
939 (br-this-level-classes))
940 (t
941 (list (br-find-class-name)))))
942 (if (and (= (length class-list) 1)
943 (br-protocol-entry-p))
944 ;; If on a protocol entry, display its definition.
945 (br-view-protocol (car class-list))
946 ;; Otherwise, list protocols for all elements of class-list.
947 (setq protocols
948 (delq nil (mapcar
949 (function
950 (lambda (class)
951 (setq class-and-protocols (br-list-protocols class)
952 has-protocols (or has-protocols
953 class-and-protocols))
954 (cons class class-and-protocols)))
955 class-list)))
956 (cond ((not class-list)
957 (beep)
958 (message "(OO-Browser): Apply 'br-protocols' to a class."))
959 ((not has-protocols)
960 (message "No class protocols.") (beep))
961 (t
962 (br-add-level-hist)
963 (br-next-buffer nil)
964 (let (buffer-read-only done-set class)
965 (mapcar
966 (function
967 (lambda (class-and-protocols)
968 (setq class (car class-and-protocols))
969 (if (not (br-set-cons done-set class))
970 (insert class " ...\n")
971 ;; Class successfully added to set, so it has not been
972 ;; listed before.
973 (insert class "\n")
974 (br-insert-features (cdr class-and-protocols) 2))))
975 protocols))
976 (message "Computing class protocols...Done")
977 (goto-char (point-min)))))))
978
979 (defun br-quit (&optional arg)
980 "Quit browser.
981 With optional prefix ARG, delete window configurations and listing
982 buffers associated with the browser."
983 (interactive "P")
984 (if (not (br-in-browser))
985 (br-interrupt arg)
986 (if (null arg)
987 (setq *br-save-wconfig* (current-window-configuration))
988 (if (featurep 'br-tree) (br-tree-kill))
989 (br-viewer-kill)
990 ;; Too dangerous to include (br-editor-kill) here.
991 ;; The user can invoke it manually if desired.
992 )
993 (and *br-prev-wconfig* (set-window-configuration *br-prev-wconfig*))
994 (br-interrupt arg)))
995
996 (defun br-refresh ()
997 "Restore OO-Browser to its state upon startup."
998 (interactive)
999 (br-window-setup)
1000 (br-top-classes t)
1001 (br-help)
1002 (setq br-in-browser (selected-frame)))
1003
1004 (defun br-report-bug ()
1005 "Send a message to the OO-Browser discussion list."
1006 (interactive)
1007 (if (br-in-browser) (br-to-view-window))
1008 (hmail:compose "oo-browser@hub.ucsb.edu" '(hypb:configuration)))
1009
1010 (defun br-sys-rebuild ()
1011 "Rescan System components of the current Environment."
1012 (interactive)
1013 (if (call-interactively 'br-build-sys-htable)
1014 (br-top-classes t)))
1015
1016 (defun br-sys-top-classes (&optional arg)
1017 "Display list of top level System classes.
1018 With prefix ARG, display all System classes."
1019 (interactive "P")
1020 (and (or (not (interactive-p))
1021 (br-in-top-buffer-p)
1022 (y-or-n-p "Exit to top-level class listing buffer? "))
1023 (cond (arg
1024 (br-show-top-classes
1025 (function (lambda () (br-all-classes "sys")))
1026 'uniq)
1027 (message "Listing of all System classes"))
1028 (t
1029 (br-show-top-classes 'br-get-sys-top-classes 'uniq)
1030 (message "Listing of top-level System classes")))
1031 (setq *br-level-hist* nil)))
1032
1033 ;;;###autoload
1034 (defun br-to-from-viewer ()
1035 "Move point to viewer window or back to last recorded listing window."
1036 (interactive)
1037 (if (br-in-view-window-p)
1038 (progn (if *br-prev-listing-window*
1039 (select-window *br-prev-listing-window*)
1040 (other-window 1))
1041 (setq *br-prev-listing-window* nil))
1042 (br-to-view-window)))
1043
1044 (defun br-toggle-c-tags ()
1045 "Toggle the value of the 'br-c-tags-flag' flag."
1046 (interactive)
1047 (setq br-c-tags-flag (not br-c-tags-flag))
1048 (message "C constructs will %sbe added to C-based language Environments."
1049 (if br-c-tags-flag "" "not ")))
1050
1051 (defun br-toggle-keep-viewed ()
1052 "Toggle the value of the 'br-keep-viewed-classes' flag."
1053 (interactive)
1054 (setq br-keep-viewed-classes (not br-keep-viewed-classes))
1055 (message "Viewed classes will no%s be kept after use."
1056 (if br-keep-viewed-classes "w" "t")))
1057
1058 (defun br-top-classes (&optional arg)
1059 "Display list of top level classes.
1060 With prefix ARG, display all Environment classes."
1061 (interactive "P")
1062 (and (or (not (interactive-p))
1063 (br-in-top-buffer-p)
1064 (y-or-n-p "Exit to top-level class listing buffer? "))
1065 (cond (arg
1066 (br-show-top-classes 'br-all-classes 'uniq)
1067 (message "Listing of all Environment classes"))
1068 (t
1069 (br-show-top-classes 'br-get-top-classes 'uniq)
1070 (message "Listing of top-level classes")))
1071 (setq *br-level-hist* nil)))
1072
1073 (defun br-unique ()
1074 "Eliminate adjacent duplicate entry names from the current listing window.
1075 If two adjacent entries look the same one is eliminated, even if they refer
1076 to different class elements."
1077 (interactive)
1078 (let ((buffer-read-only)
1079 (again t)
1080 first second)
1081 (goto-char (point-min))
1082 (setq first (br-feature-current))
1083 (while again
1084 (setq again (= (forward-line 1) 0)
1085 second (br-feature-current))
1086 (if (not (string-equal first second))
1087 (setq first second)
1088 (beginning-of-line)
1089 (delete-region (point) (progn (forward-line 1) (point)))
1090 ;; back up to first line again
1091 (forward-line -1)))
1092 (goto-char (point-min))))
1093
1094 (defun br-version ()
1095 "Display browser version number and credits."
1096 (interactive)
1097 (br-file-to-viewer "BR-VERSION")
1098 (br-funcall-in-view-window
1099 (concat br-buffer-prefix-info "Help")
1100 (function (lambda ()
1101 (if (re-search-forward "<VERSION>" nil t)
1102 (replace-match br-version t t))
1103 (center-line)
1104 (set-buffer-modified-p nil)))
1105 t))
1106
1107 (defun br-view-entry (&optional prompt)
1108 "Displays source for any browser listing entry.
1109 Optional prefix arg PROMPT means prompt for entry name."
1110 (interactive "P")
1111 (let ((entry) (sig))
1112 (if prompt
1113 (cond ((and (setq entry (br-complete-entry))
1114 (string-match br-feature-signature-regexp entry))
1115 (if (setq sig (car (br-feature-signature-and-file entry)))
1116 (br-feature nil 'view sig)
1117 (error "(br-feature-signature-and-file): Couldn't find match for: '%s'" entry)))
1118 (entry ;; class name
1119 (br-view nil nil entry))
1120 (t (error "(br-complete-entry): Exited without selecting a match")))
1121 (cond ((br-find-feature-entry)
1122 (br-feature nil 'view))
1123 ((and (setq entry (br-find-class-name))
1124 (br-class-in-table-p entry))
1125 (br-view nil nil entry))
1126 (t (error "(OO-Browser): Entry may be referenced but not defined in the Environment."))))))
1127
1128 (defun br-view (&optional prompt writable class)
1129 "Displays class file in viewer window.
1130 Optional prefix arg PROMPT means prompt for class name. Non-nil WRITABLE means
1131 allow editing, otherwise display in read-only mode. Non-nil CLASS is class to
1132 display.
1133
1134 Return t if class is displayed or sent to an external viewer, else nil."
1135 (interactive "P")
1136 (or class (setq class (if prompt (br-complete-class-name)
1137 (br-find-class-name))))
1138 (cond ((null class)
1139 (beep)
1140 (message "(OO-Browser): Select a class to view.")
1141 nil)
1142 ((not (br-class-defined-p class)) nil)
1143 ((and hyperb:window-system
1144 (cond ((and br-editor-cmd writable)
1145 (br-edit-ext br-editor-cmd (br-class-path class))
1146 t)
1147 (br-viewer-cmd
1148 (br-view-ext br-viewer-cmd (br-class-path class))
1149 t))))
1150 ;; Support custom Lisp-based edit/view cmds on any display type
1151 ((and br-editor-cmd writable (not (stringp br-editor-cmd)))
1152 (br-edit-ext br-editor-cmd (br-class-path class))
1153 t)
1154 ((and br-viewer-cmd (not (stringp br-viewer-cmd)))
1155 (br-view-ext br-viewer-cmd (br-class-path class))
1156 t)
1157 (t (let ((owind (selected-window)))
1158 (unwind-protect
1159 (progn (br-to-view-window)
1160 (if (and (not br-keep-viewed-classes) buffer-read-only
1161 (null (buffer-modified-p)))
1162 (kill-buffer (current-buffer)))
1163 (if (br-find-class class (not writable))
1164 (progn (br-major-mode)
1165 (if writable
1166 (if (file-writable-p (buffer-file-name))
1167 (setq buffer-read-only nil))
1168 (setq buffer-read-only t)
1169 (select-window owind))
1170 t)))
1171 (or writable (select-window owind)))))))
1172
1173 (defun br-view-ext (viewer-cmd file)
1174 "Invoke a non-standard VIEWER-CMD on FILE.
1175 See also 'br-viewer-cmd'."
1176 (interactive "fFile to view: ")
1177 (or viewer-cmd (setq viewer-cmd br-viewer-cmd))
1178 (if (not (stringp viewer-cmd)) ;; must be a Lisp function that takes a
1179 ;; single, file arg
1180 (funcall viewer-cmd file)
1181 (setq delete-exited-processes t)
1182 (let ((proc)
1183 (name (concat br-vw-name br-vw-num))
1184 )
1185 (setq br-vw-num (1+ br-vw-num)
1186 proc (br-view-ext-start viewer-cmd name file))
1187 (if proc
1188 (process-kill-without-query proc)
1189 (beep)
1190 (message "(OO-Browser): Could not start external view process: %s"
1191 viewer-cmd)))))
1192
1193 (defun br-view-full-frame ()
1194 "Delete all windows in the selected frame except for the viewer window."
1195 (interactive)
1196 (setq *br-save-wconfig* (current-window-configuration))
1197 (br-to-view-window)
1198 (let ((buf (current-buffer)))
1199 (br-interrupt)
1200 (delete-other-windows)
1201 (switch-to-buffer buf))
1202 (let* ((cmd (concat br-lang-prefix "browse"))
1203 (key (car (where-is-internal (intern-soft cmd)))))
1204 (message "Recall OO-Browser with: {%s}"
1205 (if key
1206 (key-description key)
1207 (concat (key-description
1208 (or (car (where-is-internal
1209 'execute-extended-command))
1210 "\M-x"))
1211 " " cmd)))))
1212
1213 (defun br-viewer-kill ()
1214 "Kill all current external viewer sub-processes."
1215 (interactive)
1216 (if (br-kill-process-group br-vw-name br-vw-num "external viewers")
1217 (setq br-vw-num 0)))
1218
1219 (defun br-viewer-scroll-down (&optional arg)
1220 "Scroll viewer window downward ARG lines or a windowful if no ARG."
1221 (interactive "P")
1222 (let ((owind (selected-window)))
1223 (unwind-protect
1224 (progn (br-to-view-window)
1225 (scroll-down arg))
1226 (select-window owind))))
1227
1228 (defun br-viewer-scroll-up (&optional arg)
1229 "Scroll viewer window upward ARG lines or a windowful if no ARG."
1230 (interactive "P")
1231 (let ((owind (selected-window)))
1232 (unwind-protect
1233 (progn (br-to-view-window)
1234 (scroll-up arg))
1235 (select-window owind))))
1236
1237 (defun br-where (&optional prompt)
1238 "Display in minibuffer and return full path of a browser listing entry.
1239 Optional prefix arg PROMPT means prompt for entry name."
1240 (interactive "P")
1241 (let ((entry) (path))
1242 (if prompt
1243 (cond ((and (setq entry (br-complete-entry))
1244 (string-match br-feature-signature-regexp entry))
1245 (setq path (cdr (br-feature-signature-and-file entry))))
1246 (entry ;; class name
1247 (setq path (br-class-defined-p entry)))
1248 (t (error "(br-complete-entry): Exited without selecting a match")))
1249 (cond ((setq entry (br-find-feature-entry))
1250 (setq path (cdr (br-feature-signature-and-file entry))))
1251 ((setq entry (br-find-class-name))
1252 (or (setq path (br-class-path entry))
1253 (error "(OO-Browser): No path for this class in current Environment")))
1254 (t (error "(OO-Browser): No entry for current line in current Environment"))))
1255 (and path (message (concat entry ": " "\"" path "\""))
1256 path)))
1257
1258 (defun br-write-buffer (file)
1259 "Write narrowed portion of current browser buffer to a file."
1260 (interactive "FFile to write buffer to: ")
1261 (write-region (point-min) (point-max) file))
1262
1263 ;;; ************************************************************************
1264 ;;; Private functions
1265 ;;; ************************************************************************
1266
1267 (defun br-add-level-hist ()
1268 ;; Even though this next line looks useless, it cures a problem with
1269 ;; window buffer correspondences when the OO-Browser is started, so don't
1270 ;; remove it.
1271 (set-buffer (window-buffer (selected-window)))
1272 (setq *br-level-hist*
1273 (cons (list (selected-window) (buffer-name) (br-wind-line-at-point))
1274 *br-level-hist*)))
1275
1276 (defun br-ancestor-roots (class-list)
1277 "Return list of CLASS-LIST's unique ancestors which do not inherit from any other class.
1278 This list may include elements from CLASS-LIST itself."
1279 (let ((rtn) (parents) func)
1280 (setq func (function
1281 (lambda (class-list)
1282 (mapcar
1283 (function
1284 (lambda (class)
1285 (if (not (setq parents (br-get-parents class)))
1286 (setq rtn (cons class rtn))
1287 (funcall func parents))))
1288 class-list))))
1289 (funcall func class-list)
1290 (br-set-of-strings (sort rtn 'string-lessp))))
1291
1292 (defun br-ancestor-trees-inverted (class-list &optional depth offset)
1293 "Insert ancestor trees starting with classes from CLASS-LIST.
1294 Ancestor trees are inverted, i.e. parents appear below children, not above.
1295 Indent each class in CLASS-LIST by optional DEPTH spaces (default is 0 in
1296 order to ensure proper initialization). Offset each child level by optional
1297 OFFSET spaces from its parent (which must be greater than zero, default 2)."
1298 (or offset (setq offset 2))
1299 (or depth (setq depth 0))
1300 (if (= depth 0) (setq br-tmp-class-set nil))
1301 (let ((prev-expansion-str " ...")
1302 parents expand-subtree)
1303 (mapcar
1304 (function
1305 (lambda (class)
1306 (setq expand-subtree (br-set-cons br-tmp-class-set class)
1307 parents (if expand-subtree (br-get-parents class)))
1308 (indent-to depth)
1309 (insert class)
1310 (and (not expand-subtree) (br-has-children-p class)
1311 (insert prev-expansion-str))
1312 (insert "\n")
1313 (if br-ancestor-function
1314 (funcall br-ancestor-function
1315 class (not expand-subtree) (+ depth offset)))
1316 (if parents
1317 (br-ancestor-trees-inverted parents (+ depth offset) offset))))
1318 class-list))
1319 (if (= depth 0) (setq br-tmp-class-set nil)))
1320
1321 (defun br-ancestor-trees (class-list &optional depth offset)
1322 "Insert ancestor trees starting with classes from CLASS-LIST.
1323 Ancestor trees are not inverted, parents appear above children as in other
1324 browser listing windows. Indent each class in CLASS-LIST by optional DEPTH
1325 spaces (default is 0 in order to ensure proper initialization). Offset each
1326 child level by optional OFFSET spaces from its parent (which must be greater
1327 than zero, default 2)."
1328 (or offset (setq offset 2))
1329 (or depth (setq depth 0 br-tmp-depth 0))
1330 (if (= depth 0) (setq br-tmp-class-set nil))
1331 (let ((prev-expansion-str " ...")
1332 parents expand-subtree)
1333 (mapcar (function
1334 (lambda (class)
1335 (setq expand-subtree (br-set-cons br-tmp-class-set class)
1336 parents (if expand-subtree (br-get-parents class)))
1337 (if parents
1338 (progn (setq br-tmp-depth
1339 (max (+ depth offset) br-tmp-depth))
1340 (br-ancestor-trees
1341 parents (+ depth offset) offset)))
1342 (indent-to (- br-tmp-depth depth))
1343 (insert class)
1344 (and (not expand-subtree) (br-has-parents-p class)
1345 (insert prev-expansion-str))
1346 (insert "\n")
1347 (if br-ancestor-function
1348 (funcall br-ancestor-function
1349 class (not expand-subtree) (+ depth offset)))
1350 (if (= depth 0) (setq br-tmp-depth 0))))
1351 class-list))
1352 (if (= depth 0) (setq br-tmp-class-set nil)))
1353
1354 (defun br-browser-buffer-p (&optional buffer)
1355 "Returns t iff optional BUFFER or current buffer is an OO-Browser specific buffer."
1356 (equal 0 (string-match (concat br-buffer-prefix-inher
1357 "\\|" br-buffer-prefix-categ
1358 "\\|" br-buffer-prefix-blank
1359 "\\|" br-buffer-prefix-info)
1360 (buffer-name buffer))))
1361
1362 (defun br-buffer-level ()
1363 "Returns current listing buffer level as a string."
1364 (let* ((name (buffer-name))
1365 (pos (string-match "-[p]*[0-9]+$" name)))
1366 (and pos (substring name (1+ pos)))))
1367
1368 (defun br-class-level ()
1369 "Returns current class hierarchy level as an integer.
1370 1 is the top level."
1371 (let* ((name (buffer-name))
1372 (pos (string-match "[0-9]" name)))
1373 (and pos (string-to-int (substring name pos)))))
1374
1375 (defun br-listing-window-num ()
1376 "Return listing window number, lefmost is 1, non-listing window = 0."
1377 (let ((wind (selected-window))
1378 (ctr 0))
1379 (br-to-view-window)
1380 (while (not (eq wind (selected-window)))
1381 (other-window 1)
1382 (setq ctr (1+ ctr)))
1383 ctr))
1384
1385 (defun br-cleanup ()
1386 "Cleanup and free browser Environment data structures."
1387 (setq br-lang-prefix nil
1388 br-sys-paths-htable nil
1389 br-lib-paths-htable nil
1390 br-paths-htable nil
1391 br-sys-parents-htable nil
1392 br-lib-parents-htable nil
1393 br-parents-htable nil
1394 br-children-htable nil
1395 br-lib-prev-search-dirs nil
1396 br-sys-prev-search-dirs nil
1397 ))
1398
1399 (defun br-clear ()
1400 "Re-initialize all browser listing buffer displays.
1401 Leave point in browser top-level class listing buffer."
1402 (let ((n (max 1 (/ (frame-width) br-min-width-window))))
1403 (br-to-view-window)
1404 (other-window 1)
1405 (br-next-buffer 1)
1406 (while (> n 1)
1407 (setq n (1- n))
1408 (br-next-buffer nil br-buffer-prefix-blank))
1409 (br-to-view-window)
1410 (other-window 1)))
1411
1412 (defun br-descendant-trees (class-list &optional indent offset)
1413 "Insert descendant trees starting with classes from CLASS-LIST.
1414 Indent each class in CLASS-LIST by optional INDENT spaces (default is 0 in
1415 order to ensure proper initialization). Offset each child level by optional
1416 OFFSET spaces from its parent (which must be greater than zero, default 2)."
1417 (or indent (setq indent 0))
1418 (or offset (setq offset 2))
1419 (if (= indent 0) (setq br-tmp-class-set nil))
1420 (let ((prev-expansion-str " ...")
1421 children expand-subtree)
1422 (mapcar (function
1423 (lambda (class)
1424 (setq expand-subtree (br-set-cons br-tmp-class-set class)
1425 children (if expand-subtree (br-get-children class)))
1426 (indent-to indent)
1427 (insert class)
1428 (and (not expand-subtree) (br-has-children-p class)
1429 (insert prev-expansion-str))
1430 (insert "\n")
1431 (if children
1432 (br-descendant-trees children (+ indent offset) offset))))
1433 class-list))
1434 (if (= indent 0) (setq br-tmp-class-set nil)))
1435
1436 (defun br-display-buffer (suffix)
1437 "Displays browser buffer ending in SUFFIX in current window."
1438 (let ((buf (get-buffer (concat br-buffer-prefix suffix))))
1439 (if buf (progn (set-window-buffer (selected-window) buf)))
1440 buf))
1441
1442 (defun br-do-in-view-window (form)
1443 "Evaluate FORM in viewer window and then return to current window."
1444 (interactive)
1445 (let ((wind (selected-window)))
1446 (unwind-protect
1447 (progn (br-to-view-window)
1448 (eval form))
1449 (select-window wind))))
1450
1451 (defun br-edit-ext-start (editor-cmd name file)
1452 "Start an external viewer given by EDITOR-CMD using NAME applied to FILE."
1453 ;; Conditionalized code is necessary because of silly (start-process) calling
1454 ;; protocol.
1455 (cond (br-ed9
1456 (start-process name name editor-cmd br-ed1 br-ed2 br-ed3 br-ed4
1457 br-ed5 br-ed6 br-ed7 br-ed8 br-ed9 file))
1458 (br-ed8
1459 (start-process name name editor-cmd br-ed1 br-ed2 br-ed3 br-ed4
1460 br-ed5 br-ed6 br-ed7 br-ed8 file))
1461 (br-ed7
1462 (start-process name name editor-cmd br-ed1 br-ed2 br-ed3 br-ed4
1463 br-ed5 br-ed6 br-ed7 file))
1464 (br-ed6
1465 (start-process name name editor-cmd br-ed1 br-ed2 br-ed3 br-ed4
1466 br-ed5 br-ed6 file))
1467 (br-ed5
1468 (start-process name name editor-cmd br-ed1 br-ed2 br-ed3 br-ed4
1469 br-ed5 file))
1470 (br-ed4
1471 (start-process name name editor-cmd br-ed1 br-ed2 br-ed3 br-ed4
1472 file))
1473 (br-ed3
1474 (start-process name name editor-cmd br-ed1 br-ed2 br-ed3 file))
1475 (br-ed2
1476 (start-process name name editor-cmd br-ed1 br-ed2 file))
1477 (br-ed1
1478 (start-process name name editor-cmd br-ed1 file))
1479 (t
1480 (start-process name name editor-cmd file))
1481 ))
1482
1483 (defun br-funcall-in-view-window (buffer function &optional no-erase)
1484 "Clear out BUFFER and display return value from invocation of FUNCTION in viewer window.
1485 Move point to beginning of buffer and then return to current window. BUFFER
1486 may be a buffer name.
1487 With optional NO-ERASE, buffer is not erased before function is called."
1488 (interactive)
1489 (let ((wind (selected-window)))
1490 (unwind-protect
1491 (progn (br-to-view-window)
1492 (set-window-buffer (selected-window) (get-buffer-create buffer))
1493 (let (buffer-read-only)
1494 (if no-erase
1495 (goto-char (point-min))
1496 (erase-buffer))
1497 (funcall function))
1498 (goto-char (point-min)))
1499 (select-window wind))))
1500
1501 (defun br-file-to-viewer (filename)
1502 "Display FILENAME from OO-Browser source directory in browser viewer window.
1503 FILENAME should not contain any path information."
1504 (br-funcall-in-view-window
1505 (concat br-buffer-prefix-info "Help")
1506 (function (lambda ()
1507 (insert-file-contents (br-pathname filename))
1508 (set-buffer-modified-p nil)))))
1509
1510 (defun br-in-browser ()
1511 "Return selected frame if the OO-Browser is active in it, else return nil."
1512 (cond ((not (eq br-in-browser (selected-frame))) nil)
1513 ((one-window-p 'nomini)
1514 (setq br-in-browser nil))
1515 (t br-in-browser)))
1516
1517
1518 (defun br-in-top-buffer-p ()
1519 "Return t if point is in the top class listing buffer, else nil."
1520 (string-equal (br-buffer-level) "1"))
1521
1522 (defun br-in-view-window-p ()
1523 "Is point in a viewer window?"
1524 (br-non-listing-window-p))
1525
1526 (defun br-init ()
1527 "Initialization common to all OO-Browser invocations."
1528 (br-feature-tags-init))
1529
1530 (defun br-insert-classes (class-list &optional indent)
1531 "Insert CLASS-LIST in current buffer indented INDENT columns."
1532 (mapcar (function
1533 (lambda (class-name)
1534 (and indent (indent-to indent))
1535 (and class-name (insert class-name "\n"))))
1536 class-list))
1537
1538 (defun br-interrupt (&optional arg)
1539 (if (null arg)
1540 (mapcar
1541 (function
1542 (lambda (buf)
1543 (set-buffer buf)
1544 (if (or (eq major-mode 'br-mode) (br-browser-buffer-p))
1545 (bury-buffer nil))))
1546 (buffer-list))
1547 (setq *br-save-wconfig* nil
1548 *br-prev-wconfig* nil
1549 *br-prev-listing-window* nil)
1550 (mapcar
1551 (function
1552 (lambda (buf)
1553 (set-buffer buf)
1554 (if (or (eq major-mode 'br-mode)
1555 (br-browser-buffer-p))
1556 (progn (br-feature-clear-signatures)
1557 (set-buffer-modified-p nil)
1558 (kill-buffer (current-buffer))))))
1559 (buffer-list))
1560 (br-cleanup))
1561 (setq br-in-browser nil))
1562
1563 (defun br-mode ()
1564 "The major mode used by OO-Browser listing windows.
1565 See the file \"br-help\" for browser usage information.
1566 It provides the following keys: \\{br-mode-map}"
1567 (interactive)
1568 (use-local-map br-mode-map)
1569 (setq major-mode 'br-mode)
1570 (setq mode-name "OO-Browse")
1571 (set-syntax-table text-mode-syntax-table)
1572 (setq local-abbrev-table text-mode-abbrev-table)
1573 (setq case-fold-search t)
1574 (setq buffer-read-only t)
1575 (run-hooks 'br-class-list-hook)
1576 (run-hooks 'br-mode-hook))
1577
1578 (defun br-narrow-to-class ()
1579 (cond ((= (point-min) (point-max)) nil)
1580 ((br-find-class-name)
1581 (narrow-to-region (match-beginning 0) (match-end 0)))
1582 (t (error
1583 "(OO-Browser): 'br-narrow-to-class', current entry is not a class"))))
1584
1585 (defun br-narrow-to-feature ()
1586 "Narrow buffer to current feature entry."
1587 (if (br-feature-at-p)
1588 (narrow-to-region (match-beginning 0) (match-end 0))
1589 (error
1590 "(OO-Browser): 'br-narrow-to-feature' no current feature.")))
1591
1592 (defun br-feature-at-p ()
1593 "Returns t iff point is on a feature listing line."
1594 (save-excursion
1595 (beginning-of-line)
1596 (looking-at (concat "[ \t]*" br-feature-entry))))
1597
1598 (defun br-next-buffer (&optional special alt-prefix)
1599 "Returns next sequential browser buffer or special one if optional SPECIAL is non-nil.
1600 Non-nil ALT-PREFIX is used as prefix in buffer name."
1601 (let* ((suffix (or special (1+ (or (br-class-level) 0))))
1602 (buf (get-buffer-create
1603 (concat (or alt-prefix br-buffer-prefix)
1604 (if (integerp suffix)
1605 (int-to-string suffix)
1606 suffix)))))
1607 (if buf (progn
1608 (or special (br-next-listing-window))
1609 (set-window-buffer (selected-window) buf)
1610 (let (buffer-read-only)
1611 (erase-buffer)
1612 (kill-all-local-variables)
1613 ;; Clear out any feature tags that may have been associated
1614 ;; with this buffer, so we don't mistakenly reference them.
1615 (br-feature-clear-signatures))
1616 (setq mode-line-format (list " %17b --" '(-3 . "%p") "-%-"))
1617 (br-mode)
1618 (br-set-mode-line)
1619 (set-buffer-modified-p nil)))
1620 buf))
1621
1622 (defun br-next-listing-window (&optional prev)
1623 "Move to next browser listing window (non-viewer window).
1624 Optional PREV means to previous window."
1625 (let ((owind (selected-window)))
1626 (while (progn (other-window (if prev -1 1))
1627 (if (br-non-listing-window-p)
1628 (not (eq (selected-window) owind)))))))
1629
1630 (defun br-pathname (filename)
1631 "Return full pathname for FILENAME in browser Elisp directory."
1632 (if br-directory
1633 (expand-file-name filename br-directory)
1634 (error "The 'br-directory' variable must be set to a string value.")))
1635
1636 (defun br-protocol-entry-p ()
1637 "Return non-nil if point is within a protocol listing entry line."
1638 (and (string-equal br-lang-prefix "objc-")
1639 (save-excursion
1640 (beginning-of-line)
1641 (looking-at "[ \t]*@ <[^\>]*>"))))
1642
1643 (defun br-resize (min-width)
1644 "Resize browser listing windows to have MIN-WIDTH."
1645 (interactive)
1646 (let* ((window-min-width 3)
1647 (oldn (1- (length (br-window-list))))
1648 (n (max 1 (/ (frame-width) min-width)))
1649 (numw n)
1650 (diff (- numw oldn))
1651 (width (/ (frame-width) numw))
1652 (obuf (current-buffer)))
1653 (br-to-first-list-window)
1654 (cond ((= diff 0)
1655 (br-resize-windows numw width))
1656 ((> diff 0)
1657 (setq n oldn)
1658 (while (> n 1)
1659 (setq n (1- n))
1660 (shrink-window-horizontally (max 0 (- (window-width)
1661 min-width)))
1662 (br-next-listing-window))
1663 (setq n diff)
1664 (while (> n 0)
1665 (setq n (1- n))
1666 (split-window-horizontally (max window-min-width
1667 (- (window-width)
1668 min-width))))
1669 (setq n oldn)
1670 (while (< n numw)
1671 (setq n (1+ n))
1672 (br-next-listing-window)
1673 (br-next-buffer n br-buffer-prefix-blank))
1674 (br-to-first-list-window)
1675 (br-resize-windows numw width)
1676 )
1677 (t ;; (< diff 0)
1678 (while (> n 0)
1679 (setq n (1- n))
1680 (br-next-listing-window))
1681 (setq n (- diff))
1682 (while (> n 0)
1683 (setq n (1- n))
1684 (delete-window))
1685 (br-to-first-list-window)
1686 (br-resize-windows numw width)
1687 ))
1688 (setq br-min-width-window min-width)
1689 (let ((owind (get-buffer-window obuf)))
1690 (if owind
1691 (select-window owind)
1692 (br-to-view-window)
1693 (br-next-listing-window)))))
1694
1695 (defun br-resize-narrow ()
1696 "Resize listing windows so are narrower by 10 characters."
1697 (interactive)
1698 (if (<= window-min-width (- br-min-width-window 10))
1699 (br-resize (max window-min-width (- br-min-width-window 10)))
1700 (beep)))
1701
1702 (defun br-resize-widen ()
1703 "Resize listing windows so are wider by 10 characters."
1704 (interactive)
1705 (if (and (>= (frame-width) (+ br-min-width-window 10))
1706 (> (length (br-window-list)) 2))
1707 (br-resize (min (frame-width) (+ br-min-width-window 10)))
1708 (beep)))
1709
1710 (defun br-resize-windows (n width)
1711 (while (> n 1)
1712 (setq n (1- n))
1713 (shrink-window-horizontally (- (window-width) width))
1714 (br-next-listing-window)))
1715
1716 (defun br-set-mode-line ()
1717 "Set mode line string."
1718 (setq mode-line-buffer-identification (list (buffer-name)))
1719 (set-buffer-modified-p t))
1720
1721 (defun br-show-top-classes (func &optional uniq)
1722 "Display list of top level classes generated by calling FUNC.
1723 Optional UNIQ means sort and eliminate duplicates."
1724 (message "Ordering classes...")
1725 (let ((classes (funcall func)))
1726 (setq classes (br-class-list-filter classes))
1727 (br-clear)
1728 (let (buffer-read-only)
1729 (erase-buffer)
1730 (br-insert-classes classes)
1731 (if uniq
1732 (progn
1733 (if (stringp br-sort-options)
1734 (call-process-region (point-min) (point-max) "sort" t t nil
1735 br-sort-options)
1736 (call-process-region (point-min) (point-max) "sort" t t nil))
1737 (if (and (stringp br-sort-options)
1738 (string-match "u" br-sort-options))
1739 ;; Then sort made the list of elements unique, so do nothing.
1740 nil
1741 (call-process-region (point-min) (point-max) "uniq" t t))))))
1742 (goto-char (point-min))
1743 (message "Ordering classes...Done"))
1744
1745 (defun br-this-level-classes (&optional keep-indent)
1746 "Return list of the classes in the current listing.
1747 Optional KEEP-INDENT non-nil means keep indentation preceding class name."
1748 (let ((classes))
1749 (save-excursion
1750 (goto-char (point-min))
1751 (while (and (not (looking-at "^[ \t]*$"))
1752 (if (looking-at (format "^[ \t]*%s "
1753 br-feature-type-regexp)) ;; a feature
1754 t ;; skip this entry
1755 ;; assume is a class
1756 (setq classes (cons (br-find-class-name keep-indent)
1757 classes)))
1758 (= (forward-line 1) 0))))
1759 (nreverse (delq nil classes))))
1760
1761 (defun br-this-level-entries ()
1762 "Return list of all entries in the current listing."
1763 (let ((entries))
1764 (save-excursion
1765 (goto-char (point-min))
1766 (while (and (not (looking-at "^[ \t]*$"))
1767 (if (looking-at (format "^[ \t]*%s "
1768 br-feature-type-regexp)) ;; a feature
1769 (setq entries
1770 (cons (br-find-feature-entry) entries))
1771 ;; assume is a class
1772 (setq entries (cons (br-find-class-name) entries)))
1773 (= (forward-line 1) 0))))
1774 (nreverse (delq nil entries))))
1775
1776 (defun br-this-level-features ()
1777 "Return list of features in the current listing."
1778 (let ((feature-regexp (concat "[ \t]*" br-feature-entry))
1779 (features))
1780 (save-excursion
1781 (goto-char (point-min))
1782 (while (progn (if (looking-at feature-regexp)
1783 (setq features
1784 (cons (br-find-feature-entry) features)))
1785 (= (forward-line 1) 0))))
1786 (nreverse (delq nil features))))
1787
1788 (defun br-to-first-list-window ()
1789 (br-to-view-window)
1790 (br-next-listing-window))
1791
1792 (defun br-to-tree ()
1793 "If point is within ... move to inher/ancestry expansion for the current class."
1794 (if (save-excursion
1795 (skip-chars-backward ".")
1796 (looking-at "\\.\\.\\."))
1797 (progn (beginning-of-line)
1798 (let ((class-expr (concat "^[ \t]*"
1799 (br-find-class-name)
1800 "$")))
1801 (if (re-search-backward class-expr nil t)
1802 (progn (skip-chars-forward " \t")
1803 (recenter '(4))
1804 t))))))
1805
1806 (defun br-to-view-window ()
1807 "Move to viewer window."
1808 (if (br-in-view-window-p)
1809 nil
1810 (setq *br-prev-listing-window* (selected-window))
1811 (while (and (not (br-in-view-window-p))
1812 (progn (other-window 1)
1813 (not (eq (selected-window)
1814 *br-prev-listing-window*)))))))
1815
1816 (defun br-window-setup ()
1817 (and (fboundp 'modify-frame-parameters)
1818 (cdr (assq 'unsplittable (frame-parameters)))
1819 (modify-frame-parameters (selected-frame) '((unsplittable))))
1820 (delete-other-windows)
1821 ;; Set top of frame line in case it is not 0.
1822 (or (fboundp 'window-highest-p)
1823 (setq br-top-of-frame (nth 1 (window-edges))))
1824 (split-window-vertically nil)
1825 (let* ((n (max 1 (/ (frame-width) br-min-width-window)))
1826 (width (/ (frame-width) n)))
1827 (br-next-buffer 1)
1828 (while (> n 1)
1829 (setq n (1- n))
1830 (split-window-horizontally width)
1831 (br-next-buffer nil br-buffer-prefix-blank))))
1832
1833 (defun br-view-ext-start (viewer-cmd name file)
1834 "Start an external viewer given by VIEWER-CMD using NAME applied to FILE."
1835 ;; Conditionalized code is necessary because of silly (start-process) calling
1836 ;; protocol.
1837 (cond (br-vw9
1838 (start-process name name viewer-cmd br-vw1 br-vw2 br-vw3 br-vw4
1839 br-vw5 br-vw6 br-vw7 br-vw8 br-vw9 file))
1840 (br-vw8
1841 (start-process name name viewer-cmd br-vw1 br-vw2 br-vw3 br-vw4
1842 br-vw5 br-vw6 br-vw7 br-vw8 file))
1843 (br-vw7
1844 (start-process name name viewer-cmd br-vw1 br-vw2 br-vw3 br-vw4
1845 br-vw5 br-vw6 br-vw7 file))
1846 (br-vw6
1847 (start-process name name viewer-cmd br-vw1 br-vw2 br-vw3 br-vw4
1848 br-vw5 br-vw6 file))
1849 (br-vw5
1850 (start-process name name viewer-cmd br-vw1 br-vw2 br-vw3 br-vw4
1851 br-vw5 file))
1852 (br-vw4
1853 (start-process name name viewer-cmd br-vw1 br-vw2 br-vw3 br-vw4
1854 file))
1855 (br-vw3
1856 (start-process name name viewer-cmd br-vw1 br-vw2 br-vw3 file))
1857 (br-vw2
1858 (start-process name name viewer-cmd br-vw1 br-vw2 file))
1859 (br-vw1
1860 (start-process name name viewer-cmd br-vw1 file))
1861 (t
1862 (start-process name name viewer-cmd file))
1863 ))
1864
1865 ;;; ************************************************************************
1866 ;;; Private variables
1867 ;;; ************************************************************************
1868
1869 (defvar br-ancestor-function nil
1870 "If non-nil, a function of 3 arguments called after each ancestor class is inserted into an ancestry listing.
1871 First argument is the class just inserted, second argument is a flag
1872 indicating whether class has previously been displayed within the listing and
1873 third argument is the number of spaces to indent each feature entry for this
1874 class.")
1875
1876 (defvar br-top-of-frame 0
1877 "Frame line number of windows at top of the OO-Browser frame.")
1878
1879 (defvar br-ed-num 0)
1880 (defvar br-ed-name "extEd")
1881 (defvar br-vw-num 0)
1882 (defvar br-vw-name "extVw")
1883
1884 (defvar br-in-browser nil
1885 "Equal to the frame displaying the OO-Browser when in use, else nil.")
1886
1887 (defvar br-lib-search-dirs nil
1888 "List of directories below which OO source files and other library
1889 directories are found. A library is a stable group of OO classes. Do not
1890 set this variable directly. Each OO language library which invokes
1891 'br-browse' should set it.")
1892
1893 (defvar br-sys-search-dirs nil
1894 "List of directories below which OO source files and other system
1895 directories are found. A system is a group of OO classes that are likely to
1896 change. Do not set this variable directly. Each OO language library which
1897 invokes 'br-browse' should set it.")
1898
1899 (defvar *br-level-hist* nil
1900 "Internal history of visited listing windows and buffers.")
1901
1902 (defvar *br-prev-listing-window* nil
1903 "Saves listing window used prior to viewer window entry.
1904 Allows return to previous listing window when done with the viewer.")
1905
1906 (defvar *br-prev-wconfig* nil
1907 "Saves window configuration prior to browser entry.")
1908
1909 (defvar *br-save-wconfig* nil
1910 "Saves window configuration between invocations of the browser.")
1911
1912 (defconst br-buffer-prefix-categ "Categ-Lvl-")
1913 (defconst br-buffer-prefix-inher "Inher-Lvl-")
1914 (defconst br-buffer-prefix-blank "Blank-")
1915 (defconst br-buffer-prefix-info "OO-Browser ")
1916 (defvar br-buffer-prefix br-buffer-prefix-inher
1917 "Browser buffer name prefix.")
1918
1919
1920 (defvar br-mode-map nil
1921 "Keymap containing OO-Browser commands.")
1922 (if br-mode-map
1923 nil
1924 (setq br-mode-map (make-keymap))
1925 (suppress-keymap br-mode-map)
1926 (define-key br-mode-map "@" 'br-at)
1927 (define-key br-mode-map "1" 'br-view-full-frame)
1928 (define-key br-mode-map "\C-c^" 'br-add-class-file)
1929 (define-key br-mode-map "a" 'br-ancestors)
1930 (define-key br-mode-map "b" 'br-buffer-menu)
1931 (define-key br-mode-map "\C-c\C-b" 'br-report-bug)
1932 (define-key br-mode-map "c" 'br-children)
1933 (define-key br-mode-map "C" 'br-categories)
1934 (define-key br-mode-map "\M-c" 'br-class-stats)
1935 (define-key br-mode-map "\C-c\C-c" 'br-env-create)
1936 (define-key br-mode-map "d" 'br-descendants)
1937 (define-key br-mode-map "\C-c\C-d" 'br-delete)
1938 ;; {M-d} is used down below for 'br-tree'
1939 (define-key br-mode-map "e" 'br-edit-entry)
1940 (define-key br-mode-map "\M-e" 'br-env-stats)
1941 (define-key br-mode-map "\C-c\C-e" 'br-env-rebuild)
1942 (define-key br-mode-map "f" 'br-features)
1943 (define-key br-mode-map "F" 'br-feature-signature)
1944 ;; {M-f} is used down below for 'br-tree-features-toggle'
1945 ;; {M-g} is used down below for 'br-tree-graph'
1946 (define-key br-mode-map "?" 'br-help)
1947 (define-key br-mode-map "h" 'br-help)
1948 (define-key br-mode-map "H" 'br-help-ms) ;; mouse help
1949 (define-key br-mode-map "i" 'br-entry-info)
1950 (define-key br-mode-map "I" 'br-implementors)
1951 (define-key br-mode-map "\C-c\C-k" 'br-kill)
1952 ;; {M-k} is used down below for 'br-tree-kill'
1953 (define-key br-mode-map "l" 'br-lib-top-classes)
1954 (define-key br-mode-map "L" 'br-lib-rebuild)
1955 (define-key br-mode-map "\C-c\C-l" 'br-env-load)
1956 (define-key br-mode-map "m" 'br-match)
1957 (define-key br-mode-map "M" 'br-match-entries)
1958 ;; "\C-c\C-m" is reserved for future use.
1959 (define-key br-mode-map "\C-n" 'br-next-entry)
1960 (define-key br-mode-map "o" 'br-order)
1961 (define-key br-mode-map "p" 'br-parents)
1962 (define-key br-mode-map "P" 'br-protocols)
1963 (define-key br-mode-map "\C-p" 'br-prev-entry)
1964 (define-key br-mode-map "q" 'br-quit)
1965 ;; {r} does the same thing as {f} and is for backward compatibility
1966 ;; with prior OO-Browser releases. It may be rebound in the future, so
1967 ;; learn to use {f} instead.
1968 (define-key br-mode-map "r" 'br-features)
1969 (define-key br-mode-map "\C-c\C-r" 'br-refresh)
1970 (define-key br-mode-map "s" 'br-sys-top-classes)
1971 (define-key br-mode-map "S" 'br-sys-rebuild)
1972 (define-key br-mode-map "\C-c\C-s" 'br-env-save)
1973 (define-key br-mode-map "t" 'br-top-classes)
1974 (define-key br-mode-map "u" 'br-unique)
1975 (define-key br-mode-map "v" 'br-view-entry)
1976 (define-key br-mode-map "V" 'br-view-friend)
1977 (define-key br-mode-map "\C-c\C-v" 'br-to-from-viewer)
1978 (define-key br-mode-map "\C-c\C-w" 'br-write-buffer)
1979 (define-key br-mode-map "w" 'br-where)
1980 (define-key br-mode-map "x" 'br-exit-level)
1981 (define-key br-mode-map "\C-x-" 'br-resize-narrow)
1982 (define-key br-mode-map "\C-x+" 'br-resize-widen)
1983 (define-key br-mode-map "#" 'br-count)
1984 (define-key br-mode-map "\C-c#" 'br-version)
1985 (define-key br-mode-map " " 'br-viewer-scroll-up)
1986 (define-key br-mode-map "\177" 'br-viewer-scroll-down)
1987 ;;
1988 ;; Define graphical browser keys if a window system is available.
1989 (if hyperb:window-system
1990 (progn (require 'br-tree)
1991 (define-key br-mode-map "\M-d" 'br-tree)
1992 (define-key br-mode-map "\M-f" 'br-tree-features-toggle)
1993 (define-key br-mode-map "\M-g" 'br-tree-graph)
1994 (define-key br-mode-map "\M-k" 'br-tree-kill))))
1995
1996 (defvar br-tmp-class-set nil
1997 "Set of classes created for temporary use by br-*-trees functions.")
1998 (defvar br-tmp-depth 0
1999 "Temporary variable indicating inheritance depth of class in 'br-ancestor-trees'.")
2000
2001 (provide 'br)