comparison lisp/prim/help.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; help.el --- help commands for XEmacs.
2 ;; Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
3
4 ;; Maintainer: FSF
5 ;; Keywords: help, internal
6
7 ;; This file is part of XEmacs.
8
9 ;; XEmacs is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; XEmacs is distributed in the hope that it will be useful, but
15 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 ;; General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with XEmacs; see the file COPYING. If not, write to the Free
21 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22
23 ;;; Synched up with: FSF 19.30.
24
25 ;;; Commentary:
26
27 ;; This code implements XEmacs's on-line help system, the one invoked by
28 ;;`M-x help-for-help'.
29
30 ;;; Code:
31
32 ;#### FSFmacs
33 ;; Get the macro make-help-screen when this is compiled,
34 ;; or run interpreted, but not when the compiled code is loaded.
35 ;(eval-when-compile (require 'help-macro))
36
37 (defvar help-map (let ((map (make-sparse-keymap)))
38 (set-keymap-name map 'help-map)
39 (set-keymap-prompt
40 map (purecopy (gettext "(Type ? for further options)")))
41 map)
42 "Keymap for characters following the Help key.")
43
44 ;; global-map definitions moved to keydefs.el
45 (fset 'help-command help-map)
46
47 (let ((ch help-char))
48 (if (integerp ch)
49 (setq ch (char-to-string ch)))
50 (define-key help-map ch 'help-for-help))
51 (define-key help-map "?" 'help-for-help)
52 (define-key help-map 'help 'help-for-help)
53
54 (define-key help-map "\C-l" 'describe-copying) ; on \C-c in FSFmacs
55 (define-key help-map "\C-d" 'describe-distribution)
56 (define-key help-map "\C-w" 'describe-no-warranty)
57 (define-key help-map "a" 'hyper-apropos) ; 'command-apropos in FSFmacs
58 (define-key help-map "A" 'command-apropos)
59
60 (define-key help-map "b" 'describe-bindings)
61 (define-key help-map "\C-p" 'describe-pointer)
62
63 (define-key help-map "c" 'describe-key-briefly)
64 (define-key help-map "k" 'describe-key)
65
66 (define-key help-map "d" 'describe-function)
67 (define-key help-map "e" 'describe-last-error)
68 (define-key help-map "f" 'describe-function)
69
70 (define-key help-map "F" 'xemacs-local-faq)
71
72 ;;; Setup so Hyperbole can be autoloaded from a key.
73 ;;; Choose a key on which to place the Hyperbole menus.
74 ;;; For most people this key binding will work and will be equivalent
75 ;;; to {C-h h}.
76 ;;;
77 (or (where-is-internal 'hyperbole)
78 (where-is-internal 'hui:menu)
79 (define-key help-map "h" 'hyperbole))
80 (autoload 'hyperbole "hsite" "Hyperbole info manager menus." t)
81
82 (define-key help-map "i" 'info)
83 (define-key help-map '(control i) 'Info-query)
84 ;; FSFmacs has Info-goto-emacs-command-node on C-f, no binding
85 ;; for Info-elisp-ref
86 (define-key help-map '(control c) 'Info-goto-emacs-command-node)
87 (define-key help-map '(control k) 'Info-goto-emacs-key-command-node)
88 (define-key help-map '(control f) 'Info-elisp-ref)
89
90 (define-key help-map "l" 'view-lossage)
91
92 (define-key help-map "m" 'describe-mode)
93
94 (define-key help-map "\C-n" 'view-emacs-news)
95 (define-key help-map "n" 'view-emacs-news)
96
97 (define-key help-map "p" 'finder-by-keyword)
98 (autoload 'finder-by-keyword "finder"
99 "Find packages matching a given keyword." t)
100
101 (define-key help-map "s" 'describe-syntax)
102
103 (define-key help-map "t" 'help-with-tutorial)
104
105 (define-key help-map "w" 'where-is)
106
107 (define-key help-map "v" 'describe-variable)
108
109 (if (fboundp 'view-last-error)
110 (define-key help-map "e" 'view-last-error))
111
112
113 (define-key help-map "q" 'help-quit)
114
115 ;#### This stuff was an attempt to have font locking and hyperlinks in the
116 ;help buffer, but it doesn't really work. Some of this stuff comes from
117 ;FSF Emacs; but the FSF Emacs implementation is rather broken, as usual.
118 ;What needs to happen is this:
119 ;
120 ; -- we probably need a "hyperlink mode" from which help-mode is derived.
121 ; -- this means we probably need multiple inheritance of modes!
122 ; Thankfully this is not hard to implement; we already have the
123 ; ability for a keymap to have multiple parents. However, we'd
124 ; have to define any multiply-inherited-from modes using a standard
125 ; `define-mode' construction instead of manually doing it, because
126 ; we don't want each guy calling `kill-all-local-variables' and
127 ; messing up the previous one.
128 ; -- we need to scan the buffer ourselves (not from font-lock, because
129 ; the user might not have font-lock enabled) and highlight only
130 ; those words that are *documented* functions and variables (and
131 ; probably excluding words without dashes in them unless enclosed
132 ; in quotes, so that common words like "list" and "point" don't
133 ; become hyperlinks.
134 ; -- we should *not* use font-lock keywords like below. Instead we
135 ; should add the font-lock stuff ourselves during the scanning phase,
136 ; if font-lock is enabled in this buffer.
137
138 ;(defun help-follow-reference (event extent user-data)
139 ; (let ((symbol (intern-soft (extent-string extent))))
140 ; (cond ((and symbol (fboundp symbol))
141 ; (describe-function symbol))
142 ; ((and symbol (boundp symbol))
143 ; (describe-variable symbol))
144 ; (t nil))))
145
146 ;(defvar help-font-lock-keywords
147 ; (let ((name-char "[-+a-zA-Z0-9_*]") (sym-char "[-+a-zA-Z0-9_:*]"))
148 ; (list
149 ; ;;
150 ; ;; The symbol itself.
151 ; (list (concat "\\`\\(" name-char "+\\)\\(:\\)?")
152 ; '(1 (if (match-beginning 2)
153 ; 'font-lock-function-name-face
154 ; 'font-lock-variable-name-face)
155 ; nil t))
156 ; ;;
157 ; ;; Words inside `' which tend to be symbol names.
158 ; (list (concat "`\\(" sym-char sym-char "+\\)'")
159 ; 1 '(prog1
160 ; 'font-lock-reference-face
161 ; (add-list-mode-item (match-beginning 1)
162 ; (match-end 1)
163 ; nil
164 ; 'help-follow-reference))
165 ; t)
166 ; ;;
167 ; ;; CLisp `:' keywords as references.
168 ; (list (concat "\\<:" sym-char "+\\>") 0 'font-lock-reference-face t)))
169 ; "Default expressions to highlight in Help mode.")
170
171 ;(put 'help-mode 'font-lock-defaults '(help-font-lock-keywords))
172
173 (define-derived-mode help-mode view-major-mode "Help"
174 "Major mode for viewing help text.
175 Entry to this mode runs the normal hook `help-mode-hook'.
176 Commands:
177 \\{help-mode-map}"
178 )
179
180 (define-key help-mode-map "q" 'help-mode-quit)
181
182 (defun help-mode-quit ()
183 "Exits from help mode, possiblely restoring the previous window configuration."
184 (interactive)
185 (cond ((local-variable-p 'help-window-config (current-buffer))
186 (let ((config help-window-config))
187 (kill-local-variable 'help-window-config)
188 (set-window-configuration config)))
189 ((one-window-p)
190 (bury-buffer))
191 (t
192 (delete-window))))
193
194 (defun help-quit ()
195 (interactive)
196 nil)
197
198 ;; This is a grody hack of the same genotype as `advertised-undo'; if the
199 ;; bindings of Backspace and C-h are the same, we want the menubar to claim
200 ;; that `info' in invoked with `C-h i', not `BS i'.
201
202 (defun deprecated-help-command ()
203 (interactive)
204 (if (eq 'help-command (key-binding "\C-h"))
205 (setq unread-command-event (character-to-event ?\C-h))
206 (help-for-help)))
207
208 ;;(define-key global-map 'backspace 'deprecated-help-command)
209
210 ;; TUTORIAL arg is XEmacs addition
211 (defun help-with-tutorial (&optional tutorial)
212 "Select the XEmacs learn-by-doing tutorial.
213 Optional arg TUTORIAL specifies the tutorial file; default is \"TUTORIAL\"."
214 (interactive)
215 (if (null tutorial)
216 (setq tutorial "TUTORIAL"))
217 (let ((file (expand-file-name (concat "~/" tutorial))))
218 (delete-other-windows)
219 (if (get-file-buffer file)
220 (switch-to-buffer (get-file-buffer file))
221 (switch-to-buffer (create-file-buffer file))
222 (setq buffer-file-name file)
223 (setq default-directory (expand-file-name "~/"))
224 (setq buffer-auto-save-file-name nil)
225 (insert-file-contents (expand-file-name tutorial data-directory))
226 (goto-char (point-min))
227 (search-forward "\n<<")
228 (beginning-of-line)
229 (delete-region (point) (progn (end-of-line) (point)))
230 (let ((n (- (window-height (selected-window))
231 (count-lines (point-min) (point))
232 6)))
233 (if (< n 12)
234 (newline n)
235 ;; Some people get confused by the large gap.
236 (newline (/ n 2))
237 (insert "[Middle of page left blank for didactic purposes. "
238 "Text continues below]")
239 (newline (- n (/ n 2)))))
240 (goto-char (point-min))
241 (set-buffer-modified-p nil))))
242
243 ;; used by describe-key and describe-key-briefly
244
245 (defun key-or-menu-binding (key &optional menu-flag)
246 ;; KEY is any value returned by next-command-event
247 ;; MENU-FLAG is a symbol that should be set to T if KEY is a menu event,
248 ;; or NIL otherwise
249 (let (defn)
250 (and menu-flag (set menu-flag nil))
251 ;; If the key typed was really a menu selection, grab the form out
252 ;; of the event object and intuit the function that would be called,
253 ;; and describe that instead.
254 (if (and (vectorp key) (= 1 (length key))
255 (or (misc-user-event-p (aref key 0))
256 (eq (car-safe (aref key 0)) 'menu-selection)))
257 (let ((event (aref key 0)))
258 (setq defn (if (eventp event)
259 (list (event-function event) (event-object event))
260 (cdr event)))
261 (and menu-flag (set menu-flag t))
262 (if (eq (car defn) 'eval)
263 (setq defn (car (cdr defn))))
264 (if (eq (car-safe defn) 'call-interactively)
265 (setq defn (car (cdr defn))))
266 (if (and (consp defn) (null (cdr defn)))
267 (setq defn (car defn))))
268 ;; else
269 (setq defn (key-binding key)))
270 ;; kludge: if a toolbar button was pressed on, try to find the
271 ;; binding of the toolbar button.
272 (if (and (eq defn 'press-toolbar-button)
273 (vectorp key)
274 (button-press-event-p (aref key (1- (length key)))))
275 ;; wait for the button release. We're on shaky ground here ...
276 (let ((event (next-command-event))
277 button)
278 (if (and (button-release-event-p event)
279 (event-over-toolbar-p event)
280 (eq 'release-and-activate-toolbar-button
281 (key-binding (vector event)))
282 (setq button (event-toolbar-button event)))
283 (toolbar-button-callback button)
284 ;; if anything went wrong, try returning the binding of
285 ;; the button-up event, of the original binding
286 (or (key-or-menu-binding (vector event))
287 defn)))
288 ;; no toolbar kludge
289 defn)
290 ))
291
292 (defun describe-key-briefly (key)
293 "Print the name of the function KEY invokes. KEY is a string."
294 (interactive "kDescribe key briefly: ")
295 (let (defn menup)
296 (setq defn (key-or-menu-binding key 'menup))
297 (if (or (null defn) (integerp defn))
298 (message "%s is undefined" (key-description key))
299 ;; If it's a keyboard macro which trivially invokes another command,
300 ;; document that instead.
301 (if (or (stringp defn) (vectorp defn))
302 (setq defn (or (key-binding defn)
303 defn)))
304 (let ((last-event (and (vectorp key)
305 (aref key (1- (length key))))))
306 (message (if (or (button-press-event-p last-event)
307 (button-release-event-p last-event))
308 (gettext "%s at that spot runs the command %s")
309 (gettext "%s runs the command %s"))
310 ;; This used to say 'This menu item' but it could also
311 ;; be a scrollbar event. We can't distinguish at the
312 ;; moment.
313 (if menup "This item" (key-description key))
314 (if (symbolp defn) defn (prin1-to-string defn)))))))
315
316 ;; #### this is a horrible piece of shit function that should
317 ;; not exist. In FSF 19.30 this function has gotten three times
318 ;; as long and has tons and tons of dumb shit checking
319 ;; special-display-buffer-names and such crap. I absolutely
320 ;; refuse to insert that Ebolification here. I wanted to delete
321 ;; this function entirely but Mly bitched.
322 ;;
323 ;; If your user-land code calls this function, rewrite it to
324 ;; call with-displaying-help-buffer.
325
326 (defun print-help-return-message (&optional function)
327 "Display or return message saying how to restore windows after help command.
328 Computes a message and applies the optional argument FUNCTION to it.
329 If FUNCTION is nil, applies `message' to it, thus printing it."
330 (and (not (get-buffer-window standard-output))
331 (funcall
332 (or function 'message)
333 (concat
334 (substitute-command-keys
335 (if (one-window-p t)
336 (if pop-up-windows
337 (gettext "Type \\[delete-other-windows] to remove help window.")
338 (gettext "Type \\[switch-to-buffer] RET to remove help window."))
339 (gettext "Type \\[switch-to-buffer-other-window] RET to restore the other window.")))
340 (substitute-command-keys
341 (gettext " \\[scroll-other-window] to scroll the help."))))))
342
343 (defvar help-selects-help-window t
344 "*If nil, use the \"old Emacs\" behavior for Help buffers.
345 This just displays the buffer in another window, rather than selecting
346 the window.")
347
348 (defvar help-window-config nil)
349
350 ;; Use this function for displaying help when C-h something is pressed
351 ;; or in similar situations. Do *not* use it when you are displaying
352 ;; a help message and then prompting for input in the minibuffer --
353 ;; this macro usually selects the help buffer, which is not what you
354 ;; want in those situations.
355 (defun with-displaying-help-buffer (thunk)
356 (let ((winconfig (current-window-configuration))
357 (was-one-window (one-window-p)))
358 (prog1 (with-output-to-temp-buffer "*Help*"
359 (prog1 (funcall thunk)
360 (save-excursion
361 (set-buffer standard-output)
362 (help-mode))))
363 (let ((helpwin (get-buffer-window "*Help*")))
364 (if helpwin
365 (progn
366 (save-excursion
367 (set-buffer (window-buffer helpwin))
368 (set (make-local-variable 'help-window-config) winconfig))
369 (if help-selects-help-window
370 (select-window helpwin))
371 (cond ((eq helpwin (selected-window))
372 (message
373 (substitute-command-keys "Type \\[help-mode-quit] to remove help window, \\[scroll-up] to scroll the help.")))
374 (was-one-window
375 (message
376 (substitute-command-keys "Type \\[delete-other-windows] to remove help window, \\[scroll-other-window] to scroll the help.")))
377 (t
378 (message
379 (substitute-command-keys "Type \\[switch-to-buffer-other-window] to restore the other window, \\[scroll-other-window] to scroll the help."))))))))))
380
381 (defun describe-key (key)
382 "Display documentation of the function invoked by KEY.
383 KEY is a string, or vector of events.
384 When called interactvely, KEY may also be a menu selection."
385 (interactive "kDescribe key: ")
386 (let ((defn (key-or-menu-binding key)))
387 (if (or (null defn) (integerp defn))
388 (message "%s is undefined" (key-description key))
389 (with-displaying-help-buffer
390 (lambda ()
391 ; (princ (key-description key))
392 ; (princ " runs the command ")
393 (prin1 defn)
394 (princ ":\n")
395 (cond ((or (stringp defn) (vectorp defn))
396 (let ((cmd (key-binding defn)))
397 (if (not cmd)
398 (princ "a keyboard macro")
399 (progn
400 (princ (format "a keyboard macro which runs the command %s:\n\n"
401 cmd))
402 (princ cmd)
403 (princ "\n")
404 (if (documentation cmd) (princ (documentation cmd)))))))
405 ((and (consp defn) (not (eq 'lambda (car-safe defn))))
406 (princ "\n")
407 (let ((describe-function-show-arglist nil))
408 (describe-function-1 (car defn) standard-output)))
409 ((documentation defn)
410 (princ (documentation defn)))
411 (t
412 (princ "not documented"))))))))
413
414 (defun describe-mode ()
415 "Display documentation of current major mode and minor modes.
416 For this to work correctly for a minor mode, the mode's indicator variable
417 \(listed in `minor-mode-alist') must also be a function whose documentation
418 describes the minor mode."
419 (interactive)
420 (with-displaying-help-buffer
421 (lambda ()
422 ;; XEmacs change: print the major-mode documentation before
423 ;; the minor modes.
424 (princ mode-name)
425 (princ " mode:\n")
426 (princ (documentation major-mode))
427 (princ "\n\n----\n\n")
428 (let ((minor-modes minor-mode-alist))
429 (while minor-modes
430 (let* ((minor-mode (car (car minor-modes)))
431 (indicator (car (cdr (car minor-modes)))))
432 ;; Document a minor mode if it is listed in minor-mode-alist,
433 ;; bound locally in this buffer, non-nil, and has a function
434 ;; definition.
435 (if (and (boundp minor-mode)
436 (symbol-value minor-mode)
437 (fboundp minor-mode))
438 (let ((pretty-minor-mode minor-mode))
439 (if (string-match "-mode\\'" (symbol-name minor-mode))
440 (setq pretty-minor-mode
441 (capitalize
442 (substring (symbol-name minor-mode)
443 0 (match-beginning 0)))))
444 (while (and (consp indicator) (extentp (car indicator)))
445 (setq indicator (cdr indicator)))
446 (while (and indicator (symbolp indicator))
447 (setq indicator (symbol-value indicator)))
448 (princ (format "%s minor mode (indicator%s):\n"
449 pretty-minor-mode indicator))
450 (princ (documentation minor-mode))
451 (princ "\n\n----\n\n"))))
452 (setq minor-modes (cdr minor-modes)))))))
453
454 ;; So keyboard macro definitions are documented correctly
455 (fset 'defining-kbd-macro (symbol-function 'start-kbd-macro))
456
457 (defun describe-distribution ()
458 "Display info on how to obtain the latest version of XEmacs."
459 (interactive)
460 (find-file-read-only
461 (expand-file-name "DISTRIB" data-directory)))
462
463 (defun describe-copying ()
464 "Display info on how you may redistribute copies of XEmacs."
465 (interactive)
466 (find-file-read-only
467 (expand-file-name "COPYING" data-directory))
468 (goto-char (point-min)))
469
470 (defun describe-pointer ()
471 "Show a list of all defined mouse buttons, and their definitions."
472 (interactive)
473 (describe-bindings nil t))
474
475 (defun describe-project ()
476 "Display info on the GNU project."
477 (interactive)
478 (find-file-read-only
479 (expand-file-name "GNU" data-directory))
480 (goto-char (point-min)))
481
482 (defun describe-no-warranty ()
483 "Display info on all the kinds of warranty XEmacs does NOT have."
484 (interactive)
485 (describe-copying)
486 (let (case-fold-search)
487 (search-forward "NO WARRANTY")
488 (recenter 0)))
489
490 (defun describe-bindings (&optional prefix mouse-only-p)
491 "Show a list of all defined keys, and their definitions.
492 The list is put in a buffer, which is displayed.
493 If the optional argument PREFIX is supplied, only commands which
494 start with that sequence of keys are described.
495 If the second argument (prefix arg, interactively) is non-null
496 then only the mouse bindings are displayed."
497 (interactive (list nil current-prefix-arg))
498 (with-displaying-help-buffer
499 (lambda ()
500 (describe-bindings-1 prefix mouse-only-p))))
501
502 (defun describe-bindings-1 (&optional prefix mouse-only-p)
503 (let ((heading (if mouse-only-p
504 (gettext "button binding\n------ -------\n")
505 (gettext "key binding\n--- -------\n")))
506 (buffer (current-buffer))
507 (minor minor-mode-map-alist)
508 (local (current-local-map))
509 (shadow '()))
510 (set-buffer standard-output)
511 (while minor
512 (let ((sym (car (car minor)))
513 (map (cdr (car minor))))
514 (if (symbol-value-in-buffer sym buffer nil)
515 (progn
516 (insert (format "Minor Mode Bindings for `%s':\n"
517 sym)
518 heading)
519 (describe-bindings-internal map nil shadow prefix mouse-only-p)
520 (insert "\n")
521 (setq shadow (cons map shadow))))
522 (setq minor (cdr minor))))
523 (if local
524 (progn
525 (insert "Local Bindings:\n" heading)
526 (describe-bindings-internal local nil shadow prefix mouse-only-p)
527 (insert "\n")
528 (setq shadow (cons local shadow))))
529 (insert "Global Bindings:\n" heading)
530 (describe-bindings-internal (current-global-map)
531 nil shadow prefix mouse-only-p)
532 (set-buffer buffer)))
533
534 (defun describe-prefix-bindings ()
535 "Describe the bindings of the prefix used to reach this command.
536 The prefix described consists of all but the last event
537 of the key sequence that ran this command."
538 (interactive)
539 (let* ((key (this-command-keys))
540 (prefix (make-vector (1- (length key)) nil))
541 i)
542 (setq i 0)
543 (while (< i (length prefix))
544 (aset prefix i (aref key i))
545 (setq i (1+ i)))
546 (with-displaying-help-buffer
547 (lambda ()
548 (princ "Key bindings starting with ")
549 (princ (key-description prefix))
550 (princ ":\n\n")
551 (describe-bindings-1 prefix nil)))))
552
553 ;; Make C-h after a prefix, when not specifically bound,
554 ;; run describe-prefix-bindings.
555 (setq prefix-help-command 'describe-prefix-bindings)
556
557 (defun view-emacs-news ()
558 "Display info on recent changes to XEmacs."
559 (interactive)
560 (require 'outl-mouse)
561 (find-file (expand-file-name "NEWS" data-directory)))
562
563 (defun xemacs-www-page ()
564 "Go to the XEmacs World Wide Web page."
565 (interactive)
566 (funcall browse-url-browser-function "http://www.xemacs.org/"))
567
568 (defun xemacs-www-faq ()
569 "View the latest and greatest XEmacs FAQ using the World Wide Web."
570 (interactive)
571 (funcall browse-url-browser-function "http://www.xemacs.org/faq/index.html"))
572
573 (defun xemacs-local-faq ()
574 "View the local copy of the XEmacs FAQ.
575 If you have access to the World Wide Web, you should use `xemacs-www-faq'
576 instead, to ensure that you get the most up-to-date information."
577 (interactive)
578 (save-window-excursion
579 (info)
580 (Info-find-node "xemacs-faq" "Top"))
581 (switch-to-buffer "*info*"))
582
583 (defun view-lossage ()
584 "Display last 100 input keystrokes and last 100 or so minibuffer messages."
585 (interactive)
586 (with-displaying-help-buffer
587 (lambda ()
588 (princ (key-description (recent-keys)))
589 (save-excursion
590 (set-buffer standard-output)
591 (goto-char (point-min))
592 (insert "Recent keystrokes:\n\n")
593 (while (progn (move-to-column 50) (not (eobp)))
594 (search-forward " " nil t)
595 (insert "\n")))
596 ;; XEmacs addition
597 (princ "\n\n\nRecent minibuffer messages (most recent first):\n\n")
598 (save-excursion
599 (let ((buffer (get-buffer " *Message-Log*"))
600 (count 0)
601 oldpoint)
602 (set-buffer buffer)
603 (goto-char (point-max))
604 (set-buffer standard-output)
605 (while (and (> (point buffer) (point-min buffer))
606 (< count 100))
607 (setq oldpoint (point buffer))
608 (forward-line -1 buffer)
609 (insert-buffer-substring buffer (point buffer) oldpoint)
610 (setq count (1+ count))))))))
611
612 (define-function 'help 'help-for-help)
613 ;; #### FSF calls `make-help-screen' here. We need to port `help-macro.el'.
614 (defun help-for-help ()
615 "You have typed \\[help-for-help], the help character. Type a Help option:
616 \(Use SPC or DEL to scroll through this text. Type \\<help-map>\\[help-quit] to exit the Help command.)
617
618 \\[hyper-apropos] Give a substring, and see a hypertext list of
619 functions and variables that contain that substring.
620 See also the `apropos' command.
621 \\[command-apropos] Give a substring, and see a list of commands
622 (functions interactively callable) that contain that substring.
623 \\[describe-bindings] Display table of all key bindings.
624 \\[describe-key-briefly] Type a command key sequence;
625 it prints the function name that sequence runs.
626 \\[Info-goto-emacs-command-node] Type a function name;
627 it takes you to the Info node for that command.
628 \\[describe-function] Type a function name and get documentation of it.
629 \\[Info-elisp-ref] Type a function name and jump to the full documentation
630 in the XEmacs Lisp Programmer's Manual.
631 \\[xemacs-local-faq] To view a local copy of the XEmacs FAQ.
632 \\[info] The info documentation reader.
633 \\[Info-query] Info reader, prompt for topic name.
634 \\[describe-key] Type a command key sequence;
635 it displays the full documentation.
636 \\[Info-goto-emacs-key-command-node] Type a command key sequence;
637 it takes you to the Info node for the command bound to that key.
638 \\[view-lossage] Shows last 100 characters you typed.
639 \\[describe-mode] Print documentation of current major mode,
640 which describes the commands peculiar to it.
641 \\[view-emacs-news] Shows emacs news file.
642 \\[finder-by-keyword] Find packages matching a given topic keyword.
643 \\[describe-pointer] Display table of all mouse-button bindings.
644 \\[describe-syntax] Display contents of syntax table, plus explanations
645 \\[help-with-tutorial] Select the XEmacs learn-by-doing tutorial.
646 \\[describe-variable] Type name of a variable;
647 it displays the variable's documentation and value.
648 \\[where-is] Type command name;
649 it prints which keystrokes invoke that command.
650 \\[describe-distribution] XEmacs ordering information.
651 \\[describe-copying] print XEmacs copying permission (General Public License).
652 \\[view-emacs-news] print print news of recent XEmacs changes.
653 \\[describe-no-warranty] print information on absence of warranty for XEmacs."
654 (interactive)
655 (let ((help-key (copy-event last-command-event))
656 event char)
657 (message (gettext "A B C F I K L M N P S T V W C-c C-d C-n C-w. Type %s again for more help: ")
658 ;; arrgh, no room for "C-i C-k C-f" !!
659 (single-key-description help-key))
660 (setq event (next-command-event)
661 char (event-to-character event))
662 (if (or (equal event help-key)
663 (eq char ??)
664 (eq 'help-command (key-binding event)))
665 (save-window-excursion
666 (switch-to-buffer "*Help*")
667 ;; #### I18N3 should mark buffer as output-translating
668 (delete-other-windows)
669 (let ((buffer-read-only nil))
670 (erase-buffer)
671 (insert (documentation 'help-for-help)))
672 (goto-char (point-min))
673 (while (or (equal event help-key)
674 (eq char ??)
675 (eq 'help-command (key-binding event))
676 (eq char ? )
677 (eq 'scroll-up (key-binding event))
678 (eq char ?\177)
679 (eq 'scroll-down (key-binding event)))
680 (if (or (eq char ? )
681 (eq 'scroll-up (key-binding event)))
682 (scroll-up))
683 (if (or (eq char ?\177)
684 (eq 'scroll-down (key-binding event)))
685 (scroll-down))
686 ;; write this way for I18N3 snarfing
687 (if (pos-visible-in-window-p (point-max))
688 (message "A B C F I K L M N P S T V W C-c C-d C-n C-w C-i C-k C-f: ")
689 (message "A B C F I K L M N P S T V W C-c C-d C-n C-w C-i C-k C-f or Space to scroll: "))
690 (let ((cursor-in-echo-area t))
691 (setq event (next-command-event event)
692 char (or (event-to-character event) event))))))
693 (let ((defn (or (lookup-key help-map (vector event))
694 (and (numberp char)
695 (lookup-key help-map (make-string 1 (downcase char)))))))
696 (message nil)
697 (if defn
698 (call-interactively defn)
699 (ding)))))
700
701 ;; Return a function which is called by the list containing point.
702 ;; If that gives no function, return a function whose name is around point.
703 ;; If that doesn't give a function, return nil.
704 (defun function-called-at-point ()
705 (or (condition-case ()
706 (save-excursion
707 (save-restriction
708 (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
709 (backward-up-list 1)
710 (forward-char 1)
711 (let (obj)
712 (setq obj (read (current-buffer)))
713 (and (symbolp obj) (fboundp obj) obj))))
714 (error nil))
715 (condition-case ()
716 (let ((stab (syntax-table)))
717 (unwind-protect
718 (save-excursion
719 (set-syntax-table emacs-lisp-mode-syntax-table)
720 (or (not (zerop (skip-syntax-backward "_w")))
721 (eq (char-syntax (following-char)) ?w)
722 (eq (char-syntax (following-char)) ?_)
723 (forward-sexp -1))
724 (skip-chars-forward "`'")
725 (let ((obj (read (current-buffer))))
726 (and (symbolp obj) (fboundp obj) obj)))
727 (set-syntax-table stab)))
728 (error nil))))
729
730 (defvar describe-function-show-arglist t ; default to nil for the non-hackers?
731 "*If true, then describe-function will show its arglist if the function is
732 not an autoload.")
733
734 (defun describe-function-find-file (function)
735 (and (boundp 'load-history) ; not standardly bound in XEmacs
736 (let ((files load-history)
737 file)
738 (while files
739 (if (memq function (cdr (car files)))
740 (setq file (car (car files)) files nil))
741 (setq files (cdr files)))
742 file)))
743
744 (defun describe-function (function)
745 "Display the full documentation of FUNCTION (a symbol)."
746 (interactive
747 (let* ((fn (function-called-at-point))
748 (val (let ((enable-recursive-minibuffers t))
749 (completing-read
750 (if fn
751 (format (gettext "Describe function (default %s): ")
752 fn)
753 (gettext "Describe function: "))
754 obarray 'fboundp t))))
755 (list (if (equal val "") fn (intern val)))))
756 (with-displaying-help-buffer
757 (lambda ()
758 (describe-function-1 function standard-output)
759 (save-excursion
760 (set-buffer standard-output)
761 ;; Return the text we displayed.
762 (buffer-string)))))
763
764 (defun function-obsolete-p (function)
765 "Return non-nil if FUNCTION is obsolete."
766 (not (null (get function 'byte-obsolete-info))))
767
768 (defun function-obsoleteness-doc (function)
769 "If FUNCTION is obsolete, return a string describing this."
770 (let ((obsolete (get function 'byte-obsolete-info)))
771 (if obsolete
772 (format "Obsolete; %s"
773 (if (stringp (car obsolete))
774 (car obsolete)
775 (format "use `%s' instead." (car obsolete)))))))
776
777 ;Here are all the possibilities below spelled out, for the benefit
778 ;of the I18N3 snarfer.
779 ;
780 ;(gettext "a built-in function")
781 ;(gettext "an interactive built-in function")
782 ;(gettext "a built-in macro")
783 ;(gettext "an interactive built-in macro")
784 ;(gettext "a compiled Lisp function")
785 ;(gettext "an interactive compiled Lisp function")
786 ;(gettext "a compiled Lisp macro")
787 ;(gettext "an interactive compiled Lisp macro")
788 ;(gettext "a Lisp function")
789 ;(gettext "an interactive Lisp function")
790 ;(gettext "a Lisp macro")
791 ;(gettext "an interactive Lisp macro")
792 ;(gettext "a mocklisp function")
793 ;(gettext "an interactive mocklisp function")
794 ;(gettext "a mocklisp macro")
795 ;(gettext "an interactive mocklisp macro")
796 ;(gettext "an autoloaded Lisp function")
797 ;(gettext "an interactive autoloaded Lisp function")
798 ;(gettext "an autoloaded Lisp macro")
799 ;(gettext "an interactive autoloaded Lisp macro")
800
801 (defun describe-function-1 (function stream &optional nodoc)
802 (prin1 function stream)
803 (princ ": " stream)
804 (let* ((def function)
805 file-name
806 (doc (or (documentation function)
807 (gettext "not documented")))
808 aliases kbd-macro-p fndef macrop)
809 (while (symbolp def)
810 (or (eq def function)
811 (if aliases
812 ;; I18N3 Need gettext due to concat
813 (setq aliases (concat aliases
814 (format "\n which is an alias for %s, "
815 (symbol-name def))))
816 (setq aliases (format "an alias for %s, " (symbol-name def)))))
817 (setq def (symbol-function def)))
818 (if (eq 'macro (car-safe def))
819 (setq fndef (cdr def)
820 macrop t)
821 (setq fndef def))
822 (if describe-function-show-arglist
823 (if (cond ((eq 'autoload (car-safe fndef))
824 nil)
825 ((eq 'lambda (car-safe fndef))
826 (princ (or (nth 1 fndef) "()") stream)
827 t)
828 ((compiled-function-p fndef)
829 (princ (or (compiled-function-arglist fndef) "()") stream)
830 t)
831 ((and (subrp fndef)
832 (string-match "[\n\t ]*\narguments: ?\\((.*)\\)\n?\\'"
833 doc))
834 (princ (substring doc (match-beginning 1) (match-end 1))
835 stream)
836 (setq doc (substring doc 0 (match-beginning 0)))
837 t)
838 (t
839 nil))
840 (princ "\n -- " stream)))
841 (if aliases (princ aliases stream))
842 (let ((int #'(lambda (string an-p macro-p)
843 (princ (format
844 (gettext (concat
845 (cond ((commandp def)
846 "an interactive ")
847 (an-p "an ")
848 (t "a "))
849 "%s"
850 (if macro-p " macro" " function")))
851 string)
852 stream))))
853 (cond ((or (stringp def) (vectorp def))
854 (princ "a keyboard macro." stream)
855 (setq kbd-macro-p t))
856 ((subrp fndef)
857 (funcall int "built-in" nil macrop))
858 ((compiled-function-p fndef)
859 (funcall int "compiled Lisp" nil macrop))
860 ; XEmacs -- we handle aliases above.
861 ; ((symbolp fndef)
862 ; (princ (format "alias for `%s'"
863 ; (prin1-to-string def)) stream))
864 ((eq (car-safe fndef) 'lambda)
865 (funcall int "Lisp" nil macrop))
866 ((eq (car-safe fndef) 'mocklisp)
867 (funcall int "mocklisp" nil macrop))
868 ((eq (car-safe def) 'autoload)
869 (setq file-name (elt def 1))
870 (funcall int "autoloaded Lisp" t (elt def 4)))
871 (t
872 nil)))
873 (or file-name
874 (setq file-name (describe-function-find-file function)))
875 (if file-name
876 (princ (format ".\n -- loads from \"%s\"" file-name) stream))
877 (princ ".")
878 (terpri)
879 (cond (kbd-macro-p
880 (princ "These characters are executed:\n\n\t" stream)
881 (princ (key-description def) stream)
882 (cond ((setq def (key-binding def))
883 (princ (format "\n\nwhich executes the command %s.\n\n" def) stream)
884 (describe-function-1 def stream))))
885 (nodoc nil)
886 (t
887 ;; tell the user about obsoleteness.
888 ;; If the function is obsolete and is aliased, don't
889 ;; even bother to report the documentation, as a further
890 ;; encouragement to use the new function.
891 (let ((obsolete (function-obsoleteness-doc function)))
892 (if obsolete
893 (progn
894 (princ obsolete stream)
895 (terpri stream)
896 (terpri stream)))
897 (if (not (and obsolete aliases))
898 (progn
899 (princ doc stream)
900 (or (eq ?\n (aref doc (1- (length doc))))
901 (terpri)))))))))
902
903
904 (defun describe-function-arglist (function)
905 (interactive (list (or (function-called-at-point)
906 (error "no function call at point"))))
907 (let ((b nil))
908 (unwind-protect
909 (save-excursion
910 (set-buffer (setq b (get-buffer-create " *arglist*")))
911 (buffer-disable-undo b)
912 (erase-buffer)
913 (describe-function-1 function b t)
914 (goto-char (point-min))
915 (end-of-line)
916 (or (eobp) (delete-char 1))
917 (just-one-space)
918 (end-of-line)
919 (message (buffer-substring (point-min) (point))))
920 (and b (kill-buffer b)))))
921
922
923 (defun variable-at-point ()
924 (condition-case ()
925 (let ((stab (syntax-table)))
926 (unwind-protect
927 (save-excursion
928 (set-syntax-table emacs-lisp-mode-syntax-table)
929 (or (not (zerop (skip-syntax-backward "_w")))
930 (eq (char-syntax (following-char)) ?w)
931 (eq (char-syntax (following-char)) ?_)
932 (forward-sexp -1))
933 (skip-chars-forward "'")
934 (let ((obj (read (current-buffer))))
935 (and (symbolp obj) (boundp obj) obj)))
936 (set-syntax-table stab)))
937 (error nil)))
938
939 (defun variable-obsolete-p (variable)
940 "Return non-nil if VARIABLE is obsolete."
941 (not (null (get variable 'byte-obsolete-variable))))
942
943 (defun variable-obsoleteness-doc (variable)
944 "If VARIABLE is obsolete, return a string describing this."
945 (let ((obsolete (get variable 'byte-obsolete-variable)))
946 (if obsolete
947 (format "Obsolete; %s"
948 (if (stringp obsolete)
949 obsolete
950 (format "use `%s' instead." obsolete))))))
951
952 (defun built-in-variable-doc (variable)
953 "Return a string describing whether VARIABLE is built-in."
954 (let ((type (built-in-variable-type variable)))
955 (cond ((eq type 'integer) "a built-in integer variable")
956 ((eq type 'const-integer) "a built-in constant integer variable")
957 ((eq type 'boolean) "a built-in boolean variable")
958 ((eq type 'const-boolean) "a built-in constant boolean variable")
959 ((eq type 'object) "a simple built-in variable")
960 ((eq type 'const-object) "a simple built-in constant variable")
961 ((eq type 'const-specifier) "a built-in constant specifier variable")
962 ((eq type 'current-buffer) "a built-in buffer-local variable")
963 ((eq type 'const-current-buffer)
964 "a built-in constant buffer-local variable")
965 ((eq type 'default-buffer)
966 "a built-in default buffer-local variable")
967 ((eq type 'selected-console) "a built-in console-local variable")
968 ((eq type 'const-selected-console)
969 "a built-in constant console-local variable")
970 ((eq type 'default-console)
971 "a built-in default console-local variable")
972 (type "an unknown type of built-in variable?")
973 (t "a variable declared in Lisp"))))
974
975 (defun describe-variable (variable)
976 "Display the full documentation of VARIABLE (a symbol)."
977 (interactive
978 (let* ((v (variable-at-point))
979 (val (let ((enable-recursive-minibuffers t))
980 (completing-read
981 (if v
982 (format "Describe variable (default %s): " v)
983 (gettext "Describe variable: "))
984 obarray 'boundp t))))
985 (list (if (equal val "") v (intern val)))))
986 (with-displaying-help-buffer
987 (lambda ()
988 (let ((origvar variable)
989 aliases)
990 (let ((print-escape-newlines t))
991 (while (variable-alias variable)
992 (let ((newvar (variable-alias variable)))
993 (if aliases
994 ;; I18N3 Need gettext due to concat
995 (setq aliases
996 (concat aliases
997 (format ",\n which is an alias for %s"
998 (symbol-name newvar))))
999 (setq aliases
1000 (format "%s is an alias for %s"
1001 (symbol-name variable)
1002 (symbol-name newvar))))
1003 (setq variable newvar)))
1004 (if aliases
1005 (princ (format "%s.\n" aliases)))
1006 (if (not (boundp variable))
1007 (princ (format "%s is void" variable))
1008 (princ (format "%s's value is " variable))
1009 (prin1 (symbol-value variable)))
1010 (terpri)
1011 (princ " -- ")
1012 (princ (built-in-variable-doc variable))
1013 (princ ".")
1014 (terpri)
1015 (cond ((local-variable-p variable (current-buffer))
1016 (let* ((void (cons nil nil))
1017 (def (condition-case nil
1018 (default-value variable)
1019 (error void))))
1020 (princ "This value is specific to the current buffer.")
1021 (terpri)
1022 (if (local-variable-p variable nil)
1023 (progn
1024 (princ "(Its value is local to each buffer.)")
1025 (terpri)))
1026 (if (if (eq def void)
1027 (boundp variable)
1028 (not (eq (symbol-value variable) def)))
1029 ;; #### I18N3 doesn't localize properly!
1030 (progn (princ "Its default-value is ")
1031 (if (eq def void)
1032 (princ "void.")
1033 (prin1 def))
1034 (terpri)))))
1035 ((local-variable-p variable (current-buffer) t)
1036 (princ "Setting it would make its value buffer-local.\n")
1037 (terpri))))
1038 (terpri)
1039 (princ "Documentation:")
1040 (terpri)
1041 (let ((doc (documentation-property variable 'variable-documentation))
1042 (obsolete (variable-obsoleteness-doc origvar)))
1043 (if obsolete
1044 (progn
1045 (princ obsolete)
1046 (terpri)
1047 (terpri)))
1048 ;; don't bother to print anything if variable is obsolete and aliased.
1049 (if (or (not obsolete) (not aliases))
1050 (if doc
1051 ;; note: documentation-property calls substitute-command-keys.
1052 (princ doc)
1053 (princ "not documented as a variable."))))
1054 (save-excursion
1055 (set-buffer standard-output)
1056 ;; Return the text we displayed.
1057 (buffer-string))))))
1058
1059 (defun where-is (definition)
1060 "Print message listing key sequences that invoke specified command.
1061 Argument is a command definition, usually a symbol with a function definition."
1062 (interactive
1063 (let ((fn (function-called-at-point))
1064 (enable-recursive-minibuffers t)
1065 val)
1066 ;; #### should use `read-command'
1067 (setq val (completing-read (if fn
1068 (format "Where is command (default %s): " fn)
1069 "Where is command: ")
1070 obarray 'commandp t nil
1071 'read-command-history))
1072 (list (if (equal val "")
1073 fn (intern val)))))
1074 (let ((keys (where-is-internal definition)))
1075 (if keys
1076 (message "%s is on %s" definition
1077 (mapconcat 'key-description
1078 (sort keys #'(lambda (x y)
1079 (< (length x) (length y))))
1080 ", "))
1081 (message "%s is not on any keys" definition)))
1082 nil)
1083
1084 (defun locate-library (library &optional nosuffix)
1085 "Show the full path name of XEmacs library LIBRARY.
1086 This command searches the directories in `load-path' like `M-x load-library'
1087 to find the file that `M-x load-library RET LIBRARY RET' would load.
1088 Optional second arg NOSUFFIX non-nil means don't add suffixes `.elc' or `.el'
1089 to the specified name LIBRARY (a la calling `load' instead of `load-library')."
1090 (interactive "sLocate library: \nP")
1091 ;; XEmacs: We have the nifty `locate-file' so we use it.
1092 (let ((file (locate-file library load-path (if nosuffix nil ".elc:.el:"))))
1093 (if file
1094 (message "Library is file %s" file)
1095 (message "No library %s in search path" library))
1096 file))
1097
1098 ;; Functions ported from C into Lisp in XEmacs
1099
1100 (defun describe-syntax ()
1101 "Describe the syntax specifications in the syntax table.
1102 The descriptions are inserted in a buffer, which is then displayed."
1103 (interactive)
1104 (with-displaying-help-buffer
1105 (lambda ()
1106 ;; defined in syntax.el
1107 (describe-syntax-table (syntax-table) standard-output))))
1108
1109 (defun list-processes ()
1110 "Display a list of all processes.
1111 \(Any processes listed as Exited or Signaled are actually eliminated
1112 after the listing is made.)"
1113 (interactive)
1114 (with-output-to-temp-buffer "*Process List*"
1115 (set-buffer standard-output)
1116 (buffer-disable-undo standard-output)
1117 (make-local-variable 'truncate-lines)
1118 (setq truncate-lines t)
1119 (let ((stream standard-output))
1120 ;; 00000000001111111111222222222233333333334444444444
1121 ;; 01234567890123456789012345678901234567890123456789
1122 ;; rewritten for I18N3. This one should stay rewritten
1123 ;; so that the dashes will line up properly.
1124 (princ "Proc Status Buffer Tty Command\n---- ------ ------ --- -------\n" stream)
1125 (let ((tail (process-list)))
1126 (while tail
1127 (let* ((p (car tail))
1128 (pid (process-id p))
1129 (s (process-status p)))
1130 (setq tail (cdr tail))
1131 (princ (format "%-13s" (process-name p)) stream)
1132 ;(if (and (eq system-type 'vax-vms)
1133 ; (eq s 'signal)
1134 ; (< (process-exit-status p) NSIG))
1135 ; (princ (aref sys_errlist (process-exit-status p)) stream))
1136 (princ s stream)
1137 (if (and (eq s 'exit) (/= (process-exit-status p) 0))
1138 (princ (format " %d" (process-exit-status p)) stream))
1139 (if (memq s '(signal exit closed))
1140 ;; Do delete-exited-processes' work
1141 (delete-process p))
1142 (indent-to 22 1) ;####
1143 (let ((b (process-buffer p)))
1144 (cond ((not b)
1145 (princ "(none)" stream))
1146 ((not (buffer-name b))
1147 (princ "(killed)" stream))
1148 (t
1149 (princ (buffer-name b) stream))))
1150 (indent-to 37 1) ;####
1151 (let ((tn (process-tty-name p)))
1152 (cond ((not tn)
1153 (princ "(none)" stream))
1154 (t
1155 (princ (format "%s" tn) stream))))
1156 (indent-to 49 1) ;####
1157 (if (not (integerp pid))
1158 (progn
1159 (princ "network stream connection " stream)
1160 (princ (car pid) stream)
1161 (princ "@" stream)
1162 (princ (cdr pid) stream))
1163 (let ((cmd (process-command p)))
1164 (while cmd
1165 (princ (car cmd) stream)
1166 (setq cmd (cdr cmd))
1167 (if cmd (princ " " stream)))))
1168 (terpri stream)))))))