1 ;;; apropos-fn+var.el --- Apropos for functions and variables
3 ;; Filename: apropos-fn.el
4 ;; Description: Apropos for functions and variables
6 ;; Maintainer: Drew Adams
7 ;; Copyright (C) 1996-2012, Drew Adams, all rights reserved.
8 ;; Created: Mon Nov 28 15:41:09 2005
10 ;; Last-Updated: Fri May 11 16:27:59 2012 (-0700)
13 ;; URL: http://www.emacswiki.org/cgi-bin/wiki/apropos-fn+var.el
15 ;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x
17 ;; Features that might be required by this library:
19 ;; `apropos', `naked'.
21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25 ;; Standard `apropos' commands `apropos-variable' and
26 ;; `apropos-command' do not distinguish, by command name, between the
27 ;; different types of target object (but you can do that via `C-u').
28 ;; This library provides individual `apropos' commands for user
29 ;; options, variables in general (not just options), and functions in
30 ;; general (not just commands). These commands are defined here:
32 ;; `apropos-option' - Apropos a user option
33 ;; `apropos-variable' - Apropos any variable, not just user option
34 ;; `apropos-function' - Apropos any function, not just command
37 ;; ***** NOTE: The following functions defined in `apropos.el' have
38 ;; been REDEFINED HERE:
40 ;; `apropos-variable' - See above (the standard command does what
41 ;; `apropos-option' does here).
42 ;; `apropos-print' - Identifies user options with label `Option'.
45 ;; Slightly different versions of `apropos-function' and
46 ;; `apropos-variable' were posted by Kevin Rodgers to bug-gnu-emacs,
47 ;; Tue, 06 Sep 2005 14:34:54 -0600. Kevin didn't actually redefine
48 ;; `apropos-variable' (he would never do that ;-)), but he provided
49 ;; the new definition. I redefined `apropos-print' and added button
50 ;; type `apropos-option'.
52 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
57 ;; apropos-print: Updated for Emacs 24.
59 ;; Button apropos-option: Added properties face and apropos-short-label (same as var).
61 ;; Added soft require of naked.el.
62 ;; apropos-print: Use naked-key-description if available.
64 ;; apropos-print: Added Emacs 24+ version.
66 ;; Updated to latest Emacs 22 CVS version:
67 ;; apropos-orig-regexp was renamed to apropos-pattern.
68 ;; apropos-print now has an additional optional arg.
70 ;; apropos-variable: Added ignored optional arg, for compatibility.
72 ;; Added redefinition of apropos-print and button type apropos-option.
73 ;; Made arg to apropos-function and apropos-variable mandatory.
75 ;; Redefined apropos-variable. Defined apropos-option as old version.
77 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
79 ;; This program is free software; you can redistribute it and/or modify
80 ;; it under the terms of the GNU General Public License as published by
81 ;; the Free Software Foundation; either version 2, or (at your option)
84 ;; This program is distributed in the hope that it will be useful,
85 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
86 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87 ;; GNU General Public License for more details.
89 ;; You should have received a copy of the GNU General Public License
90 ;; along with this program; see the file COPYING. If not, write to
91 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
92 ;; Floor, Boston, MA 02110-1301, USA.
94 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
100 (require 'naked nil t) ;; (no error if not found): naked-key-description
102 ;; Quiet byte compiler
103 (defvar apropos-compact-layout)
104 (defvar apropos-multi-type)
105 (defvar apropos-pattern)
106 (defvar apropos-sort-by-scores)
108 ;;;;;;;;;;;;;;;;;;;;;;;;
110 (if (< emacs-major-version 22)
111 (defun apropos-function (pattern)
112 "Show functions that match PATTERN (a regular expression).
113 This includes functions that are not commands."
114 (interactive "i") ; Ignored when interactive
116 (let ((apropos-do-all t))
117 (call-interactively 'apropos-command))
118 (apropos-command pattern t)))
119 (defun apropos-function (pattern)
120 "Show functions that match PATTERN.
121 This includes functions that are not commands.
122 PATTERN can be a word, a list of words (separated by spaces),
123 or a regexp (using some regexp special characters). If it is a word,
124 search for matches for that word as a substring. If it is a list of words,
125 search for matches for any two (or more) of those words.
127 When called from a Lisp program, a string PATTERN is used as a regexp,
128 while a list of strings is used as a word list."
129 (interactive "i") ; Ignored when interactive
131 (let ((apropos-do-all t))
132 (call-interactively 'apropos-command))
133 (apropos-command pattern t))))
136 ;;; REPLACE ORIGINAL defined in `apropos.el'.
137 ;;; Allow for non user-option variables too.
138 ;;; Rename original command as `apropos-option'.
140 (or (fboundp 'apropos-option)
141 (fset 'apropos-option (symbol-function 'apropos-variable)))
143 (if (< emacs-major-version 22)
144 (defun apropos-variable (pattern &optional ignore)
145 "Show variables that match PATTERN (a regular expression).
146 This includes variables that are not user options."
147 (interactive "i") ; Ignored when interactive
149 (let ((apropos-do-all t))
150 (call-interactively 'apropos-option))
151 (apropos-option pattern t)))
152 (defun apropos-variable (pattern &optional ignore)
153 "Show variables that match PATTERN.
154 This includes variables that are not user options.
155 PATTERN can be a word, a list of words (separated by spaces),
156 or a regexp (using some regexp special characters). If it is a word,
157 search for matches for that word as a substring. If it is a list of
158 words, search for matches for any two (or more) of those words."
159 (interactive "i") ; Ignored when interactive
161 (let ((apropos-do-all t))
162 (call-interactively 'apropos-option))
163 (apropos-option pattern t))))
166 ;;; REPLACE ORIGINAL defined in `apropos.el'.
167 ;;; Use label "Option" for user options.
169 (cond ((< emacs-major-version 22) ; Emacs 20 and 21.
170 (defun apropos-print (do-keys spacing)
171 "Output result of apropos searching into buffer `*Apropos*'.
172 The value of `apropos-accumulator' is the list of items to output.
173 Each element should have the format (SYMBOL FN-DOC VAR-DOC [PLIST-DOC]).
174 The return value is the list that was in `apropos-accumulator', sorted
175 alphabetically by symbol name; but this function also sets
176 `apropos-accumulator' to nil before returning."
177 (if (null apropos-accumulator)
178 (message "No apropos matches for `%s'" apropos-regexp)
179 (setq apropos-accumulator
180 (sort apropos-accumulator (lambda (a b)
181 (string-lessp (car a) (car b)))))
182 (and apropos-label-face
183 (symbolp apropos-label-face)
184 (setq apropos-label-face `(face ,apropos-label-face
185 mouse-face highlight)))
186 (with-output-to-temp-buffer "*Apropos*"
187 (let ((p apropos-accumulator)
188 (old-buffer (current-buffer))
189 symbol item point1 point2)
190 (set-buffer standard-output)
193 (insert "If you move the mouse over text that changes color,\n"
194 (substitute-command-keys
195 "you can click \\[apropos-mouse-follow] to get more information.\n")))
196 (insert (substitute-command-keys
197 "In this buffer, type \\[apropos-follow] to get full documentation.\n\n"))
199 (or (not spacing) (bobp) (terpri))
200 (setq apropos-item (car p)
201 symbol (car apropos-item)
204 (princ symbol) ; print symbol name
205 (setq point2 (point))
206 ;; Calculate key-bindings if we want them.
212 (set-buffer old-buffer)
213 (where-is-internal symbol)))
215 ;; Copy over the list of key sequences,
216 ;; omitting any that contain a buffer or a frame.
218 (let ((key (car keys))
221 (while (< i (length key))
222 (if (or (framep (aref key i))
223 (bufferp (aref key i)))
227 (setq filtered (cons key filtered))))
228 (setq keys (cdr keys)))
229 (setq item filtered))
230 ;; Convert the remaining keys to a string and insert.
234 (setq key (condition-case ()
235 (if (fboundp 'naked-key-description)
236 (naked-key-description key)
237 (key-description key))
239 (if apropos-keybinding-face
240 (put-text-property 0 (length key)
241 'face apropos-keybinding-face
246 (put-text-property (- (point) 3) (point)
247 'face apropos-keybinding-face)
248 (insert " " (symbol-name symbol) " ")
250 (put-text-property (- (point) 3) (point)
251 'face apropos-keybinding-face)))
253 ;; only now so we don't propagate text attributes all over
254 (put-text-property point1 point2 'item
255 (if (eval `(or ,@(cdr apropos-item)))
258 (if apropos-symbol-face
259 (put-text-property point1 point2 'face apropos-symbol-face))
260 (apropos-print-doc 'describe-function 1 (if (commandp symbol)
262 (if (apropos-macrop symbol)
266 ;; We used to use customize-variable-other-window instead
267 ;; for a customizable variable, but that is slow.
268 ;; It is better to show an ordinary help buffer
269 ;; and let the user click on the customization button
270 ;; in that buffer, if he wants to.
271 ;; Likewise for `customize-face-other-window'.
272 (apropos-print-doc 'describe-variable 2 (if (user-variable-p symbol)
276 (apropos-print-doc 'customize-group-other-window 6 "Group" t)
277 (apropos-print-doc 'describe-face 5 "Face" t)
278 (apropos-print-doc 'widget-browse-other-window 4 "Widget" t)
279 (apropos-print-doc 'apropos-describe-plist 3 "Plist" nil))
280 (setq buffer-read-only t))))
281 (prog1 apropos-accumulator
282 (setq apropos-accumulator ()))))
283 ((< emacs-major-version 24) ; Emacs 22 and 23.
284 (defun apropos-print (do-keys spacing &optional text nosubst)
285 "Output result of apropos searching into buffer `*Apropos*'.
286 The value of `apropos-accumulator' is the list of items to output.
287 Each element should have the format
288 (SYMBOL SCORE FN-DOC VAR-DOC [PLIST-DOC WIDGET-DOC FACE-DOC GROUP-DOC]).
289 The return value is the list that was in `apropos-accumulator', sorted
290 alphabetically by symbol name; but this function also sets
291 `apropos-accumulator' to nil before returning.
293 If SPACING is non-nil, it should be a string; separate items with that string.
294 If non-nil TEXT is a string that will be printed as a heading."
295 (if (null apropos-accumulator)
296 (message "No apropos matches for `%s'" apropos-pattern)
297 (setq apropos-accumulator
298 (sort apropos-accumulator
300 ;; Don't sort by score if user can't see the score.
301 ;; It would be confusing. -- rms.
302 (if (and (boundp 'apropos-sort-by-scores)
303 apropos-sort-by-scores)
304 (or (> (cadr a) (cadr b))
305 (and (= (cadr a) (cadr b))
306 (string-lessp (car a) (car b))))
307 (string-lessp (car a) (car b))))))
308 (with-output-to-temp-buffer "*Apropos*"
309 (let ((p apropos-accumulator)
310 (old-buffer (current-buffer))
312 (set-buffer standard-output)
314 (if (display-mouse-p)
316 "If moving the mouse over text changes the text's color, "
318 "mouse-2 (second button from right) on that text to "
319 "get more information.\n"))
320 (insert "In this buffer, go to the name of the command, function, or variable,\n"
321 (substitute-command-keys
322 "and type \\[apropos-follow] to get full documentation.\n\n"))
323 (if text (insert text "\n\n"))
325 (when (and spacing (not (bobp)))
327 (setq apropos-item (car p)
328 symbol (car apropos-item)
330 ;; Insert dummy score element for backwards compatibility with 21.x
331 ;; apropos-item format.
332 (if (not (numberp (cadr apropos-item)))
334 (cons (car apropos-item)
335 (cons nil (cdr apropos-item)))))
336 (insert-text-button (symbol-name symbol)
337 'type 'apropos-symbol
338 ;; Can't use default, since user may have
339 ;; changed the variable!
340 ;; Just say `no' to variables containing faces!
341 'face apropos-symbol-face)
342 (if (and (eq apropos-sort-by-scores 'verbose)
344 (insert " (" (number-to-string (cadr apropos-item)) ") "))
345 ;; Calculate key-bindings if we want them.
351 (set-buffer old-buffer)
352 (where-is-internal symbol)))
354 ;; Copy over the list of key sequences,
355 ;; omitting any that contain a buffer or a frame.
357 (let ((key (car keys))
360 (while (< i (length key))
361 (if (or (framep (aref key i))
362 (bufferp (aref key i)))
366 (setq filtered (cons key filtered))))
367 (setq keys (cdr keys)))
368 (setq item filtered))
369 ;; Convert the remaining keys to a string and insert.
373 (setq key (condition-case ()
374 (if (fboundp 'naked-key-description)
375 (naked-key-description key)
376 (key-description key))
378 (if apropos-keybinding-face
379 (put-text-property 0 (length key)
380 'face apropos-keybinding-face
384 (insert "M-x ... RET")
385 (when apropos-keybinding-face
386 (put-text-property (- (point) 11) (- (point) 8)
387 'face apropos-keybinding-face)
388 (put-text-property (- (point) 3) (point)
389 'face apropos-keybinding-face))))
391 (apropos-print-doc 2 (if (commandp symbol)
393 (if (apropos-macrop symbol)
397 (apropos-print-doc 3 (if (user-variable-p symbol)
401 (apropos-print-doc 7 'apropos-group t)
402 (apropos-print-doc 6 'apropos-face t)
403 (apropos-print-doc 5 'apropos-widget t)
404 (apropos-print-doc 4 'apropos-plist nil))
405 (setq buffer-read-only t))))
406 (prog1 apropos-accumulator
407 (setq apropos-accumulator ())))) ; permit gc
409 (defun apropos-print (do-keys spacing &optional text nosubst)
410 "Output result of apropos searching into buffer `*Apropos*'.
411 The value of `apropos-accumulator' is the list of items to output.
412 Each element should have the format
413 (SYMBOL SCORE FN-DOC VAR-DOC [PLIST-DOC WIDGET-DOC FACE-DOC GROUP-DOC]).
414 The return value is the list that was in `apropos-accumulator', sorted
415 alphabetically by symbol name; but this function also sets
416 `apropos-accumulator' to nil before returning.
418 If SPACING is non-nil, it should be a string; separate items with that string.
419 If non-nil TEXT is a string that will be printed as a heading."
420 (if (null apropos-accumulator)
421 (message "No apropos matches for `%s'" apropos-pattern)
422 (setq apropos-accumulator
423 (sort apropos-accumulator
425 ;; Don't sort by score if user can't see the score.
426 ;; It would be confusing. -- rms.
427 (if apropos-sort-by-scores
428 (or (> (cadr a) (cadr b))
429 (and (= (cadr a) (cadr b))
430 (string-lessp (car a) (car b))))
431 (string-lessp (car a) (car b))))))
432 (with-output-to-temp-buffer "*Apropos*"
433 (let ((p apropos-accumulator)
434 (old-buffer (current-buffer))
435 (inhibit-read-only t)
437 (set-buffer standard-output)
439 (insert (substitute-command-keys "Type \\[apropos-follow] on ")
440 (if apropos-multi-type "a type label" "an entry")
441 " to view its full documentation.\n\n")
442 (if text (insert text "\n\n"))
443 (dolist (apropos-item p)
444 (when (and spacing (not (bobp)))
446 (setq symbol (car apropos-item))
447 ;; Insert dummy score element for backwards compatibility with 21.x
448 ;; apropos-item format.
449 (if (not (numberp (cadr apropos-item)))
451 (cons (car apropos-item)
452 (cons nil (cdr apropos-item)))))
453 (insert-text-button (symbol-name symbol)
454 'type 'apropos-symbol
455 'skip apropos-multi-type
456 'face (if (boundp 'apropos-symbol-face)
459 (if (and (eq apropos-sort-by-scores 'verbose)
461 (insert " (" (number-to-string (cadr apropos-item)) ") "))
462 ;; Calculate key-bindings if we want them.
463 (unless apropos-compact-layout
466 (not (eq symbol 'self-insert-command))
469 (with-current-buffer old-buffer
470 (where-is-internal symbol)))
472 ;; Copy over the list of key sequences,
473 ;; omitting any that contain a buffer or a frame.
474 ;; FIXME: Why omit keys that contain buffers and
475 ;; frames? This looks like a bad workaround rather
476 ;; than a proper fix. Does anybody know what problem
477 ;; this is trying to address? --Stef
481 (while (< i (length key))
482 (if (or (framep (aref key i))
483 (bufferp (aref key i)))
487 (push key filtered))))
488 (setq item filtered))
489 ;; Convert the remaining keys to a string and insert.
493 (setq key (condition-case ()
494 (if (fboundp 'naked-key-description)
495 (naked-key-description key)
496 (key-description key))
498 (put-text-property 0 (length key)
499 'face (if (boundp 'apropos-keybinding-face)
500 apropos-keybinding-face
505 (insert "M-x ... RET")
506 (put-text-property (- (point) 11) (- (point) 8)
507 'face (if (boundp 'apropos-keybinding-face)
508 apropos-keybinding-face
509 'apropos-keybinding))
510 (put-text-property (- (point) 3) (point)
511 'face (if (boundp 'apropos-keybinding-face)
512 apropos-keybinding-face
513 'apropos-keybinding))))
515 (apropos-print-doc 2 (if (commandp symbol)
517 (if (apropos-macrop symbol)
521 (apropos-print-doc 3 (if (user-variable-p symbol)
525 (apropos-print-doc 7 'apropos-group t)
526 (apropos-print-doc 6 'apropos-face t)
527 (apropos-print-doc 5 'apropos-widget t)
528 (apropos-print-doc 4 'apropos-plist nil))
529 (set (make-local-variable 'truncate-partial-width-windows) t)
530 (set (make-local-variable 'truncate-lines) t))))
531 (prog1 apropos-accumulator
532 (setq apropos-accumulator ()))))) ; permit gc
534 (when (>= emacs-major-version 22)
535 (defface apropos-option '((t (:inherit font-lock-variable-name-face)))
536 "Face used for option names in Apropos buffers."
539 (define-button-type 'apropos-option
540 'apropos-label "Option"
541 'apropos-short-label "v" ; Same as variable
542 'face '(apropos-option button)
543 'help-echo "mouse-2, RET: Display more help on this user option (variable)"
545 'action (lambda (button)
546 (describe-variable (button-get button 'apropos-symbol))))
548 ;;; (define-button-type 'apropos-function
549 ;;; 'apropos-label "Function"
550 ;;; 'apropos-short-label "f"
551 ;;; 'face '(font-lock-function-name-face button)
552 ;;; 'help-echo "mouse-2, RET: Display more help on this function"
554 ;;; 'action (lambda (button)
555 ;;; (describe-function (button-get button 'apropos-symbol))))
557 ;;; (define-button-type 'apropos-macro
558 ;;; 'apropos-label "Macro"
559 ;;; 'apropos-short-label "m"
560 ;;; 'face '(font-lock-function-name-face button)
561 ;;; 'help-echo "mouse-2, RET: Display more help on this macro"
563 ;;; 'action (lambda (button)
564 ;;; (describe-function (button-get button 'apropos-symbol))))
566 ;;; (define-button-type 'apropos-command
567 ;;; 'apropos-label "Command"
568 ;;; 'apropos-short-label "c"
569 ;;; 'face '(font-lock-function-name-face button)
570 ;;; 'help-echo "mouse-2, RET: Display more help on this command"
572 ;;; 'action (lambda (button)
573 ;;; (describe-function (button-get button 'apropos-symbol))))
575 ;;; ;; We used to use `customize-variable-other-window' instead for a
576 ;;; ;; customizable variable, but that is slow. It is better to show an
577 ;;; ;; ordinary help buffer and let the user click on the customization
578 ;;; ;; button in that buffer, if he wants to.
579 ;;; ;; Likewise for `customize-face-other-window'.
580 ;;; (define-button-type 'apropos-variable
581 ;;; 'apropos-label "Variable"
582 ;;; 'apropos-short-label "v"
583 ;;; 'face '(font-lock-variable-name-face button)
584 ;;; 'help-echo "mouse-2, RET: Display more help on this variable"
586 ;;; 'action (lambda (button)
587 ;;; (describe-variable (button-get button 'apropos-symbol))))
589 ;;; (define-button-type 'apropos-face
590 ;;; 'apropos-label "Face"
591 ;;; 'apropos-short-label "F"
592 ;;; 'face '(font-lock-variable-name-face button)
593 ;;; 'help-echo "mouse-2, RET: Display more help on this face"
595 ;;; 'action (lambda (button)
596 ;;; (describe-face (button-get button 'apropos-symbol))))
598 ;;; (define-button-type 'apropos-group
599 ;;; 'apropos-label "Group"
600 ;;; 'apropos-short-label "g"
601 ;;; 'face '(font-lock-builtin-face button)
602 ;;; 'help-echo "mouse-2, RET: Display more help on this group"
604 ;;; 'action (lambda (button)
605 ;;; (customize-group-other-window
606 ;;; (button-get button 'apropos-symbol))))
608 ;;; (define-button-type 'apropos-widget
609 ;;; 'apropos-label "Widget"
610 ;;; 'apropos-short-label "w"
611 ;;; 'face '(font-lock-builtin-face button)
612 ;;; 'help-echo "mouse-2, RET: Display more help on this widget"
614 ;;; 'action (lambda (button)
615 ;;; (widget-browse-other-window (button-get button 'apropos-symbol))))
617 ;;; (define-button-type 'apropos-plist
618 ;;; 'apropos-label "Properties"
619 ;;; 'apropos-short-label "p"
620 ;;; 'face '(font-lock-keyword-face button)
621 ;;; 'help-echo "mouse-2, RET: Display more help on this plist"
623 ;;; 'action (lambda (button)
624 ;;; (apropos-describe-plist (button-get button 'apropos-symbol))))
626 ;;; (define-button-type 'apropos-library
627 ;;; 'help-echo "mouse-2, RET: Display more help on this library"
629 ;;; 'action (lambda (button)
630 ;;; (apropos-library (button-get button 'apropos-symbol))))
635 (provide 'apropos-fn+var)
637 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
638 ;;; apropos-fn.el ends here