(standard-display-european): Doc fix.
[bpt/emacs.git] / lisp / apropos.el
CommitLineData
3925e76d 1;;; apropos.el --- apropos commands for users and programmers.
c0274f38 2
3925e76d 3;; Copyright (C) 1989, 1994, 1995 Free Software Foundation, Inc.
9750e079 4
e5167999 5;; Author: Joe Wells <jbw@bigbird.bu.edu>
3925e76d 6;; Rewritten: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
e9571d2a 7;; Keywords: help
e5167999 8
6f8e447f
RS
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
e5167999 13;; the Free Software Foundation; either version 2, or (at your option)
6f8e447f
RS
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
6f8e447f 25
e5167999 26;;; Commentary:
6f8e447f
RS
27
28;; The ideas for this package were derived from the C code in
29;; src/keymap.c and elsewhere. The functions in this file should
30;; always be byte-compiled for speed. Someone should rewrite this in
31;; C (as part of src/keymap.c) for speed.
32
33;; The idea for super-apropos is based on the original implementation
34;; by Lynn Slater <lrs@esl.com>.
35
36;; History:
37;; Fixed bug, current-local-map can return nil.
38;; Change, doesn't calculate key-bindings unless needed.
39;; Added super-apropos capability, changed print functions.
3925e76d
KH
40;;; Made fast-apropos and super-apropos share code.
41;;; Sped up fast-apropos again.
6f8e447f 42;; Added apropos-do-all option.
3925e76d 43;;; Added fast-command-apropos.
6f8e447f 44;; Changed doc strings to comments for helping functions.
3925e76d 45;;; Made doc file buffer read-only, buried it.
6f8e447f
RS
46;; Only call substitute-command-keys if do-all set.
47
645c4f6a
KH
48;; Optionally use configurable faces to make the output more legible.
49;; Differentiate between command, function and macro.
3925e76d
KH
50;; Apropos-command (ex command-apropos) does cmd and optionally user var.
51;; Apropos shows all 3 aspects of symbols (fn, var and plist)
52;; Apropos-documentation (ex super-apropos) now finds all it should.
53;; New apropos-value snoops through all values and optionally plists.
54;; Reading DOC file doesn't load nroff.
55;; Added hypertext following of documentation, mouse-2 on variable gives value
56;; from buffer in active window.
57
e5167999
ER
58;;; Code:
59
ddd2f740
RS
60(defgroup apropos nil
61 "Apropos commands for users and programmers"
62 :group 'Help
63 :prefix "apropos")
64
3925e76d 65;; I see a degradation of maybe 10-20% only.
ddd2f740 66(defcustom apropos-do-all nil
3925e76d 67 "*Whether the apropos commands should do more.
ddd2f740
RS
68
69Slows them down more or less. Set this non-nil if you have a fast machine."
70 :group 'apropos
71 :type 'boolean)
3925e76d
KH
72
73
ddd2f740
RS
74(defcustom apropos-symbol-face (if window-system 'bold)
75 "*Face for symbol name in apropos output or `nil'.
76This looks good, but slows down the commands several times."
77 :group 'apropos
78 :type 'face)
645c4f6a 79
ddd2f740 80(defcustom apropos-keybinding-face (if window-system 'underline)
645c4f6a 81 "*Face for keybinding display in apropos output or `nil'.
ddd2f740
RS
82This looks good, but slows down the commands several times."
83 :group 'apropos
84 :type 'face)
645c4f6a 85
ddd2f740 86(defcustom apropos-label-face (if window-system 'italic)
645c4f6a
KH
87 "*Face for label (Command, Variable ...) in apropos output or `nil'.
88If this is `nil' no mouse highlighting occurs.
89This looks good, but slows down the commands several times.
90When this is a face name, as it is initially, it gets transformed to a
ddd2f740
RS
91text-property list for efficiency."
92 :group 'apropos
93 :type 'face)
645c4f6a 94
ddd2f740 95(defcustom apropos-property-face (if window-system 'bold-italic)
645c4f6a 96 "*Face for property name in apropos output or `nil'.
ddd2f740
RS
97This looks good, but slows down the commands several times."
98 :group 'apropos
99 :type 'face)
645c4f6a 100
ddd2f740 101(defcustom apropos-match-face (if window-system 'secondary-selection)
645c4f6a 102 "*Face for matching part in apropos-documentation/value output or `nil'.
ddd2f740
RS
103This looks good, but slows down the commands several times."
104 :group 'apropos
105 :type 'face)
3925e76d 106
6f8e447f 107
26a4a227 108(defvar apropos-mode-map
3925e76d
KH
109 (let ((map (make-sparse-keymap)))
110 (define-key map "\C-m" 'apropos-follow)
685b1bef
RS
111 (define-key map " " 'scroll-up)
112 (define-key map "\177" 'scroll-down)
3925e76d
KH
113 (define-key map [mouse-2] 'apropos-mouse-follow)
114 (define-key map [down-mouse-2] nil)
115 map)
26a4a227 116 "Keymap used in Apropos mode.")
4de5599d 117
3925e76d 118
645c4f6a
KH
119(defvar apropos-regexp nil
120 "Regexp used in current apropos run.")
121
122(defvar apropos-files-scanned ()
1259a080 123 "List of elc files already scanned in current run of `apropos-documentation'.")
645c4f6a
KH
124
125(defvar apropos-accumulator ()
126 "Alist of symbols already found in current apropos run.")
3925e76d 127
645c4f6a
KH
128(defvar apropos-item ()
129 "Current item in or for apropos-accumulator.")
130\f
26a4a227
KH
131(defun apropos-mode ()
132 "Major mode for following hyperlinks in output of apropos commands.
133
134\\{apropos-mode-map}"
135 (interactive)
136 (kill-all-local-variables)
137 (use-local-map apropos-mode-map)
138 (setq major-mode 'apropos-mode
139 mode-name "Apropos"))
140
f38fd610
RS
141;;;###autoload
142(defun apropos-variable (regexp)
143 (interactive (list (read-string "Apropos variable (regexp): ")))
144 (apropos-command regexp nil t))
26a4a227 145
645c4f6a
KH
146;; For auld lang syne:
147;;;###autoload
148(fset 'command-apropos 'apropos-command)
6f8e447f 149;;;###autoload
f38fd610 150(defun apropos-command (apropos-regexp &optional do-all just-vars)
3ccee345
KH
151 "Show commands (interactively callable functions) that match REGEXP.
152With optional prefix ARG, or if `apropos-do-all' is non-nil, also show
f38fd610
RS
153variables. If JUST-VARS is non-nil, show only variables."
154 (interactive (list (read-string (concat
155 "Apropos command "
156 (if (or current-prefix-arg
157 apropos-do-all)
158 "or variable ")
159 "(regexp): "))
645c4f6a 160 current-prefix-arg))
3925e76d 161 (let ((message
26a4a227 162 (let ((standard-output (get-buffer-create "*Apropos*")))
3925e76d 163 (print-help-return-message 'identity))))
645c4f6a
KH
164 (or do-all (setq do-all apropos-do-all))
165 (setq apropos-accumulator
166 (apropos-internal apropos-regexp
167 (if do-all
168 (lambda (symbol) (or (commandp symbol)
169 (user-variable-p symbol)))
f38fd610
RS
170 (if just-vars 'user-variable-p
171 'commandp))))
3925e76d 172 (if (apropos-print
3925e76d
KH
173 t
174 (lambda (p)
175 (let (doc symbol)
176 (while p
177 (setcar p (list
178 (setq symbol (car p))
f38fd610
RS
179 (if (or do-all (not just-vars))
180 (if (commandp symbol)
181 (if (setq doc (documentation symbol t))
182 (substring doc 0 (string-match "\n" doc))
183 "(not documented)")))
3925e76d
KH
184 (and do-all
185 (user-variable-p symbol)
186 (if (setq doc (documentation-property
187 symbol 'variable-documentation t))
188 (substring doc 0
189 (string-match "\n" doc))))))
190 (setq p (cdr p)))))
191 nil)
192 (and message (message message)))))
193
194
3925e76d 195;;;###autoload
645c4f6a
KH
196(defun apropos (apropos-regexp &optional do-all)
197 "Show all bound symbols whose names match REGEXP.
198With optional prefix ARG or if `apropos-do-all' is non-nil, also show unbound
199symbols and key bindings, which is a little more time-consuming.
6f8e447f 200Returns list of symbols and documentation found."
3925e76d 201 (interactive "sApropos symbol (regexp): \nP")
645c4f6a
KH
202 (setq apropos-accumulator
203 (apropos-internal apropos-regexp
204 (and (not do-all)
205 (not apropos-do-all)
206 (lambda (symbol)
207 (or (fboundp symbol)
208 (boundp symbol)
5edc67d3 209 (facep symbol)
645c4f6a 210 (symbol-plist symbol))))))
3925e76d 211 (apropos-print
645c4f6a 212 (or do-all apropos-do-all)
3925e76d 213 (lambda (p)
d69e3b68 214 (let (symbol doc properties)
3925e76d
KH
215 (while p
216 (setcar p (list
217 (setq symbol (car p))
d69e3b68
KH
218 (when (fboundp symbol)
219 (if (setq doc (documentation symbol t))
220 (substring doc 0 (string-match "\n" doc))
221 "(not documented)"))
222 (when (boundp symbol)
223 (if (setq doc (documentation-property
224 symbol 'variable-documentation t))
225 (substring doc 0 (string-match "\n" doc))
226 "(not documented)"))
227 (when (setq properties (symbol-plist symbol))
228 (setq doc (list (car properties)))
229 (while (setq properties (cdr (cdr properties)))
230 (setq doc (cons (car properties) doc)))
5edc67d3
RS
231 (mapconcat #'symbol-name (nreverse doc) " "))
232 (when (get symbol 'widget-type)
233 (if (setq doc (documentation-property
234 symbol 'widget-documentation t))
235 (substring doc 0
236 (string-match "\n" doc))
237 "(not documented)"))
238 (when (facep symbol)
239 (if (setq doc (documentation-property
240 symbol 'face-documentation t))
241 (substring doc 0
242 (string-match "\n" doc))
2be7e3fa
RS
243 "(not documented)"))
244 (when (get symbol 'custom-group)
245 (if (setq doc (documentation-property
246 symbol 'group-documentation t))
247 (substring doc 0
248 (string-match "\n" doc))
5edc67d3 249 "(not documented)"))))
3925e76d
KH
250 (setq p (cdr p)))))
251 nil))
252
253
6f8e447f 254;;;###autoload
645c4f6a 255(defun apropos-value (apropos-regexp &optional do-all)
3925e76d
KH
256 "Show all symbols whose value's printed image matches REGEXP.
257With optional prefix ARG or if `apropos-do-all' is non-nil, also looks
258at the function and at the names and values of properties.
645c4f6a 259Returns list of symbols and values found."
3925e76d 260 (interactive "sApropos value (regexp): \nP")
645c4f6a
KH
261 (or do-all (setq do-all apropos-do-all))
262 (setq apropos-accumulator ())
263 (let (f v p)
3925e76d
KH
264 (mapatoms
265 (lambda (symbol)
266 (setq f nil v nil p nil)
645c4f6a
KH
267 (or (memq symbol '(apropos-regexp do-all apropos-accumulator
268 symbol f v p))
269 (setq v (apropos-value-internal 'boundp symbol 'symbol-value)))
3925e76d 270 (if do-all
645c4f6a
KH
271 (setq f (apropos-value-internal 'fboundp symbol 'symbol-function)
272 p (apropos-format-plist symbol "\n " t)))
3925e76d 273 (if (or f v p)
645c4f6a
KH
274 (setq apropos-accumulator (cons (list symbol f v p)
275 apropos-accumulator))))))
276 (apropos-print nil nil t))
3925e76d
KH
277
278
645c4f6a
KH
279;;;###autoload
280(defun apropos-documentation (apropos-regexp &optional do-all)
26a4a227 281 "Show symbols whose documentation contain matches for REGEXP.
645c4f6a
KH
282With optional prefix ARG or if `apropos-do-all' is non-nil, also use
283documentation that is not stored in the documentation file and show key
284bindings.
285Returns list of symbols and documentation found."
286 (interactive "sApropos documentation (regexp): \nP")
287 (or do-all (setq do-all apropos-do-all))
288 (setq apropos-accumulator () apropos-files-scanned ())
289 (let ((standard-input (get-buffer-create " apropos-temp"))
290 f v)
291 (unwind-protect
292 (save-excursion
293 (set-buffer standard-input)
294 (apropos-documentation-check-doc-file)
295 (if do-all
296 (mapatoms
297 (lambda (symbol)
298 (setq f (apropos-safe-documentation symbol)
26a4a227
KH
299 v (get symbol 'variable-documentation))
300 (if (integerp v) (setq v))
301 (setq f (apropos-documentation-internal f)
302 v (apropos-documentation-internal v))
645c4f6a
KH
303 (if (or f v)
304 (if (setq apropos-item
305 (cdr (assq symbol apropos-accumulator)))
306 (progn
307 (if f
308 (setcar apropos-item f))
309 (if v
310 (setcar (cdr apropos-item) v)))
311 (setq apropos-accumulator
312 (cons (list symbol f v)
313 apropos-accumulator)))))))
26a4a227 314 (apropos-print nil nil t))
645c4f6a
KH
315 (kill-buffer standard-input))))
316
317\f
318(defun apropos-value-internal (predicate symbol function)
319 (if (funcall predicate symbol)
320 (progn
321 (setq symbol (prin1-to-string (funcall function symbol)))
322 (if (string-match apropos-regexp symbol)
323 (progn
324 (if apropos-match-face
325 (put-text-property (match-beginning 0) (match-end 0)
326 'face apropos-match-face
327 symbol))
328 symbol)))))
329
330(defun apropos-documentation-internal (doc)
331 (if (consp doc)
332 (apropos-documentation-check-elc-file (car doc))
333 (and doc
334 (string-match apropos-regexp doc)
335 (progn
336 (if apropos-match-face
337 (put-text-property (match-beginning 0)
338 (match-end 0)
339 'face apropos-match-face
340 (setq doc (copy-sequence doc))))
341 doc))))
342
343(defun apropos-format-plist (pl sep &optional compare)
3925e76d
KH
344 (setq pl (symbol-plist pl))
345 (let (p p-out)
346 (while pl
347 (setq p (format "%s %S" (car pl) (nth 1 pl)))
645c4f6a
KH
348 (if (or (not compare) (string-match apropos-regexp p))
349 (if apropos-property-face
3925e76d 350 (put-text-property 0 (length (symbol-name (car pl)))
645c4f6a 351 'face apropos-property-face p))
3925e76d 352 (setq p nil))
645c4f6a
KH
353 (if p
354 (progn
355 (and compare apropos-match-face
356 (put-text-property (match-beginning 0) (match-end 0)
357 'face apropos-match-face
358 p))
359 (setq p-out (concat p-out (if p-out sep) p))))
3925e76d
KH
360 (setq pl (nthcdr 2 pl)))
361 p-out))
362
6f8e447f 363
645c4f6a 364;; Finds all documentation related to APROPOS-REGEXP in internal-doc-file-name.
3925e76d 365
645c4f6a 366(defun apropos-documentation-check-doc-file ()
26a4a227
KH
367 (let (type symbol (sepa 2) sepb beg end)
368 (insert ?\^_)
369 (backward-char)
645c4f6a 370 (insert-file-contents (concat doc-directory internal-doc-file-name))
26a4a227
KH
371 (forward-char)
372 (while (save-excursion
373 (setq sepb (search-forward "\^_"))
374 (not (eobp)))
375 (beginning-of-line 2)
376 (if (save-restriction
377 (narrow-to-region (point) (1- sepb))
378 (re-search-forward apropos-regexp nil t))
379 (progn
380 (setq beg (match-beginning 0)
381 end (point))
382 (goto-char (1+ sepa))
383 (or (setq type (if (eq ?F (preceding-char))
384 1 ; function documentation
385 2) ; variable documentation
386 symbol (read)
387 beg (- beg (point) 1)
388 end (- end (point) 1)
389 doc (buffer-substring (1+ (point)) (1- sepb))
390 apropos-item (assq symbol apropos-accumulator))
391 (setq apropos-item (list symbol nil nil)
392 apropos-accumulator (cons apropos-item
393 apropos-accumulator)))
394 (if apropos-match-face
395 (put-text-property beg end 'face apropos-match-face doc))
396 (setcar (nthcdr type apropos-item) doc)))
397 (setq sepa (goto-char sepb)))))
645c4f6a
KH
398
399(defun apropos-documentation-check-elc-file (file)
400 (if (member file apropos-files-scanned)
401 nil
26a4a227 402 (let (symbol doc beg end this-is-a-variable)
645c4f6a
KH
403 (setq apropos-files-scanned (cons file apropos-files-scanned))
404 (erase-buffer)
405 (insert-file-contents file)
406 (while (search-forward "\n#@" nil t)
407 ;; Read the comment length, and advance over it.
408 (setq end (read)
26a4a227
KH
409 beg (1+ (point))
410 end (+ (point) end -1))
411 (forward-char)
412 (if (save-restriction
413 ;; match ^ and $ relative to doc string
414 (narrow-to-region beg end)
415 (re-search-forward apropos-regexp nil t))
645c4f6a 416 (progn
26a4a227
KH
417 (goto-char (+ end 2))
418 (setq doc (buffer-substring beg end)
419 end (- (match-end 0) beg)
420 beg (- (match-beginning 0) beg)
421 this-is-a-variable (looking-at "(def\\(var\\|const\\) ")
645c4f6a
KH
422 symbol (progn
423 (skip-chars-forward "(a-z")
26a4a227 424 (forward-char)
645c4f6a
KH
425 (read))
426 symbol (if (consp symbol)
427 (nth 1 symbol)
428 symbol))
429 (if (if this-is-a-variable
430 (get symbol 'variable-documentation)
431 (and (fboundp symbol) (apropos-safe-documentation symbol)))
432 (progn
433 (or (setq apropos-item (assq symbol apropos-accumulator))
434 (setq apropos-item (list symbol nil nil)
435 apropos-accumulator (cons apropos-item
436 apropos-accumulator)))
437 (if apropos-match-face
26a4a227 438 (put-text-property beg end 'face apropos-match-face
645c4f6a
KH
439 doc))
440 (setcar (nthcdr (if this-is-a-variable 2 1)
441 apropos-item)
26a4a227 442 doc)))))))))
645c4f6a
KH
443
444
445
446(defun apropos-safe-documentation (function)
6f8e447f
RS
447 "Like documentation, except it avoids calling `get_doc_string'.
448Will return nil instead."
3925e76d 449 (while (and function (symbolp function))
6f8e447f 450 (setq function (if (fboundp function)
3925e76d 451 (symbol-function function))))
d2e1218f
RS
452 (if (eq (car-safe function) 'macro)
453 (setq function (cdr function)))
3925e76d 454 (setq function (if (byte-code-function-p function)
645c4f6a
KH
455 (if (> (length function) 4)
456 (aref function 4))
457 (if (eq (car-safe function) 'autoload)
458 (nth 2 function)
459 (if (eq (car-safe function) 'lambda)
460 (if (stringp (nth 2 function))
461 (nth 2 function)
462 (if (stringp (nth 3 function))
463 (nth 3 function)))))))
464 (if (integerp function)
465 nil
466 function))
467
468
469
470(defun apropos-print (do-keys doc-fn spacing)
471 "Output result of various apropos commands with `apropos-regexp'.
472APROPOS-ACCUMULATOR is a list. Optional DOC-FN is called for each element
473of apropos-accumulator and may modify it resulting in (symbol fn-doc
3925e76d
KH
474var-doc [plist-doc]). Returns sorted list of symbols and documentation
475found."
645c4f6a
KH
476 (if (null apropos-accumulator)
477 (message "No apropos matches for `%s'" apropos-regexp)
3925e76d 478 (if doc-fn
645c4f6a
KH
479 (funcall doc-fn apropos-accumulator))
480 (setq apropos-accumulator
481 (sort apropos-accumulator (lambda (a b)
26a4a227 482 (string-lessp (car a) (car b)))))
645c4f6a
KH
483 (and apropos-label-face
484 (symbolp apropos-label-face)
485 (setq apropos-label-face `(face ,apropos-label-face
486 mouse-face highlight)))
09e32aaf 487 (with-output-to-temp-buffer "*Apropos*"
645c4f6a 488 (let ((p apropos-accumulator)
3925e76d 489 (old-buffer (current-buffer))
645c4f6a 490 symbol item point1 point2)
26a4a227
KH
491 (set-buffer standard-output)
492 (apropos-mode)
493 (if window-system
1f64403f
EN
494 (insert "If you move the mouse over text that changes color,\n"
495 (substitute-command-keys
3787cf2c 496 "you can click \\[apropos-mouse-follow] to get more information.\n")))
26a4a227
KH
497 (insert (substitute-command-keys
498 "In this buffer, type \\[apropos-follow] to get full documentation.\n\n"))
499 (while (consp p)
500 (or (not spacing) (bobp) (terpri))
501 (setq apropos-item (car p)
502 symbol (car apropos-item)
503 p (cdr p)
504 point1 (point))
505 (princ symbol) ; print symbol name
506 (setq point2 (point))
98ce2330 507 ;; Calculate key-bindings if we want them.
26a4a227
KH
508 (and do-keys
509 (commandp symbol)
510 (indent-to 30 1)
98ce2330
RS
511 (if (let ((keys
512 (save-excursion
513 (set-buffer old-buffer)
514 (where-is-internal symbol)))
515 filtered)
516 ;; Copy over the list of key sequences,
517 ;; omitting any that contain a buffer or a frame.
518 (while keys
519 (let ((key (car keys))
520 (i 0)
521 loser)
522 (while (< i (length key))
523 (if (or (framep (aref key i))
524 (bufferp (aref key i)))
525 (setq loser t))
526 (setq i (1+ i)))
527 (or loser
528 (setq filtered (cons key filtered))))
529 (setq keys (cdr keys)))
530 (setq item filtered))
531 ;; Convert the remaining keys to a string and insert.
532 (insert
26a4a227 533 (mapconcat
98ce2330
RS
534 (lambda (key)
535 (setq key (key-description key))
536 (if apropos-keybinding-face
26a4a227
KH
537 (put-text-property 0 (length key)
538 'face apropos-keybinding-face
98ce2330
RS
539 key))
540 key)
541 item ", "))
82fbaa5e
RS
542 (insert "M-x")
543 (put-text-property (- (point) 3) (point)
544 'face apropos-keybinding-face)
545 (insert " " (symbol-name symbol) " ")
546 (insert "RET")
547 (put-text-property (- (point) 3) (point)
548 'face apropos-keybinding-face)))
26a4a227
KH
549 (terpri)
550 ;; only now so we don't propagate text attributes all over
551 (put-text-property point1 point2 'item
552 (if (eval `(or ,@(cdr apropos-item)))
553 (car apropos-item)
554 apropos-item))
555 (if apropos-symbol-face
556 (put-text-property point1 point2 'face apropos-symbol-face))
557 (apropos-print-doc 'describe-function 1
558 (if (commandp symbol)
559 "Command"
560 (if (apropos-macrop symbol)
561 "Macro"
562 "Function"))
563 do-keys)
5edc67d3
RS
564 (if (get symbol 'custom-type)
565 (apropos-print-doc 'customize-variable-other-window 2
566 "User Option" do-keys)
567 (apropos-print-doc 'describe-variable 2
568 "Variable" do-keys))
6cb0a57b 569 (apropos-print-doc 'customize-group-other-window 6 "Group" do-keys)
5edc67d3
RS
570 (apropos-print-doc 'customize-face-other-window 5 "Face" do-keys)
571 (apropos-print-doc 'widget-browse-other-window 4 "Widget" do-keys)
26a4a227
KH
572 (apropos-print-doc 'apropos-describe-plist 3
573 "Plist" nil)))))
645c4f6a
KH
574 (prog1 apropos-accumulator
575 (setq apropos-accumulator ()))) ; permit gc
576
3925e76d 577
645c4f6a
KH
578(defun apropos-macrop (symbol)
579 "T if SYMBOL is a Lisp macro."
580 (and (fboundp symbol)
581 (consp (setq symbol
582 (symbol-function symbol)))
583 (or (eq (car symbol) 'macro)
584 (if (eq (car symbol) 'autoload)
585 (memq (nth 4 symbol)
586 '(macro t))))))
3925e76d 587
645c4f6a
KH
588
589(defun apropos-print-doc (action i str do-keys)
590 (if (stringp (setq i (nth i apropos-item)))
3925e76d
KH
591 (progn
592 (insert " ")
593 (put-text-property (- (point) 2) (1- (point))
594 'action action)
645c4f6a
KH
595 (insert str ": ")
596 (if apropos-label-face
597 (add-text-properties (- (point) (length str) 2)
3925e76d 598 (1- (point))
645c4f6a
KH
599 apropos-label-face))
600 (insert (if do-keys (substitute-command-keys i) i))
601 (or (bolp) (terpri)))))
3925e76d
KH
602
603
604(defun apropos-mouse-follow (event)
605 (interactive "e")
26a4a227 606 (let ((other (if (eq (current-buffer) (get-buffer "*Apropos*"))
3925e76d
KH
607 ()
608 (current-buffer))))
17ef0353
RS
609 (save-excursion
610 (set-buffer (window-buffer (posn-window (event-start event))))
611 (goto-char (posn-point (event-start event)))
612 (or (and (not (eobp)) (get-text-property (point) 'mouse-face))
613 (and (not (bobp)) (get-text-property (1- (point)) 'mouse-face))
614 (error "There is nothing to follow here"))
17ef0353 615 (apropos-follow other))))
3925e76d
KH
616
617
618(defun apropos-follow (&optional other)
619 (interactive)
17ef0353
RS
620 (let* (;; Properties are always found at the beginning of the line.
621 (bol (save-excursion (beginning-of-line) (point)))
622 ;; If there is no `item' property here, look behind us.
623 (item (get-text-property bol 'item))
624 (item-at (if item nil (previous-single-property-change bol 'item)))
625 ;; Likewise, if there is no `action' property here, look in front.
626 (action (get-text-property bol 'action))
627 (action-at (if action nil (next-single-property-change bol 'action))))
628 (and (null item) item-at
629 (setq item (get-text-property (1- item-at) 'item)))
630 (and (null action) action-at
631 (setq action (get-text-property action-at 'action)))
632 (if (not (and item action))
0a812366 633 (error "There is nothing to follow here"))
17ef0353
RS
634 (if (consp item) (error "There is nothing to follow in `%s'" (car item)))
635 (if other (set-buffer other))
636 (funcall action item)))
3925e76d
KH
637
638
639
640(defun apropos-describe-plist (symbol)
641 "Display a pretty listing of SYMBOL's plist."
642 (with-output-to-temp-buffer "*Help*"
643 (set-buffer standard-output)
644 (princ "Symbol ")
645 (prin1 symbol)
646 (princ "'s plist is\n (")
645c4f6a
KH
647 (if apropos-symbol-face
648 (put-text-property 8 (- (point) 14) 'face apropos-symbol-face))
3925e76d 649 (insert (apropos-format-plist symbol "\n "))
26a4a227
KH
650 (princ ")")
651 (print-help-return-message)))
6f8e447f 652
896546cd
RS
653(provide 'apropos)
654
c0274f38 655;;; apropos.el ends here