(x-decompose-font-name): While seting each field of
[bpt/emacs.git] / lisp / help.el
CommitLineData
1a06eabd
ER
1;;; help.el --- help commands for Emacs
2
d733c5ec 3;; Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
3a801d0c 4
e5167999 5;; Maintainer: FSF
fd7fa35a 6;; Keywords: help, internal
e5167999 7
433ae6f6
RS
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
e5167999 12;; the Free Software Foundation; either version 2, or (at your option)
433ae6f6
RS
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
b578f267
EN
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
433ae6f6 24
d9ecc911
ER
25;;; Commentary:
26
a1c9f209 27;; This code implements GNU Emacs' on-line help system, the one invoked by
d9ecc911
ER
28;;`M-x help-for-help'.
29
e5167999
ER
30;;; Code:
31
8aa3a187
RS
32;; Get the macro make-help-screen when this is compiled,
33;; or run interpreted, but not when the compiled code is loaded.
b1fe9304 34(eval-when-compile (require 'help-macro))
41b8542b 35
433ae6f6
RS
36(defvar help-map (make-sparse-keymap)
37 "Keymap for characters following the Help key.")
38
afaa65e4
KH
39(defvar help-mode-map (make-sparse-keymap)
40 "Keymap for help mode.")
41
e17d2fd1 42(define-key global-map (char-to-string help-char) 'help-command)
0af3df1c
RS
43(define-key global-map [help] 'help-command)
44(define-key global-map [f1] 'help-command)
433ae6f6
RS
45(fset 'help-command help-map)
46
e17d2fd1 47(define-key help-map (char-to-string help-char) 'help-for-help)
0af3df1c
RS
48(define-key help-map [help] 'help-for-help)
49(define-key help-map [f1] 'help-for-help)
433ae6f6
RS
50(define-key help-map "?" 'help-for-help)
51
52(define-key help-map "\C-c" 'describe-copying)
53(define-key help-map "\C-d" 'describe-distribution)
54(define-key help-map "\C-w" 'describe-no-warranty)
76766f2d 55(define-key help-map "\C-p" 'describe-project)
122955bf 56(define-key help-map "a" 'apropos-command)
433ae6f6
RS
57
58(define-key help-map "b" 'describe-bindings)
59
60(define-key help-map "c" 'describe-key-briefly)
61(define-key help-map "k" 'describe-key)
62
63(define-key help-map "d" 'describe-function)
64(define-key help-map "f" 'describe-function)
65
7ee71cf1
RS
66(define-key help-map "F" 'view-emacs-FAQ)
67
433ae6f6 68(define-key help-map "i" 'info)
e5d77022
JB
69(define-key help-map "\C-f" 'Info-goto-emacs-command-node)
70(define-key help-map "\C-k" 'Info-goto-emacs-key-command-node)
f2102d2c 71(define-key help-map "\C-i" 'word-help)
433ae6f6
RS
72
73(define-key help-map "l" 'view-lossage)
74
75(define-key help-map "m" 'describe-mode)
76
77(define-key help-map "\C-n" 'view-emacs-news)
78(define-key help-map "n" 'view-emacs-news)
79
06b98c51 80(define-key help-map "p" 'finder-by-keyword)
3e9c095d
RS
81(autoload 'finder-by-keyword "finder"
82 "Find packages matching a given keyword." t)
06b98c51 83
433ae6f6
RS
84(define-key help-map "s" 'describe-syntax)
85
86(define-key help-map "t" 'help-with-tutorial)
87
88(define-key help-map "w" 'where-is)
89
90(define-key help-map "v" 'describe-variable)
91
2fc9d9f4
RS
92(define-key help-map "q" 'help-quit)
93
507fb916 94(defvar help-font-lock-keywords
0e0ee795
RS
95 (eval-when-compile
96 (let ((name-char "[-+a-zA-Z0-9_*]") (sym-char "[-+a-zA-Z0-9_:*]"))
97 (list
98 ;;
99 ;; The symbol itself.
100 (list (concat "\\`\\(" name-char "+\\)\\(\\(:\\)\\|\\('\\)\\)")
8743d4cb
RS
101 '(1 (if (match-beginning 3)
102 font-lock-function-name-face
b8077811 103 font-lock-variable-name-face)))
0e0ee795
RS
104 ;;
105 ;; Words inside `' which tend to be symbol names.
106 (list (concat "`\\(" sym-char sym-char "+\\)'")
107 1 'font-lock-reference-face t)
108 ;;
109 ;; CLisp `:' keywords as references.
110 (list (concat "\\<:" sym-char "+\\>") 0 'font-lock-reference-face t))))
507fb916
SM
111 "Default expressions to highlight in Help mode.")
112
afaa65e4
KH
113(defun help-mode ()
114 "Major mode for viewing help text.
115Entry to this mode runs the normal hook `help-mode-hook'.
116Commands:
117\\{help-mode-map}"
118 (interactive)
119 (kill-all-local-variables)
120 (use-local-map help-mode-map)
121 (setq mode-name "Help")
122 (setq major-mode 'help-mode)
507fb916 123 (make-local-variable 'font-lock-defaults)
dd7d85ba 124 (setq font-lock-defaults '(help-font-lock-keywords))
42499979 125 (view-mode)
afaa65e4
KH
126 (run-hooks 'help-mode-hook))
127
2fc9d9f4
RS
128(defun help-quit ()
129 (interactive)
130 nil)
131
0634ea78
KH
132(defun help-with-tutorial (&optional arg)
133 "Select the Emacs learn-by-doing tutorial.
134A tutorial written in the current primary language is selected.
135If there's no tutorial in the language, \"TUTORIAL\" is selected.
136With arg, users are asked to select language."
137 (interactive "P")
138 (let* ((filename
139 (let ((lang (if arg (read-language-name 'tutorial "Language: ")
140 primary-language)))
141 (get-language-info lang 'tutorial)))
142 (file (expand-file-name (concat "~/" filename))))
433ae6f6
RS
143 (delete-other-windows)
144 (if (get-file-buffer file)
145 (switch-to-buffer (get-file-buffer file))
146 (switch-to-buffer (create-file-buffer file))
147 (setq buffer-file-name file)
148 (setq default-directory (expand-file-name "~/"))
79058860 149 (setq buffer-auto-save-file-name nil)
0634ea78 150 (insert-file-contents (expand-file-name filename data-directory))
433ae6f6
RS
151 (goto-char (point-min))
152 (search-forward "\n<<")
153 (beginning-of-line)
154 (delete-region (point) (progn (end-of-line) (point)))
857a1de6 155 (let ((n (- (window-height (selected-window))
433ae6f6 156 (count-lines (point-min) (point))
857a1de6 157 6)))
d0da2301 158 (if (< n 12)
857a1de6
KH
159 (newline n)
160 ;; Some people get confused by the large gap.
161 (newline (/ n 2))
162 (insert "[Middle of page left blank for didactic purposes. "
163 "Text continues below]")
164 (newline (- n (/ n 2)))))
433ae6f6
RS
165 (goto-char (point-min))
166 (set-buffer-modified-p nil))))
167
168(defun describe-key-briefly (key)
169 "Print the name of the function KEY invokes. KEY is a string."
170 (interactive "kDescribe key briefly: ")
5f296b78
RS
171 ;; If this key seq ends with a down event, discard the
172 ;; following click or drag event. Otherwise that would
173 ;; erase the message.
174 (let ((type (aref key (1- (length key)))))
175 (if (listp type) (setq type (car type)))
176 (and (symbolp type)
177 (memq 'down (event-modifiers type))
fca4b775 178 (read-event)))
fc558e4d
RS
179 (save-excursion
180 (let ((modifiers (event-modifiers (aref key 0)))
181 window position)
182 ;; For a mouse button event, go to the button it applies to
183 ;; to get the right key bindings. And go to the right place
184 ;; in case the keymap depends on where you clicked.
185 (if (or (memq 'click modifiers) (memq 'down modifiers)
186 (memq 'drag modifiers))
187 (setq window (posn-window (event-start (aref key 0)))
188 position (posn-point (event-start (aref key 0)))))
189 (if (windowp window)
190 (progn
191 (set-buffer (window-buffer window))
192 (goto-char position)))
193 ;; Ok, now look up the key and name the command.
194 (let ((defn (key-binding key)))
195 (if (or (null defn) (integerp defn))
196 (message "%s is undefined" (key-description key))
197 (message (if (windowp window)
198 "%s at that spot runs the command %s"
199 "%s runs the command %s")
200 (key-description key)
201 (if (symbolp defn) defn (prin1-to-string defn))))))))
433ae6f6
RS
202
203(defun print-help-return-message (&optional function)
204 "Display or return message saying how to restore windows after help command.
205Computes a message and applies the optional argument FUNCTION to it.
206If FUNCTION is nil, applies `message' to it, thus printing it."
207 (and (not (get-buffer-window standard-output))
d536293f 208 (let ((first-message
a1c9f209 209 (cond ((special-display-p (buffer-name standard-output))
d536293f
RS
210 ;; If the help output buffer is a special display buffer,
211 ;; don't say anything about how to get rid of it.
212 ;; First of all, the user will do that with the window
213 ;; manager, not with Emacs.
214 ;; Secondly, the buffer has not been displayed yet,
215 ;; so we don't know whether its frame will be selected.
d536293f
RS
216 nil)
217 ((not (one-window-p t))
218 "Type \\[switch-to-buffer-other-window] RET to restore the other window.")
219 (pop-up-windows
220 "Type \\[delete-other-windows] to remove help window.")
221 (t
222 "Type \\[switch-to-buffer] RET to remove help window."))))
223 (funcall (or function 'message)
224 (concat
225 (if first-message
226 (substitute-command-keys first-message)
227 "")
228 (if first-message " " "")
125a8d70
RS
229 ;; If the help buffer will go in a separate frame,
230 ;; it's no use mentioning a command to scroll, so don't.
a1c9f209 231 (if (special-display-p (buffer-name standard-output))
125a8d70 232 nil
a1c9f209 233 (if (same-window-p (buffer-name standard-output))
125a8d70
RS
234 ;; Say how to scroll this window.
235 (substitute-command-keys
236 "\\[scroll-up] to scroll the help.")
237 ;; Say how to scroll some other window.
6e7f5182 238 (substitute-command-keys
125a8d70 239 "\\[scroll-other-window] to scroll the help."))))))))
433ae6f6
RS
240
241(defun describe-key (key)
242 "Display documentation of the function invoked by KEY. KEY is a string."
243 (interactive "kDescribe key: ")
5f296b78
RS
244 ;; If this key seq ends with a down event, discard the
245 ;; following click or drag event. Otherwise that would
246 ;; erase the message.
247 (let ((type (aref key (1- (length key)))))
248 (if (listp type) (setq type (car type)))
249 (and (symbolp type)
250 (memq 'down (event-modifiers type))
251 (read-event)))
fc558e4d
RS
252 (save-excursion
253 (let ((modifiers (event-modifiers (aref key 0)))
254 window position)
255 ;; For a mouse button event, go to the button it applies to
256 ;; to get the right key bindings. And go to the right place
257 ;; in case the keymap depends on where you clicked.
258 (if (or (memq 'click modifiers) (memq 'down modifiers)
259 (memq 'drag modifiers))
260 (setq window (posn-window (event-start (aref key 0)))
261 position (posn-point (event-start (aref key 0)))))
262 (if (windowp window)
263 (progn
264 (set-buffer (window-buffer window))
265 (goto-char position)))
266 (let ((defn (key-binding key)))
267 (if (or (null defn) (integerp defn))
268 (message "%s is undefined" (key-description key))
269 (with-output-to-temp-buffer "*Help*"
270 (princ (key-description key))
271 (if (windowp window)
272 (princ " at that spot"))
273 (princ " runs the command ")
274 (prin1 defn)
275 (princ ":\n")
fb3fc9b8
RS
276 (let ((doc (documentation defn)))
277 (if doc
278 (progn (terpri)
279 (princ doc))
280 (princ "not documented")))
fc558e4d
RS
281 (save-excursion
282 (set-buffer standard-output)
283 (help-mode))
284 (print-help-return-message)))))))
433ae6f6 285
ad023904
RS
286(defun describe-mode ()
287 "Display documentation of current major mode and minor modes.
433ae6f6 288For this to work correctly for a minor mode, the mode's indicator variable
61c6b658 289\(listed in `minor-mode-alist') must also be a function whose documentation
433ae6f6 290describes the minor mode."
7192540b 291 (interactive)
433ae6f6 292 (with-output-to-temp-buffer "*Help*"
7192540b 293 (let ((minor-modes minor-mode-alist)
ddbe99e0 294 (first t))
7192540b
RS
295 (while minor-modes
296 (let* ((minor-mode (car (car minor-modes)))
ddbe99e0 297 (indicator (car (cdr (car minor-modes)))))
7192540b
RS
298 ;; Document a minor mode if it is listed in minor-mode-alist,
299 ;; bound locally in this buffer, non-nil, and has a function
300 ;; definition.
ddbe99e0 301 (if (and (symbol-value minor-mode)
7192540b
RS
302 (fboundp minor-mode))
303 (let ((pretty-minor-mode minor-mode))
304 (if (string-match "-mode$" (symbol-name minor-mode))
305 (setq pretty-minor-mode
306 (capitalize
307 (substring (symbol-name minor-mode)
308 0 (match-beginning 0)))))
309 (while (and indicator (symbolp indicator))
310 (setq indicator (symbol-value indicator)))
83f86594
RS
311 (if first
312 (princ "The minor modes are described first,
313followed by the major mode, which is described on the last page.\n\f\n"))
314 (setq first nil)
2ef581f3
RS
315 (princ (format "%s minor mode (%s):\n"
316 pretty-minor-mode
317 (if indicator
318 (format "indicator%s" indicator)
319 "no indicator")))
7192540b 320 (princ (documentation minor-mode))
83f86594 321 (princ "\n\f\n"))))
7192540b 322 (setq minor-modes (cdr minor-modes))))
433ae6f6 323 (princ mode-name)
ad023904 324 (princ " mode:\n")
433ae6f6 325 (princ (documentation major-mode))
c46bbd92
KH
326 (save-excursion
327 (set-buffer standard-output)
328 (help-mode))
433ae6f6
RS
329 (print-help-return-message)))
330
331;; So keyboard macro definitions are documented correctly
332(fset 'defining-kbd-macro (symbol-function 'start-kbd-macro))
333
334(defun describe-distribution ()
335 "Display info on how to obtain the latest version of GNU Emacs."
336 (interactive)
337 (find-file-read-only
1e6dacf6 338 (expand-file-name "DISTRIB" data-directory)))
433ae6f6
RS
339
340(defun describe-copying ()
341 "Display info on how you may redistribute copies of GNU Emacs."
342 (interactive)
343 (find-file-read-only
1e6dacf6 344 (expand-file-name "COPYING" data-directory))
433ae6f6
RS
345 (goto-char (point-min)))
346
76766f2d
RS
347(defun describe-project ()
348 "Display info on the GNU project."
349 (interactive)
350 (find-file-read-only
351 (expand-file-name "GNU" data-directory))
352 (goto-char (point-min)))
353
433ae6f6
RS
354(defun describe-no-warranty ()
355 "Display info on all the kinds of warranty Emacs does NOT have."
356 (interactive)
357 (describe-copying)
358 (let (case-fold-search)
359 (search-forward "NO WARRANTY")
360 (recenter 0)))
361
61c6b658 362(defun describe-prefix-bindings ()
c7cba9cb
RS
363 "Describe the bindings of the prefix used to reach this command.
364The prefix described consists of all but the last event
365of the key sequence that ran this command."
61c6b658 366 (interactive)
ccc06dcc
KH
367 (let* ((key (this-command-keys)))
368 (describe-bindings
369 (if (stringp key)
370 (substring key 0 (1- (length key)))
371 (let ((prefix (make-vector (1- (length key)) nil))
372 (i 0))
373 (while (< i (length prefix))
374 (aset prefix i (aref key i))
375 (setq i (1+ i)))
376 prefix)))))
c7cba9cb
RS
377;; Make C-h after a prefix, when not specifically bound,
378;; run describe-prefix-bindings.
61c6b658
RS
379(setq prefix-help-command 'describe-prefix-bindings)
380
433ae6f6
RS
381(defun view-emacs-news ()
382 "Display info on recent changes to Emacs."
383 (interactive)
1e6dacf6 384 (find-file-read-only (expand-file-name "NEWS" data-directory)))
433ae6f6 385
7ee71cf1
RS
386(defun view-emacs-FAQ ()
387 "Display the Emacs Frequently Asked Questions (FAQ) file."
388 (interactive)
389 (find-file-read-only (expand-file-name "FAQ" data-directory)))
390
433ae6f6
RS
391(defun view-lossage ()
392 "Display last 100 input keystrokes."
393 (interactive)
394 (with-output-to-temp-buffer "*Help*"
298a7c8c
RS
395 (princ (mapconcat (function (lambda (key)
396 (if (or (integerp key)
397 (symbolp key)
398 (listp key))
399 (single-key-description key)
400 (prin1-to-string key nil))))
401 (recent-keys)
402 " "))
433ae6f6
RS
403 (save-excursion
404 (set-buffer standard-output)
405 (goto-char (point-min))
406 (while (progn (move-to-column 50) (not (eobp)))
407 (search-forward " " nil t)
c46bbd92
KH
408 (insert "\n"))
409 (help-mode))
433ae6f6
RS
410 (print-help-return-message)))
411
2fc9d9f4 412(defalias 'help 'help-for-help)
41b8542b 413(make-help-screen help-for-help
224d56a3 414 "a b c f C-f i k C-k l m n p s t v w C-c C-d C-n C-w, or ? for more help:"
76766f2d 415 "You have typed \\[help-command], the help character. Type a Help option:
efcce2d2 416\(Use SPC or DEL to scroll through this text. Type \\<help-map>\\[help-quit] to exit the Help command.)
433ae6f6 417
21ee8c42
RM
418a command-apropos. Give a substring, and see a list of commands
419 (functions interactively callable) that contain
420 that substring. See also the apropos command.
af6a9de9
RS
421b describe-bindings. Display table of all key bindings.
422c describe-key-briefly. Type a command key sequence;
21ee8c42 423 it prints the function name that sequence runs.
af6a9de9 424f describe-function. Type a function name and get documentation of it.
21ee8c42
RM
425C-f Info-goto-emacs-command-node. Type a function name;
426 it takes you to the Info node for that command.
7ee71cf1 427F view-emacs-FAQ. Shows emacs frequently asked questions file.
af6a9de9
RS
428i info. The info documentation reader.
429k describe-key. Type a command key sequence;
21ee8c42
RM
430 it displays the full documentation.
431C-k Info-goto-emacs-key-command-node. Type a command key sequence;
432 it takes you to the Info node for the command bound to that key.
af6a9de9
RS
433l view-lossage. Shows last 100 characters you typed.
434m describe-mode. Print documentation of current major mode,
21ee8c42 435 which describes the commands peculiar to it.
af6a9de9
RS
436n view-emacs-news. Shows emacs news file.
437p finder-by-keyword. Find packages matching a given topic keyword.
438s describe-syntax. Display contents of syntax table, plus explanations
439t help-with-tutorial. Select the Emacs learn-by-doing tutorial.
440v describe-variable. Type name of a variable;
21ee8c42 441 it displays the variable's documentation and value.
af6a9de9 442w where-is. Type command name; it prints which keystrokes
21ee8c42 443 invoke that command.
433ae6f6
RS
444C-c print Emacs copying permission (General Public License).
445C-d print Emacs ordering information.
446C-n print news of recent Emacs changes.
76766f2d 447C-p print information about the GNU project.
433ae6f6 448C-w print information on absence of warranty for GNU Emacs."
41b8542b 449 help-map)
433ae6f6
RS
450
451;; Return a function which is called by the list containing point.
452;; If that gives no function, return a function whose name is around point.
453;; If that doesn't give a function, return nil.
454(defun function-called-at-point ()
455 (or (condition-case ()
456 (save-excursion
457 (save-restriction
458 (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
459 (backward-up-list 1)
460 (forward-char 1)
461 (let (obj)
462 (setq obj (read (current-buffer)))
463 (and (symbolp obj) (fboundp obj) obj))))
464 (error nil))
465 (condition-case ()
914a48d0
RS
466 (let ((stab (syntax-table)))
467 (unwind-protect
468 (save-excursion
469 (set-syntax-table emacs-lisp-mode-syntax-table)
470 (or (not (zerop (skip-syntax-backward "_w")))
471 (eq (char-syntax (following-char)) ?w)
472 (eq (char-syntax (following-char)) ?_)
473 (forward-sexp -1))
474 (skip-chars-forward "'")
475 (let ((obj (read (current-buffer))))
476 (and (symbolp obj) (fboundp obj) obj)))
477 (set-syntax-table stab)))
433ae6f6
RS
478 (error nil))))
479
ca5ed196
RS
480(defun describe-function-find-file (function)
481 (let ((files load-history)
482 file functions)
483 (while files
484 (if (memq function (cdr (car files)))
485 (setq file (car (car files)) files nil))
486 (setq files (cdr files)))
487 file))
488
433ae6f6
RS
489(defun describe-function (function)
490 "Display the full documentation of FUNCTION (a symbol)."
491 (interactive
492 (let ((fn (function-called-at-point))
493 (enable-recursive-minibuffers t)
494 val)
495 (setq val (completing-read (if fn
496 (format "Describe function (default %s): " fn)
497 "Describe function: ")
498 obarray 'fboundp t))
499 (list (if (equal val "")
500 fn (intern val)))))
00d3de8e
RS
501 (if function
502 (with-output-to-temp-buffer "*Help*"
503 (prin1 function)
504 (princ ": ")
505 (let* ((def (symbol-function function))
506 file-name
507 (beg (if (commandp def) "an interactive " "a ")))
508 (princ (cond ((or (stringp def)
509 (vectorp def))
510 "a keyboard macro")
511 ((subrp def)
512 (concat beg "built-in function"))
513 ((byte-code-function-p def)
514 (concat beg "compiled Lisp function"))
515 ((symbolp def)
516 (format "alias for `%s'" def))
517 ((eq (car-safe def) 'lambda)
518 (concat beg "Lisp function"))
519 ((eq (car-safe def) 'macro)
520 "a Lisp macro")
521 ((eq (car-safe def) 'mocklisp)
522 "a mocklisp function")
523 ((eq (car-safe def) 'autoload)
524 (setq file-name (nth 1 def))
525 (format "%s autoloaded Lisp %s"
526 (if (commandp def) "an interactive" "an")
527 (if (nth 4 def) "macro" "function")
528 ))
529 (t "")))
530 (or file-name
531 (setq file-name (describe-function-find-file function)))
532 (if file-name
533 (progn
534 (princ " in `")
535 ;; We used to add .el to the file name,
536 ;; but that's completely wrong when the user used load-file.
537 (princ file-name)
538 (princ "'")))
539 (princ ".")
540 (terpri)
541 (let ((arglist (cond ((byte-code-function-p def)
542 (car (append def nil)))
543 ((eq (car-safe def) 'lambda)
544 (nth 1 def))
545 (t t))))
546 (if (listp arglist)
547 (progn
548 (princ (cons function
549 (mapcar (lambda (arg)
550 (if (memq arg '(&optional &rest))
551 arg
552 (intern (upcase (symbol-name arg)))))
553 arglist)))
554 (terpri))))
555 (let ((doc (documentation function)))
556 (if doc
557 (progn (terpri)
558 (princ doc))
559 (princ "not documented"))))
560 (print-help-return-message)
561 (save-excursion
562 (set-buffer standard-output)
563 (help-mode)
564 ;; Return the text we displayed.
565 (buffer-string)))
566 (message "You didn't specify a function")))
567
568;; We return 0 if we can't find a variable to return.
433ae6f6
RS
569(defun variable-at-point ()
570 (condition-case ()
914a48d0
RS
571 (let ((stab (syntax-table)))
572 (unwind-protect
573 (save-excursion
574 (set-syntax-table emacs-lisp-mode-syntax-table)
575 (or (not (zerop (skip-syntax-backward "_w")))
576 (eq (char-syntax (following-char)) ?w)
577 (eq (char-syntax (following-char)) ?_)
578 (forward-sexp -1))
579 (skip-chars-forward "'")
580 (let ((obj (read (current-buffer))))
00d3de8e
RS
581 (or (and (symbolp obj) (boundp obj) obj)
582 0)))
914a48d0 583 (set-syntax-table stab)))
00d3de8e 584 (error 0)))
433ae6f6
RS
585
586(defun describe-variable (variable)
587 "Display the full documentation of VARIABLE (a symbol).
588Returns the documentation as a string, also."
589 (interactive
590 (let ((v (variable-at-point))
591 (enable-recursive-minibuffers t)
592 val)
00d3de8e 593 (setq val (completing-read (if (symbolp v)
433ae6f6
RS
594 (format "Describe variable (default %s): " v)
595 "Describe variable: ")
596 obarray 'boundp t))
597 (list (if (equal val "")
598 v (intern val)))))
00d3de8e 599 (if (symbolp variable)
9a656d19
RS
600 (let (valvoid)
601 (with-output-to-temp-buffer "*Help*"
602 (prin1 variable)
603 (if (not (boundp variable))
604 (progn
605 (princ " is void")
606 (terpri)
607 (setq valvoid t))
608 (princ "'s value is ")
609 (terpri)
610 (pp (symbol-value variable))
611 (terpri))
612 (if (local-variable-p variable)
613 (progn
614 (princ (format "Local in buffer %s; " (buffer-name)))
615 (if (not (default-boundp variable))
616 (princ "globally void")
617 (princ "global value is ")
618 (terpri)
619 (pp (default-value variable)))
620 (terpri)))
621 (terpri)
622 (save-current-buffer
623 (set-buffer standard-output)
624 (if (> (count-lines (point-min) (point-max)) 10)
625 (progn
626 (goto-char (point-min))
627 (if valvoid
628 (forward-line 1)
629 (forward-sexp 1)
630 (delete-region (point) (progn (end-of-line) (point)))
631 (insert "'s value is shown below.\n\n")
632 (save-excursion
633 (insert "\n\nValue:"))))))
634 (princ "Documentation:")
635 (terpri)
636 (let ((doc (documentation-property variable 'variable-documentation)))
637 (princ (or doc "not documented as a variable.")))
638 (print-help-return-message)
639 (save-excursion
640 (set-buffer standard-output)
641 (help-mode)
642 ;; Return the text we displayed.
643 (buffer-string))))
00d3de8e 644 (message "You did not specify a variable")))
433ae6f6 645
54c0b967
RS
646(defun where-is (definition)
647 "Print message listing key sequences that invoke specified command.
648Argument is a command definition, usually a symbol with a function definition."
649 (interactive
650 (let ((fn (function-called-at-point))
651 (enable-recursive-minibuffers t)
652 val)
653 (setq val (completing-read (if fn
654 (format "Where is command (default %s): " fn)
655 "Where is command: ")
656 obarray 'fboundp t))
657 (list (if (equal val "")
658 fn (intern val)))))
659 (let* ((keys (where-is-internal definition overriding-local-map nil nil))
660 (keys1 (mapconcat 'key-description keys ", ")))
661 (if (> (length keys1) 0)
662 (message "%s is on %s" definition keys1)
663 (message "%s is not on any key" definition)))
664 nil)
665
a130d829 666(defun locate-library (library &optional nosuffix path interactive-call)
2747503c 667 "Show the precise file name of Emacs library LIBRARY.
433ae6f6
RS
668This command searches the directories in `load-path' like `M-x load-library'
669to find the file that `M-x load-library RET LIBRARY RET' would load.
670Optional second arg NOSUFFIX non-nil means don't add suffixes `.elc' or `.el'
9dc176a0
RS
671to the specified name LIBRARY.
672
673If the optional third arg PATH is specified, that list of directories
674is used instead of `load-path'."
a130d829
RS
675 (interactive (list (read-string "Locate library: ")
676 nil nil
677 t))
678 (let (result)
679 (catch 'answer
680 (mapcar
a1c9f209
EN
681 (lambda (dir)
682 (mapcar
683 (lambda (suf)
684 (let ((try (expand-file-name (concat library suf) dir)))
685 (and (file-readable-p try)
686 (null (file-directory-p try))
687 (progn
688 (setq result try)
689 (throw 'answer try)))))
690 (if nosuffix
691 '("")
692 (let ((basic '(".elc" ".el" ""))
693 (compressed '(".Z" ".gz" "")))
694 ;; If autocompression mode is on,
695 ;; consider all combinations of library suffixes
696 ;; and compression suffixes.
697 (if (rassq 'jka-compr-handler file-name-handler-alist)
698 (apply 'nconc
699 (mapcar (lambda (compelt)
700 (mapcar (lambda (baselt)
701 (concat baselt compelt))
702 basic))
703 compressed))
704 basic)))))
a130d829
RS
705 (or path load-path)))
706 (and interactive-call
707 (if result
708 (message "Library is file %s" result)
709 (message "No library %s in search path" library)))
710 result))
1a06eabd
ER
711
712;;; help.el ends here