(w32_ring_bell): Flash window correctly.
[bpt/emacs.git] / lisp / help.el
CommitLineData
1a06eabd
ER
1;;; help.el --- help commands for Emacs
2
400a1b1f 3;; Copyright (C) 1985, 1986, 1993, 1994, 1998 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)
32884eab 71(define-key help-map "\C-i" 'info-lookup-symbol)
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
400a1b1f
RS
94(define-key help-mode-map [mouse-2] 'help-follow-mouse)
95(define-key help-mode-map "\C-c\C-b" 'help-go-back)
96(define-key help-mode-map "\C-c\C-c" 'help-follow)
97(define-key help-mode-map "\t" 'help-next-ref)
98(define-key help-mode-map [backtab] 'help-previous-ref)
306a5e68 99(define-key help-mode-map [(shift tab)] 'help-previous-ref)
400a1b1f
RS
100;; Documentation only, since we use minor-mode-overriding-map-alist.
101(define-key help-mode-map "\r" 'help-follow)
102
103;; Font-locking is incompatible with the new xref stuff.
104;(defvar help-font-lock-keywords
105; (eval-when-compile
106; (let ((name-char "[-+a-zA-Z0-9_*]") (sym-char "[-+a-zA-Z0-9_:*]"))
107; (list
108; ;;
109; ;; The symbol itself.
110; (list (concat "\\`\\(" name-char "+\\)\\(\\(:\\)\\|\\('\\)\\)")
111; '(1 (if (match-beginning 3)
112; font-lock-function-name-face
113; font-lock-variable-name-face)))
114; ;;
115; ;; Words inside `' which tend to be symbol names.
116; (list (concat "`\\(" sym-char sym-char "+\\)'")
117; 1 'font-lock-constant-face t)
118; ;;
119; ;; CLisp `:' keywords as references.
120; (list (concat "\\<:" sym-char "+\\>") 0 'font-lock-builtin-face t))))
121; "Default expressions to highlight in Help mode.")
122
123(defvar help-xref-stack nil
124 "A stack of ways by which to return to help buffers after following xrefs.
125Used by `help-follow' and `help-xref-go-back'.")
126(put 'help-xref-stack 'permanent-local t)
127
128(defvar help-xref-stack-item nil
129 "An item for `help-follow' in this buffer to push onto `help-xref-stack'.")
130(put 'help-xref-stack-item 'permanent-local t)
131
132(setq-default help-xref-stack nil help-xref-stack-item nil)
507fb916 133
afaa65e4 134(defun help-mode ()
400a1b1f 135 "Major mode for viewing help text and navigating references in it.
afaa65e4
KH
136Entry to this mode runs the normal hook `help-mode-hook'.
137Commands:
138\\{help-mode-map}"
139 (interactive)
140 (kill-all-local-variables)
141 (use-local-map help-mode-map)
142 (setq mode-name "Help")
143 (setq major-mode 'help-mode)
507fb916 144 (make-local-variable 'font-lock-defaults)
400a1b1f 145 (setq font-lock-defaults nil) ; font-lock would defeat xref
42499979 146 (view-mode)
f90b6922
RS
147 (make-local-variable 'view-no-disable-on-exit)
148 (setq view-no-disable-on-exit t)
400a1b1f
RS
149 ;; `help-make-xrefs' would be run here if not invoked from
150 ;; `help-mode-maybe'.
afaa65e4
KH
151 (run-hooks 'help-mode-hook))
152
21de5941
KH
153(defun help-mode-maybe ()
154 (if (eq major-mode 'fundamental-mode)
01364a75 155 (help-mode))
400a1b1f
RS
156 (when (eq major-mode 'help-mode)
157 ;; View mode's read-only status of existing *Help* buffer is lost
158 ;; by with-output-to-temp-buffer.
159 (toggle-read-only 1)
160 (help-make-xrefs (current-buffer)))
01364a75
RS
161 (setq view-return-to-alist
162 (list (cons (selected-window) help-return-method))))
21de5941
KH
163
164(add-hook 'temp-buffer-show-hook 'help-mode-maybe)
165
2fc9d9f4
RS
166(defun help-quit ()
167 (interactive)
168 nil)
169
0634ea78
KH
170(defun help-with-tutorial (&optional arg)
171 "Select the Emacs learn-by-doing tutorial.
da412772 172If there is a tutorial version written in the language
71e9bd71 173of the selected language environment, that version is used.
da412772 174If there's no tutorial in that language, `TUTORIAL' is selected.
c822b44b 175With arg, you are asked to choose which language."
0634ea78 176 (interactive "P")
3060bf83
KH
177 (let ((lang (if arg
178 (read-language-name 'tutorial "Language: " "English")
179 (if (get-language-info current-language-environment 'tutorial)
180 current-language-environment
ad21fa07
RS
181 "English")))
182 file filename)
3060bf83 183 (setq filename (get-language-info lang 'tutorial))
7c9b148e 184 (setq file (expand-file-name (concat "~/" filename)))
433ae6f6
RS
185 (delete-other-windows)
186 (if (get-file-buffer file)
187 (switch-to-buffer (get-file-buffer file))
188 (switch-to-buffer (create-file-buffer file))
189 (setq buffer-file-name file)
190 (setq default-directory (expand-file-name "~/"))
79058860 191 (setq buffer-auto-save-file-name nil)
0634ea78 192 (insert-file-contents (expand-file-name filename data-directory))
433ae6f6
RS
193 (goto-char (point-min))
194 (search-forward "\n<<")
195 (beginning-of-line)
196 (delete-region (point) (progn (end-of-line) (point)))
857a1de6 197 (let ((n (- (window-height (selected-window))
433ae6f6 198 (count-lines (point-min) (point))
857a1de6 199 6)))
d0da2301 200 (if (< n 12)
857a1de6
KH
201 (newline n)
202 ;; Some people get confused by the large gap.
203 (newline (/ n 2))
204 (insert "[Middle of page left blank for didactic purposes. "
205 "Text continues below]")
206 (newline (- n (/ n 2)))))
433ae6f6
RS
207 (goto-char (point-min))
208 (set-buffer-modified-p nil))))
209
e88a2c59
RS
210(defun describe-key-briefly (key &optional insert)
211 "Print the name of the function KEY invokes. KEY is a string.
212If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
213 (interactive "kDescribe key briefly: \nP")
5f296b78
RS
214 ;; If this key seq ends with a down event, discard the
215 ;; following click or drag event. Otherwise that would
216 ;; erase the message.
217 (let ((type (aref key (1- (length key)))))
218 (if (listp type) (setq type (car type)))
219 (and (symbolp type)
220 (memq 'down (event-modifiers type))
fca4b775 221 (read-event)))
fc558e4d
RS
222 (save-excursion
223 (let ((modifiers (event-modifiers (aref key 0)))
e88a2c59 224 (standard-output (if insert (current-buffer) t))
fc558e4d
RS
225 window position)
226 ;; For a mouse button event, go to the button it applies to
227 ;; to get the right key bindings. And go to the right place
228 ;; in case the keymap depends on where you clicked.
229 (if (or (memq 'click modifiers) (memq 'down modifiers)
230 (memq 'drag modifiers))
231 (setq window (posn-window (event-start (aref key 0)))
232 position (posn-point (event-start (aref key 0)))))
233 (if (windowp window)
234 (progn
235 (set-buffer (window-buffer window))
236 (goto-char position)))
237 ;; Ok, now look up the key and name the command.
e88a2c59
RS
238 (let ((defn (key-binding key))
239 (key-desc (key-description key)))
fc558e4d 240 (if (or (null defn) (integerp defn))
e88a2c59
RS
241 (princ (format "%s is undefined" key-desc))
242 (princ (format (if insert
243 "%s (%s)"
244 (if (windowp window)
245 "%s at that spot runs the command %s"
246 "%s runs the command %s"))
247 key-desc
248 (if (symbolp defn) defn (prin1-to-string defn)))))))))
433ae6f6 249
01364a75
RS
250(defvar help-return-method nil
251 "What to do to \"exit\" the help buffer.
252This is a list
253 (WINDOW . t) delete the selected window, go to WINDOW.
254 (WINDOW . quit-window) do quit-window, then select WINDOW.
255 (WINDOW BUF START POINT) display BUF at START, POINT, then select WINDOW.")
256
433ae6f6
RS
257(defun print-help-return-message (&optional function)
258 "Display or return message saying how to restore windows after help command.
259Computes a message and applies the optional argument FUNCTION to it.
260If FUNCTION is nil, applies `message' to it, thus printing it."
261 (and (not (get-buffer-window standard-output))
d536293f 262 (let ((first-message
a1c9f209 263 (cond ((special-display-p (buffer-name standard-output))
01364a75 264 (setq help-return-method (cons (selected-window) t))
d536293f
RS
265 ;; If the help output buffer is a special display buffer,
266 ;; don't say anything about how to get rid of it.
267 ;; First of all, the user will do that with the window
268 ;; manager, not with Emacs.
269 ;; Secondly, the buffer has not been displayed yet,
270 ;; so we don't know whether its frame will be selected.
d536293f
RS
271 nil)
272 ((not (one-window-p t))
01364a75
RS
273 (setq help-return-method
274 (cons (selected-window) 'quit-window))
d536293f
RS
275 "Type \\[switch-to-buffer-other-window] RET to restore the other window.")
276 (pop-up-windows
01364a75 277 (setq help-return-method (cons (selected-window) t))
d536293f
RS
278 "Type \\[delete-other-windows] to remove help window.")
279 (t
01364a75
RS
280 (setq help-return-method
281 (list (selected-window) (window-buffer)
282 (window-start) (window-point)))
d536293f
RS
283 "Type \\[switch-to-buffer] RET to remove help window."))))
284 (funcall (or function 'message)
285 (concat
286 (if first-message
287 (substitute-command-keys first-message)
288 "")
289 (if first-message " " "")
125a8d70
RS
290 ;; If the help buffer will go in a separate frame,
291 ;; it's no use mentioning a command to scroll, so don't.
a1c9f209 292 (if (special-display-p (buffer-name standard-output))
125a8d70 293 nil
a1c9f209 294 (if (same-window-p (buffer-name standard-output))
125a8d70
RS
295 ;; Say how to scroll this window.
296 (substitute-command-keys
297 "\\[scroll-up] to scroll the help.")
298 ;; Say how to scroll some other window.
6e7f5182 299 (substitute-command-keys
125a8d70 300 "\\[scroll-other-window] to scroll the help."))))))))
433ae6f6
RS
301
302(defun describe-key (key)
303 "Display documentation of the function invoked by KEY. KEY is a string."
304 (interactive "kDescribe key: ")
5f296b78
RS
305 ;; If this key seq ends with a down event, discard the
306 ;; following click or drag event. Otherwise that would
307 ;; erase the message.
308 (let ((type (aref key (1- (length key)))))
309 (if (listp type) (setq type (car type)))
310 (and (symbolp type)
311 (memq 'down (event-modifiers type))
312 (read-event)))
fc558e4d
RS
313 (save-excursion
314 (let ((modifiers (event-modifiers (aref key 0)))
315 window position)
316 ;; For a mouse button event, go to the button it applies to
317 ;; to get the right key bindings. And go to the right place
318 ;; in case the keymap depends on where you clicked.
319 (if (or (memq 'click modifiers) (memq 'down modifiers)
320 (memq 'drag modifiers))
321 (setq window (posn-window (event-start (aref key 0)))
322 position (posn-point (event-start (aref key 0)))))
323 (if (windowp window)
324 (progn
325 (set-buffer (window-buffer window))
326 (goto-char position)))
327 (let ((defn (key-binding key)))
328 (if (or (null defn) (integerp defn))
329 (message "%s is undefined" (key-description key))
330 (with-output-to-temp-buffer "*Help*"
331 (princ (key-description key))
332 (if (windowp window)
333 (princ " at that spot"))
334 (princ " runs the command ")
335 (prin1 defn)
05f6170c
KH
336 (princ "\n which is ")
337 (describe-function-1 defn nil)
fc558e4d 338 (print-help-return-message)))))))
433ae6f6 339
ad023904
RS
340(defun describe-mode ()
341 "Display documentation of current major mode and minor modes.
433ae6f6 342For this to work correctly for a minor mode, the mode's indicator variable
61c6b658 343\(listed in `minor-mode-alist') must also be a function whose documentation
433ae6f6 344describes the minor mode."
7192540b 345 (interactive)
433ae6f6 346 (with-output-to-temp-buffer "*Help*"
7192540b 347 (let ((minor-modes minor-mode-alist)
ddbe99e0 348 (first t))
7192540b
RS
349 (while minor-modes
350 (let* ((minor-mode (car (car minor-modes)))
ddbe99e0 351 (indicator (car (cdr (car minor-modes)))))
7192540b
RS
352 ;; Document a minor mode if it is listed in minor-mode-alist,
353 ;; bound locally in this buffer, non-nil, and has a function
354 ;; definition.
ddbe99e0 355 (if (and (symbol-value minor-mode)
7192540b
RS
356 (fboundp minor-mode))
357 (let ((pretty-minor-mode minor-mode))
358 (if (string-match "-mode$" (symbol-name minor-mode))
359 (setq pretty-minor-mode
360 (capitalize
361 (substring (symbol-name minor-mode)
362 0 (match-beginning 0)))))
363 (while (and indicator (symbolp indicator))
364 (setq indicator (symbol-value indicator)))
83f86594
RS
365 (if first
366 (princ "The minor modes are described first,
367followed by the major mode, which is described on the last page.\n\f\n"))
368 (setq first nil)
2ef581f3
RS
369 (princ (format "%s minor mode (%s):\n"
370 pretty-minor-mode
371 (if indicator
372 (format "indicator%s" indicator)
373 "no indicator")))
7192540b 374 (princ (documentation minor-mode))
83f86594 375 (princ "\n\f\n"))))
7192540b 376 (setq minor-modes (cdr minor-modes))))
433ae6f6 377 (princ mode-name)
ad023904 378 (princ " mode:\n")
433ae6f6 379 (princ (documentation major-mode))
400a1b1f 380 (help-setup-xref (cons #'help-xref-mode (current-buffer)) (interactive-p))
433ae6f6
RS
381 (print-help-return-message)))
382
383;; So keyboard macro definitions are documented correctly
384(fset 'defining-kbd-macro (symbol-function 'start-kbd-macro))
385
386(defun describe-distribution ()
387 "Display info on how to obtain the latest version of GNU Emacs."
388 (interactive)
389 (find-file-read-only
1e6dacf6 390 (expand-file-name "DISTRIB" data-directory)))
433ae6f6
RS
391
392(defun describe-copying ()
393 "Display info on how you may redistribute copies of GNU Emacs."
394 (interactive)
395 (find-file-read-only
1e6dacf6 396 (expand-file-name "COPYING" data-directory))
433ae6f6
RS
397 (goto-char (point-min)))
398
76766f2d
RS
399(defun describe-project ()
400 "Display info on the GNU project."
401 (interactive)
402 (find-file-read-only
403 (expand-file-name "GNU" data-directory))
404 (goto-char (point-min)))
405
433ae6f6
RS
406(defun describe-no-warranty ()
407 "Display info on all the kinds of warranty Emacs does NOT have."
408 (interactive)
409 (describe-copying)
410 (let (case-fold-search)
411 (search-forward "NO WARRANTY")
412 (recenter 0)))
413
61c6b658 414(defun describe-prefix-bindings ()
c7cba9cb
RS
415 "Describe the bindings of the prefix used to reach this command.
416The prefix described consists of all but the last event
417of the key sequence that ran this command."
61c6b658 418 (interactive)
ccc06dcc
KH
419 (let* ((key (this-command-keys)))
420 (describe-bindings
421 (if (stringp key)
422 (substring key 0 (1- (length key)))
423 (let ((prefix (make-vector (1- (length key)) nil))
424 (i 0))
425 (while (< i (length prefix))
426 (aset prefix i (aref key i))
427 (setq i (1+ i)))
428 prefix)))))
c7cba9cb
RS
429;; Make C-h after a prefix, when not specifically bound,
430;; run describe-prefix-bindings.
61c6b658
RS
431(setq prefix-help-command 'describe-prefix-bindings)
432
382d018a
RS
433(defun view-emacs-news (&optional arg)
434 "Display info on recent changes to Emacs.
435With numeric argument display information on correspondingly older changes."
436 (interactive "P")
437 (let* ((arg (if arg (prefix-numeric-value arg) 0)))
438 (find-file-read-only
439 (expand-file-name (concat (make-string arg ?O) "NEWS")
440 data-directory))))
433ae6f6 441
7ee71cf1
RS
442(defun view-emacs-FAQ ()
443 "Display the Emacs Frequently Asked Questions (FAQ) file."
444 (interactive)
445 (find-file-read-only (expand-file-name "FAQ" data-directory)))
446
433ae6f6
RS
447(defun view-lossage ()
448 "Display last 100 input keystrokes."
449 (interactive)
450 (with-output-to-temp-buffer "*Help*"
298a7c8c
RS
451 (princ (mapconcat (function (lambda (key)
452 (if (or (integerp key)
453 (symbolp key)
454 (listp key))
455 (single-key-description key)
456 (prin1-to-string key nil))))
457 (recent-keys)
458 " "))
433ae6f6
RS
459 (save-excursion
460 (set-buffer standard-output)
461 (goto-char (point-min))
462 (while (progn (move-to-column 50) (not (eobp)))
463 (search-forward " " nil t)
613a39b9
RS
464 (insert "\n"))
465 (setq help-xref-stack nil
466 help-xref-stack-item nil))
433ae6f6
RS
467 (print-help-return-message)))
468
2fc9d9f4 469(defalias 'help 'help-for-help)
41b8542b 470(make-help-screen help-for-help
a30a106b 471 "a b c C f F C-f i I k C-k l L m n p s t v w C-c C-d C-n C-p C-w; ? for help:"
76766f2d 472 "You have typed \\[help-command], the help character. Type a Help option:
efcce2d2 473\(Use SPC or DEL to scroll through this text. Type \\<help-map>\\[help-quit] to exit the Help command.)
433ae6f6 474
21ee8c42
RM
475a command-apropos. Give a substring, and see a list of commands
476 (functions interactively callable) that contain
477 that substring. See also the apropos command.
af6a9de9
RS
478b describe-bindings. Display table of all key bindings.
479c describe-key-briefly. Type a command key sequence;
21ee8c42 480 it prints the function name that sequence runs.
a30a106b
RS
481C describe-coding-system. This describes either a specific coding system
482 (if you type its name) or the coding systems currently in use
483 (if you type just RET).
af6a9de9 484f describe-function. Type a function name and get documentation of it.
21ee8c42
RM
485C-f Info-goto-emacs-command-node. Type a function name;
486 it takes you to the Info node for that command.
af6a9de9 487i info. The info documentation reader.
a30a106b
RS
488I describe-input-method. Describe a specific input method (if you type
489 its name) or the current input method (if you type just RET).
af6a9de9 490k describe-key. Type a command key sequence;
21ee8c42
RM
491 it displays the full documentation.
492C-k Info-goto-emacs-key-command-node. Type a command key sequence;
493 it takes you to the Info node for the command bound to that key.
af6a9de9 494l view-lossage. Shows last 100 characters you typed.
a30a106b
RS
495L describe-language-environment. This describes either the a
496 specific language environment (if you type its name)
497 or the current language environment (if you type just RET).
ed13681f
KH
498m describe-mode. Print documentation of current minor modes,
499 and the current major mode, including their special commands.
af6a9de9
RS
500n view-emacs-news. Shows emacs news file.
501p finder-by-keyword. Find packages matching a given topic keyword.
502s describe-syntax. Display contents of syntax table, plus explanations
503t help-with-tutorial. Select the Emacs learn-by-doing tutorial.
504v describe-variable. Type name of a variable;
21ee8c42 505 it displays the variable's documentation and value.
af6a9de9 506w where-is. Type command name; it prints which keystrokes
21ee8c42 507 invoke that command.
a30a106b
RS
508
509F Display the frequently asked questions file.
510h Display the HELLO file which illustrates various scripts.
511C-c Display Emacs copying permission (General Public License).
512C-d Display Emacs ordering information.
513C-n Display news of recent Emacs changes.
514C-p Display information about the GNU project.
515C-w Display information on absence of warranty for GNU Emacs."
41b8542b 516 help-map)
433ae6f6
RS
517
518;; Return a function which is called by the list containing point.
519;; If that gives no function, return a function whose name is around point.
520;; If that doesn't give a function, return nil.
521(defun function-called-at-point ()
11267867
KH
522 (let ((stab (syntax-table)))
523 (set-syntax-table emacs-lisp-mode-syntax-table)
524 (unwind-protect
525 (or (condition-case ()
526 (save-excursion
527 (save-restriction
528 (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
529 ;; Move up to surrounding paren, then after the open.
530 (backward-up-list 1)
531 (forward-char 1)
532 ;; If there is space here, this is probably something
533 ;; other than a real Lisp function call, so ignore it.
534 (if (looking-at "[ \t]")
535 (error "Probably not a Lisp function call"))
536 (let (obj)
537 (setq obj (read (current-buffer)))
538 (and (symbolp obj) (fboundp obj) obj))))
539 (error nil))
540 (condition-case ()
914a48d0 541 (save-excursion
914a48d0
RS
542 (or (not (zerop (skip-syntax-backward "_w")))
543 (eq (char-syntax (following-char)) ?w)
544 (eq (char-syntax (following-char)) ?_)
545 (forward-sexp -1))
546 (skip-chars-forward "'")
547 (let ((obj (read (current-buffer))))
548 (and (symbolp obj) (fboundp obj) obj)))
11267867
KH
549 (error nil)))
550 (set-syntax-table stab))))
433ae6f6 551
ca5ed196
RS
552(defun describe-function-find-file (function)
553 (let ((files load-history)
554 file functions)
555 (while files
556 (if (memq function (cdr (car files)))
557 (setq file (car (car files)) files nil))
558 (setq files (cdr files)))
559 file))
560
433ae6f6
RS
561(defun describe-function (function)
562 "Display the full documentation of FUNCTION (a symbol)."
563 (interactive
564 (let ((fn (function-called-at-point))
565 (enable-recursive-minibuffers t)
566 val)
567 (setq val (completing-read (if fn
568 (format "Describe function (default %s): " fn)
569 "Describe function: ")
1bacc93e 570 obarray 'fboundp t nil nil (symbol-name fn)))
433ae6f6
RS
571 (list (if (equal val "")
572 fn (intern val)))))
00d3de8e
RS
573 (if function
574 (with-output-to-temp-buffer "*Help*"
575 (prin1 function)
eea844b2
RS
576 ;; Use " is " instead of a colon so that
577 ;; it is easier to get out the function name using forward-sexp.
578 (princ " is ")
05f6170c 579 (describe-function-1 function nil)
00d3de8e
RS
580 (print-help-return-message)
581 (save-excursion
582 (set-buffer standard-output)
00d3de8e
RS
583 ;; Return the text we displayed.
584 (buffer-string)))
585 (message "You didn't specify a function")))
586
05f6170c
KH
587(defun describe-function-1 (function parens)
588 (let* ((def (symbol-function function))
589 file-name string need-close
590 (beg (if (commandp def) "an interactive " "a ")))
591 (setq string
592 (cond ((or (stringp def)
593 (vectorp def))
594 "a keyboard macro")
595 ((subrp def)
596 (concat beg "built-in function"))
597 ((byte-code-function-p def)
598 (concat beg "compiled Lisp function"))
599 ((symbolp def)
600 (format "alias for `%s'" def))
601 ((eq (car-safe def) 'lambda)
602 (concat beg "Lisp function"))
603 ((eq (car-safe def) 'macro)
604 "a Lisp macro")
605 ((eq (car-safe def) 'mocklisp)
606 "a mocklisp function")
607 ((eq (car-safe def) 'autoload)
608 (setq file-name (nth 1 def))
609 (format "%s autoloaded Lisp %s"
610 (if (commandp def) "an interactive" "an")
611 (if (nth 4 def) "macro" "function")
612 ))
613 (t "")))
614 (when (and parens (not (equal string "")))
615 (setq need-close t)
616 (princ "("))
617 (princ string)
618 (or file-name
619 (setq file-name (describe-function-find-file function)))
620 (if file-name
621 (progn
622 (princ " in `")
623 ;; We used to add .el to the file name,
624 ;; but that's completely wrong when the user used load-file.
625 (princ file-name)
2676e099
DL
626 (princ "'")
627 ;; Make a hyperlink to the library.
628 (with-current-buffer "*Help*"
629 (save-excursion
630 (re-search-backward "`\\([^`']+\\)'" nil t)
7dcf1127
RS
631 (help-xref-button 1 #'(lambda (arg)
632 (let ((location
633 (find-function-noselect arg)))
634 (display-buffer (nth 0 location))
635 (goto-char (nth 1 location))))
636 function)))))
05f6170c
KH
637 (if need-close (princ ")"))
638 (princ ".")
639 (terpri)
640 (let* ((inner-function (if (and (listp def) 'macro)
641 (cdr def)
642 def))
643 (arglist (cond ((byte-code-function-p inner-function)
644 (car (append inner-function nil)))
645 ((eq (car-safe inner-function) 'lambda)
646 (nth 1 inner-function))
647 (t t))))
648 (if (listp arglist)
649 (progn
650 (princ (cons function
651 (mapcar (lambda (arg)
652 (if (memq arg '(&optional &rest))
653 arg
654 (intern (upcase (symbol-name arg)))))
655 arglist)))
656 (terpri))))
657 (let ((doc (documentation function)))
658 (if doc
659 (progn (terpri)
660 (princ doc)
661 (help-setup-xref (cons #'describe-function function) (interactive-p)))
662 (princ "not documented")))))
663
00d3de8e 664;; We return 0 if we can't find a variable to return.
433ae6f6
RS
665(defun variable-at-point ()
666 (condition-case ()
914a48d0
RS
667 (let ((stab (syntax-table)))
668 (unwind-protect
669 (save-excursion
670 (set-syntax-table emacs-lisp-mode-syntax-table)
671 (or (not (zerop (skip-syntax-backward "_w")))
672 (eq (char-syntax (following-char)) ?w)
673 (eq (char-syntax (following-char)) ?_)
674 (forward-sexp -1))
675 (skip-chars-forward "'")
676 (let ((obj (read (current-buffer))))
00d3de8e
RS
677 (or (and (symbolp obj) (boundp obj) obj)
678 0)))
914a48d0 679 (set-syntax-table stab)))
00d3de8e 680 (error 0)))
433ae6f6
RS
681
682(defun describe-variable (variable)
683 "Display the full documentation of VARIABLE (a symbol).
684Returns the documentation as a string, also."
685 (interactive
686 (let ((v (variable-at-point))
687 (enable-recursive-minibuffers t)
688 val)
00d3de8e 689 (setq val (completing-read (if (symbolp v)
433ae6f6
RS
690 (format "Describe variable (default %s): " v)
691 "Describe variable: ")
d5645846
KH
692 obarray 'boundp t nil nil
693 (if (symbolp v) (symbol-name v))))
433ae6f6
RS
694 (list (if (equal val "")
695 v (intern val)))))
00d3de8e 696 (if (symbolp variable)
9a656d19
RS
697 (let (valvoid)
698 (with-output-to-temp-buffer "*Help*"
699 (prin1 variable)
700 (if (not (boundp variable))
701 (progn
702 (princ " is void")
703 (terpri)
704 (setq valvoid t))
705 (princ "'s value is ")
706 (terpri)
707 (pp (symbol-value variable))
708 (terpri))
709 (if (local-variable-p variable)
710 (progn
711 (princ (format "Local in buffer %s; " (buffer-name)))
712 (if (not (default-boundp variable))
713 (princ "globally void")
714 (princ "global value is ")
715 (terpri)
716 (pp (default-value variable)))
717 (terpri)))
718 (terpri)
719 (save-current-buffer
720 (set-buffer standard-output)
721 (if (> (count-lines (point-min) (point-max)) 10)
722 (progn
723 (goto-char (point-min))
724 (if valvoid
725 (forward-line 1)
726 (forward-sexp 1)
727 (delete-region (point) (progn (end-of-line) (point)))
728 (insert "'s value is shown below.\n\n")
729 (save-excursion
730 (insert "\n\nValue:"))))))
731 (princ "Documentation:")
732 (terpri)
733 (let ((doc (documentation-property variable 'variable-documentation)))
734 (princ (or doc "not documented as a variable.")))
400a1b1f 735 (help-setup-xref (cons #'describe-variable variable) (interactive-p))
9a656d19
RS
736 (print-help-return-message)
737 (save-excursion
738 (set-buffer standard-output)
9a656d19
RS
739 ;; Return the text we displayed.
740 (buffer-string))))
00d3de8e 741 (message "You did not specify a variable")))
433ae6f6 742
a8ad43aa
RS
743(defun describe-bindings (&optional prefix)
744 "Show a list of all defined keys, and their definitions.
745We put that list in a buffer, and display the buffer.
746
747The optional argument PREFIX, if non-nil, should be a key sequence;
748then we display only bindings that start with that prefix."
a249d3a0 749 (interactive "P")
613a39b9
RS
750 (describe-bindings-internal nil prefix)
751 (with-current-buffer "*Help*"
752 (setq help-xref-stack nil
753 help-xref-stack-item nil)))
a8ad43aa 754
e88a2c59 755(defun where-is (definition &optional insert)
54c0b967 756 "Print message listing key sequences that invoke specified command.
e88a2c59
RS
757Argument is a command definition, usually a symbol with a function definition.
758If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
54c0b967
RS
759 (interactive
760 (let ((fn (function-called-at-point))
761 (enable-recursive-minibuffers t)
762 val)
763 (setq val (completing-read (if fn
764 (format "Where is command (default %s): " fn)
765 "Where is command: ")
766 obarray 'fboundp t))
767 (list (if (equal val "")
e88a2c59
RS
768 fn (intern val))
769 current-prefix-arg)))
54c0b967 770 (let* ((keys (where-is-internal definition overriding-local-map nil nil))
e88a2c59
RS
771 (keys1 (mapconcat 'key-description keys ", "))
772 (standard-output (if insert (current-buffer) t)))
773 (if insert
774 (if (> (length keys1) 0)
775 (princ (format "%s (%s)" keys1 definition))
776 (princ (format "M-x %s RET" definition)))
777 (if (> (length keys1) 0)
778 (princ (format "%s is on %s" definition keys1))
779 (princ (format "%s is not on any key" definition)))))
54c0b967
RS
780 nil)
781
a130d829 782(defun locate-library (library &optional nosuffix path interactive-call)
2747503c 783 "Show the precise file name of Emacs library LIBRARY.
433ae6f6
RS
784This command searches the directories in `load-path' like `M-x load-library'
785to find the file that `M-x load-library RET LIBRARY RET' would load.
786Optional second arg NOSUFFIX non-nil means don't add suffixes `.elc' or `.el'
9dc176a0
RS
787to the specified name LIBRARY.
788
789If the optional third arg PATH is specified, that list of directories
790is used instead of `load-path'."
a130d829
RS
791 (interactive (list (read-string "Locate library: ")
792 nil nil
793 t))
dd557bb8 794 (let (result)
a130d829
RS
795 (catch 'answer
796 (mapcar
a1c9f209
EN
797 (lambda (dir)
798 (mapcar
799 (lambda (suf)
800 (let ((try (expand-file-name (concat library suf) dir)))
801 (and (file-readable-p try)
802 (null (file-directory-p try))
803 (progn
804 (setq result try)
805 (throw 'answer try)))))
806 (if nosuffix
807 '("")
dd557bb8
KH
808 '(".elc" ".el" "")
809;;; load doesn't handle this yet.
810;;; (let ((basic '(".elc" ".el" ""))
811;;; (compressed '(".Z" ".gz" "")))
812;;; ;; If autocompression mode is on,
813;;; ;; consider all combinations of library suffixes
814;;; ;; and compression suffixes.
815;;; (if (rassq 'jka-compr-handler file-name-handler-alist)
816;;; (apply 'nconc
817;;; (mapcar (lambda (compelt)
818;;; (mapcar (lambda (baselt)
819;;; (concat baselt compelt))
820;;; basic))
821;;; compressed))
822;;; basic))
823 )))
a130d829
RS
824 (or path load-path)))
825 (and interactive-call
826 (if result
827 (message "Library is file %s" result)
828 (message "No library %s in search path" library)))
829 result))
1a06eabd 830
400a1b1f
RS
831\f
832;;; Grokking cross-reference information in doc strings and
833;;; hyperlinking it.
834
835;; This may have some scope for extension and the same or something
836;; similar should be done for widget doc strings, which currently use
837;; another mechanism.
838
839(defcustom help-highlight-p t
840 "*If non-nil, `help-make-xrefs' highlight cross-references.
841Under a window system it highlights them with face defined by
842`help-highlight-face'. On a character terminal highlighted
843references look like cross-references in info mode."
844 :group 'help
845 :version "20.3"
846 :type 'boolean)
847
848(defcustom help-highlight-face 'underline
849 "Face used by `help-make-xrefs' to highlight cross-references.
850Must be previously-defined."
851 :group 'help
852 :version "20.3"
7f082394 853 :type 'face)
400a1b1f
RS
854
855(defvar help-back-label "[back]"
856 "Label to use by `help-make-xrefs' for the go-back reference.")
857
858(defvar help-xref-symbol-regexp
859 (concat "\\(\\<\\(\\(variable\\|option\\)\\|"
860 "\\(function\\|command\\)\\|"
861 "\\(symbol\\)\\)\\s-+\\)?"
862 ;; Note starting with word-syntax character:
863 "`\\(\\sw\\(\\sw\\|\\s_\\)+\\)'")
864 "Regexp matching doc string references to symbols.
865
866The words preceding the quoted symbol can be used in doc strings to
867distinguish references to variables, functions and symbols.")
868
869(defvar help-xref-info-regexp
870 "\\<info\\s-+node\\s-`\\([^']+\\)'"
871 "Regexp matching doc string references to an Info node.")
872
873(defun help-setup-xref (item interactive-p)
874 "Invoked from commands using the \"*Help*\" buffer to install some xref info.
875
876ITEM is a (function . args) pair appropriate for recreating the help
877buffer after following a reference. INTERACTIVE-P is non-nil if the
878calling command was invoked interactively. In this case the stack of
879items for help buffer \"back\" buttons is cleared."
880 (if interactive-p
881 (setq help-xref-stack nil))
882 (setq help-xref-stack-item item))
883
884(defun help-make-xrefs (&optional buffer)
885 "Parse and hyperlink documentation cross-references in the given BUFFER.
886
887Find cross-reference information in a buffer and, if
888`help-highlight-p' is non-nil, highlight it with face defined by
889`help-highlight-face'; activate such cross references for selection
890with `help-follow'. Cross-references have the canonical form `...'
891and the type of reference may be disambiguated by the preceding
892word(s) used in `help-xref-symbol-regexp'.
893
894A special reference `back' is made to return back through a stack of
895help buffers. Variable `help-back-label' specifies the text for
896that."
897 (interactive "b")
898 (save-excursion
899 (set-buffer (or buffer (current-buffer)))
900 (goto-char (point-min))
901 ;; Skip the header-type info, though it might be useful to parse
902 ;; it at some stage (e.g. "function in `library'").
903 (forward-paragraph)
904 (let ((old-modified (buffer-modified-p)))
905 (let ((stab (syntax-table))
906 (case-fold-search t)
907 (inhibit-read-only t))
908 (set-syntax-table emacs-lisp-mode-syntax-table)
909 ;; The following should probably be abstracted out.
910 (unwind-protect
911 (progn
912 ;; Quoted symbols
913 (save-excursion
914 (while (re-search-forward help-xref-symbol-regexp nil t)
915 (let* ((data (match-string 6))
916 (sym (intern-soft data)))
917 (if sym
918 (cond
919 ((match-string 3) ; `variable' &c
920 (and (boundp sym) ; `variable' doesn't ensure
921 ; it's actually bound
922 (help-xref-button 6 #'describe-variable sym)))
923 ((match-string 4) ; `function' &c
924 (and (fboundp sym) ; similarly
925 (help-xref-button 6 #'describe-function sym)))
926 ((match-string 5)) ; nothing for symbol
927 ((and (boundp sym) (fboundp sym))
928 ;; We can't intuit whether to use the
929 ;; variable or function doc -- supply both.
930 (help-xref-button 6 #'help-xref-interned sym))
931 ((boundp sym)
932 (help-xref-button 6 #'describe-variable sym))
933 ((fboundp sym)
934 (help-xref-button 6 #'describe-function sym)))))))
935 ;; Info references
936 (save-excursion
937 (while (re-search-forward help-xref-info-regexp nil t)
938 (help-xref-button 1 #'Info-goto-node (list (match-data 1)))))
939 ;; An obvious case of a key substitution:
940 (save-excursion
941 (while (re-search-forward
942 "\\<M-x\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)" nil t)
943 (let ((sym (intern-soft (match-string 1))))
944 (if (fboundp sym)
ff3453e4
DL
945 (help-xref-button 1 #'describe-function sym)))))
946 ;; Look for commands in whole keymap substitutions:
947 (save-excursion
948 ;; Find a header and the column at which the command
949 ;; name will be found.
950 (while (re-search-forward "^key +binding\n\\(-+ +\\)-+\n\n"
951 nil t)
952 (let ((col (- (match-end 1) (match-beginning 1))))
953 (while
954 ;; Ignore single blank lines in table, but not
955 ;; double ones, which should terminate it.
956 (and (looking-at "^\n?[^\n]")
957 (progn
958 (if (and (> (move-to-column col) 0)
959 (looking-at "\\(\\sw\\|\\s_\\)+$"))
960 ;;
961 (let ((sym (intern-soft (match-string 0))))
962 (if (fboundp sym)
963 (help-xref-button
964 0 #'describe-function sym))))
965 t)
966 (zerop (forward-line))
967 (move-to-column 0)))))))
400a1b1f
RS
968 (set-syntax-table stab))
969 ;; Make a back-reference in this buffer if appropriate.
970 (when help-xref-stack
971 (goto-char (point-max))
972 (save-excursion
973 (insert "\n\n" help-back-label))
974 ;; Just to provide the match data:
975 (looking-at (concat "\n\n\\(" (regexp-quote help-back-label) "\\)"))
613a39b9 976 (help-xref-button 1 #'help-xref-go-back (current-buffer))))
400a1b1f
RS
977 ;; View mode steals RET from us.
978 (set (make-local-variable 'minor-mode-overriding-map-alist)
979 (list (cons 'view-mode
980 (let ((map (make-sparse-keymap)))
ff3453e4 981 (set-keymap-parent map view-mode-map)
400a1b1f
RS
982 (define-key map "\r" 'help-follow)
983 map))))
984 (set-buffer-modified-p old-modified))))
985
986(defun help-xref-button (match-number function data)
987 "Make a hyperlink for cross-reference text previously matched.
988
989MATCH-NUMBER is the subexpression of interest in the last matched
990regexp. FUNCTION is a function to invoke when the button is
991activated, applied to DATA. DATA may be a single value or a list.
992See `help-make-xrefs'."
ff3453e4 993 (add-text-properties (match-beginning match-number)
400a1b1f 994 (match-end match-number)
ff3453e4 995 (list 'mouse-face 'highlight
400a1b1f
RS
996 'help-xref (cons function
997 (if (listp data)
998 data
999 (list data)))))
ff3453e4
DL
1000 (if help-highlight-p
1001 (put-text-property (match-beginning match-number)
1002 (match-end match-number)
1003 'face help-highlight-face)))
400a1b1f
RS
1004
1005\f
1006;; Additional functions for (re-)creating types of help buffers.
1007(defun help-xref-interned (symbol)
1008 "Follow a hyperlink which appeared to be an arbitrary interned SYMBOL.
1009
1010Both variable and function documentation are extracted into a single
1011help buffer."
1012 (let ((fdoc (describe-function symbol)))
1013 (describe-variable symbol)
1014 ;; We now have a help buffer on the variable. Insert the function
1015 ;; text after it.
1016 (goto-char (point-max))
1017 (insert "\n\n" fdoc))
1018 (goto-char (point-min))
1019 (help-setup-xref (cons #'help-xref-interned symbol) nil))
1020
1021(defun help-xref-mode (buffer)
1022 "Do a `describe-mode' for the specified BUFFER."
1023 (save-excursion
1024 (set-buffer buffer)
1025 (describe-mode)))
1026\f
1027;;; Navigation/hyperlinking with xrefs
1028
1029(defun help-follow-mouse (click)
1030 "Follow the cross-reference that you click on."
1031 (interactive "e")
1032 (save-excursion
1033 (let* ((start (event-start click))
1034 (window (car start))
1035 (pos (car (cdr start))))
1036 (set-buffer (window-buffer window))
1037 (help-follow pos))))
1038
613a39b9
RS
1039(defun help-xref-go-back (buffer)
1040 "Go back to the previous help buffer text using info on `help-xref-stack'."
400a1b1f 1041 (interactive)
613a39b9
RS
1042 (let (item method args)
1043 (with-current-buffer buffer
1044 (when help-xref-stack
1045 (setq help-xref-stack (cdr help-xref-stack)) ; due to help-follow
1046 (setq item (car help-xref-stack)
1047 method (car item)
1048 args (cdr item))
1049 (setq help-xref-stack (cdr help-xref-stack))))
1050 (if (listp args)
1051 (apply method args)
1052 (funcall method args))))
400a1b1f
RS
1053
1054(defun help-go-back ()
1055 (interactive)
1056 (help-follow (1- (point-max))))
1057
1058(defun help-follow (&optional pos)
1059 "Follow cross-reference at POS, defaulting to point.
1060
1061For the cross-reference format, see `help-make-xrefs'."
1062 (interactive "d")
1063 (let* ((help-data (get-text-property pos 'help-xref))
1064 (method (car help-data))
1065 (args (cdr help-data)))
1066 (setq help-xref-stack (cons help-xref-stack-item help-xref-stack))
1067 (setq help-xref-stack-item nil)
1068 (when help-data
1069 ;; There is a reference at point. Follow it.
1070 (apply method args))))
1071
1072;; For tabbing through buffer.
1073(defun help-next-ref ()
1074 "Find the next help cross-reference in the buffer."
1075 (interactive)
1076 (let (pos)
1077 (while (not pos)
1078 (if (get-text-property (point) 'help-xref) ; move off reference
ff3453e4
DL
1079 (goto-char (or (next-single-property-change (point) 'help-xref)
1080 (point))))
400a1b1f
RS
1081 (cond ((setq pos (next-single-property-change (point) 'help-xref))
1082 (if pos (goto-char pos)))
1083 ((bobp)
1084 (message "No cross references in the buffer.")
1085 (setq pos t))
1086 (t ; be circular
1087 (goto-char (point-min)))))))
1088
1089(defun help-previous-ref ()
1090 "Find the previous help cross-reference in the buffer."
1091 (interactive)
1092 (let (pos)
1093 (while (not pos)
1094 (if (get-text-property (point) 'help-xref) ; move off reference
1095 (goto-char (or (previous-single-property-change (point) 'help-xref)
1096 (point))))
1097 (cond ((setq pos (previous-single-property-change (point) 'help-xref))
1098 (if pos (goto-char pos)))
1099 ((bobp)
1100 (message "No cross references in the buffer.")
1101 (setq pos t))
1102 (t ; be circular
1103 (goto-char (point-max)))))))
1104
1a06eabd 1105;;; help.el ends here