comparison lisp/help.el @ 209:41ff10fd062f r20-4b3

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