Switch to recommended form of GPLv3 permissions notice.
[bpt/emacs.git] / lisp / help.el
CommitLineData
1a06eabd
ER
1;;; help.el --- help commands for Emacs
2
0d30b337 3;; Copyright (C) 1985, 1986, 1993, 1994, 1998, 1999, 2000, 2001, 2002,
409cc4a3 4;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
3a801d0c 5
e5167999 6;; Maintainer: FSF
fd7fa35a 7;; Keywords: help, internal
e5167999 8
433ae6f6
RS
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
b4aa6026 13;; the Free Software Foundation; either version 3, or (at your option)
433ae6f6
RS
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267 22;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
433ae6f6 25
d9ecc911
ER
26;;; Commentary:
27
a1c9f209 28;; This code implements GNU Emacs' on-line help system, the one invoked by
95ac0a6f 29;; `M-x help-for-help'.
d9ecc911 30
e5167999
ER
31;;; Code:
32
8aa3a187
RS
33;; Get the macro make-help-screen when this is compiled,
34;; or run interpreted, but not when the compiled code is loaded.
b1fe9304 35(eval-when-compile (require 'help-macro))
788d62cf
MB
36
37;; This makes `with-output-to-temp-buffer' buffers use `help-mode'.
38(add-hook 'temp-buffer-setup-hook 'help-mode-setup)
39(add-hook 'temp-buffer-show-hook 'help-mode-finish)
41b8542b 40
cde56121
MR
41;; The variable `help-window' below is used by `help-mode-finish' to
42;; communicate the window displaying help (the "help window") to the
43;; macro `with-help-window'. The latter sets `help-window' to t before
44;; invoking `with-output-to-temp-buffer'. If and only if `help-window'
45;; is eq to t, `help-mode-finish' (called by `temp-buffer-setup-hook')
46;; sets `help-window' to the window selected by `display-buffer'.
47;; Exiting `with-help-window' and calling `print-help-return-message'
48;; reset `help-window' to nil.
49(defvar help-window nil
50 "Window chosen for displaying help.")
51
52;; `help-window-point-marker' is a marker you can move to a valid
53;; position of the buffer shown in the help window in order to override
54;; the standard positioning mechanism (`point-min') chosen by
55;; `with-output-to-temp-buffer'. `with-help-window' has this point
56;; nowhere before exiting. Currently used by `view-lossage' to assert
57;; that the last keystrokes are always visible.
7b01c8d7 58(defvar help-window-point-marker (make-marker)
cde56121
MR
59 "Marker to override default `window-point' of `help-window'.")
60
604aa5f0
SM
61(defvar help-map
62 (let ((map (make-sparse-keymap)))
63 (define-key map (char-to-string help-char) 'help-for-help)
64 (define-key map [help] 'help-for-help)
65 (define-key map [f1] 'help-for-help)
66 (define-key map "." 'display-local-help)
67 (define-key map "?" 'help-for-help)
68
d4a18332 69 (define-key map "\C-a" 'about-emacs)
604aa5f0 70 (define-key map "\C-c" 'describe-copying)
7b01c8d7
KS
71 (define-key map "\C-d" 'view-emacs-debugging)
72 (define-key map "\C-e" 'view-external-packages)
604aa5f0
SM
73 (define-key map "\C-f" 'view-emacs-FAQ)
74 (define-key map "\C-m" 'view-order-manuals)
75 (define-key map "\C-n" 'view-emacs-news)
7b01c8d7
KS
76 (define-key map "\C-o" 'describe-distribution)
77 (define-key map "\C-p" 'view-emacs-problems)
78 (define-key map "\C-t" 'view-emacs-todo)
604aa5f0
SM
79 (define-key map "\C-w" 'describe-no-warranty)
80
81 ;; This does not fit the pattern, but it is natural given the C-\ command.
82 (define-key map "\C-\\" 'describe-input-method)
83
84 (define-key map "C" 'describe-coding-system)
85 (define-key map "F" 'Info-goto-emacs-command-node)
86 (define-key map "I" 'describe-input-method)
87 (define-key map "K" 'Info-goto-emacs-key-command-node)
88 (define-key map "L" 'describe-language-environment)
89 (define-key map "S" 'info-lookup-symbol)
90
91 (define-key map "a" 'apropos-command)
92 (define-key map "b" 'describe-bindings)
93 (define-key map "c" 'describe-key-briefly)
94 (define-key map "d" 'apropos-documentation)
95 (define-key map "e" 'view-echo-area-messages)
96 (define-key map "f" 'describe-function)
7b01c8d7 97 (define-key map "g" 'describe-gnu-project)
604aa5f0
SM
98 (define-key map "h" 'view-hello-file)
99
100 (define-key map "i" 'info)
101 (define-key map "4i" 'info-other-window)
102
103 (define-key map "k" 'describe-key)
104 (define-key map "l" 'view-lossage)
105 (define-key map "m" 'describe-mode)
106 (define-key map "n" 'view-emacs-news)
107 (define-key map "p" 'finder-by-keyword)
108 (define-key map "r" 'info-emacs-manual)
109 (define-key map "s" 'describe-syntax)
110 (define-key map "t" 'help-with-tutorial)
111 (define-key map "w" 'where-is)
112 (define-key map "v" 'describe-variable)
113 (define-key map "q" 'help-quit)
114 map)
433ae6f6
RS
115 "Keymap for characters following the Help key.")
116
e17d2fd1 117(define-key global-map (char-to-string help-char) 'help-command)
0af3df1c
RS
118(define-key global-map [help] 'help-command)
119(define-key global-map [f1] 'help-command)
433ae6f6
RS
120(fset 'help-command help-map)
121
3e9c095d
RS
122(autoload 'finder-by-keyword "finder"
123 "Find packages matching a given keyword." t)
06b98c51 124
e25e90b4
DP
125;; insert-button makes the action nil if it is not store somewhere
126(defvar help-button-cache nil)
127
0cf0d828 128\f
2fc9d9f4 129(defun help-quit ()
3120a677 130 "Just exit from the Help command's command loop."
2fc9d9f4
RS
131 (interactive)
132 nil)
133
01364a75
RS
134(defvar help-return-method nil
135 "What to do to \"exit\" the help buffer.
136This is a list
a8e7142c
EZ
137 (WINDOW . t) delete the selected window (and possibly its frame,
138 see `quit-window' and `View-quit'), go to WINDOW.
01364a75
RS
139 (WINDOW . quit-window) do quit-window, then select WINDOW.
140 (WINDOW BUF START POINT) display BUF at START, POINT, then select WINDOW.")
141
433ae6f6
RS
142(defun print-help-return-message (&optional function)
143 "Display or return message saying how to restore windows after help command.
d009b6e9
RS
144This function assumes that `standard-output' is the help buffer.
145It computes a message, and applies the optional argument FUNCTION to it.
a8e7142c
EZ
146If FUNCTION is nil, it applies `message', thus displaying the message.
147In addition, this function sets up `help-return-method', which see, that
148specifies what to do when the user exits the help buffer."
cde56121
MR
149 ;; Reset `help-window' here to avoid confusing `help-mode-finish'.
150 (setq help-window nil)
433ae6f6 151 (and (not (get-buffer-window standard-output))
d536293f 152 (let ((first-message
a8e7142c
EZ
153 (cond ((or
154 pop-up-frames
155 (special-display-p (buffer-name standard-output)))
01364a75 156 (setq help-return-method (cons (selected-window) t))
d536293f
RS
157 ;; If the help output buffer is a special display buffer,
158 ;; don't say anything about how to get rid of it.
159 ;; First of all, the user will do that with the window
160 ;; manager, not with Emacs.
161 ;; Secondly, the buffer has not been displayed yet,
162 ;; so we don't know whether its frame will be selected.
d536293f 163 nil)
f3ad2fc8
GM
164 (display-buffer-reuse-frames
165 (setq help-return-method (cons (selected-window)
166 'quit-window))
167 nil)
d536293f 168 ((not (one-window-p t))
01364a75
RS
169 (setq help-return-method
170 (cons (selected-window) 'quit-window))
cb0b6766 171 "Type \\[display-buffer] RET to restore the other window.")
d536293f 172 (pop-up-windows
01364a75 173 (setq help-return-method (cons (selected-window) t))
d536293f
RS
174 "Type \\[delete-other-windows] to remove help window.")
175 (t
01364a75
RS
176 (setq help-return-method
177 (list (selected-window) (window-buffer)
178 (window-start) (window-point)))
d536293f
RS
179 "Type \\[switch-to-buffer] RET to remove help window."))))
180 (funcall (or function 'message)
181 (concat
182 (if first-message
376b2a24
DL
183 (substitute-command-keys first-message))
184 (if first-message " ")
125a8d70
RS
185 ;; If the help buffer will go in a separate frame,
186 ;; it's no use mentioning a command to scroll, so don't.
7b057a3d
EZ
187 (if (or pop-up-windows
188 (special-display-p (buffer-name standard-output)))
125a8d70 189 nil
a1c9f209 190 (if (same-window-p (buffer-name standard-output))
125a8d70
RS
191 ;; Say how to scroll this window.
192 (substitute-command-keys
193 "\\[scroll-up] to scroll the help.")
194 ;; Say how to scroll some other window.
6e7f5182 195 (substitute-command-keys
125a8d70 196 "\\[scroll-other-window] to scroll the help."))))))))
433ae6f6 197
433ae6f6
RS
198;; So keyboard macro definitions are documented correctly
199(fset 'defining-kbd-macro (symbol-function 'start-kbd-macro))
200
a4bdcdf3
RS
201(defalias 'help 'help-for-help-internal)
202;; find-function can find this.
203(defalias 'help-for-help 'help-for-help-internal)
204;; It can't find this, but nobody will look.
205(make-help-screen help-for-help-internal
7b01c8d7 206 "Type a help option: [abcCdefFgiIkKlLmnprstvw.] C-[cdefmnoptw] or ?"
788d62cf
MB
207 "You have typed %THIS-KEY%, the help character. Type a Help option:
208\(Use SPC or DEL to scroll through this text. Type \\<help-map>\\[help-quit] to exit the Help command.)
209
7b01c8d7
KS
210a PATTERN Show commands whose name matches the PATTERN (a list of words
211 or a regexp). See also the `apropos' command.
212b Display all key bindings.
213c KEYS Display the command name run by the given key sequence.
214C CODING Describe the given coding system, or RET for current ones.
215d PATTERN Show a list of functions, variables, and other items whose
216 documentation matches the PATTERN (a list of words or a regexp).
217e Go to the *Messages* buffer which logs echo-area messages.
218f FUNCTION Display documentation for the given function.
219F COMMAND Show the on-line manual's section that describes the command.
220g Display information about the GNU project.
221h Display the HELLO file which illustrates various scripts.
222i Start the Info documentation reader: read on-line manuals.
223I METHOD Describe a specific input method, or RET for current.
224k KEYS Display the full documentation for the key sequence.
225K KEYS Show the on-line manual's section for the command bound to KEYS.
226l Show last 100 characters you typed (lossage).
227L LANG-ENV Describes a specific language environment, or RET for current.
228m Display documentation of current minor modes and current major mode,
229 including their special commands.
230n Display news of recent Emacs changes.
231p TOPIC Find packages matching a given topic keyword.
232r Display the Emacs manual in Info mode.
233s Display contents of current syntax table, plus explanations.
234S SYMBOL Show the section for the given symbol in the on-line manual
235 for the programming language used in this buffer.
236t Start the Emacs learn-by-doing tutorial.
237v VARIABLE Display the given variable's documentation and value.
238w COMMAND Display which keystrokes invoke the given command (where-is).
239. Display any available local help at point in the echo area.
240
241C-a Information about Emacs.
242C-c Emacs copying permission (GNU General Public License).
243C-d Instructions for debugging GNU Emacs.
244C-e External packages and information about Emacs.
245C-f Emacs FAQ.
246C-m How to order printed Emacs manuals.
247C-n News of recent Emacs changes.
248C-o Emacs ordering and distribution information.
249C-p Info about known Emacs problems.
250C-t Emacs TODO list.
251C-w Information on absence of warranty for GNU Emacs."
788d62cf
MB
252 help-map)
253
254\f
255
256(defun function-called-at-point ()
257 "Return a function around point or else called by the list containing point.
258If that doesn't give a function, return nil."
542e904c
JL
259 (or (with-syntax-table emacs-lisp-mode-syntax-table
260 (or (condition-case ()
261 (save-excursion
262 (or (not (zerop (skip-syntax-backward "_w")))
263 (eq (char-syntax (following-char)) ?w)
264 (eq (char-syntax (following-char)) ?_)
265 (forward-sexp -1))
266 (skip-chars-forward "'")
267 (let ((obj (read (current-buffer))))
268 (and (symbolp obj) (fboundp obj) obj)))
269 (error nil))
270 (condition-case ()
271 (save-excursion
272 (save-restriction
273 (narrow-to-region (max (point-min)
274 (- (point) 1000)) (point-max))
275 ;; Move up to surrounding paren, then after the open.
276 (backward-up-list 1)
277 (forward-char 1)
278 ;; If there is space here, this is probably something
279 ;; other than a real Lisp function call, so ignore it.
280 (if (looking-at "[ \t]")
281 (error "Probably not a Lisp function call"))
282 (let ((obj (read (current-buffer))))
283 (and (symbolp obj) (fboundp obj) obj))))
284 (error nil))))
285 (let* ((str (find-tag-default))
918f2e56
JL
286 (sym (if str (intern-soft str))))
287 (if (and sym (fboundp sym))
288 sym
289 (save-match-data
290 (when (and str (string-match "\\`\\W*\\(.*?\\)\\W*\\'" str))
291 (setq sym (intern-soft (match-string 1 str)))
292 (and (fboundp sym) sym)))))))
788d62cf
MB
293
294\f
295;;; `User' help functions
296
7b01c8d7
KS
297(defun view-help-file (file &optional dir)
298 (view-file (expand-file-name file (or dir data-directory)))
299 (goto-address)
300 (goto-char (point-min)))
301
433ae6f6
RS
302(defun describe-distribution ()
303 "Display info on how to obtain the latest version of GNU Emacs."
304 (interactive)
7b01c8d7 305 (view-help-file "DISTRIB"))
433ae6f6
RS
306
307(defun describe-copying ()
308 "Display info on how you may redistribute copies of GNU Emacs."
309 (interactive)
7b01c8d7 310 (view-help-file "COPYING"))
433ae6f6 311
7b01c8d7 312(defun describe-gnu-project ()
76766f2d
RS
313 "Display info on the GNU project."
314 (interactive)
7b01c8d7 315 (view-help-file "THE-GNU-PROJECT"))
76766f2d 316
4e44f5ce
KS
317(define-obsolete-function-alias 'describe-project 'describe-gnu-project "22.2")
318
433ae6f6
RS
319(defun describe-no-warranty ()
320 "Display info on all the kinds of warranty Emacs does NOT have."
321 (interactive)
322 (describe-copying)
323 (let (case-fold-search)
324 (search-forward "NO WARRANTY")
325 (recenter 0)))
326
61c6b658 327(defun describe-prefix-bindings ()
c7cba9cb
RS
328 "Describe the bindings of the prefix used to reach this command.
329The prefix described consists of all but the last event
330of the key sequence that ran this command."
61c6b658 331 (interactive)
0f101663 332 (let ((key (this-command-keys)))
ccc06dcc
KH
333 (describe-bindings
334 (if (stringp key)
335 (substring key 0 (1- (length key)))
336 (let ((prefix (make-vector (1- (length key)) nil))
337 (i 0))
338 (while (< i (length prefix))
339 (aset prefix i (aref key i))
340 (setq i (1+ i)))
341 prefix)))))
788d62cf 342;; Make C-h after a prefix, when not specifically bound,
c7cba9cb 343;; run describe-prefix-bindings.
61c6b658
RS
344(setq prefix-help-command 'describe-prefix-bindings)
345
e38cc268 346(defun view-emacs-news (&optional version)
382d018a 347 "Display info on recent changes to Emacs.
598ea453 348With argument, display info only for the selected version."
382d018a 349 (interactive "P")
e38cc268
KS
350 (unless version
351 (setq version emacs-major-version))
352 (when (consp version)
353 (let* ((all-versions
354 (let (res)
cc6650af 355 (mapc
e38cc268
KS
356 (lambda (file)
357 (with-temp-buffer
358 (insert-file-contents
359 (expand-file-name file data-directory))
360 (while (re-search-forward
361 (if (member file '("NEWS.18" "NEWS.1-17"))
362 "Changes in \\(?:Emacs\\|version\\)?[ \t]*\\([0-9]+\\(?:\\.[0-9]+\\)?\\)"
363 "^\* [^0-9\n]*\\([0-9]+\\.[0-9]+\\)") nil t)
364 (setq res (cons (match-string-no-properties 1) res)))))
365 (cons "NEWS"
366 (directory-files data-directory nil
367 "^NEWS\\.[0-9][-0-9]*$" nil)))
368 (sort (delete-dups res) (lambda (a b) (string< b a)))))
8c9fc4be 369 (current (car all-versions)))
e38cc268
KS
370 (setq version (completing-read
371 (format "Read NEWS for the version (default %s): " current)
372 all-versions nil nil nil nil current))
373 (if (integerp (string-to-number version))
374 (setq version (string-to-number version))
375 (unless (or (member version all-versions)
376 (<= (string-to-number version) (string-to-number current)))
377 (error "No news about version %s" version)))))
378 (when (integerp version)
379 (cond ((<= version 12)
380 (setq version (format "1.%d" version)))
381 ((<= version 18)
382 (setq version (format "%d" version)))
383 ((> version emacs-major-version)
e08b54f2 384 (error "No news about Emacs %d (yet)" version))))
e38cc268
KS
385 (let* ((vn (if (stringp version)
386 (string-to-number version)
387 version))
388 (file (cond
389 ((>= vn emacs-major-version) "NEWS")
390 ((< vn 18) "NEWS.1-17")
8c9fc4be
KS
391 (t (format "NEWS.%d" vn))))
392 res)
e38cc268
KS
393 (view-file (expand-file-name file data-directory))
394 (widen)
395 (goto-char (point-min))
396 (when (stringp version)
397 (when (re-search-forward
398 (concat (if (< vn 19)
399 "Changes in Emacs[ \t]*"
400 "^\* [^0-9\n]*") version "$")
401 nil t)
402 (beginning-of-line)
403 (narrow-to-region
404 (point)
405 (save-excursion
406 (while (and (setq res
407 (re-search-forward
408 (if (< vn 19)
409 "Changes in \\(?:Emacs\\|version\\)?[ \t]*\\([0-9]+\\(?:\\.[0-9]+\\)?\\)"
410 "^\* [^0-9\n]*\\([0-9]+\\.[0-9]+\\)") nil t))
411 (equal (match-string-no-properties 1) version)))
412 (or res (goto-char (point-max)))
413 (beginning-of-line)
414 (point)))))))
415
7b01c8d7 416(defun view-emacs-todo (&optional arg)
1ebc1f01
RS
417 "Display the Emacs TODO list."
418 (interactive "P")
7b01c8d7 419 (view-help-file "TODO"))
1ebc1f01 420
4e44f5ce
KS
421(define-obsolete-function-alias 'view-todo 'view-emacs-todo "22.2")
422
423
4f16ea85
RS
424(defun view-echo-area-messages ()
425 "View the log of recent echo-area messages: the `*Messages*' buffer.
426The number of messages retained in that buffer
427is specified by the variable `message-log-max'."
428 (interactive)
429 (switch-to-buffer (get-buffer-create "*Messages*")))
430
754084bb
GM
431(defun view-order-manuals ()
432 "Display the Emacs ORDERS file."
433 (interactive)
7b01c8d7 434 (view-help-file "ORDERS"))
754084bb 435
7ee71cf1
RS
436(defun view-emacs-FAQ ()
437 "Display the Emacs Frequently Asked Questions (FAQ) file."
438 (interactive)
94ea540b 439 ;; (find-file-read-only (expand-file-name "FAQ" data-directory))
279b772d 440 (info "(efaq)"))
7ee71cf1 441
4cbff657
DL
442(defun view-emacs-problems ()
443 "Display info on known problems with Emacs and possible workarounds."
444 (interactive)
7b01c8d7
KS
445 (view-help-file "PROBLEMS"))
446
447(defun view-emacs-debugging ()
448 "Display info on how to debug Emacs problems."
449 (interactive)
450 (view-help-file "DEBUG"))
451
452(defun view-external-packages ()
453 "Display external packages and information about Emacs."
454 (interactive)
455 (view-help-file "MORE.STUFF"))
4cbff657 456
433ae6f6 457(defun view-lossage ()
50b57199
EZ
458 "Display last 100 input keystrokes.
459
460To record all your input on a file, use `open-dribble-file'."
433ae6f6 461 (interactive)
3e5929af 462 (help-setup-xref (list #'view-lossage) (interactive-p))
cde56121 463 (with-help-window (help-buffer)
02dfca16
SM
464 (princ (mapconcat (lambda (key)
465 (if (or (integerp key) (symbolp key) (listp key))
466 (single-key-description key)
467 (prin1-to-string key nil)))
298a7c8c
RS
468 (recent-keys)
469 " "))
b0fbf754 470 (with-current-buffer standard-output
433ae6f6
RS
471 (goto-char (point-min))
472 (while (progn (move-to-column 50) (not (eobp)))
e5fe3a6c
JB
473 (when (search-forward " " nil t)
474 (delete-char -1))
cde56121
MR
475 (insert "\n"))
476 ;; jidanni wants to see the last keystrokes immediately.
477 (set-marker help-window-point-marker (point)))))
433ae6f6 478
788d62cf
MB
479\f
480;; Key bindings
433ae6f6 481
4c45295b 482(defun describe-bindings (&optional prefix buffer)
a8ad43aa
RS
483 "Show a list of all defined keys, and their definitions.
484We put that list in a buffer, and display the buffer.
485
486The optional argument PREFIX, if non-nil, should be a key sequence;
4c45295b
KH
487then we display only bindings that start with that prefix.
488The optional argument BUFFER specifies which buffer's bindings
abca4ad7
LT
489to display (default, the current buffer). BUFFER can be a buffer
490or a buffer name."
3e5929af 491 (interactive)
4c45295b 492 (or buffer (setq buffer (current-buffer)))
3e5929af 493 (help-setup-xref (list #'describe-bindings prefix buffer) (interactive-p))
4c45295b 494 (with-current-buffer buffer
3e5929af 495 (describe-bindings-internal nil prefix)))
a8ad43aa 496
94ea540b
SM
497;; This function used to be in keymap.c.
498(defun describe-bindings-internal (&optional menus prefix)
499 "Show a list of all defined keys, and their definitions.
500We put that list in a buffer, and display the buffer.
501
502The optional argument MENUS, if non-nil, says to mention menu bindings.
503\(Ordinarily these are omitted from the output.)
504The optional argument PREFIX, if non-nil, should be a key sequence;
505then we display only bindings that start with that prefix."
506 (interactive)
507 (let ((buf (current-buffer)))
cde56121 508 (with-help-window "*Help*"
94ea540b
SM
509 (with-current-buffer standard-output
510 (describe-buffer-bindings buf prefix menus)))))
511
e88a2c59 512(defun where-is (definition &optional insert)
b2c85790 513 "Print message listing key sequences that invoke the command DEFINITION.
e88a2c59
RS
514Argument is a command definition, usually a symbol with a function definition.
515If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
54c0b967
RS
516 (interactive
517 (let ((fn (function-called-at-point))
788d62cf 518 (enable-recursive-minibuffers t)
54c0b967 519 val)
3829bcc5
SM
520 (setq val (completing-read
521 (if fn
522 (format "Where is command (default %s): " fn)
523 "Where is command: ")
524 obarray 'commandp t))
525 (list (if (equal val "") fn (intern val)) current-prefix-arg)))
463d75ac 526 (unless definition (error "No command"))
7a698dc1 527 (let ((func (indirect-function definition))
3829bcc5 528 (defs nil)
7a698dc1 529 (standard-output (if insert (current-buffer) t)))
740b479c 530 ;; In DEFS, find all symbols that are aliases for DEFINITION.
3829bcc5
SM
531 (mapatoms (lambda (symbol)
532 (and (fboundp symbol)
533 (not (eq symbol definition))
d92c2757
RS
534 (eq func (condition-case ()
535 (indirect-function symbol)
536 (error symbol)))
3829bcc5 537 (push symbol defs))))
740b479c
RS
538 ;; Look at all the symbols--first DEFINITION,
539 ;; then its aliases.
540 (dolist (symbol (cons definition defs))
541 (let* ((remapped (command-remapping symbol))
542 (keys (where-is-internal
543 symbol overriding-local-map nil nil remapped))
544 (keys (mapconcat 'key-description keys ", "))
545 string)
546 (setq string
547 (if insert
548 (if (> (length keys) 0)
549 (if remapped
550 (format "%s (%s) (remapped from %s)"
551 keys remapped symbol)
552 (format "%s (%s)" keys symbol))
553 (format "M-x %s RET" symbol))
554 (if (> (length keys) 0)
555 (if remapped
556 (format "%s is remapped to %s which is on %s"
a5f43550 557 symbol remapped keys)
740b479c
RS
558 (format "%s is on %s" symbol keys))
559 ;; If this is the command the user asked about,
560 ;; and it is not on any key, say so.
561 ;; For other symbols, its aliases, say nothing
562 ;; about them unless they are on keys.
563 (if (eq symbol definition)
564 (format "%s is not on any key" symbol)))))
565 (when string
566 (unless (eq symbol definition)
567 (princ ";\n its alias "))
568 (princ string)))))
54c0b967
RS
569 nil)
570
02dfca16
SM
571(defun help-key-description (key untranslated)
572 (let ((string (key-description key)))
ae1bb8ac
SM
573 (if (or (not untranslated)
574 (and (eq (aref untranslated 0) ?\e) (not (eq (aref key 0) ?\e))))
02dfca16
SM
575 string
576 (let ((otherstring (key-description untranslated)))
577 (if (equal string otherstring)
578 string
579 (format "%s (translated from %s)" string otherstring))))))
71296446 580
6527c983
EZ
581(defun describe-key-briefly (&optional key insert untranslated)
582 "Print the name of the function KEY invokes. KEY is a string.
583If INSERT (the prefix arg) is non-nil, insert the message in the buffer.
584If non-nil, UNTRANSLATED is a vector of the untranslated events.
585It can also be a number in which case the untranslated events from
586the last key hit are used.
587
588If KEY is a menu item or a tool-bar button that is disabled, this command
8ee320fc 589temporarily enables it to allow getting help on disabled items and buttons."
2c8ed538
RS
590 (interactive
591 (let ((enable-disabled-menus-and-buttons t)
592 (cursor-in-echo-area t)
593 saved-yank-menu)
594 (unwind-protect
595 (let (key)
596 ;; If yank-menu is empty, populate it temporarily, so that
597 ;; "Select and Paste" menu can generate a complete event.
598 (when (null (cdr yank-menu))
599 (setq saved-yank-menu (copy-sequence yank-menu))
600 (menu-bar-update-yank-menu "(any string)" nil))
601 (setq key (read-key-sequence "Describe key (or click or menu item): "))
46d91fa0 602 ;; If KEY is a down-event, read and discard the
91a2acb2
DK
603 ;; corresponding up-event. Note that there are also
604 ;; down-events on scroll bars and mode lines: the actual
605 ;; event then is in the second element of the vector.
606 (and (vectorp key)
badf89ea
RS
607 (let ((last-idx (1- (length key))))
608 (and (eventp (aref key last-idx))
609 (memq 'down (event-modifiers (aref key last-idx)))))
91a2acb2 610 (read-event))
2c8ed538
RS
611 (list
612 key
774a814f
RS
613 (if current-prefix-arg (prefix-numeric-value current-prefix-arg))
614 1))
2c8ed538
RS
615 ;; Put yank-menu back as it was, if we changed it.
616 (when saved-yank-menu
617 (setq yank-menu (copy-sequence saved-yank-menu))
618 (fset 'yank-menu (cons 'keymap yank-menu))))))
02dfca16
SM
619 (if (numberp untranslated)
620 (setq untranslated (this-single-command-raw-keys)))
91a2acb2
DK
621 (let* ((event (if (and (symbolp (aref key 0))
622 (> (length key) 1)
623 (consp (aref key 1)))
624 (aref key 1)
625 (aref key 0)))
626 (modifiers (event-modifiers event))
627 (standard-output (if insert (current-buffer) t))
24a27882
KS
628 (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
629 (memq 'drag modifiers)) " at that spot" ""))
630 (defn (key-binding key t))
631 key-desc)
632 ;; Handle the case where we faked an entry in "Select and Paste" menu.
633 (if (and (eq defn nil)
634 (stringp (aref key (1- (length key))))
635 (eq (key-binding (substring key 0 -1)) 'yank-menu))
636 (setq defn 'menu-bar-select-yank))
637 ;; Don't bother user with strings from (e.g.) the select-paste menu.
638 (if (stringp (aref key (1- (length key))))
639 (aset key (1- (length key)) "(any string)"))
640 (if (and (> (length untranslated) 0)
641 (stringp (aref untranslated (1- (length untranslated)))))
642 (aset untranslated (1- (length untranslated)) "(any string)"))
643 ;; Now describe the key, perhaps as changed.
644 (setq key-desc (help-key-description key untranslated))
645 (if (or (null defn) (integerp defn) (equal defn 'undefined))
646 (princ (format "%s%s is undefined" key-desc mouse-msg))
647 (princ (format "%s%s runs the command %S" key-desc mouse-msg defn)))))
96ede6b2 648
6527c983
EZ
649(defun describe-key (&optional key untranslated up-event)
650 "Display documentation of the function invoked by KEY.
651KEY can be any kind of a key sequence; it can include keyboard events,
652mouse events, and/or menu events. When calling from a program,
653pass KEY as a string or a vector.
654
655If non-nil, UNTRANSLATED is a vector of the corresponding untranslated events.
656It can also be a number, in which case the untranslated events from
657the last key sequence entered are used.
658UP-EVENT is the up-event that was discarded by reading KEY, or nil.
659
660If KEY is a menu item or a tool-bar button that is disabled, this command
8ee320fc 661temporarily enables it to allow getting help on disabled items and buttons."
2c8ed538
RS
662 (interactive
663 (let ((enable-disabled-menus-and-buttons t)
664 (cursor-in-echo-area t)
665 saved-yank-menu)
666 (unwind-protect
667 (let (key)
668 ;; If yank-menu is empty, populate it temporarily, so that
669 ;; "Select and Paste" menu can generate a complete event.
670 (when (null (cdr yank-menu))
671 (setq saved-yank-menu (copy-sequence yank-menu))
672 (menu-bar-update-yank-menu "(any string)" nil))
673 (setq key (read-key-sequence "Describe key (or click or menu item): "))
674 (list
675 key
676 (prefix-numeric-value current-prefix-arg)
c3f82997 677 ;; If KEY is a down-event, read and include the
badf89ea
RS
678 ;; corresponding up-event. Note that there are also
679 ;; down-events on scroll bars and mode lines: the actual
680 ;; event then is in the second element of the vector.
91a2acb2 681 (and (vectorp key)
badf89ea
RS
682 (let ((last-idx (1- (length key))))
683 (and (eventp (aref key last-idx))
684 (memq 'down (event-modifiers (aref key last-idx)))))
91a2acb2 685 (or (and (eventp (aref key 0))
98da283b
CY
686 (memq 'down (event-modifiers (aref key 0)))
687 ;; However, for the C-down-mouse-2 popup
688 ;; menu, there is no subsequent up-event. In
689 ;; this case, the up-event is the next
690 ;; element in the supplied vector.
691 (= (length key) 1))
91a2acb2
DK
692 (and (> (length key) 1)
693 (eventp (aref key 1))
694 (memq 'down (event-modifiers (aref key 1)))))
695 (read-event))))
2c8ed538
RS
696 ;; Put yank-menu back as it was, if we changed it.
697 (when saved-yank-menu
698 (setq yank-menu (copy-sequence saved-yank-menu))
699 (fset 'yank-menu (cons 'keymap yank-menu))))))
02dfca16
SM
700 (if (numberp untranslated)
701 (setq untranslated (this-single-command-raw-keys)))
05ca18a8
KS
702 (let* ((event (aref key (if (and (symbolp (aref key 0))
703 (> (length key) 1)
704 (consp (aref key 1)))
705 1
706 0)))
91a2acb2 707 (modifiers (event-modifiers event))
24a27882
KS
708 (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
709 (memq 'drag modifiers)) " at that spot" ""))
05ca18a8
KS
710 (defn (key-binding key t))
711 defn-up defn-up-tricky ev-type
712 mouse-1-remapped mouse-1-tricky)
91a2acb2 713
05ca18a8 714 ;; Handle the case where we faked an entry in "Select and Paste" menu.
24a27882 715 (when (and (eq defn nil)
91a2acb2
DK
716 (stringp (aref key (1- (length key))))
717 (eq (key-binding (substring key 0 -1)) 'yank-menu))
24a27882
KS
718 (setq defn 'menu-bar-select-yank))
719 (if (or (null defn) (integerp defn) (equal defn 'undefined))
720 (message "%s%s is undefined"
721 (help-key-description key untranslated) mouse-msg)
722 (help-setup-xref (list #'describe-function defn) (interactive-p))
723 ;; Don't bother user with strings from (e.g.) the select-paste menu.
724 (when (stringp (aref key (1- (length key))))
725 (aset key (1- (length key)) "(any string)"))
726 (when (and untranslated
91a2acb2 727 (stringp (aref untranslated (1- (length untranslated)))))
24a27882
KS
728 (aset untranslated (1- (length untranslated))
729 "(any string)"))
730 ;; Need to do this before erasing *Help* buffer in case event
731 ;; is a mouse click in an existing *Help* buffer.
732 (when up-event
733 (setq ev-type (event-basic-type up-event))
734 (let ((sequence (vector up-event)))
735 (when (and (eq ev-type 'mouse-1)
736 mouse-1-click-follows-link
737 (not (eq mouse-1-click-follows-link 'double))
738 (setq mouse-1-remapped
739 (mouse-on-link-p (event-start up-event))))
740 (setq mouse-1-tricky (and (integerp mouse-1-click-follows-link)
741 (> mouse-1-click-follows-link 0)))
742 (cond ((stringp mouse-1-remapped)
743 (setq sequence mouse-1-remapped))
744 ((vectorp mouse-1-remapped)
745 (setcar up-event (elt mouse-1-remapped 0)))
746 (t (setcar up-event 'mouse-2))))
747 (setq defn-up (key-binding sequence nil nil (event-start up-event)))
748 (when mouse-1-tricky
749 (setq sequence (vector up-event))
750 (aset sequence 0 'mouse-1)
751 (setq defn-up-tricky (key-binding sequence nil nil (event-start up-event))))))
cde56121 752 (with-help-window (help-buffer)
24a27882
KS
753 (princ (help-key-description key untranslated))
754 (princ (format "\
b96817c3 755%s runs the command %S, which is "
24a27882
KS
756 mouse-msg defn))
757 (describe-function-1 defn)
05ca18a8 758 (when up-event
24a27882
KS
759 (unless (or (null defn-up)
760 (integerp defn-up)
761 (equal defn-up 'undefined))
762 (princ (format "
763
764----------------- up-event %s----------------
765
b96817c3 766<%S>%s%s runs the command %S, which is "
24a27882
KS
767 (if mouse-1-tricky "(short click) " "")
768 ev-type mouse-msg
769 (if mouse-1-remapped
b96817c3 770 " is remapped to <mouse-2>, which" "")
24a27882
KS
771 defn-up))
772 (describe-function-1 defn-up))
773 (unless (or (null defn-up-tricky)
774 (integerp defn-up-tricky)
775 (eq defn-up-tricky 'undefined))
776 (princ (format "
777
778----------------- up-event (long click) ----------------
779
780Pressing <%S>%s for longer than %d milli-seconds
b96817c3 781runs the command %S, which is "
24a27882
KS
782 ev-type mouse-msg
783 mouse-1-click-follows-link
784 defn-up-tricky))
cde56121 785 (describe-function-1 defn-up-tricky)))))))
400a1b1f 786\f
788d62cf
MB
787(defun describe-mode (&optional buffer)
788 "Display documentation of current major mode and minor modes.
efde809a
JPW
789A brief summary of the minor modes comes first, followed by the
790major mode description. This is followed by detailed
791descriptions of the minor modes, each on a separate page.
792
793For this to work correctly for a minor mode, the mode's indicator
794variable \(listed in `minor-mode-alist') must also be a function
795whose documentation describes the minor mode."
f3b5dd74 796 (interactive "@")
dd39c336
SM
797 (unless buffer (setq buffer (current-buffer)))
798 (help-setup-xref (list #'describe-mode buffer)
9639be74
RS
799 (interactive-p))
800 ;; For the sake of help-do-xref and help-xref-go-back,
801 ;; don't switch buffers before calling `help-buffer'.
cde56121 802 (with-help-window (help-buffer)
dd39c336 803 (with-current-buffer buffer
f6c57ef6 804 (let (minor-modes)
dd39c336
SM
805 ;; Older packages do not register in minor-mode-list but only in
806 ;; minor-mode-alist.
807 (dolist (x minor-mode-alist)
808 (setq x (car x))
809 (unless (memq x minor-mode-list)
810 (push x minor-mode-list)))
f6c57ef6
RS
811 ;; Find enabled minor mode we will want to mention.
812 (dolist (mode minor-mode-list)
813 ;; Document a minor mode if it is listed in minor-mode-alist,
814 ;; non-nil, and has a function definition.
af5f4483
SM
815 (let ((fmode (or (get mode :minor-mode-function) mode)))
816 (and (boundp mode) (symbol-value mode)
817 (fboundp fmode)
818 (let ((pretty-minor-mode
819 (if (string-match "\\(\\(-minor\\)?-mode\\)?\\'"
820 (symbol-name fmode))
821 (capitalize
822 (substring (symbol-name fmode)
823 0 (match-beginning 0)))
824 fmode)))
825 (push (list fmode pretty-minor-mode
826 (format-mode-line (assq mode minor-mode-alist)))
827 minor-modes)))))
f6c57ef6
RS
828 (setq minor-modes
829 (sort minor-modes
af5f4483 830 (lambda (a b) (string-lessp (cadr a) (cadr b)))))
f6c57ef6 831 (when minor-modes
71723367 832 (princ "Enabled minor modes:\n")
e25e90b4
DP
833 (make-local-variable 'help-button-cache)
834 (with-current-buffer standard-output
835 (dolist (mode minor-modes)
af5f4483
SM
836 (let ((mode-function (nth 0 mode))
837 (pretty-minor-mode (nth 1 mode))
e25e90b4
DP
838 (indicator (nth 2 mode)))
839 (add-text-properties 0 (length pretty-minor-mode)
840 '(face bold) pretty-minor-mode)
841 (save-excursion
842 (goto-char (point-max))
843 (princ "\n\f\n")
844 (push (point-marker) help-button-cache)
845 ;; Document the minor modes fully.
846 (insert pretty-minor-mode)
71723367
RS
847 (princ (format " minor mode (%s):\n"
848 (if (zerop (length indicator))
849 "no indicator"
850 (format "indicator%s"
d8a869ea 851 indicator))))
e25e90b4 852 (princ (documentation mode-function)))
e25e90b4
DP
853 (insert-button pretty-minor-mode
854 'action (car help-button-cache)
72b64ad5 855 'follow-link t
e25e90b4 856 'help-echo "mouse-2, RET: show full information")
71723367
RS
857 (newline)))
858 (forward-line -1)
859 (fill-paragraph nil)
860 (forward-line 1))
861
862 (princ "\n(Information about these minor modes follows the major mode info.)\n\n"))
f6c57ef6 863 ;; Document the major mode.
e25e90b4
DP
864 (let ((mode mode-name))
865 (with-current-buffer standard-output
4e6d3170 866 (let ((start (point)))
145fe412 867 (insert (format-mode-line mode nil nil buffer))
4e6d3170 868 (add-text-properties start (point) '(face bold)))))
f6c57ef6 869 (princ " mode:\n")
cde56121 870 (princ (documentation major-mode))))))
400a1b1f 871
f6c57ef6 872
8e864068 873(defun describe-minor-mode (minor-mode)
335028c3
MY
874 "Display documentation of a minor mode given as MINOR-MODE.
875MINOR-MODE can be a minor mode symbol or a minor mode indicator string
876appeared on the mode-line."
7ada28ac 877 (interactive (list (completing-read
335028c3
MY
878 "Minor mode: "
879 (nconc
880 (describe-minor-mode-completion-table-for-symbol)
881 (describe-minor-mode-completion-table-for-indicator)
882 ))))
883 (if (symbolp minor-mode)
884 (setq minor-mode (symbol-name minor-mode)))
885 (let ((symbols (describe-minor-mode-completion-table-for-symbol))
886 (indicators (describe-minor-mode-completion-table-for-indicator)))
887 (cond
888 ((member minor-mode symbols)
889 (describe-minor-mode-from-symbol (intern minor-mode)))
890 ((member minor-mode indicators)
891 (describe-minor-mode-from-indicator minor-mode))
892 (t
893 (error "No such minor mode: %s" minor-mode)))))
894
7ada28ac 895;; symbol
335028c3
MY
896(defun describe-minor-mode-completion-table-for-symbol ()
897 ;; In order to list up all minor modes, minor-mode-list
898 ;; is used here instead of minor-mode-alist.
899 (delq nil (mapcar 'symbol-name minor-mode-list)))
900(defun describe-minor-mode-from-symbol (symbol)
901 "Display documentation of a minor mode given as a symbol, SYMBOL"
7ada28ac 902 (interactive (list (intern (completing-read
335028c3
MY
903 "Minor mode symbol: "
904 (describe-minor-mode-completion-table-for-symbol)))))
905 (if (fboundp symbol)
906 (describe-function symbol)
907 (describe-variable symbol)))
908
909;; indicator
910(defun describe-minor-mode-completion-table-for-indicator ()
7ada28ac 911 (delq nil
335028c3
MY
912 (mapcar (lambda (x)
913 (let ((i (format-mode-line x)))
914 ;; remove first space if existed
915 (cond
916 ((= 0 (length i))
917 nil)
94318c8a 918 ((eq (aref i 0) ?\s)
335028c3 919 (substring i 1))
7ada28ac 920 (t
335028c3
MY
921 i))))
922 minor-mode-alist)))
8e864068 923(defun describe-minor-mode-from-indicator (indicator)
335028c3
MY
924 "Display documentation of a minor mode specified by INDICATOR.
925If you call this function interactively, you can give indicator which
926is currently activated with completion."
7ada28ac
LT
927 (interactive (list
928 (completing-read
8e864068 929 "Minor mode indicator: "
335028c3 930 (describe-minor-mode-completion-table-for-indicator))))
8e864068
JB
931 (let ((minor-mode (lookup-minor-mode-from-indicator indicator)))
932 (if minor-mode
335028c3 933 (describe-minor-mode-from-symbol minor-mode)
8e864068
JB
934 (error "Cannot find minor mode for `%s'" indicator))))
935
936(defun lookup-minor-mode-from-indicator (indicator)
937 "Return a minor mode symbol from its indicator on the modeline."
335028c3 938 ;; remove first space if existed
7ada28ac 939 (if (and (< 0 (length indicator))
94318c8a 940 (eq (aref indicator 0) ?\s))
335028c3 941 (setq indicator (substring indicator 1)))
8e864068
JB
942 (let ((minor-modes minor-mode-alist)
943 result)
944 (while minor-modes
945 (let* ((minor-mode (car (car minor-modes)))
7ada28ac 946 (anindicator (format-mode-line
335028c3
MY
947 (car (cdr (car minor-modes))))))
948 ;; remove first space if existed
7ada28ac 949 (if (and (stringp anindicator)
335028c3 950 (> (length anindicator) 0)
94318c8a 951 (eq (aref anindicator 0) ?\s))
335028c3
MY
952 (setq anindicator (substring anindicator 1)))
953 (if (equal indicator anindicator)
8e864068
JB
954 (setq result minor-mode
955 minor-modes nil)
956 (setq minor-modes (cdr minor-modes)))))
957 result))
958
48ce3c22
RS
959\f
960;;; Automatic resizing of temporary buffers.
961
4483ddc5 962(defcustom temp-buffer-max-height (lambda (buffer) (/ (- (frame-height) 2) 2))
4e6d3170 963 "Maximum height of a window displaying a temporary buffer.
90e357ae
RS
964This is effective only when Temp Buffer Resize mode is enabled.
965The value is the maximum height (in lines) which `resize-temp-buffer-window'
48ce3c22 966will give to a window displaying a temporary buffer.
90e357ae
RS
967It can also be a function to be called to choose the height for such a buffer.
968It gets one argumemt, the buffer, and should return a positive integer."
48ce3c22
RS
969 :type '(choice integer function)
970 :group 'help
971 :version "20.4")
972
4e1ede6c
SM
973(define-minor-mode temp-buffer-resize-mode
974 "Toggle the mode which makes windows smaller for temporary buffers.
48ce3c22
RS
975With prefix argument ARG, turn the resizing of windows displaying temporary
976buffers on if ARG is positive or off otherwise.
4e1ede6c
SM
977This makes the window the right height for its contents, but never
978more than `temp-buffer-max-height' nor less than `window-min-height'.
979This applies to `help', `apropos' and `completion' buffers, and some others."
b0fbf754 980 :global t :group 'help
4e1ede6c 981 (if temp-buffer-resize-mode
57f43907 982 ;; `help-make-xrefs' may add a `back' button and thus increase the
4e1ede6c
SM
983 ;; text size, so `resize-temp-buffer-window' must be run *after* it.
984 (add-hook 'temp-buffer-show-hook 'resize-temp-buffer-window 'append)
8304a3bb 985 (remove-hook 'temp-buffer-show-hook 'resize-temp-buffer-window)))
48ce3c22
RS
986
987(defun resize-temp-buffer-window ()
2a5f11a2 988 "Resize the selected window to fit its contents.
4483ddc5 989Will not make it higher than `temp-buffer-max-height' nor smaller than
b2c85790 990`window-min-height'. Do nothing if it is the only window on its frame, if it
48ce3c22
RS
991is not as wide as the frame or if some of the window's contents are scrolled
992out of view."
993 (unless (or (one-window-p 'nomini)
994 (not (pos-visible-in-window-p (point-min)))
2a5f11a2 995 (not (window-full-width-p)))
d9c30bdf
MB
996 (fit-window-to-buffer
997 (selected-window)
998 (if (functionp temp-buffer-max-height)
999 (funcall temp-buffer-max-height (current-buffer))
1000 temp-buffer-max-height))))
48ce3c22 1001
172892e3 1002\f
cde56121
MR
1003;;; help-window
1004
1005(defcustom help-window-select 'other
1006 "Non-nil means select help window for viewing.
1007Choices are:
1008 never (nil) Select help window only if there is no other window
1009 on its frame.
1010 other Select help window unless the selected window is the
1011 only other window on its frame.
1012 always (t) Always select the help window.
1013
1014This option has effect if and only if the help window was created
1015by `with-help-window'"
1016 :type '(choice (const :tag "never (nil)" nil)
1017 (const :tag "other" other)
1018 (const :tag "always (t)" t))
1019 :group 'help
1020 :version "23.1")
1021
1022(defun help-window-display-message (quit-part window &optional other)
1023 "Display message telling how to quit and scroll help window.
1024QUIT-PART is a string telling how to quit the help window WINDOW.
1025Optional argument OTHER non-nil means return text telling how to
1026scroll the \"other\" window."
1027 (let ((scroll-part
1028 (cond
1029 ((pos-visible-in-window-p
1030 (with-current-buffer (window-buffer window)
1031 (point-max)) window)
1032 ;; Buffer end is visible.
1033 ".")
1034 (other ", \\[scroll-other-window] to scroll help.")
1035 (t ", \\[scroll-up] to scroll help."))))
f6e7ec02 1036 (message "%s"
cde56121
MR
1037 (substitute-command-keys (concat quit-part scroll-part)))))
1038
1039(defun help-window-setup-finish (window &optional reuse keep-frame)
1040 "Finish setting up help window WINDOW.
1041Select WINDOW according to the value of `help-window-select'.
1042Display message telling how to scroll and eventually quit WINDOW.
1043
1044Optional argument REUSE non-nil means WINDOW has been reused \(by
1045`display-buffer'\) for displaying help. Optional argument
1046KEEP-FRAME non-nil means that quitting must no delete the frame
1047of WINDOW."
1048 (let ((number-of-windows
1049 (length (window-list (window-frame window) 'no-mini window))))
1050 (cond
1051 ((eq window (selected-window))
1052 ;; The help window is the selected window, probably the
1053 ;; `pop-up-windows' nil case.
1054 (help-window-display-message
1055 (if reuse
1056 "Type \"q\" to restore this window"
1057 ;; This should not be taken.
1058 "Type \"q\" to quit") window))
1059 ((= number-of-windows 1)
1060 ;; The help window is alone on a frame and not the selected
1061 ;; window, could be the `pop-up-frames' t case.
1062 (help-window-display-message
1063 (cond
1064 (keep-frame "Type \"q\" to delete this window")
1065 (reuse "Type \"q\" to restore this window")
1066 (view-remove-frame-by-deleting "Type \"q\" to delete this frame")
1067 (t "Type \"q\" to iconify this frame"))
1068 window))
1069 ((and (= number-of-windows 2)
1070 (eq (window-frame window) (window-frame (selected-window))))
1071 ;; There are two windows on the help window's frame and the other
1072 ;; window is the selected one.
1073 (if (memq help-window-select '(nil other))
1074 ;; Do not select the help window.
1075 (help-window-display-message
1076 (if reuse
1077 ;; Offer `display-buffer' for consistency with
1078 ;; `print-help-return-message'. This is hardly TRT when
1079 ;; the other window and the selected window display the
1080 ;; same buffer but has been handled this way ever since.
1081 "Type \\[display-buffer] RET to restore the other window"
1082 ;; The classic "two windows" configuration.
1083 "Type \\[delete-other-windows] to delete the help window")
1084 window t)
1085 ;; Select help window and tell how to quit.
1086 (select-window window)
1087 (help-window-display-message
1088 (if reuse
1089 "Type \"q\" to restore this window"
1090 "Type \"q\" to delete this window") window)))
1091 (help-window-select
1092 ;; Issuing a message with 3 or more windows on the same frame
1093 ;; without selecting the help window doesn't make any sense.
1094 (select-window window)
1095 (help-window-display-message
1096 (if reuse
1097 "Type \"q\" to restore this window"
1098 "Type \"q\" to delete this window") window)))))
1099
1100(defun help-window-setup (list-of-frames list-of-window-tuples)
1101 "Set up help window.
1102LIST-OF-FRAMES and LIST-OF-WINDOW-TUPLES are the lists of frames
1103and window quadruples built by `with-help-window'. The help
1104window itself is specified by the variable `help-window'."
1105 (let* ((help-buffer (window-buffer help-window))
1106 ;; `help-buffer' now denotes the help window's buffer.
1107 (view-entry
1108 (assq help-window
1109 (buffer-local-value 'view-return-to-alist help-buffer)))
1110 (help-entry (assq help-window list-of-window-tuples)))
1111
1112 ;; Handle `help-window-point-marker'.
1113 (when (eq (marker-buffer help-window-point-marker) help-buffer)
1114 (set-window-point help-window help-window-point-marker)
1115 ;; Reset `help-window-point-marker'.
1116 (set-marker help-window-point-marker nil))
1117
1118 (cond
1119 (view-entry
1120 ;; `view-return-to-alist' has an entry for the help window.
1121 (cond
1122 ((eq help-window (selected-window))
1123 ;; The help window is the selected window, probably because the
1124 ;; user followed a backward/forward button or a cross reference.
1125 ;; In this case just purge stale entries from
1126 ;; `view-return-to-alist' but leave the entry alone and don't
1127 ;; display a message.
1128 (view-return-to-alist-update help-buffer))
1129 ((and help-entry (eq (cadr help-entry) help-buffer))
1130 ;; The help window was not selected but displayed the help
1131 ;; buffer. In this case reuse existing exit information but try
1132 ;; to get back to the selected window when quitting. Don't
1133 ;; display a message since the user must have seen one before.
1134 (view-return-to-alist-update
1135 help-buffer (cons help-window
1136 (cons (selected-window) (cddr view-entry)))))
1137 (help-entry
1138 ;; The help window was not selected, did display the help buffer
1139 ;; earlier, but displayed another buffer when help was invoked.
1140 ;; Set up things so that quitting will show that buffer again.
1141 (view-return-to-alist-update
1142 help-buffer (cons help-window
1143 (cons (selected-window) (cdr help-entry))))
1144 (help-window-setup-finish help-window t))
1145 (t
1146 ;; The help window is new but `view-return-to-alist' had an
1147 ;; entry for it. This should never happen.
1148 (view-return-to-alist-update
1149 help-buffer (cons help-window
1150 (cons (selected-window) 'quit-window)))
1151 (help-window-setup-finish help-window t))))
1152 (help-entry
1153 ;; `view-return-to-alist' does not have an entry for help window
1154 ;; but `list-of-window-tuples' does. Hence `display-buffer' must
1155 ;; have reused an existing window.
1156 (if (eq (cadr help-entry) help-buffer)
1157 ;; The help window displayed `help-buffer' before but no
1158 ;; `view-return-to-alist' entry was found probably because the
1159 ;; user manually switched to the help buffer. Set up things
1160 ;; for `quit-window' although `view-exit-action' should be
1161 ;; able to handle this case all by itself.
1162 (progn
1163 (view-return-to-alist-update
1164 help-buffer (cons help-window
1165 (cons (selected-window) 'quit-window)))
1166 (help-window-setup-finish help-window t))
1167 ;; The help window displayed another buffer before. Set up
1168 ;; things in a way that quitting can orderly show that buffer
1169 ;; again. The window-start and window-point information from
1170 ;; `list-of-window-tuples' provide the necessary information.
1171 (view-return-to-alist-update
1172 help-buffer (cons help-window
1173 (cons (selected-window) (cdr help-entry))))
1174 (help-window-setup-finish help-window t)))
1175 ((memq (window-frame help-window) list-of-frames)
1176 ;; The help window is a new window on an existing frame. This
1177 ;; case must be handled specially by `help-window-setup-finish'
1178 ;; and `view-mode-exit' to ascertain that quitting does _not_
1179 ;; inadvertently delete the frame.
1180 (view-return-to-alist-update
1181 help-buffer (cons help-window
1182 (cons (selected-window) 'keep-frame)))
1183 (help-window-setup-finish help-window nil t))
1184 (t
1185 ;; The help window is shown on a new frame. In this case quitting
1186 ;; shall handle both, the help window _and_ its frame. We changed
1187 ;; the default of `view-remove-frame-by-deleting' to t in order to
1188 ;; intuitively DTRT here.
1189 (view-return-to-alist-update
1190 help-buffer (cons help-window (cons (selected-window) t)))
1191 (help-window-setup-finish help-window)))))
1192
1193;; `with-help-window' is a wrapper for `with-output-to-temp-buffer'
1194;; providing the following additional twists:
1195
1196;; (1) Issue more accurate messages telling how to scroll and quit the
1197;; help window.
1198
1199;; (2) Make `view-mode-exit' DTRT in more cases.
1200
1201;; (3) An option (customizable via `help-window-select') to select the
1202;; help window automatically.
1203
1204;; (4) A marker (`help-window-point-marker') to move point in the help
1205;; window to an arbitrary buffer position.
1206
1207;; Note: It's usually always wrong to use `print-help-return-message' in
1208;; the body of `with-help-window'.
1209(defmacro with-help-window (buffer-name &rest body)
1210 "Display buffer BUFFER-NAME in a help window evaluating BODY.
1211Select help window if the actual value of the user option
1212`help-window-select' says so."
1213 (declare (indent 1) (debug t))
1214 ;; Bind list-of-frames to `frame-list' and list-of-window-tuples to a
1215 ;; list of one <window window-buffer window-start window-point> tuple
1216 ;; for each live window.
1217 `(let ((list-of-frames (frame-list))
1218 (list-of-window-tuples
1219 (let (list)
1220 (walk-windows
1221 (lambda (window)
1222 (push (list window (window-buffer window)
1223 (window-start window) (window-point window))
1224 list))
1225 'no-mini t)
1226 list)))
1227 ;; We set `help-window' to t in order to trigger `help-mode-finish'
1228 ;; to set `help-window' to the actual help window.
1229 (setq help-window t)
1230 ;; Make `help-window-point-marker' point nowhere (the only place
1231 ;; where this should be set to a buffer position is within BODY).
1232 (set-marker help-window-point-marker nil)
1233
1234 (with-output-to-temp-buffer ,buffer-name
1235 (progn ,@body))
1236
1237 (when (windowp help-window)
1238 ;; Set up help window.
1239 (help-window-setup list-of-frames list-of-window-tuples))
1240
1241 ;; Reset `help-window' to nil to avoid confusing future calls of
1242 ;; `help-mode-finish' by "plain" `with-output-to-temp-buffer'.
1243 (setq help-window nil)))
1244\f
172892e3
JB
1245(provide 'help)
1246
dd39c336 1247;; arch-tag: cf427352-27e9-49b7-9a6f-741ebab02423
1a06eabd 1248;;; help.el ends here