comparison lisp/help-funs.el @ 39726:19d78cd38271

New file, contents mostly from `help.el'. (describe-variable): Use `condition-case' instead of `ignore-errors'.
author Miles Bader <miles@gnu.org>
date Tue, 09 Oct 2001 11:15:19 +0000
parents
children 67f0a4191315
comparison
equal deleted inserted replaced
39725:c64d3e3adf5d 39726:19d78cd38271
1 ;;; help-funs.el --- Complex help functions
2
3 ;; Copyright (C) 1985, 1986, 1993, 1994, 1998, 1999, 2000, 2001
4 ;; Free Software Foundation, Inc.
5
6 ;; Maintainer: FSF
7 ;; Keywords: help, internal
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26 ;;; Commentary:
27
28 ;; This file contains those help commands which are complicated, and
29 ;; which may not be used in every session. For example
30 ;; `describe-function' will probably be heavily used when doing elisp
31 ;; programming, but not if just editing C files. Simpler help commands
32 ;; are in help.el
33
34 ;;; Code:
35
36 ;;;###autoload
37 (defun help-with-tutorial (&optional arg)
38 "Select the Emacs learn-by-doing tutorial.
39 If there is a tutorial version written in the language
40 of the selected language environment, that version is used.
41 If there's no tutorial in that language, `TUTORIAL' is selected.
42 With arg, you are asked to choose which language."
43 (interactive "P")
44 (let ((lang (if arg
45 (read-language-name 'tutorial "Language: " "English")
46 (if (get-language-info current-language-environment 'tutorial)
47 current-language-environment
48 "English")))
49 file filename)
50 (setq filename (get-language-info lang 'tutorial))
51 (setq file (expand-file-name (concat "~/" filename)))
52 (delete-other-windows)
53 (if (get-file-buffer file)
54 (switch-to-buffer (get-file-buffer file))
55 (switch-to-buffer (create-file-buffer file))
56 (setq buffer-file-name file)
57 (setq default-directory (expand-file-name "~/"))
58 (setq buffer-auto-save-file-name nil)
59 (insert-file-contents (expand-file-name filename data-directory))
60 (goto-char (point-min))
61 (search-forward "\n<<")
62 (beginning-of-line)
63 (delete-region (point) (progn (end-of-line) (point)))
64 (let ((n (- (window-height (selected-window))
65 (count-lines (point-min) (point))
66 6)))
67 (if (< n 12)
68 (newline n)
69 ;; Some people get confused by the large gap.
70 (newline (/ n 2))
71 (insert "[Middle of page left blank for didactic purposes. "
72 "Text continues below]")
73 (newline (- n (/ n 2)))))
74 (goto-char (point-min))
75 (set-buffer-modified-p nil))))
76
77 ;;;###autoload
78 (defun locate-library (library &optional nosuffix path interactive-call)
79 "Show the precise file name of Emacs library LIBRARY.
80 This command searches the directories in `load-path' like `M-x load-library'
81 to find the file that `M-x load-library RET LIBRARY RET' would load.
82 Optional second arg NOSUFFIX non-nil means don't add suffixes `.elc' or `.el'
83 to the specified name LIBRARY.
84
85 If the optional third arg PATH is specified, that list of directories
86 is used instead of `load-path'.
87
88 When called from a program, the file name is normaly returned as a
89 string. When run interactively, the argument INTERACTIVE-CALL is t,
90 and the file name is displayed in the echo area."
91 (interactive (list (read-string "Locate library: ")
92 nil nil
93 t))
94 (let (result)
95 (catch 'answer
96 (mapc
97 (lambda (dir)
98 (mapc
99 (lambda (suf)
100 (let ((try (expand-file-name (concat library suf) dir)))
101 (and (file-readable-p try)
102 (null (file-directory-p try))
103 (progn
104 (setq result try)
105 (throw 'answer try)))))
106 (if nosuffix
107 '("")
108 '(".elc" ".el" "")
109 (let ((basic '(".elc" ".el" ""))
110 (compressed '(".Z" ".gz" "")))
111 ;; If autocompression mode is on,
112 ;; consider all combinations of library suffixes
113 ;; and compression suffixes.
114 (if (rassq 'jka-compr-handler file-name-handler-alist)
115 (apply 'nconc
116 (mapcar (lambda (compelt)
117 (mapcar (lambda (baselt)
118 (concat baselt compelt))
119 basic))
120 compressed))
121 basic)))))
122 (or path load-path)))
123 (and interactive-call
124 (if result
125 (message "Library is file %s" result)
126 (message "No library %s in search path" library)))
127 result))
128
129
130 ;; Functions
131
132 ;;;###autoload
133 (defun describe-function (function)
134 "Display the full documentation of FUNCTION (a symbol)."
135 (interactive
136 (let ((fn (function-called-at-point))
137 (enable-recursive-minibuffers t)
138 val)
139 (setq val (completing-read (if fn
140 (format "Describe function (default %s): " fn)
141 "Describe function: ")
142 obarray 'fboundp t nil nil (symbol-name fn)))
143 (list (if (equal val "")
144 fn (intern val)))))
145 (if (null function)
146 (message "You didn't specify a function")
147 (with-output-to-temp-buffer "*Help*"
148 (prin1 function)
149 ;; Use " is " instead of a colon so that
150 ;; it is easier to get out the function name using forward-sexp.
151 (princ " is ")
152 (describe-function-1 function nil (interactive-p))
153 (print-help-return-message)
154 (save-excursion
155 (set-buffer standard-output)
156 ;; Return the text we displayed.
157 (buffer-string)))))
158
159 (defun describe-function-1 (function parens interactive-p)
160 (let* ((def (if (symbolp function)
161 (symbol-function function)
162 function))
163 file-name string need-close
164 (beg (if (commandp def) "an interactive " "a ")))
165 (setq string
166 (cond ((or (stringp def)
167 (vectorp def))
168 "a keyboard macro")
169 ((subrp def)
170 (if (eq 'unevalled (cdr (subr-arity def)))
171 (concat beg "special form")
172 (concat beg "built-in function")))
173 ((byte-code-function-p def)
174 (concat beg "compiled Lisp function"))
175 ((symbolp def)
176 (while (symbolp (symbol-function def))
177 (setq def (symbol-function def)))
178 (format "an alias for `%s'" def))
179 ((eq (car-safe def) 'lambda)
180 (concat beg "Lisp function"))
181 ((eq (car-safe def) 'macro)
182 "a Lisp macro")
183 ((eq (car-safe def) 'mocklisp)
184 "a mocklisp function")
185 ((eq (car-safe def) 'autoload)
186 (setq file-name (nth 1 def))
187 (format "%s autoloaded %s"
188 (if (commandp def) "an interactive" "an")
189 (if (eq (nth 4 def) 'keymap) "keymap"
190 (if (nth 4 def) "Lisp macro" "Lisp function"))
191 ))
192 ;; perhaps use keymapp here instead
193 ((eq (car-safe def) 'keymap)
194 (let ((is-full nil)
195 (elts (cdr-safe def)))
196 (while elts
197 (if (char-table-p (car-safe elts))
198 (setq is-full t
199 elts nil))
200 (setq elts (cdr-safe elts)))
201 (if is-full
202 "a full keymap"
203 "a sparse keymap")))
204 (t "")))
205 (when (and parens (not (equal string "")))
206 (setq need-close t)
207 (princ "("))
208 (princ string)
209 (with-current-buffer "*Help*"
210 (save-excursion
211 (save-match-data
212 (if (re-search-backward "alias for `\\([^`']+\\)'" nil t)
213 (help-xref-button 1 'help-function def)))))
214 (or file-name
215 (setq file-name (symbol-file function)))
216 (if file-name
217 (progn
218 (princ " in `")
219 ;; We used to add .el to the file name,
220 ;; but that's completely wrong when the user used load-file.
221 (princ file-name)
222 (princ "'")
223 ;; Make a hyperlink to the library.
224 (with-current-buffer "*Help*"
225 (save-excursion
226 (re-search-backward "`\\([^`']+\\)'" nil t)
227 (help-xref-button 1 'help-function-def function file-name)))))
228 (if need-close (princ ")"))
229 (princ ".")
230 (terpri)
231 (when (commandp function)
232 (let ((keys (where-is-internal
233 function overriding-local-map nil nil)))
234 (when keys
235 (princ "It is bound to ")
236 ;; FIXME: This list can be very long (f.ex. for self-insert-command).
237 (princ (mapconcat 'key-description keys ", "))
238 (princ ".")
239 (terpri))))
240 ;; Handle symbols aliased to other symbols.
241 (setq def (indirect-function def))
242 ;; If definition is a macro, find the function inside it.
243 (if (eq (car-safe def) 'macro)
244 (setq def (cdr def)))
245 (let ((arglist (cond ((byte-code-function-p def)
246 (car (append def nil)))
247 ((eq (car-safe def) 'lambda)
248 (nth 1 def))
249 ((and (eq (car-safe def) 'autoload)
250 (not (eq (nth 4 def) 'keymap)))
251 (concat "[Arg list not available until "
252 "function definition is loaded.]"))
253 (t t))))
254 (cond ((listp arglist)
255 (princ (cons (if (symbolp function) function "anonymous")
256 (mapcar (lambda (arg)
257 (if (memq arg '(&optional &rest))
258 arg
259 (intern (upcase (symbol-name arg)))))
260 arglist)))
261 (terpri))
262 ((stringp arglist)
263 (princ arglist)
264 (terpri))))
265 (let ((doc (documentation function)))
266 (if doc
267 (progn (terpri)
268 (princ doc)
269 (if (subrp def)
270 (with-current-buffer standard-output
271 (beginning-of-line)
272 ;; Builtins get the calling sequence at the end of
273 ;; the doc string. Move it to the same place as
274 ;; for other functions.
275
276 ;; In cases where `function' has been fset to a
277 ;; subr we can't search for function's name in
278 ;; the doc string. Kluge round that using the
279 ;; printed representation. The arg list then
280 ;; shows the wrong function name, but that
281 ;; might be a useful hint.
282 (let* ((rep (prin1-to-string def))
283 (name (progn
284 (string-match " \\([^ ]+\\)>$" rep)
285 (match-string 1 rep))))
286 (if (looking-at (format "(%s[ )]" (regexp-quote name)))
287 (let ((start (point-marker)))
288 (goto-char (point-min))
289 (forward-paragraph)
290 (insert-buffer-substring (current-buffer) start)
291 (insert ?\n)
292 (delete-region (1- start) (point-max)))
293 (goto-char (point-min))
294 (forward-paragraph)
295 (insert
296 "[Missing arglist. Please make a bug report.]\n")))
297 (goto-char (point-max))))
298 (help-setup-xref (list #'describe-function function)
299 interactive-p))
300 (princ "not documented")))))
301
302
303 ;; Variables
304
305 ;;;###autoload
306 (defun variable-at-point ()
307 "Return the bound variable symbol found around point.
308 Return 0 if there is no such symbol."
309 (condition-case ()
310 (with-syntax-table emacs-lisp-mode-syntax-table
311 (save-excursion
312 (or (not (zerop (skip-syntax-backward "_w")))
313 (eq (char-syntax (following-char)) ?w)
314 (eq (char-syntax (following-char)) ?_)
315 (forward-sexp -1))
316 (skip-chars-forward "'")
317 (let ((obj (read (current-buffer))))
318 (or (and (symbolp obj) (boundp obj) obj)
319 0))))
320 (error 0)))
321
322 ;;;###autoload
323 (defun describe-variable (variable &optional buffer)
324 "Display the full documentation of VARIABLE (a symbol).
325 Returns the documentation as a string, also.
326 If VARIABLE has a buffer-local value in BUFFER (default to the current buffer),
327 it is displayed along with the global value."
328 (interactive
329 (let ((v (variable-at-point))
330 (enable-recursive-minibuffers t)
331 val)
332 (setq val (completing-read (if (symbolp v)
333 (format
334 "Describe variable (default %s): " v)
335 "Describe variable: ")
336 obarray 'boundp t nil nil
337 (if (symbolp v) (symbol-name v))))
338 (list (if (equal val "")
339 v (intern val)))))
340 (unless (bufferp buffer) (setq buffer (current-buffer)))
341 (if (not (symbolp variable))
342 (message "You did not specify a variable")
343 (let (valvoid)
344 (with-current-buffer buffer
345 (with-output-to-temp-buffer "*Help*"
346 (prin1 variable)
347 (if (not (boundp variable))
348 (progn
349 (princ " is void")
350 (setq valvoid t))
351 (let ((val (symbol-value variable)))
352 (with-current-buffer standard-output
353 (princ "'s value is ")
354 (terpri)
355 (let ((from (point)))
356 (pp val)
357 (help-xref-on-pp from (point))
358 (if (< (point) (+ from 20))
359 (save-excursion
360 (goto-char from)
361 (delete-char -1)))))))
362 (terpri)
363 (when (local-variable-p variable)
364 (princ (format "Local in buffer %s; " (buffer-name)))
365 (if (not (default-boundp variable))
366 (princ "globally void")
367 (let ((val (default-value variable)))
368 (with-current-buffer standard-output
369 (princ "global value is ")
370 (terpri)
371 ;; Fixme: pp can take an age if you happen to
372 ;; ask for a very large expression. We should
373 ;; probably print it raw once and check it's a
374 ;; sensible size before prettyprinting. -- fx
375 (let ((from (point)))
376 (pp val)
377 (help-xref-on-pp from (point))
378 (if (< (point) (+ from 20))
379 (save-excursion
380 (goto-char from)
381 (delete-char -1)))))))
382 (terpri))
383 (terpri)
384 (with-current-buffer standard-output
385 (when (> (count-lines (point-min) (point-max)) 10)
386 ;; Note that setting the syntax table like below
387 ;; makes forward-sexp move over a `'s' at the end
388 ;; of a symbol.
389 (set-syntax-table emacs-lisp-mode-syntax-table)
390 (goto-char (point-min))
391 (if valvoid
392 (forward-line 1)
393 (forward-sexp 1)
394 (delete-region (point) (progn (end-of-line) (point)))
395 (insert " value is shown below.\n\n")
396 (save-excursion
397 (insert "\n\nValue:"))))
398 ;; Add a note for variables that have been make-var-buffer-local.
399 (when (and (local-variable-if-set-p variable)
400 (or (not (local-variable-p variable))
401 (with-temp-buffer
402 (local-variable-if-set-p variable))))
403 (save-excursion
404 (forward-line -1)
405 (insert "Automatically becomes buffer-local when set in any fashion.\n"))))
406 (princ "Documentation:")
407 (terpri)
408 (let ((doc (documentation-property variable 'variable-documentation)))
409 (princ (or doc "not documented as a variable.")))
410 (help-setup-xref (list #'describe-variable variable (current-buffer))
411 (interactive-p))
412
413 ;; Make a link to customize if this variable can be customized.
414 ;; Note, it is not reliable to test only for a custom-type property
415 ;; because those are only present after the var's definition
416 ;; has been loaded.
417 (if (or (get variable 'custom-type) ; after defcustom
418 (get variable 'custom-loads) ; from loaddefs.el
419 (get variable 'standard-value)) ; from cus-start.el
420 (let ((customize-label "customize"))
421 (terpri)
422 (terpri)
423 (princ (concat "You can " customize-label " this variable."))
424 (with-current-buffer standard-output
425 (save-excursion
426 (re-search-backward
427 (concat "\\(" customize-label "\\)") nil t)
428 (help-xref-button 1 'help-customize-variable variable)))))
429 ;; Make a hyperlink to the library if appropriate. (Don't
430 ;; change the format of the buffer's initial line in case
431 ;; anything expects the current format.)
432 (let ((file-name (symbol-file variable)))
433 (when (equal file-name "loaddefs.el")
434 ;; Find the real def site of the preloaded variable.
435 (let ((location
436 (condition-case nil
437 (find-variable-noselect variable file-name)
438 (error nil))))
439 (when location
440 (with-current-buffer (car location)
441 (goto-char (cdr location))
442 (when (re-search-backward
443 "^;;; Generated autoloads from \\(.*\\)" nil t)
444 (setq file-name (match-string 1)))))))
445 (when file-name
446 (princ "\n\nDefined in `")
447 (princ file-name)
448 (princ "'.")
449 (with-current-buffer standard-output
450 (save-excursion
451 (re-search-backward "`\\([^`']+\\)'" nil t)
452 (help-xref-button 1 'help-variable-def
453 variable file-name)))))
454
455 (print-help-return-message)
456 (save-excursion
457 (set-buffer standard-output)
458 ;; Return the text we displayed.
459 (buffer-string)))))))
460
461
462 ;; `help-manyarg-func-alist' is defined primitively (in doc.c).
463 ;; New primitives with `MANY' or `UNEVALLED' arglists should be added
464 ;; to this alist.
465 ;; The parens and function name are redundant, but it's messy to add
466 ;; them in `documentation'.
467
468 ;; This will find any missing items:
469 ;; (let (l)
470 ;; (mapatoms (lambda (x)
471 ;; (if (and (fboundp x)
472 ;; (subrp (symbol-function x))
473 ;; (not (numberp (cdr (subr-arity (symbol-function x)))))
474 ;; (not (assq x help-manyarg-func-alist)))
475 ;; (push x l))))
476 ;; l)
477 (defconst help-manyarg-func-alist
478 (purecopy
479 '((list . "(list &rest OBJECTS)")
480 (vector . "(vector &rest OBJECTS)")
481 (make-byte-code . "(make-byte-code &rest ELEMENTS)")
482 (call-process
483 . "(call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)")
484 (call-process-region
485 . "(call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS)")
486 (string . "(string &rest CHARACTERS)")
487 (+ . "(+ &rest NUMBERS-OR-MARKERS)")
488 (- . "(- &optional NUMBER-OR-MARKER &rest MORE-NUMBERS-OR-MARKERS)")
489 (* . "(* &rest NUMBERS-OR-MARKERS)")
490 (/ . "(/ DIVIDEND DIVISOR &rest DIVISORS)")
491 (max . "(max NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS)")
492 (min . "(min NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS)")
493 (logand . "(logand &rest INTS-OR-MARKERS)")
494 (logior . "(logior &rest INTS-OR-MARKERS)")
495 (logxor . "(logxor &rest INTS-OR-MARKERS)")
496 (encode-time
497 . "(encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE)")
498 (insert . "(insert &rest ARGS)")
499 (insert-and-inherit . "(insert-and-inherit &rest ARGS)")
500 (insert-before-markers . "(insert-before-markers &rest ARGS)")
501 (message . "(message STRING &rest ARGUMENTS)")
502 (message-box . "(message-box STRING &rest ARGUMENTS)")
503 (message-or-box . "(message-or-box STRING &rest ARGUMENTS)")
504 (propertize . "(propertize STRING &rest PROPERTIES)")
505 (format . "(format STRING &rest OBJECTS)")
506 (apply . "(apply FUNCTION &rest ARGUMENTS)")
507 (run-hooks . "(run-hooks &rest HOOKS)")
508 (run-hook-with-args . "(run-hook-with-args HOOK &rest ARGS)")
509 (run-hook-with-args-until-failure
510 . "(run-hook-with-args-until-failure HOOK &rest ARGS)")
511 (run-hook-with-args-until-success
512 . "(run-hook-with-args-until-success HOOK &rest ARGS)")
513 (funcall . "(funcall FUNCTION &rest ARGUMENTS)")
514 (append . "(append &rest SEQUENCES)")
515 (concat . "(concat &rest SEQUENCES)")
516 (vconcat . "(vconcat &rest SEQUENCES)")
517 (nconc . "(nconc &rest LISTS)")
518 (widget-apply . "(widget-apply WIDGET PROPERTY &rest ARGS)")
519 (make-hash-table . "(make-hash-table &rest KEYWORD-ARGS)")
520 (insert-string . "(insert-string &rest ARGS)")
521 (start-process . "(start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)")
522 (setq-default . "(setq-default SYMBOL VALUE [SYMBOL VALUE...])")
523 (save-excursion . "(save-excursion &rest BODY)")
524 (save-current-buffer . "(save-current-buffer &rest BODY)")
525 (save-restriction . "(save-restriction &rest BODY)")
526 (or . "(or CONDITIONS ...)")
527 (and . "(and CONDITIONS ...)")
528 (if . "(if COND THEN ELSE...)")
529 (cond . "(cond CLAUSES...)")
530 (progn . "(progn BODY ...)")
531 (prog1 . "(prog1 FIRST BODY...)")
532 (prog2 . "(prog2 X Y BODY...)")
533 (setq . "(setq SYM VAL SYM VAL ...)")
534 (quote . "(quote ARG)")
535 (function . "(function ARG)")
536 (defun . "(defun NAME ARGLIST [DOCSTRING] BODY...)")
537 (defmacro . "(defmacro NAME ARGLIST [DOCSTRING] BODY...)")
538 (defvar . "(defvar SYMBOL [INITVALUE DOCSTRING])")
539 (defconst . "(defconst SYMBOL INITVALUE [DOCSTRING])")
540 (let* . "(let* VARLIST BODY...)")
541 (let . "(let VARLIST BODY...)")
542 (while . "(while TEST BODY...)")
543 (catch . "(catch TAG BODY...)")
544 (unwind-protect . "(unwind-protect BODYFORM UNWINDFORMS...)")
545 (condition-case . "(condition-case VAR BODYFORM HANDLERS...)")
546 (track-mouse . "(track-mouse BODY ...)")
547 (ml-if . "(ml-if COND THEN ELSE...)")
548 (ml-provide-prefix-argument . "(ml-provide-prefix-argument ARG1 ARG2)")
549 (ml-prefix-argument-loop . "(ml-prefix-argument-loop ...)")
550 (with-output-to-temp-buffer
551 . "(with-output-to-temp-buffer BUFFNAME BODY ...)")
552 (save-window-excursion . "(save-window-excursion BODY ...)")
553 (find-operation-coding-system
554 . "(find-operation-coding-system OPERATION ARGUMENTS ...)")
555 (insert-before-markers-and-inherit
556 . "(insert-before-markers-and-inherit &rest ARGS)"))))
557
558
559 (provide 'help-funs)
560
561 ;;; help-funs.el ends here
562
563