4 ;; SUMMARY: OO-Browser support functions.
5 ;; USAGE: GNU Emacs Lisp Library
6 ;; KEYWORDS: oop, tools
11 ;; ORIG-DATE: 22-Mar-90
12 ;; LAST-MOD: 10-May-01 at 15:17:10 by Bob Weiner
14 ;;; ************************************************************************
16 ;;; ************************************************************************
18 (defsubst br-get-children-htable ()
19 "Loads or builds `br-children-htable' if necessary and returns value."
20 (br-get-htable "children"))
22 (defsubst br-get-paths-htable ()
23 "Loads or builds `br-paths-htable' if necessary and returns value."
24 (br-get-htable "paths"))
26 (defsubst br-get-parents-htable ()
27 "Loads or builds `br-parents-htable' if necessary and returns value."
28 (br-get-htable "parents"))
30 ;;; ************************************************************************
31 ;;; Other required Elisp libraries
32 ;;; ************************************************************************
40 ;;; ************************************************************************
42 ;;; ************************************************************************
44 (defvar br-null-path "<none>"
45 "Pathname associated with OO-Browser entities which have no source file.
46 That is, virtual entities, such as categories.")
48 (defvar br-empty-htable (hash-make 0)
49 "An empty hash table used to check whether OO-Browser hash tables are empty.")
51 ;;; ************************************************************************
52 ;;; General public functions
53 ;;; ************************************************************************
55 (defun br-add-default-classes (class-list)
56 "Add classes from CLASS-LIST as default classes for the current Environment.
57 Default class names should be surrounded by square brackets.
58 Add classes to the list of System classes."
59 (mapcar (function (lambda (class)
60 (br-add-class class br-null-path nil)))
63 (defun br-buffer-replace (regexp to-str &optional literal-flag)
64 "In current buffer, replace all occurrences of REGEXP with TO-STR.
65 Optional LITERAL-FLAG non-nil means ignore special regexp characters
66 and just insert them literally."
67 (goto-char (point-min))
68 (while (re-search-forward regexp nil t)
69 (replace-match to-str t literal-flag)
72 (if (fboundp 'buffer-substring-no-properties)
73 (defalias 'br-buffer-substring 'buffer-substring-no-properties)
74 (defalias 'br-buffer-substring 'buffer-substring))
76 (defun br-buffer-delete-c-comments ()
77 "Remove all // and /* */ comments from the current buffer.
78 Assumes the buffer is not read-only and does not handled nested
81 (goto-char (point-min))
82 (while (re-search-forward "//.*" nil t) (replace-match "" t t))
83 (goto-char (point-min))
84 (while (re-search-forward "/\\*" nil t)
85 (delete-region (match-beginning 0)
86 (if (re-search-forward "\\*/" nil t)
90 (defun br-c-to-comments-begin ()
91 "Skip back from current point past any preceding C-based comments at the beginning of lines.
92 Presumes no \"/*\" strings are nested within multi-line comments."
94 (while (progn (setq opoint (point))
96 (if (zerop (forward-line -1))
98 ;; If begins with "//" or ends with "*/", then is a
100 ((looking-at "[ \t]*\\(//\\|$\\)"))
101 ((looking-at ".*\\*/[ \t]*$")
103 ;; Avoid //*** single line comments here.
104 (if (re-search-backward "\\(^\\|[^/]\\)/\\*" nil t)
105 (progn (beginning-of-line)
106 (looking-at "[ \t]*/\\*")))))
109 ;; Skip past whitespace
110 (skip-chars-forward " \t\n\r\f")
111 (beginning-of-line)))
113 (defun br-delete-space (string)
114 "Delete any leading and trailing space from STRING and return the STRING."
115 (if (string-match "\\`[ \t\n\r\f]+" string)
116 (setq string (substring string (match-end 0))))
117 (if (string-match "[ \t\n\r\f]+\\'" string)
118 (setq string (substring string 0 (match-beginning 0))))
121 (defun br-first-match (regexp list)
122 "Return non-nil if REGEXP matches to an element of LIST.
123 All elements of LIST must be strings.
124 The value returned is the first matched element."
125 (while (and list (not (string-match regexp (car list))))
126 (setq list (cdr list)))
129 (defun br-filename-head (path)
130 (regexp-quote (file-name-sans-extension
131 (file-name-nondirectory path))))
133 (defun br-flatten (obj)
134 "Return a single-level list of all atoms in OBJ in original order.
135 OBJ must be a list, cons cell, vector or atom."
136 ;; Test case: (br-flatten '((a b (c . d)) e (f (g [h (i j) [k l m]] (n)))))
137 ;; Should produce: => (a b c d e f g h i j k l m n)
138 (cond ((null obj) nil)
141 (setq obj (append obj nil))
143 (append (br-flatten (car obj)) (br-flatten (cdr obj))))
144 ((atom obj) (list obj))
146 (error "(br-flatten): Invalid type, '%s'" obj))
148 (append (br-flatten (car obj)) (br-flatten (cdr obj))))))
150 (defun br-duplicate-and-unique-strings (sorted-strings)
151 "Return SORTED-STRINGS list with a list of duplicate entries consed onto the front of the list."
152 (let ((elt1) (elt2) (lst sorted-strings)
153 (count 0) (repeat) (duplicates))
154 (while (setq elt1 (car lst) elt2 (car (cdr lst)))
155 (cond ((not (string-equal elt1 elt2))
156 (setq lst (cdr lst)))
158 ;; Already recorded this duplicate.
159 (setcdr lst (cdr (cdr lst))))
161 (setq count (1+ count)
162 duplicates (cons elt1 duplicates)
164 (setcdr lst (cdr (cdr lst))))))
165 (cons (sort duplicates 'string-lessp) sorted-strings)))
167 (defun br-set-of-strings (sorted-strings &optional count)
168 "Return SORTED-STRINGS list with any duplicate entries removed.
169 Optional COUNT conses number of duplicates on to front of list before return."
170 (and count (setq count 0))
171 (let ((elt1) (elt2) (lst sorted-strings)
174 (lambda (a b) (if (string-equal a b)
175 (setq count (1+ count)))))
176 (function (lambda (a b) (string-equal a b))))))
177 (while (setq elt1 (car lst) elt2 (car (cdr lst)))
178 (if (funcall test elt1 elt2)
179 (setcdr lst (cdr (cdr lst)))
180 (setq lst (cdr lst)))))
181 (if count (cons count sorted-strings) sorted-strings))
183 (defun br-member-sorted-strings (elt list)
184 "Return non-nil if ELT is an element of LIST. Comparison done with `string-equal'.
185 All ELTs must be strings and the list must be sorted in ascending order.
186 The value returned is actually the tail of LIST whose car is ELT."
187 (while (and list (not (string-equal (car list) elt)))
188 (setq list (and (string-lessp (car list) elt)
192 (defun br-delete-sorted-strings (elt set)
193 "Removes element ELT from SET and returns new set.
194 Assumes SET is a valid set of sorted strings.
195 Use (setq set (br-delete-sorted-strings elt set)) to assure that the set is
196 always properly modified."
197 (let ((rest (br-member-sorted-strings elt set)))
199 (cond ((= (length set) 1) (setq set nil))
201 (setcdr (nthcdr (- (length set) 2) set) nil))
202 (t (setcar rest (car (cdr rest)))
203 (setcdr rest (cdr (cdr rest)))))))
206 (defun br-pathname-head (path)
207 (if (string-match "\\(.+\\)\\." path)
208 (substring path 0 (match-end 1))
211 (defun br-quote-match (match-num)
212 "Quote special symbols in last matched expression MATCH-NUM."
213 (br-regexp-quote (br-buffer-substring (match-beginning match-num)
214 (match-end match-num))))
216 (defun br-rassoc (elt list)
217 "Return non-nil if ELT is the cdr of an element of LIST.
218 Comparison done with `equal'. The value is actually the tail of LIST
219 starting at the element whose cdr is ELT."
220 (while (and list (not (equal (cdr (car list)) elt)))
221 (setq list (cdr list)))
224 (defun br-regexp-quote (obj)
225 "If OBJ is a string, quote and return it for use in a regular expression."
226 ;; Don't use (stringp obj) here since we want to signal an error if some
227 ;; caller ever passes in a non-nil, non-string object, to aid in debugging.
228 (if obj (regexp-quote obj)))
230 (defun br-relative-path (filename &optional directory)
231 "Convert FILENAME to be relative to DIRECTORY or default-directory.
232 The shorter of the absolute and relative paths is returned."
233 (let ((relative-path (file-relative-name filename directory)))
234 (if (< (length relative-path) (length filename))
238 (defmacro br-set-cons (set elt)
239 "Add to SET element ELT. Returns nil iff ELT is already in SET.
240 Uses `equal' for comparison."
241 (` (if (br-member (, elt) (, set))
243 (setq (, set) (cons (, elt) (, set))))))
245 (if (fboundp 'temp-directory)
246 (defalias 'br-temp-directory 'temp-directory)
247 (defun br-temp-directory ()
249 (file-name-as-directory
250 (or (getenv "TMPDIR")
253 (if (file-directory-p "/tmp/") "/tmp/")
254 (if (file-directory-p "C:/tmp/") "C:/tmp/")
255 (if hyperb:microcruft-os-p
257 (progn (make-directory "C:/tmp/") "C:/tmp/")
258 (error (expand-file-name "~")))
260 (progn (make-directory "/tmp/") "/tmp/")
261 (error (expand-file-name "~"))))))))
262 (if (file-writable-p tmp-dir)
263 (progn (setenv "TMPDIR" tmp-dir) tmp-dir)
264 (error "(br-temp-directory): Temp dir, \"%s\", is not writable."
267 (defun br-wind-line-at-point ()
268 "Return window relative line number that point is on."
269 (max 0 (1- (- (count-lines 1 (min (1+ (point)) (point-max)))
270 (count-lines 1 (window-start))))))
272 ;;; ************************************************************************
273 ;;; Browser public functions
274 ;;; ************************************************************************
276 (defun br-add-class (class-name &optional class-path lib-table-p save-file)
277 "Add or replace CLASS-NAME in current Environment.
278 Find class source in optional CLASS-PATH. Interactively or when optional
279 CLASS-PATH is nil, defaults to current buffer file as CLASS-PATH. If
280 optional LIB-TABLE-P is non-nil, add to Library Environment, otherwise add to
281 System Environment. If optional SAVE-FILE is t, the Environment is then
282 stored to filename given by `br-env-file'. If SAVE-FILE is non-nil and
283 not t, its string value is used as the file to which to save the Environment.
284 Does not update children lookup table."
286 (list (read-string "Class name to add: ")
287 (read-file-name (concat "Class file name"
289 " (default <current file>)")
291 nil buffer-file-name t)
292 (y-or-n-p "Add to Library, rather than System tables? ")
294 (concat "Save tables after addition to " br-env-file "? "))))
298 ;; If class-name is in table
299 ;; If function called interactively
300 ;; Query whether should overwrite class-name in tables
302 ;; Replace class and its features
304 ;; Don't add class; do nothing
307 ;; Store class without its features in all necessary tables
310 ;; Store class and its features under key in all necessary tables
313 (or class-path (setq class-path buffer-file-name)
314 (error "No class pathname specified."))
315 (if (or (string-equal class-name "")
316 (not (or (equal class-path br-null-path)
317 (file-exists-p class-path))))
318 (error "Invalid class specified, `%s', in: \"%s\"" class-name class-path))
319 ;; Is class already in Environment?
320 (if (hash-key-p class-name (br-get-htable
321 (if lib-table-p "lib-parents" "sys-parents")))
322 (if (or (not (interactive-p))
323 (y-or-n-p (format "Overwrite existing `%s' entry? " class-name)))
324 (br-real-add-class lib-table-p class-name class-path t)
325 (setq save-file nil))
326 (br-real-add-class lib-table-p class-name class-path))
327 (cond ((eq save-file nil))
328 ((eq save-file t) (br-env-save))
329 ((br-env-save save-file))))
331 (defun br-build-lib-htable ()
332 "Build Library dependent Environment."
334 (cond ((and (interactive-p)
335 (not (y-or-n-p "Rebuild Library Environment? ")))
338 (message "Building Library Environment...")
340 (br-real-build-alists br-lib-search-dirs)
341 (if (interactive-p) (br-feature-build-htables))
342 (setq br-lib-paths-htable (hash-make br-paths-alist)
343 br-lib-parents-htable (hash-make br-parents-alist))
344 (run-hooks 'br-after-build-lib-hook)
346 ;; Set prev-search-dirs so table rebuilds are not triggered.
347 (setq br-lib-prev-search-dirs br-lib-search-dirs)
348 (if (interactive-p) (br-env-save))
349 (message "Building Library Environment...Done")
352 (defun br-build-sys-htable ()
353 "Build System dependent class Environment."
355 (cond ((and (interactive-p)
356 (not (y-or-n-p "Rebuild System Environment? ")))
359 (message "Building System Environment...")
361 (br-real-build-alists br-sys-search-dirs)
362 (if (interactive-p) (br-feature-build-htables))
363 (setq br-sys-paths-htable (hash-make br-paths-alist)
364 br-sys-parents-htable (hash-make br-parents-alist))
365 (run-hooks 'br-after-build-sys-hook)
367 ;; Set prev-search-dirs so table rebuilds are not triggered.
368 (setq br-sys-prev-search-dirs br-sys-search-dirs)
369 (if (interactive-p) (br-env-save))
370 (message "Building System Environment...Done")
373 (defun br-class-in-table-p (class-name)
374 "Return t iff CLASS-NAME is referenced within the current Environment."
375 (interactive (list (br-complete-class-name)))
376 (if class-name (hash-key-p class-name (br-get-parents-htable))))
378 ;;; The OO-Browser depends on the name of this next function; don't change it.
379 (defun br-class-list-identity (class-list top-only-flag)
382 (defun br-class-path (class-name &optional insert)
383 "Return full path, if any, to CLASS-NAME.
384 With optional prefix argument INSERT non-nil, insert path at point.
385 Only the first matching class is returned, so each CLASS-NAME should be
386 unique. Set `br-lib/sys-search-dirs' properly before use."
387 (interactive (list (br-complete-class-name)))
388 (setq class-name (if class-name (br-set-case class-name)))
390 (class-htable (br-get-paths-htable)))
393 (function (lambda (val-key-cons)
394 (and (br-member class-name (car val-key-cons))
395 (setq class-path (br-select-path val-key-cons nil))
398 (if (equal class-path br-null-path)
399 (setq class-path nil))
400 (and (interactive-p) (setq insert current-prefix-arg))
401 (if (and insert class-path)
407 "(OO-Browser): No `%s' class found in `br-lib/sys-search-dirs'."
411 (defun br-find-class (&optional class-name view-only other-win)
412 "Display file of class text matching CLASS-NAME in VIEW-ONLY mode if non-nil.
413 Return the line number of the start of the class displayed when successful, nil
414 otherwise. Can also signal an error when called interactively."
416 (and (interactive-p) (setq view-only current-prefix-arg))
418 (info (equal br-lang-prefix "info-"))
422 (or class-name (br-complete-class-name))
423 class-path (br-class-path class-name))
425 (info (br-find-info-node class-path class-name (not view-only))
426 (setq found (br-line-number)))
428 (if (file-readable-p class-path)
430 (funcall br-view-file-function class-path other-win)
431 (funcall br-edit-file-function class-path other-win)
432 ;; Handle case of already existing buffer in
434 (and buffer-read-only
435 (file-writable-p class-path)
436 (progn (setq buffer-read-only nil)
437 ;; Force mode-line redisplay
438 (set-buffer-modified-p
439 (buffer-modified-p)))))
441 (let ((opoint (point))
447 (goto-char (point-min))
448 (if br-narrow-view-to-class
449 ;; Display file narrowed to definition of
451 (if (br-to-class-definition class-name)
452 ;; Narrow display to this class
453 (progn (narrow-to-region
456 (match-beginning 0)))
457 (br-back-over-comments)
461 (progn (br-to-class-end)
465 (narrow-to-region pmin pmax)
466 (setq err (format "(OO-Browser): No `%s' in \"%s\""
467 class-name class-path)))
468 (if (br-to-class-definition class-name)
469 (progn (setq opoint (goto-char (match-beginning 0)))
470 (br-back-over-comments)
473 (narrow-to-region pmin pmax)
474 (setq err (format "(OO-Browser): No `%s' in %s" class-name
476 (if err nil (setq found (br-line-number))))
477 (setq err (format "(OO-Browser): %s's source file, \"%s\", was not found or was unreadable"
478 class-name class-path))))
480 (setq err (format "(OO-Browser): No `%s' class defined in Environment"
484 (message "(OO-Browser): `%s' class in \"%s\""
485 class-name (br-env-substitute-home class-path)))
488 (defun br-to-class-definition (class-name)
489 "Search forward past the definition signature of CLASS-NAME within the current buffer.
490 Return non-nil iff definition is found. Leave match patterns intact after the search."
491 (let ((class-def (br-class-definition-regexp class-name))
493 (while (and (setq found (re-search-forward class-def nil t))
494 (fboundp 'c-within-comment-p)
495 (save-match-data (c-within-comment-p)))
499 (defun br-back-over-comments ()
500 "Skip back over any preceding comments stopping if the current line would leave the window."
501 (let ((opoint (point)))
502 ;; Language-specific.
503 (br-to-comments-begin)
504 ;; The following elaborate conditional is true if moving back past the
505 ;; comments has pushed the original display line outside of the window
506 ;; bounds. The simpler check of (window-end) is not used because
507 ;; redisplay has not yet been run and thus (window-end) does not yet
508 ;; recorded the updated value. It is better to err on the high
509 ;; side when subtracting lines from the (window-height) here to ensure
510 ;; that the original line is displayed.
511 (if (> (count-lines (point) opoint) (- (window-height) 3))
512 (progn (goto-char opoint)
513 ;; Make current line the last in the window in order to show as
514 ;; much commentary as possible without scrolling the current
515 ;; code line outside of the window.
519 (defun br-line-number ()
520 "Return the present absolute line number within the current buffer counting from 1."
523 (1+ (count-lines 1 (point)))))
525 (defun br-display-code (start)
526 "Goto START, skip back past preceding comments and then display."
528 (skip-chars-forward " \t\n\r")
530 ;; If the definition line is at the end of a list,
531 ;; e.g. following a closing brace, ensure that the
532 ;; beginning of the expression is visible.
534 (if (looking-at "[ \t]*\\s\)")
535 (progn (goto-char (match-end 0))
537 (progn (backward-list 1)
540 (br-back-over-comments)
544 (defun br-major-mode ()
545 "Invoke language-specific major mode on current buffer if not already set."
546 (or (eq major-mode (symbol-function 'br-lang-mode))
548 (not buffer-file-name)
551 (defun br-class-category-p (name)
552 "Return (category) if NAME contains a class category."
553 (and (string-equal br-lang-prefix "objc-")
554 (string-match "\([^\)]+\)" name)
555 (substring name (match-beginning 0) (match-end 0))))
557 (defalias 'br-protocol-support-p 'br-interface-support-p)
558 (defun br-interface-support-p ()
559 "Return t if the present OO-Browser Environment language contains interface (protocol) browsing support."
560 (if (br-member br-lang-prefix '("java-" "objc-")) t))
562 (defalias 'br-protocol-p 'br-interface-p)
563 (defun br-interface-p (class-name)
564 "Return CLASS-NAME if it is an interface or protocol which specifies method interfaces to which classes conform, else nil.
565 In Java, these are called interfaces. In Objective-C, they are called protocols."
566 (and (br-interface-support-p)
567 (eq (aref class-name 0) ?\<)
570 (defun br-default-class-p (class-name)
571 "Return CLASS-NAME if it is a default class, one generated by the OO-Browser, else nil."
572 (if (eq (aref class-name 0) ?\[) class-name))
574 (defun br-concrete-class-p (class-name)
575 "Return CLASS-NAME if it is not an interface or protocol, which generally means that all methods are implemented, else nil."
576 (if (not (br-interface-p class-name)) class-name))
578 (defun br-scan-mode ()
579 "Invoke language-specific major mode for current buffer without running its hooks.
580 This is used when scanning source files to build Environments."
582 (intern-soft (concat (symbol-name (symbol-function 'br-lang-mode))
585 (eval (` (let ((, mode-hook-sym)) (br-lang-mode))))
588 (defun br-show-children (class-name)
589 "Return children of CLASS-NAME from current Environment."
590 (interactive (list (br-complete-class-name t)))
592 (br-get-children class-name)))
594 (defun br-show-parents (class-name)
595 "Return parents of CLASS-NAME from Environment or scan of current buffer's source."
596 (interactive (list (br-complete-class-name t)))
598 (if (br-class-in-table-p class-name)
599 (br-get-parents class-name)
600 (if (and buffer-file-name (file-readable-p buffer-file-name))
601 (let ((br-view-file-function 'br-insert-file-contents))
602 (br-get-parents-from-source buffer-file-name class-name))))))
604 (defun br-undefined-classes ()
605 "Return a list of the classes referenced but not defined within the current Environment."
606 (let ((classes (hash-get br-null-path (br-get-paths-htable))))
607 (delq nil (mapcar (function (lambda (class)
608 ;; Remove default classes
609 (if (not (eq (aref class 0) ?\[))
613 ;;; ************************************************************************
614 ;;; Private functions
615 ;;; ************************************************************************
617 (defun br-add-to-paths-htable (class-name paths-key htable)
618 "Add CLASS-NAME under PATHS-KEY in paths lookup HTABLE."
619 (let ((other-classes (hash-get paths-key htable)))
620 (if (and other-classes (br-member class-name other-classes))
622 (hash-add (cons class-name other-classes) paths-key htable))))
624 (defun br-build-lib-parents-htable ()
626 (if (not br-lib-search-dirs)
628 (message "Building Library parents...")
630 (if br-lib-paths-htable
631 (setq br-lib-parents-htable
633 (br-real-build-parents-alist br-lib-paths-htable)))
634 (br-real-build-alists br-lib-search-dirs)
635 (br-feature-build-htables)
636 (setq br-lib-parents-htable (hash-make br-parents-alist)))
637 (if (interactive-p) (br-env-save))
638 (message "Building Library parents...Done")))
640 (defun br-build-lib-paths-htable ()
642 (if (not br-lib-search-dirs)
644 (message "Building Library paths...")
646 (br-real-build-alists br-lib-search-dirs)
647 (br-feature-build-htables)
648 (setq br-lib-paths-htable (hash-make br-paths-alist))
649 (if (interactive-p) (br-env-save))
650 (message "Building Library paths...Done")))
652 (defun br-build-sys-parents-htable ()
654 (if (not br-sys-search-dirs)
656 (message "Building System parents...")
658 (if br-sys-paths-htable
659 (setq br-sys-parents-htable
661 (br-real-build-parents-alist br-sys-paths-htable)))
662 (br-real-build-alists br-sys-search-dirs)
663 (br-feature-build-htables)
664 (setq br-sys-parents-htable
665 (hash-make br-parents-alist)))
666 (if (interactive-p) (br-env-save))
667 (message "Building System parents...Done")))
669 (defun br-build-sys-paths-htable ()
671 (if (not br-sys-search-dirs)
673 (message "Building System paths...")
675 (br-real-build-alists br-sys-search-dirs)
676 (br-feature-build-htables)
677 (setq br-sys-paths-htable (hash-make br-paths-alist))
678 (if (interactive-p) (br-env-save))
679 (message "Building System paths...Done")))
681 (defun br-build-children-htable ()
683 (setq br-children-htable (br-real-build-children-htable))
684 (if (interactive-p) (br-env-save)))
686 (defun br-build-parents-htable ()
688 (br-build-sys-parents-htable)
689 (br-build-lib-parents-htable)
690 ;; Make System entries override Library entries which they duplicate, since
691 ;; this is generally more desireable than merging the two.
692 (br-merge-parents-htables)
693 (if (interactive-p) (br-env-save)))
695 (defun br-merge-parents-htables ()
696 (let ((hash-merge-values-function 'hash-merge-first-value))
697 (setq br-parents-htable (hash-merge br-sys-parents-htable
698 br-lib-parents-htable))))
700 (defun br-build-paths-htable ()
702 (br-build-sys-paths-htable)
703 (br-build-lib-paths-htable)
704 (br-merge-paths-htables)
705 (if (interactive-p) (br-env-save)))
707 (defun br-merge-paths-htables ()
708 (setq br-paths-htable (hash-merge br-sys-paths-htable br-lib-paths-htable))
710 ;; We may have merged two tables where a single class-name was referenced
711 ;; in one and defined in the other which means it will have both a path
712 ;; entry and a br-null-path entry; remove the latter.
713 (let ((null-path-classes (hash-get br-null-path br-paths-htable))
714 (null-lib-classes (sort (hash-get br-null-path br-lib-paths-htable)
716 (null-sys-default-classes
718 (mapcar (function (lambda (class)
719 (if (br-default-class-p class) class)))
720 (hash-get br-null-path br-sys-paths-htable))))
721 (null-sys-referenced-classes
722 ;; Eliminates default classes; need this for System classes only
723 ;; since default classes are not added to the Library hash tables.
726 (mapcar (function (lambda (class)
727 (if (br-default-class-p class) nil class)))
728 (hash-get br-null-path br-sys-paths-htable)))
731 (progn (hash-delete br-null-path br-paths-htable)
732 (setq null-path-classes
737 (if (or (br-default-class-p class)
738 (not (br-class-path class)))
740 ;; Class path exists, but we may need to
741 ;; remove a null entry from the Library or
742 ;; System table if it was referenced but not
743 ;; defined in one of these.
744 (setq null-lib-classes
745 (br-delete-sorted-strings
746 class null-lib-classes))
747 (setq null-sys-referenced-classes
748 (br-delete-sorted-strings
749 class null-sys-referenced-classes))
751 null-path-classes))))
752 (if null-path-classes
753 (hash-add null-path-classes br-null-path br-paths-htable)
754 (hash-delete br-null-path br-paths-htable))
756 (hash-add null-lib-classes br-null-path br-lib-paths-htable)
757 (hash-delete br-null-path br-lib-paths-htable))
758 (let ((null-sys-classes (nconc null-sys-default-classes
759 null-sys-referenced-classes)))
761 (hash-add null-sys-classes br-null-path br-sys-paths-htable)
762 (hash-delete br-null-path br-sys-paths-htable))))))
764 (defun br-class-defined-p (class)
765 "Return path for CLASS if defined in current Environment.
766 Otherwise, display error and return nil."
767 (or (br-class-path class)
771 (if (br-class-in-table-p class)
772 (format "(OO-Browser): Class `%s' referenced but not defined in Environment."
774 (format "(OO-Browser): Class `%s' not defined in Environment."
778 (defun br-check-for-class (cl &optional other-win)
779 "Try to display class CL.
780 Display message and return nil if unsucessful."
781 (if (br-class-in-table-p cl)
782 (or (br-find-class cl nil other-win)
786 (format "(OO-Browser): Class `%s' referenced but not defined in Environment."
790 (defun br-get-parents (class-name)
791 "Return list of parents of CLASS-NAME from parent lookup table.
792 Those from which CLASS-NAME directly inherits."
793 (setq class-name (if class-name (br-set-case class-name)))
794 (br-set-of-strings (hash-get class-name (br-get-parents-htable))))
796 (defun br-get-children (class-name)
797 "Return list of children of CLASS-NAME from child lookup table.
798 Those which directly inherit from CLASS-NAME."
799 (setq class-name (if class-name (br-set-case class-name)))
800 (br-set-of-strings (hash-get class-name (br-get-children-htable))))
802 (defun br-get-children-from-parents-htable (class-name)
803 "Returns list of children of CLASS-NAME.
804 Those that directly inherit from CLASS-NAME. Uses parent lookup table to
806 (setq class-name (and class-name (br-set-case class-name)))
807 (delq nil (hash-map (function (lambda (cns)
809 (br-member class-name (car cns)))
811 (br-get-parents-htable))))
813 (defun br-get-htable (htable-type)
814 "Returns hash table corresponding to string, HTABLE-TYPE.
815 When necessary, loads the hash table from a file or builds it."
816 (let* ((htable-symbol (intern-soft (concat "br-" htable-type "-htable")))
817 (htable-specific (if (string-match "sys\\|lib" htable-type)
818 (substring htable-type (match-beginning 0)
820 changed-types non-matched-types)
821 (if (equal htable-type "children")
823 (if (and (or (not htable-specific) (equal htable-specific "lib"))
824 (or (null (symbol-value htable-symbol))
825 (not (equal br-lib-prev-search-dirs br-lib-search-dirs))))
826 (setq changed-types '("lib")))
827 (if (and (or (not htable-specific) (equal htable-specific "sys"))
828 (or (null (symbol-value htable-symbol))
829 (not (equal br-sys-prev-search-dirs br-sys-search-dirs))))
830 (setq changed-types (cons "sys" changed-types))))
831 (if (and (or br-lib-search-dirs br-sys-search-dirs)
832 (or changed-types (null (symbol-value htable-symbol)))
833 (not (boundp 'br-loaded)))
835 ;; Then need to load or rebuild htable.
837 (progn (if (and br-env-file
838 (file-exists-p br-env-file))
840 ;; Try to load from file.
842 (progn (setq non-matched-types
843 (br-env-load-matching-htables changed-types))
844 (if non-matched-types
853 (and changed-types (br-env-set-htables t))
854 (setq changed-types nil)
855 (cond (htable-specific)
856 ((equal htable-type "children")
857 (progn (goto-char (point-min))
858 (setq br-children-htable
859 (cdr (br-env-file-sym-val
860 "br-children-htable")))))
862 (concat "-" htable-type "-htable"))
863 (hash-merge-values-function
865 ;; Make System entries override
866 ;; Library entries which they
867 ;; duplicate, if this is the parents
869 (if (equal htable-type "parents")
870 (setq hash-merge-values-function
871 'hash-merge-first-value))
876 (concat "br-sys" suffix)))
882 ;; Rebuild any lists that need to be changed.
886 (let ((suffix (concat "-" htable-type "-htable")))
887 (funcall (intern-soft
888 (if (string-match "sys\\|lib" htable-type)
889 (concat "br-build" suffix)
890 (concat "br-build-" type-str suffix))))
892 ;; Make System entries override Library entries
893 ;; which they duplicate, if this is the parents
895 (let ((hash-merge-values-function
897 (if (equal htable-type "parents")
898 (setq hash-merge-values-function
899 'hash-merge-first-value))
901 (hash-merge (symbol-value
903 (concat "br-sys" suffix)))
906 (concat "br-lib" suffix)))
909 (if (and changed-types br-env-file)
911 (let ((buf (get-file-buffer br-env-file)))
912 (and buf (kill-buffer buf)))))
913 ;; Return non-nil hash table.
914 (if (null (symbol-value htable-symbol))
915 (set htable-symbol (hash-make 0))
916 (symbol-value htable-symbol))))
918 (defun br-get-top-class-list (htable-type-str)
919 "Returns unordered list of top-level classes.
920 Those that do not explicitly inherit from any other classes. Obtains classes
921 from list denoted by HTABLE-TYPE-STR whose values may be:
922 \"parents\", \"sys-parents\", or \"lib-parents\"."
923 (delq nil (hash-map (function
925 (if (null (car cns)) (cdr cns))))
926 (br-get-htable htable-type-str))))
928 (defun br-get-top-classes ()
929 "Returns lexicographically ordered list of top-level classes.
930 Those that do not explicitly inherit from any other classes."
931 (br-get-top-class-list "parents"))
933 (defun br-get-lib-top-classes ()
934 "Returns lexicographically ordered list of top-level Library classes.
935 Those that do not explicitly inherit from any other classes."
936 (br-get-top-class-list "lib-parents"))
938 (defun br-get-sys-top-classes ()
939 "Returns lexicographically ordered list of top-level System classes.
940 Those that do not explicitly inherit from any other classes."
941 (br-get-top-class-list "sys-parents"))
943 (defun br-has-children-p (class-name)
944 "Return non-nil iff CLASS-NAME has at least one child.
945 That is a class that directly inherits from CLASS-NAME."
946 (setq class-name (and class-name (br-set-case class-name)))
947 (hash-get class-name (br-get-children-htable)))
949 (defun br-has-parents-p (class-name)
950 "Return non-nil iff CLASS-NAME has at least one parent.
951 That is a class which is a direct ancestor of CLASS-NAME."
952 (setq class-name (and class-name (br-set-case class-name)))
953 (hash-get class-name (br-get-parents-htable)))
955 (defun br-get-process-group (group max)
956 "Return list of all active processes in GROUP (a string).
957 MAX is max number of processes to check for."
962 proc-list (cons (get-process (concat group (int-to-string i)))
964 (delq nil proc-list)))
967 (defun br-kill-process-group (group max group-descrip)
968 "Optionally question user, then kill all subprocesses in named GROUP.
969 Processes are numbered one to MAX, some of which may have been killed already.
970 User is prompted with a string containing GROUP-DESCRIP, only if non-nil.
971 Return list of processes killed."
972 (let ((proc-list (br-get-process-group group max)))
974 (if (or (null group-descrip)
975 (y-or-n-p (concat "Terminate all " group-descrip "? ")))
976 (prog1 (mapcar 'delete-process proc-list)
979 (defun br-real-add-class (lib-table-p class-name class-path &optional replace)
980 "Add or replace class and its features within the current Environment.
981 If LIB-TABLE-P is non-nil, add to Library Environment, otherwise add to
982 System Environment. Add class CLASS-NAME located in CLASS-PATH to
983 Environment. If CLASS-PATH is nil, use current buffer file as CLASS-PATH.
984 Optional REPLACE non-nil means replace already existing class. Does not
985 update children lookup table."
986 (or class-path (setq class-path buffer-file-name))
988 (paths-key class-path)
992 (setq func 'hash-replace
993 class-name (br-first-match
994 (concat "^" (regexp-quote class-name) "$")
997 (br-get-htable "lib-paths")
998 (br-get-htable "sys-paths"))))
1000 (and (stringp class-path) (file-readable-p class-path)
1001 (let ((br-view-file-function 'br-insert-file-contents))
1002 (br-get-parents-from-source class-path class-name))))
1003 (setq func 'hash-add))
1004 ;; Signal error if class-name is invalid.
1005 (if (null class-name)
1007 (error "(br-real-add-class): `%s' not found in %s classes, so cannot replace it."
1008 class (if lib-table-p "Library" "System"))
1010 "(br-real-add-class): Attempt to add null class to %s classes."
1011 (if lib-table-p "Library" "System"))))
1016 (let ((par-htable (br-get-htable (concat type "parents")))
1017 (path-htable (br-get-htable (concat type "paths"))))
1018 (funcall func par-list class-name par-htable)
1019 (br-add-to-paths-htable class-name paths-key path-htable))))
1020 (list (if lib-table-p "lib-" "sys-") ""))
1021 (and (stringp class-path) (file-readable-p class-path)
1022 (let ((br-view-file-function 'br-insert-file-contents))
1023 (br-get-classes-from-source class-path)))))
1025 (defun br-real-delete-class (class-name)
1026 "Delete class CLASS-NAME from current Environment.
1027 No error occurs if the class is undefined in the Environment."
1029 (br-feature-tags-delete class-name)
1030 (let ((paths-key (br-class-path class-name))
1033 (br-first-match (concat "^" class-name "$")
1034 (hash-get paths-key (br-get-paths-htable))))
1039 (hash-delete class-name
1040 (br-get-htable (concat type "parents")))
1041 (setq htable (br-get-htable (concat type "paths")))
1042 (if (hash-key-p paths-key htable)
1046 (hash-get paths-key htable))
1047 paths-key htable))))
1048 '("lib-" "sys-" ""))
1049 (hash-delete class-name (br-get-children-htable))
1050 (if (hashp br-features-htable)
1051 (hash-delete class-name br-features-htable))))))
1053 (defun br-real-build-children-htable ()
1054 "Build and return Environment parent to child lookup table."
1055 (let* ((par-ht (br-get-parents-htable))
1056 (htable (hash-make (hash-size par-ht)))
1060 (lambda (par-child-cns)
1061 (setq child (cdr par-child-cns))
1066 (cons child (hash-get parent htable))
1068 (car par-child-cns))))
1071 (lambda (children-parent-cns)
1072 (hash-replace (sort (car children-parent-cns) 'string-lessp)
1073 (cdr children-parent-cns) htable)))
1077 (defun br-real-get-children (class-name)
1078 "Return list of child classes of CLASS-NAME listed in Environment parents htable."
1082 (if (and (consp cns)
1083 (br-member class-name (car cns)))
1085 (br-get-parents-htable))))
1087 (defun br-real-build-alists (search-dirs)
1088 "Use SEARCH-DIRS to build `br-paths-alist' and `br-parents-alist'."
1089 (setq br-paths-alist nil br-parents-alist nil)
1090 (br-feature-tags-init nil)
1091 ;; These locals are used as free variables in the `br-real-build-al'
1092 ;; function. We define them here to prevent repeated stack usage as
1093 ;; that function recurses.
1094 (let ((inhibit-local-variables nil)
1095 (enable-local-variables t)
1097 ;; Treat as though running in batch mode so that major-mode-specific
1098 ;; messages (e.g. those in Python mode) may be suppressed as files
1099 ;; are read in for scanning.
1101 ;; These are used in the `br-search-directory' function
1102 ;; called by `br-real-built-al'.
1103 (br-view-file-function 'br-insert-file-contents)
1104 classes parents paths-parents-cons)
1105 (br-real-build-al search-dirs nil
1106 (if (string-equal br-lang-prefix "python-")
1107 'python-search-directory
1108 'br-search-directory)))
1109 (setq br-paths-alist br-paths-alist)
1112 (defvar br-paths-alist nil)
1113 (defvar br-parents-alist nil)
1115 (defun br-skip-dir-p (dir-name)
1116 "Returns non-nil iff DIR-NAME is matched by a member of `br-skip-dir-regexps'."
1119 (lambda (dir-regexp)
1120 (string-match dir-regexp
1121 (file-name-nondirectory
1122 (directory-file-name dir-name)))))
1123 br-skip-dir-regexps)))
1125 (defun br-real-build-al (search-dirs subdirectories-flag search-dir-func)
1126 "Descend SEARCH-DIRS and build `br-paths-alist' and `br-parents-alist'.
1127 SUBDIRECTORIES-FLAG is t when SEARCH-DIRS are subdirectories of the root
1128 Environment search directories. SEARCH-DIR-FUNC is the function which
1129 processes each directory, generally `br-search-directory'.
1130 Does not initialize `br-paths-alist' or `br-parents-alist' to nil."
1134 (if (or (null dir) (equal dir "")
1135 (progn (setq dir (file-name-as-directory dir))
1136 ;; Skip subdirectory symlinks but not root-level ones.
1137 (and subdirectories-flag
1138 (file-symlink-p (directory-file-name dir))))
1139 (br-skip-dir-p dir))
1141 (setq files (if (and (file-directory-p dir)
1142 (file-readable-p dir))
1143 (directory-files dir t br-file-dir-regexp)))
1144 ;; Extract all class/parent names in all source files in a
1145 ;; particular directory.
1147 (progn (message "Scanning %s in %s ..."
1148 (file-name-nondirectory
1149 (directory-file-name dir))
1150 (br-abbreviate-file-name
1151 (or (file-name-directory
1152 (directory-file-name dir))
1154 (funcall search-dir-func dir files)
1155 ;; Call same function on all the directories below
1158 (mapcar (function (lambda (f)
1159 (if (file-directory-p f) f)))
1161 t search-dir-func))))))
1164 (defun br-search-directory (dir files)
1168 (if (file-readable-p f)
1169 (progn (message "Scanning %s in %s ..."
1170 (file-name-nondirectory f)
1171 (br-abbreviate-file-name
1172 (or (file-name-directory f) default-directory)))
1173 (setq paths-parents-cons
1174 (br-get-classes-from-source f nil t)
1175 classes (car paths-parents-cons)
1176 parents (cdr paths-parents-cons)
1179 (cons (cons classes f) br-paths-alist)
1181 br-parents-alist (if parents
1182 (append br-parents-alist
1186 (message "(OO-Browser): Unreadable file: %s in %s"
1187 (file-name-nondirectory f)
1188 (br-abbreviate-file-name
1189 (or (file-name-directory f) default-directory)))
1191 ;; List of files potentially containing classes.
1196 (and (string-match br-src-file-regexp f)
1197 (not (file-directory-p f))
1201 (defun br-real-build-parents-alist (paths-htable)
1202 "Build and return `br-parents-alist' of (parent-list . class) elements built from PATHS-HTABLE.
1203 Initializes `br-parents-alist' to nil."
1204 (let ((inhibit-local-variables nil)
1205 (enable-local-variables t)
1206 (br-view-file-function 'br-insert-file-contents)
1210 (lambda (classes-file-cons)
1211 (setq dir (cdr classes-file-cons))
1214 (lambda (class-name)
1215 (setq br-parents-alist
1220 (br-get-parents-from-source
1224 br-parents-alist))))
1225 (car classes-file-cons))))
1229 (defun br-set-lang-env (func sym-list val)
1230 "Use FUNC to set each element in SYM-LIST.
1231 If VAL is non-nil, set `br' element to the value of the current OO-Browser
1232 language element with the same name, otherwise set it to a function that
1233 when called signals an error that the function is undefined for this language."
1237 (setq br (intern (concat "br-" nm))
1238 lang (intern-soft (concat br-lang-prefix nm)))
1239 (if (and (or (null lang) (not (boundp lang)))
1241 ;; Don't try to set an unbound language-specific variable.
1243 (funcall func br (if val
1245 (or lang 'br-undefined-function))))))
1248 (defun br-undefined-function (&rest ignore)
1250 (error "(OO-Browser): That command is not supported for this language."))
1252 (defun br-setup-functions ()
1253 "Initialize appropriate function pointers for the current browser language."
1254 (br-set-lang-env 'fset
1255 '("class-definition-regexp" "class-list-filter"
1256 "get-classes-from-source" "get-parents-from-source"
1257 "insert-class-info" "insert-entry-info"
1258 "set-case" "set-case-type"
1259 "store-class-info" "store-entry-info"
1260 "to-class-end" "to-comments-begin" "to-definition"
1263 "feature-edit-declaration"
1264 "feature-implementors"
1265 "feature-locate-p" "feature-name-to-regexp"
1267 "feature-signature-to-name"
1268 "feature-signature-to-regexp"
1269 "feature-view-declaration" "list-categories"
1270 "list-protocols" "view-friend")
1273 (defun br-setup-constants (env-file)
1274 "Initialize appropriate constant values for the current browser language using ENV-FILE."
1275 ;; Initialize auxiliary Env file variables.
1277 ;; Clear language-dependent hooks.
1278 (setq br-after-build-lib-hook nil
1279 br-after-build-sys-hook nil)
1280 ;; Set language-specific constants.
1281 (br-set-lang-env 'set '("class-def-regexp" "env-file"
1282 "identifier" "identifier-chars"
1283 "src-file-regexp" "narrow-view-to-class"
1284 "tag-fields-regexp" "type-tag-separator")
1286 (if (not (eq br-env-name t))
1287 (br-set-lang-env 'set '("env-name") t)))
1289 (defun br-find-info-node (filename node edit)
1290 "Show (FILENAME)NODE in current window.
1291 If EDIT is non-nil, NODE is made editable."
1292 (if (string-match "-[1-9][0-9]*$" filename)
1293 (setq filename (substring filename 0 (match-beginning 0))) )
1294 (Info-find-node filename node t)
1295 (if edit (let ((Info-enable-edit t))
1298 ;;; ************************************************************************
1299 ;;; Private variables
1300 ;;; ************************************************************************
1302 (defvar br-lib-search-dirs nil
1303 "List of directories below which library dirs and source files are found.
1304 A library is a stable group of classes. Value is language-specific.")
1305 (defvar br-sys-search-dirs nil
1306 "List of directories below which system dirs and source files are found.
1307 A system is a group of classes that are likely to change. Value is
1308 language-specific.")
1310 (defvar br-lib-prev-search-dirs nil
1311 "Used to check if `br-lib-paths-htable' must be regenerated.
1312 Value is language-specific.")
1313 (defvar br-sys-prev-search-dirs nil
1314 "Used to check if `br-sys-paths-htable' must be regenerated.
1315 Value is language-specific.")
1317 (defun br-pop-to-buffer (bufname &optional other-win read-only)
1318 "Display BUFNAME for editing, creating a new buffer if needed.
1319 Optional OTHER-WIN means show in other window unless Hyperbole
1320 is loaded in which case `hpath:display-buffer' determines where
1321 to display the buffer. Optional READ-ONLY means make the buffer
1323 (interactive "BEdit or create buffer named: ")
1324 (funcall (cond ((br-in-browser)
1326 (hpath:push-tag-mark)
1328 ((fboundp 'hpath:display-buffer)
1329 'hpath:display-buffer)
1330 (other-win 'switch-to-buffer-other-window)
1331 (t 'switch-to-buffer))
1332 (get-buffer-create bufname))
1333 (if read-only (setq buffer-read-only t)))
1335 (defun br-find-file (filename &optional other-win read-only)
1336 "Edit file FILENAME.
1337 Switch to a buffer visiting file FILENAME, creating one if none already
1338 exists. Optional OTHER-WIN means show in other window unless Hyperbole is
1339 loaded in which case `hpath:display-buffer' determines where to display the
1340 file. Optional READ-ONLY means make the buffer read-only."
1341 (interactive "FFind file: ")
1342 (funcall (cond ((br-in-browser)
1344 (hpath:push-tag-mark)
1346 ((fboundp 'hpath:display-buffer)
1347 'hpath:display-buffer)
1348 (other-win 'switch-to-buffer-other-window)
1349 (t 'switch-to-buffer))
1350 (find-file-noselect filename))
1351 (if read-only (setq buffer-read-only t)))
1353 (defun br-find-file-read-only (filename &optional other-win)
1354 "Display file FILENAME read-only.
1355 Switch to a buffer visiting file FILENAME, creating one if none
1356 already exists. Optional OTHER-WIN means show in other window."
1357 (interactive "FFind file read-only: ")
1358 (br-find-file filename other-win t))
1360 (defvar br-edit-file-function 'br-find-file
1361 "*Function to call to edit a class file within the browser.")
1362 (defvar br-view-file-function
1363 (if (eq br-edit-file-function 'br-find-file)
1364 'br-find-file-read-only
1365 br-edit-file-function)
1366 "*Function to call to view a class file within the browser.")
1368 (defvar br-find-file-noselect-function 'br-find-file-noselect
1369 "Function to call to load a browser file but not select it.
1370 The function must return the buffer containing the file's contents.")
1372 (defvar *br-tmp-buffer* " oo-browser-tmp"
1373 "Name of temporary buffer used by the OO-Browser for parsing source files.")
1375 (defun br-find-file-noselect (filename)
1376 "Read in the file given by FILENAME without selecting it or running any `find-file-hooks'."
1377 (let (find-file-hooks)
1378 (find-file-noselect filename)))
1380 (defun br-insert-file-contents (filename &optional unused)
1381 "Insert after point into a temporary buffer the contents of FILENAME and temporarily select the buffer.
1382 Optional second arg UNUSED is necessary since when used as a setting for
1383 `br-view-file-function' this may be sent two arguments.
1385 Does not run any find-file or mode specific hooks. Marks buffer read-only to
1386 prevent any accidental editing.
1388 Set `br-view-file-function' to this function when parsing OO-Browser source
1389 files for fast loading of many files."
1390 (set-buffer (get-buffer-create *br-tmp-buffer*))
1391 ;; Don't bother saving anything for this temporary buffer
1392 (buffer-disable-undo (current-buffer))
1393 (setq buffer-auto-save-file-name nil
1394 buffer-read-only nil)
1396 (insert-file-contents filename)
1398 (setq buffer-read-only t))
1400 (defvar br-lang-prefix nil
1401 "Prefix string that starts language-specific symbol names.")
1403 (defvar br-children-htable nil
1404 "Htable whose elements are of the form: (LIST-OF-CHILD-CLASSES . CLASS-NAME).
1405 Used to traverse class inheritance graph. `br-build-children-htable' builds
1406 this list. Value is language-specific.")
1407 (defvar br-parents-htable nil
1408 "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
1409 Used to traverse class inheritance graph. `br-build-parents-htable' builds
1410 this list. Value is language-specific.")
1411 (defvar br-paths-htable nil
1412 "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . DIRECTORY).
1413 DIRECTORY gives the location of classes found in LIST-OF-CLASS-NAMES.
1414 `br-build-paths-htable' builds this list. Value is language-specific.")
1416 (defvar br-features-htable nil
1417 "Htable whose elements are of the form: (LIST-OF-CLASS-FEATURES . CLASS).
1418 `br-feature-build-htables' builds this htable. Value is language-specific.")
1419 (defvar br-feature-paths-htable nil
1420 "Htable whose elements are of the form: (PATHNAME . PATHNAME-NUMBER).
1421 PATHNAME-NUMBER is an index stored in `br-features-htable' used to look up
1422 the file of definition for individual class features.
1423 `br-feature-build-htables' builds this htable. Value is language-specific.")
1425 (defvar br-lib-parents-htable nil
1426 "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
1427 Only classes from stable software libraries are used to build the list.
1428 Value is language-specific.")
1429 (defvar br-lib-paths-htable nil
1430 "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . DIRECTORY).
1431 DIRECTORY gives the location of classes found in LIST-OF-CLASS-NAMES.
1432 Only classes from stable software libraries are used to build the list.
1433 Value is language-specific.")
1435 (defvar br-sys-parents-htable nil
1436 "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
1437 Only classes from systems that are likely to change are used to build the
1438 list. Value is language-specific.")
1439 (defvar br-sys-paths-htable nil
1440 "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . DIRECTORY).
1441 DIRECTORY gives the location of classes found in LIST-OF-CLASS-NAMES.
1442 Only classes from systems that are likely to change are used to build the
1443 list. Value is language-specific.")
1445 (defvar br-file-dir-regexp "\\`[^.~#]\\(.*[^.~#]\\)?\\'"
1446 "Regexp that matches only to files and directories that the OO-Browser should scan.
1447 Others are ignored.")
1449 (defvar br-src-file-regexp nil
1450 "Regular expression matching a unique part of source file names and no others.")
1452 (defvar br-narrow-view-to-class nil
1453 "Non-nil means narrow buffer to just the matching class definition when displayed.
1454 Don't set this, use the language specific variable instead.")