(event-apply-alt-modifier, etc): Doc fixes.
[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
0f2aa0e1 243 "`%s' (`%s')"
e88a2c59
RS
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))
7e824765
RS
736
737 ;; Make a link to customize if this variable can be customized.
738 (if (or (get variable 'custom-type)
739 (user-variable-p variable))
740 (let ((customize-label "customize"))
741 (terpri)
742 (terpri)
743 (princ (concat "You can " customize-label " this variable."))
744 (with-current-buffer "*Help*"
745 (save-excursion
746 (re-search-backward
747 (concat "\\(" customize-label "\\)") nil t)
748 (help-xref-button 1 #'(lambda (v)
749 (customize-variable v)) variable)
750 ))))
751
9a656d19
RS
752 (print-help-return-message)
753 (save-excursion
754 (set-buffer standard-output)
9a656d19
RS
755 ;; Return the text we displayed.
756 (buffer-string))))
00d3de8e 757 (message "You did not specify a variable")))
433ae6f6 758
a8ad43aa
RS
759(defun describe-bindings (&optional prefix)
760 "Show a list of all defined keys, and their definitions.
761We put that list in a buffer, and display the buffer.
762
763The optional argument PREFIX, if non-nil, should be a key sequence;
764then we display only bindings that start with that prefix."
a249d3a0 765 (interactive "P")
613a39b9
RS
766 (describe-bindings-internal nil prefix)
767 (with-current-buffer "*Help*"
768 (setq help-xref-stack nil
769 help-xref-stack-item nil)))
a8ad43aa 770
e88a2c59 771(defun where-is (definition &optional insert)
54c0b967 772 "Print message listing key sequences that invoke specified command.
e88a2c59
RS
773Argument is a command definition, usually a symbol with a function definition.
774If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
54c0b967
RS
775 (interactive
776 (let ((fn (function-called-at-point))
777 (enable-recursive-minibuffers t)
778 val)
779 (setq val (completing-read (if fn
780 (format "Where is command (default %s): " fn)
781 "Where is command: ")
782 obarray 'fboundp t))
783 (list (if (equal val "")
e88a2c59
RS
784 fn (intern val))
785 current-prefix-arg)))
54c0b967 786 (let* ((keys (where-is-internal definition overriding-local-map nil nil))
e88a2c59
RS
787 (keys1 (mapconcat 'key-description keys ", "))
788 (standard-output (if insert (current-buffer) t)))
789 (if insert
790 (if (> (length keys1) 0)
791 (princ (format "%s (%s)" keys1 definition))
792 (princ (format "M-x %s RET" definition)))
793 (if (> (length keys1) 0)
794 (princ (format "%s is on %s" definition keys1))
795 (princ (format "%s is not on any key" definition)))))
54c0b967
RS
796 nil)
797
a130d829 798(defun locate-library (library &optional nosuffix path interactive-call)
2747503c 799 "Show the precise file name of Emacs library LIBRARY.
433ae6f6
RS
800This command searches the directories in `load-path' like `M-x load-library'
801to find the file that `M-x load-library RET LIBRARY RET' would load.
802Optional second arg NOSUFFIX non-nil means don't add suffixes `.elc' or `.el'
9dc176a0
RS
803to the specified name LIBRARY.
804
805If the optional third arg PATH is specified, that list of directories
806is used instead of `load-path'."
a130d829
RS
807 (interactive (list (read-string "Locate library: ")
808 nil nil
809 t))
dd557bb8 810 (let (result)
a130d829
RS
811 (catch 'answer
812 (mapcar
a1c9f209
EN
813 (lambda (dir)
814 (mapcar
815 (lambda (suf)
816 (let ((try (expand-file-name (concat library suf) dir)))
817 (and (file-readable-p try)
818 (null (file-directory-p try))
819 (progn
820 (setq result try)
821 (throw 'answer try)))))
822 (if nosuffix
823 '("")
dd557bb8
KH
824 '(".elc" ".el" "")
825;;; load doesn't handle this yet.
826;;; (let ((basic '(".elc" ".el" ""))
827;;; (compressed '(".Z" ".gz" "")))
828;;; ;; If autocompression mode is on,
829;;; ;; consider all combinations of library suffixes
830;;; ;; and compression suffixes.
831;;; (if (rassq 'jka-compr-handler file-name-handler-alist)
832;;; (apply 'nconc
833;;; (mapcar (lambda (compelt)
834;;; (mapcar (lambda (baselt)
835;;; (concat baselt compelt))
836;;; basic))
837;;; compressed))
838;;; basic))
839 )))
a130d829
RS
840 (or path load-path)))
841 (and interactive-call
842 (if result
843 (message "Library is file %s" result)
844 (message "No library %s in search path" library)))
845 result))
1a06eabd 846
400a1b1f
RS
847\f
848;;; Grokking cross-reference information in doc strings and
849;;; hyperlinking it.
850
851;; This may have some scope for extension and the same or something
852;; similar should be done for widget doc strings, which currently use
853;; another mechanism.
854
855(defcustom help-highlight-p t
856 "*If non-nil, `help-make-xrefs' highlight cross-references.
857Under a window system it highlights them with face defined by
858`help-highlight-face'. On a character terminal highlighted
859references look like cross-references in info mode."
860 :group 'help
861 :version "20.3"
862 :type 'boolean)
863
864(defcustom help-highlight-face 'underline
865 "Face used by `help-make-xrefs' to highlight cross-references.
866Must be previously-defined."
867 :group 'help
868 :version "20.3"
7f082394 869 :type 'face)
400a1b1f
RS
870
871(defvar help-back-label "[back]"
872 "Label to use by `help-make-xrefs' for the go-back reference.")
873
874(defvar help-xref-symbol-regexp
875 (concat "\\(\\<\\(\\(variable\\|option\\)\\|"
876 "\\(function\\|command\\)\\|"
877 "\\(symbol\\)\\)\\s-+\\)?"
878 ;; Note starting with word-syntax character:
879 "`\\(\\sw\\(\\sw\\|\\s_\\)+\\)'")
880 "Regexp matching doc string references to symbols.
881
882The words preceding the quoted symbol can be used in doc strings to
883distinguish references to variables, functions and symbols.")
884
885(defvar help-xref-info-regexp
886 "\\<info\\s-+node\\s-`\\([^']+\\)'"
887 "Regexp matching doc string references to an Info node.")
888
889(defun help-setup-xref (item interactive-p)
890 "Invoked from commands using the \"*Help*\" buffer to install some xref info.
891
892ITEM is a (function . args) pair appropriate for recreating the help
893buffer after following a reference. INTERACTIVE-P is non-nil if the
894calling command was invoked interactively. In this case the stack of
895items for help buffer \"back\" buttons is cleared."
896 (if interactive-p
897 (setq help-xref-stack nil))
898 (setq help-xref-stack-item item))
899
900(defun help-make-xrefs (&optional buffer)
901 "Parse and hyperlink documentation cross-references in the given BUFFER.
902
903Find cross-reference information in a buffer and, if
904`help-highlight-p' is non-nil, highlight it with face defined by
905`help-highlight-face'; activate such cross references for selection
906with `help-follow'. Cross-references have the canonical form `...'
907and the type of reference may be disambiguated by the preceding
908word(s) used in `help-xref-symbol-regexp'.
909
910A special reference `back' is made to return back through a stack of
911help buffers. Variable `help-back-label' specifies the text for
912that."
913 (interactive "b")
914 (save-excursion
915 (set-buffer (or buffer (current-buffer)))
916 (goto-char (point-min))
917 ;; Skip the header-type info, though it might be useful to parse
918 ;; it at some stage (e.g. "function in `library'").
919 (forward-paragraph)
920 (let ((old-modified (buffer-modified-p)))
921 (let ((stab (syntax-table))
922 (case-fold-search t)
923 (inhibit-read-only t))
924 (set-syntax-table emacs-lisp-mode-syntax-table)
925 ;; The following should probably be abstracted out.
926 (unwind-protect
927 (progn
928 ;; Quoted symbols
929 (save-excursion
930 (while (re-search-forward help-xref-symbol-regexp nil t)
931 (let* ((data (match-string 6))
932 (sym (intern-soft data)))
933 (if sym
934 (cond
935 ((match-string 3) ; `variable' &c
936 (and (boundp sym) ; `variable' doesn't ensure
937 ; it's actually bound
938 (help-xref-button 6 #'describe-variable sym)))
939 ((match-string 4) ; `function' &c
940 (and (fboundp sym) ; similarly
941 (help-xref-button 6 #'describe-function sym)))
942 ((match-string 5)) ; nothing for symbol
943 ((and (boundp sym) (fboundp sym))
944 ;; We can't intuit whether to use the
945 ;; variable or function doc -- supply both.
946 (help-xref-button 6 #'help-xref-interned sym))
947 ((boundp sym)
948 (help-xref-button 6 #'describe-variable sym))
949 ((fboundp sym)
950 (help-xref-button 6 #'describe-function sym)))))))
951 ;; Info references
952 (save-excursion
953 (while (re-search-forward help-xref-info-regexp nil t)
954 (help-xref-button 1 #'Info-goto-node (list (match-data 1)))))
955 ;; An obvious case of a key substitution:
956 (save-excursion
957 (while (re-search-forward
958 "\\<M-x\\s-+\\(\\sw\\(\\sw\\|\\s_\\)+\\)" nil t)
959 (let ((sym (intern-soft (match-string 1))))
960 (if (fboundp sym)
ff3453e4
DL
961 (help-xref-button 1 #'describe-function sym)))))
962 ;; Look for commands in whole keymap substitutions:
963 (save-excursion
964 ;; Find a header and the column at which the command
965 ;; name will be found.
966 (while (re-search-forward "^key +binding\n\\(-+ +\\)-+\n\n"
967 nil t)
968 (let ((col (- (match-end 1) (match-beginning 1))))
969 (while
970 ;; Ignore single blank lines in table, but not
971 ;; double ones, which should terminate it.
972 (and (looking-at "^\n?[^\n]")
973 (progn
974 (if (and (> (move-to-column col) 0)
975 (looking-at "\\(\\sw\\|\\s_\\)+$"))
976 ;;
977 (let ((sym (intern-soft (match-string 0))))
978 (if (fboundp sym)
979 (help-xref-button
980 0 #'describe-function sym))))
981 t)
982 (zerop (forward-line))
983 (move-to-column 0)))))))
400a1b1f
RS
984 (set-syntax-table stab))
985 ;; Make a back-reference in this buffer if appropriate.
986 (when help-xref-stack
987 (goto-char (point-max))
988 (save-excursion
989 (insert "\n\n" help-back-label))
990 ;; Just to provide the match data:
991 (looking-at (concat "\n\n\\(" (regexp-quote help-back-label) "\\)"))
613a39b9 992 (help-xref-button 1 #'help-xref-go-back (current-buffer))))
400a1b1f
RS
993 ;; View mode steals RET from us.
994 (set (make-local-variable 'minor-mode-overriding-map-alist)
995 (list (cons 'view-mode
996 (let ((map (make-sparse-keymap)))
ff3453e4 997 (set-keymap-parent map view-mode-map)
400a1b1f
RS
998 (define-key map "\r" 'help-follow)
999 map))))
1000 (set-buffer-modified-p old-modified))))
1001
1002(defun help-xref-button (match-number function data)
1003 "Make a hyperlink for cross-reference text previously matched.
1004
1005MATCH-NUMBER is the subexpression of interest in the last matched
1006regexp. FUNCTION is a function to invoke when the button is
1007activated, applied to DATA. DATA may be a single value or a list.
1008See `help-make-xrefs'."
ff3453e4 1009 (add-text-properties (match-beginning match-number)
400a1b1f 1010 (match-end match-number)
ff3453e4 1011 (list 'mouse-face 'highlight
400a1b1f
RS
1012 'help-xref (cons function
1013 (if (listp data)
1014 data
1015 (list data)))))
ff3453e4
DL
1016 (if help-highlight-p
1017 (put-text-property (match-beginning match-number)
1018 (match-end match-number)
1019 'face help-highlight-face)))
400a1b1f
RS
1020
1021\f
1022;; Additional functions for (re-)creating types of help buffers.
1023(defun help-xref-interned (symbol)
1024 "Follow a hyperlink which appeared to be an arbitrary interned SYMBOL.
1025
1026Both variable and function documentation are extracted into a single
1027help buffer."
1028 (let ((fdoc (describe-function symbol)))
1029 (describe-variable symbol)
1030 ;; We now have a help buffer on the variable. Insert the function
1031 ;; text after it.
1032 (goto-char (point-max))
1033 (insert "\n\n" fdoc))
1034 (goto-char (point-min))
1035 (help-setup-xref (cons #'help-xref-interned symbol) nil))
1036
1037(defun help-xref-mode (buffer)
1038 "Do a `describe-mode' for the specified BUFFER."
1039 (save-excursion
1040 (set-buffer buffer)
1041 (describe-mode)))
1042\f
1043;;; Navigation/hyperlinking with xrefs
1044
1045(defun help-follow-mouse (click)
1046 "Follow the cross-reference that you click on."
1047 (interactive "e")
1048 (save-excursion
1049 (let* ((start (event-start click))
1050 (window (car start))
1051 (pos (car (cdr start))))
1052 (set-buffer (window-buffer window))
1053 (help-follow pos))))
1054
613a39b9
RS
1055(defun help-xref-go-back (buffer)
1056 "Go back to the previous help buffer text using info on `help-xref-stack'."
400a1b1f 1057 (interactive)
613a39b9
RS
1058 (let (item method args)
1059 (with-current-buffer buffer
1060 (when help-xref-stack
1061 (setq help-xref-stack (cdr help-xref-stack)) ; due to help-follow
1062 (setq item (car help-xref-stack)
1063 method (car item)
1064 args (cdr item))
1065 (setq help-xref-stack (cdr help-xref-stack))))
1066 (if (listp args)
1067 (apply method args)
1068 (funcall method args))))
400a1b1f
RS
1069
1070(defun help-go-back ()
1071 (interactive)
1072 (help-follow (1- (point-max))))
1073
1074(defun help-follow (&optional pos)
1075 "Follow cross-reference at POS, defaulting to point.
1076
1077For the cross-reference format, see `help-make-xrefs'."
1078 (interactive "d")
1079 (let* ((help-data (get-text-property pos 'help-xref))
1080 (method (car help-data))
1081 (args (cdr help-data)))
1082 (setq help-xref-stack (cons help-xref-stack-item help-xref-stack))
1083 (setq help-xref-stack-item nil)
1084 (when help-data
1085 ;; There is a reference at point. Follow it.
1086 (apply method args))))
1087
1088;; For tabbing through buffer.
1089(defun help-next-ref ()
1090 "Find the next 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
ff3453e4
DL
1095 (goto-char (or (next-single-property-change (point) 'help-xref)
1096 (point))))
400a1b1f
RS
1097 (cond ((setq pos (next-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-min)))))))
1104
1105(defun help-previous-ref ()
1106 "Find the previous help cross-reference in the buffer."
1107 (interactive)
1108 (let (pos)
1109 (while (not pos)
1110 (if (get-text-property (point) 'help-xref) ; move off reference
1111 (goto-char (or (previous-single-property-change (point) 'help-xref)
1112 (point))))
1113 (cond ((setq pos (previous-single-property-change (point) 'help-xref))
1114 (if pos (goto-char pos)))
1115 ((bobp)
1116 (message "No cross references in the buffer.")
1117 (setq pos t))
1118 (t ; be circular
1119 (goto-char (point-max)))))))
1120
1a06eabd 1121;;; help.el ends here