]> code.delx.au - gnu-emacs/blobdiff - lisp/help.el
(describe-variable): Don't insert a second `'s' in front
[gnu-emacs] / lisp / help.el
index d0ca865a9dedca2f55169ff493071ec840d472e0..c3dfc518aaf26c1d1d56076ac978b3e09a6f2c6b 100644 (file)
 (defvar help-xref-stack nil
   "A stack of ways by which to return to help buffers after following xrefs.
 Used by `help-follow' and `help-xref-go-back'.
-An element looks like (POSITION FUNCTION ARGS...).
-To use the element, do (apply FUNCTION ARGS) then (goto-char POSITION).")
+An element looks like (POSITION FUNCTION ARGS...), where POSITION is
+`(POINT . BUFFER-NAME)'.
+To use the element, do (apply FUNCTION ARGS) then goto the point in
+the named buffer.")
 (put 'help-xref-stack 'permanent-local t)
 
 (defvar help-xref-stack-item nil
@@ -287,9 +289,8 @@ If FUNCTION is nil, applies `message' to it, thus printing it."
         (funcall (or function 'message)
                  (concat
                   (if first-message
-                      (substitute-command-keys first-message)
-                    "")
-                  (if first-message "  " "")
+                      (substitute-command-keys first-message))
+                  (if first-message "  ")
                   ;; If the help buffer will go in a separate frame,
                   ;; it's no use mentioning a command to scroll, so don't.
                   (if (special-display-p (buffer-name standard-output))
@@ -441,7 +442,7 @@ With numeric argument display information on correspondingly older changes."
   "Display the Emacs Frequently Asked Questions (FAQ) file."
   (interactive)
 ;;;  (find-file-read-only (expand-file-name "FAQ" data-directory))
-  (info "(emacs-faq)"))
+  (info "(efaq)"))
 
 (defun view-emacs-problems ()
   "Display info on known problems with Emacs and possible workarounds."
@@ -620,7 +621,9 @@ It can also be nil, if the definition is not associated with any file."
                     (vectorp def))
                 "a keyboard macro")
                ((subrp def)
-                (concat beg "built-in function"))
+                (if (eq 'unevalled (cdr (subr-arity def)))
+                    (concat beg "special form")
+                  (concat beg "built-in function")))
                ((byte-code-function-p def)
                 (concat beg "compiled Lisp function"))
                ((symbolp def)
@@ -715,19 +718,35 @@ It can also be nil, if the definition is not associated with any file."
       (if doc
          (progn (terpri)
                 (princ doc)
-                (with-current-buffer standard-output
-                  (beginning-of-line)
-                  ;; Builtins get the calling sequence at the end of
-                  ;; the doc string.  Move it to the same place as
-                  ;; for other functions.
-                  (when (looking-at (format "(%S[ )]" function))
-                    (let ((start (point-marker)))
-                      (goto-char (point-min))
-                      (forward-paragraph)
-                      (insert-buffer-substring (current-buffer) start)
-                      (insert ?\n)
-                      (delete-region (1- start) (point-max))
-                      (goto-char (point-max)))))
+                (if (subrp (symbol-function function))
+                    (with-current-buffer standard-output
+                      (beginning-of-line)
+                      ;; Builtins get the calling sequence at the end of
+                      ;; the doc string.  Move it to the same place as
+                      ;; for other functions.
+
+                      ;; In cases where `function' has been fset to a
+                      ;; subr we can't search for function's name in
+                      ;; the doc string.  Kluge round that using the
+                      ;; printed representation.  The arg list then
+                      ;; shows the wrong function name, but that
+                      ;; might be a useful hint.
+                      (let* ((rep (prin1-to-string def))
+                             (name (progn
+                                     (string-match " \\([^ ]+\\)>$" rep)
+                                     (match-string 1 rep))))
+                        (if (looking-at (format "(%s[ )]" name))
+                            (let ((start (point-marker)))
+                              (goto-char (point-min))
+                              (forward-paragraph)
+                              (insert-buffer-substring (current-buffer) start)
+                              (insert ?\n)
+                              (delete-region (1- start) (point-max)))
+                          (goto-char (point-min))
+                          (forward-paragraph)
+                          (insert
+                           "[Missing arglist.  Please make a bug report.]\n")))
+                      (goto-char (point-max))))
                 (help-setup-xref (list #'describe-function function)
                                  interactive-p))
        (princ "not documented")))))
@@ -751,6 +770,34 @@ Return 0 if there is no such symbol."
          (set-syntax-table stab)))
     (error 0)))
 
+(defun help-xref-on-pp (from to)
+  "Add xrefs for symbols in `pp's output between FROM and TO."
+  (let ((ost (syntax-table)))
+    (unwind-protect
+       (save-excursion
+         (save-restriction
+           (set-syntax-table emacs-lisp-mode-syntax-table)
+           (narrow-to-region from to)
+           (goto-char (point-min))
+           (while (not (eobp))
+             (cond
+              ((looking-at "\"") (forward-sexp 1))
+              ((looking-at "#<") (search-forward ">" nil 'move))
+              ((looking-at "\\(\\(\\sw\\|\\s_\\)+\\)")
+               (let* ((sym (intern-soft
+                            (buffer-substring (match-beginning 1)
+                                              (match-end 1))))
+                      (fn (cond ((fboundp sym) #'describe-function)
+                                ((or (memq sym '(t nil))
+                                     (keywordp sym))
+                                 nil)
+                                ((and sym (boundp sym))
+                                 #'describe-variable))))
+                 (when fn (help-xref-button 1 fn sym)))
+               (goto-char (match-end 1)))
+              (t (forward-char 1))))))
+      (set-syntax-table ost))))
+
 (defun describe-variable (variable)
   "Display the full documentation of VARIABLE (a symbol).
 Returns the documentation as a string, also."
@@ -759,7 +806,8 @@ Returns the documentation as a string, also."
         (enable-recursive-minibuffers t)
         val)
      (setq val (completing-read (if (symbolp v)
-                                   (format "Describe variable (default %s): " v)
+                                   (format
+                                    "Describe variable (default %s): " v)
                                  "Describe variable: ")
                                obarray 'boundp t nil nil
                                (if (symbolp v) (symbol-name v))))
@@ -772,33 +820,43 @@ Returns the documentation as a string, also."
          (if (not (boundp variable))
              (progn
                (princ " is void")
-               (terpri)
                (setq valvoid t))
-           (princ "'s value is ")
-           (terpri)
-           (pp (symbol-value variable))
-           (terpri))
+           (let ((val (symbol-value variable)))
+             (with-current-buffer standard-output
+               (princ "'s value is ")
+               (terpri)
+               (let ((from (point)))
+                 (pp val)
+                 (help-xref-on-pp from (point))))))
+         (terpri)
          (if (local-variable-p variable)
              (progn
                (princ (format "Local in buffer %s; " (buffer-name)))
                (if (not (default-boundp variable))
                    (princ "globally void")
-                 (princ "global value is ")
-                 (terpri)
-                 (pp (default-value variable)))
+                 (let ((val (default-value variable)))
+                   (with-current-buffer standard-output
+                     (princ "global value is ")
+                     (terpri)
+                     (let ((from (point)))
+                       (pp val)
+                       (help-xref-on-pp from (point))))))
                (terpri)))
          (terpri)
          (save-current-buffer
            (set-buffer standard-output)
            (if (> (count-lines (point-min) (point-max)) 10)
                (progn
+                 ;; Note that setting the syntax table like below
+                 ;; makes forward-sexp move over a `'s' at the end
+                 ;; of a symbol.
                  (set-syntax-table emacs-lisp-mode-syntax-table)
                  (goto-char (point-min))
                  (if valvoid
                      (forward-line 1)
                    (forward-sexp 1)
                    (delete-region (point) (progn (end-of-line) (point)))
-                   (insert "'s value is shown below.\n\n")
+                   (insert " value is shown below.\n\n")
                    (save-excursion
                      (insert "\n\nValue:"))))))
          (princ "Documentation:")
@@ -822,11 +880,12 @@ Returns the documentation as a string, also."
                  (save-excursion
                    (re-search-backward 
                     (concat "\\(" customize-label "\\)") nil t)
-                   (help-xref-button 1 #'(lambda (v)
-                                           (customize-variable v))
+                   (help-xref-button 1 (lambda (v)
+                                         (if help-xref-stack
+                                             (pop help-xref-stack))
+                                         (customize-variable v))
                                      variable
-                                     "mouse-2, RET: customize variable")
-                   ))))
+                                     "mouse-2, RET: customize variable")))))
          ;; Make a hyperlink to the library if appropriate.  (Don't
          ;; change the format of the buffer's initial line in case
          ;; anything expects the current format.)
@@ -914,9 +973,9 @@ and the file name is displayed in the echo area."
                     t))
   (let (result)
     (catch 'answer
-      (mapcar
+      (mapc
        (lambda (dir)
-        (mapcar
+        (mapc
          (lambda (suf)
            (let ((try (expand-file-name (concat library suf) dir)))
              (and (file-readable-p try)
@@ -978,6 +1037,7 @@ Must be previously-defined."
 (defconst help-xref-symbol-regexp
   (purecopy (concat "\\(\\<\\(\\(variable\\|option\\)\\|"
                    "\\(function\\|command\\)\\|"
+                   "\\(face\\)\\|"
                    "\\(symbol\\)\\)\\s-+\\)?"
                    ;; Note starting with word-syntax character:
                    "`\\(\\sw\\(\\sw\\|\\s_\\)+\\)'"))
@@ -1001,6 +1061,9 @@ items for help buffer \"back\" buttons is cleared."
       (setq help-xref-stack nil))
   (setq help-xref-stack-item item))
 
+(defvar help-xref-following nil
+  "Non-nil when following a help cross-reference.")
+
 (defun help-make-xrefs (&optional buffer)
   "Parse and hyperlink documentation cross-references in the given BUFFER.
 
@@ -1041,7 +1104,7 @@ that."
               ;; Quoted symbols
               (save-excursion
                 (while (re-search-forward help-xref-symbol-regexp nil t)
-                  (let* ((data (match-string 6))
+                  (let* ((data (match-string 7))
                          (sym (intern-soft data)))
                     (if sym
                         (cond
@@ -1049,28 +1112,35 @@ that."
                           (and (boundp sym) ; `variable' doesn't ensure
                                         ; it's actually bound
                                (help-xref-button
-                               6 #'describe-variable sym
+                               7 #'describe-variable sym
                                "mouse-2, RET: describe this variable")))
                          ((match-string 4) ; `function' &c
                           (and (fboundp sym) ; similarly
                                (help-xref-button
-                               6 #'describe-function sym
+                               7 #'describe-function sym
                                "mouse-2, RET: describe this function")))
-                         ((match-string 5)) ; nothing for symbol
+                        ((match-string 5) ; `face'
+                         (and (facep sym)
+                              (help-xref-button 7 #'describe-face sym
+                               "mouse-2, RET: describe this face")))
+                         ((match-string 6)) ; nothing for symbol
                          ((and (boundp sym) (fboundp sym))
                           ;; We can't intuit whether to use the
                           ;; variable or function doc -- supply both.
                           (help-xref-button
-                          6 #'help-xref-interned sym
+                          7 #'help-xref-interned sym
                           "mouse-2, RET: describe this symbol"))
                          ((boundp sym)
                          (help-xref-button
-                          6 #'describe-variable sym
+                          7 #'describe-variable sym
                           "mouse-2, RET: describe this variable"))
                         ((fboundp sym)
                          (help-xref-button
-                          6 #'describe-function sym
-                          "mouse-2, RET: describe this function")))))))
+                          7 #'describe-function sym
+                          "mouse-2, RET: describe this function"))
+                        ((facep sym)
+                         (help-xref-button
+                          7 #'describe-face sym)))))))
               ;; An obvious case of a key substitution:
               (save-excursion              
                 (while (re-search-forward
@@ -1109,7 +1179,7 @@ that."
                               (zerop (forward-line)))))))))
           (set-syntax-table stab))
         ;; Make a back-reference in this buffer if appropriate.
-        (when help-xref-stack
+        (when (and help-xref-following help-xref-stack)
           (goto-char (point-max))
           (save-excursion
             (insert "\n\n" help-back-label))
@@ -1158,16 +1228,23 @@ If optional arg HELP-ECHO is supplied, it is used as a help string."
 
 Both variable and function documentation are extracted into a single
 help buffer."
-  (let ((fdoc (when (fboundp symbol) (describe-function symbol))))
+  (let ((fdoc (when (fboundp symbol) (describe-function symbol)))
+       (facedoc (when (facep symbol) (describe-face symbol))))
     (when (or (boundp symbol) (not fdoc))
       (describe-variable symbol)
       ;; We now have a help buffer on the variable.  Insert the function
       ;; text before it.
-      (when fdoc
+      (when (or fdoc facedoc)
        (with-current-buffer "*Help*"
          (goto-char (point-min))
          (let ((inhibit-read-only t))
-           (insert fdoc "\n\n" (symbol-name symbol) " is also a variable.\n\n"))
+           (when fdoc
+             (insert fdoc "\n\n"))
+           (when facedoc
+             (insert (make-string 30 ?-) "\n\n" (symbol-name symbol)
+                     " is also a " "face." "\n\n" facedoc "\n\n"))
+           (insert (make-string 30 ?-) "\n\n" (symbol-name symbol)
+                   " is also a " "variable." "\n\n"))
          (help-setup-xref (list #'help-xref-interned symbol) nil))))))
 
 (defun help-xref-mode (buffer)
@@ -1193,16 +1270,16 @@ help buffer."
     (with-current-buffer buffer
       (when help-xref-stack
        (setq help-xref-stack (cdr help-xref-stack)) ; due to help-follow
-       (setq item (car help-xref-stack)
+       (setq item (pop help-xref-stack)
              position (car item)
              method (cadr item)
-             args (cddr item))
-       (setq help-xref-stack (cdr help-xref-stack))))
+             args (cddr item))))
     (apply method args)
-    ;; We're not in the right buffer to do this, and we don't actually
-    ;; know which we should be in.
-    ;;(goto-char position)
-    ))
+    ;; We assume that the buffer we just recreated has the saved name,
+    ;; which might not always be true.
+    (when (get-buffer (cdr position))
+      (with-current-buffer (cdr position)
+       (goto-char (car position))))))
 
 (defun help-go-back ()
   "Invoke the [back] button (if any) in the Help mode buffer."
@@ -1234,11 +1311,13 @@ For the cross-reference format, see `help-make-xrefs'."
          (method (car help-data))
          (args (cdr help-data)))
     (when help-data
-      (setq help-xref-stack (cons (cons (point) help-xref-stack-item)
+      (setq help-xref-stack (cons (cons (cons pos (buffer-name))
+                                       help-xref-stack-item)
                                  help-xref-stack))
       (setq help-xref-stack-item nil)
       ;; There is a reference at point.  Follow it.
-      (apply method args))))
+      (let ((help-xref-following t))
+       (apply method args)))))
 
 ;; For tabbing through buffer.
 (defun help-next-ref ()
@@ -1338,7 +1417,7 @@ out of view."
                          temp-buffer-max-height))
            (win-height (1- (window-height)))
            (min-height (1- window-min-height))
-           (text-height (window-buffer-height(selected-window)))
+           (text-height (count-screen-lines))
            (new-height (max (min text-height max-height) min-height)))
       (enlarge-window (- new-height win-height)))))
 
@@ -1354,6 +1433,8 @@ out of view."
      (make-byte-code . "(make-byte-code &rest ELEMENTS)")
      (call-process
       . "(call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)")
+     (call-process-region
+      . "(call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS)")
      (string . "(string &rest CHARACTERS)")
      (+ . "(+ &rest NUMBERS-OR-MARKERS)")
      (- . "(- &optional NUMBER-OR-MARKER &rest MORE-NUMBERS-OR-MARKERS)")
@@ -1375,6 +1456,11 @@ out of view."
      (format . "(format STRING &rest OBJECTS)")
      (apply . "(apply FUNCTION &rest ARGUMENTS)")
      (run-hooks . "(run-hooks &rest HOOKS)")
+     (run-hook-with-args . "(run-hook-with-args HOOK &rest ARGS)")
+     (run-hook-with-args-until-failure
+      . "(run-hook-with-args-until-failure HOOK &rest ARGS)")
+     (run-hook-with-args-until-success
+      . "(run-hook-with-args-until-success HOOK &rest ARGS)")
      (funcall . "(funcall FUNCTION &rest ARGUMENTS)")
      (append . "(append &rest SEQUENCES)")
      (concat . "(concat &rest SEQUENCES)")
@@ -1408,7 +1494,11 @@ out of view."
      (catch . "(catch TAG BODY...)")
      (unwind-protect . "(unwind-protect BODYFORM UNWINDFORMS...)")
      (condition-case . "(condition-case VAR BODYFORM HANDLERS...)")
-     (track-mouse . "(track-mouse BOFY ...)")
-     (ml-if . "(ml-if COND THEN ELSE...)"))))
+     (track-mouse . "(track-mouse BODY ...)")
+     (ml-if . "(ml-if COND THEN ELSE...)")
+     (ml-provide-prefix-argument . "(ml-provide-prefix-argument ARG1 ARG2)")
+     (with-output-to-temp-buffer
+        . "(with-output-to-temp-buffer BUFFNAME BODY ...)")
+     (save-window-excursion . "(save-window-excursion BODY ...)"))))
 
 ;;; help.el ends here