]> code.delx.au - gnu-emacs/blobdiff - lisp/help-fns.el
Add advertised calling convention for redirect-frame-focus (Bug#12030).
[gnu-emacs] / lisp / help-fns.el
index 183253878f5649e60b3bbc773a4523fffab3586a..2e56da0bcaa67223ada809e815e580bd36675ae7 100644 (file)
@@ -380,6 +380,42 @@ suitable file is found, return nil."
 
 (declare-function ad-get-advice-info "advice" (function))
 
+(defun help-fns--compiler-macro (function)
+  (let ((handler nil))
+    ;; FIXME: Copied from macroexp.el.
+    (while (and (symbolp function)
+                (not (setq handler (get function 'compiler-macro)))
+                (fboundp function))
+      ;; Follow the sequence of aliases.
+      (setq function (symbol-function function)))
+    (when handler
+      (princ "This function has a compiler macro")
+      (let ((lib (get function 'compiler-macro-file)))
+        ;; FIXME: rather than look at the compiler-macro-file property,
+        ;; just look at `handler' itself.
+        (when (stringp lib)
+          (princ (format " in `%s'" lib))
+          (with-current-buffer standard-output
+            (save-excursion
+              (re-search-backward "`\\([^`']+\\)'" nil t)
+              (help-xref-button 1 'help-function-cmacro function lib)))))
+      (princ ".\n\n"))))
+
+;; We could use `symbol-file' but this is a wee bit more efficient.
+(defun help-fns--autoloaded-p (function file)
+  "Return non-nil if FUNCTION has previously been autoloaded.
+FILE is the file where FUNCTION was probably defined."
+  (let* ((file (file-name-sans-extension (file-truename file)))
+        (load-hist load-history)
+        (target (cons t function))
+        found)
+    (while (and load-hist (not found))
+      (and (caar load-hist)
+          (equal (file-name-sans-extension (caar load-hist)) file)
+          (setq found (member target (cdar load-hist))))
+      (setq load-hist (cdr load-hist)))
+    found))
+
 ;;;###autoload
 (defun describe-function-1 (function)
   (let* ((advised (and (symbolp function) (featurep 'advice)
@@ -395,59 +431,67 @@ suitable file is found, return nil."
         (def (if (symbolp real-function)
                  (symbol-function real-function)
                function))
-        file-name string
-        (beg (if (commandp def) "an interactive " "a "))
+        (aliased (symbolp def))
+        (real-def (if aliased
+                      (let ((f def))
+                        (while (and (fboundp f)
+                                    (symbolp (symbol-function f)))
+                          (setq f (symbol-function f)))
+                        f)
+                    def))
+        (file-name (find-lisp-object-file-name function def))
          (pt1 (with-current-buffer (help-buffer) (point)))
-        errtype)
-    (setq string
-         (cond ((or (stringp def) (vectorp def))
-                "a keyboard macro")
-               ((subrp def)
-                (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)
-                (while (and (fboundp def)
-                            (symbolp (symbol-function def)))
-                  (setq def (symbol-function def)))
-                ;; Handle (defalias 'foo 'bar), where bar is undefined.
-                (or (fboundp def) (setq errtype 'alias))
-                (format "an alias for `%s'" def))
-               ((eq (car-safe def) 'lambda)
-                (concat beg "Lisp function"))
-               ((eq (car-safe def) 'macro)
-                "a Lisp macro")
-               ((eq (car-safe def) 'closure)
-                (concat beg "Lisp closure"))
-               ((eq (car-safe def) 'autoload)
-                (format "%s autoloaded %s"
-                        (if (commandp def) "an interactive" "an")
-                        (if (eq (nth 4 def) 'keymap) "keymap"
-                          (if (nth 4 def) "Lisp macro" "Lisp function"))))
-                ((keymapp def)
-                 (let ((is-full nil)
-                       (elts (cdr-safe def)))
-                   (while elts
-                     (if (char-table-p (car-safe elts))
-                         (setq is-full t
-                               elts nil))
-                     (setq elts (cdr-safe elts)))
-                   (if is-full
-                       "a full keymap"
-                     "a sparse keymap")))
-               (t "")))
-    (princ string)
-    (if (eq errtype 'alias)
+        (beg (if (and (or (byte-code-function-p def)
+                          (keymapp def)
+                          (memq (car-safe def) '(macro lambda closure)))
+                      file-name
+                      (help-fns--autoloaded-p function file-name))
+                 (if (commandp def)
+                     "an interactive autoloaded "
+                   "an autoloaded ")
+               (if (commandp def) "an interactive " "a "))))
+
+    ;; Print what kind of function-like object FUNCTION is.
+    (princ (cond ((or (stringp def) (vectorp def))
+                 "a keyboard macro")
+                ((subrp def)
+                 (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"))
+                (aliased
+                 (format "an alias for `%s'" real-def))
+                ((eq (car-safe def) 'lambda)
+                 (concat beg "Lisp function"))
+                ((eq (car-safe def) 'macro)
+                 (concat beg "Lisp macro"))
+                ((eq (car-safe def) 'closure)
+                 (concat beg "Lisp closure"))
+                ((eq (car-safe def) 'autoload)
+                 (format "%s autoloaded %s"
+                         (if (commandp def) "an interactive" "an")
+                         (if (eq (nth 4 def) 'keymap) "keymap"
+                           (if (nth 4 def) "Lisp macro" "Lisp function"))))
+                ((keymapp def)
+                 (let ((is-full nil)
+                       (elts (cdr-safe def)))
+                   (while elts
+                     (if (char-table-p (car-safe elts))
+                         (setq is-full t
+                               elts nil))
+                     (setq elts (cdr-safe elts)))
+                   (concat beg (if is-full "keymap" "sparse keymap"))))
+                (t "")))
+
+    (if (and aliased (not (fboundp real-def)))
        (princ ",\nwhich is not defined.  Please make a bug report.")
       (with-current-buffer standard-output
        (save-excursion
          (save-match-data
            (when (re-search-backward "alias for `\\([^`']+\\)'" nil t)
-             (help-xref-button 1 'help-function def)))))
+             (help-xref-button 1 'help-function real-def)))))
 
-      (setq file-name (find-lisp-object-file-name function def))
       (when file-name
        (princ " in `")
        ;; We used to add .el to the file name,
@@ -482,12 +526,14 @@ suitable file is found, return nil."
                  (if (member (event-modifiers (aref key 0)) '(nil (shift)))
                      (push key non-modified-keys)))
                (when remapped
-                 (princ "It is remapped to `")
+                 (princ "Its keys are remapped to `")
                  (princ (symbol-name remapped))
-                 (princ "'"))
+                 (princ "'.\n"))
 
                (when keys
-                 (princ (if remapped ", which is bound to " "It is bound to "))
+                 (princ (if remapped
+                            "Without this remapping, it would be bound to "
+                          "It is bound to "))
                  ;; If lots of ordinary text characters run this command,
                  ;; don't mention them one by one.
                  (if (< (length non-modified-keys) 10)
@@ -507,25 +553,22 @@ suitable file is found, return nil."
            (fill-region-as-paragraph pt2 (point))
            (unless (looking-back "\n\n")
              (terpri)))))
-      ;; Note that list* etc do not get this property until
-      ;; cl-hack-byte-compiler runs, after bytecomp is loaded.
-      (when (and (symbolp function)
-                 (eq (get function 'byte-compile)
-                     'cl-byte-compile-compiler-macro))
-       (princ "This function has a compiler macro")
-       (let ((lib (get function 'compiler-macro-file)))
-         (when (stringp lib)
-           (princ (format " in `%s'" lib))
-           (with-current-buffer standard-output
-             (save-excursion
-               (re-search-backward "`\\([^`']+\\)'" nil t)
-               (help-xref-button 1 'help-function-cmacro function lib)))))
-       (princ ".\n\n"))
-      (let* ((advertised (gethash def advertised-signature-table t))
+      (help-fns--compiler-macro function)
+      (let* ((advertised (gethash real-def advertised-signature-table t))
             (arglist (if (listp advertised)
-                         advertised (help-function-arglist def)))
-            (doc (condition-case err (documentation function)
-                    (error (format "No Doc! %S" err))))
+                         advertised (help-function-arglist real-def)))
+            (doc-raw (condition-case err
+                         (documentation function t)
+                       (error (format "No Doc! %S" err))))
+            ;; If the function is autoloaded, and its docstring has
+            ;; key substitution constructs, load the library.
+            (doc (progn
+                   (and (eq (car-safe real-def) 'autoload)
+                        help-enable-auto-load
+                        (string-match "\\([^\\]=\\|[^=]\\|\\`\\)\\\\[[{<]"
+                                      doc-raw)
+                        (load (cadr real-def) t))
+                   (substitute-command-keys doc-raw)))
             (usage (help-split-fundoc doc function)))
        (with-current-buffer standard-output
          ;; If definition is a keymap, skip arglist note.
@@ -546,9 +589,9 @@ suitable file is found, return nil."
                                                          function)))))
                            usage)
                          (car usage))
-                        ((or (stringp def)
-                             (vectorp def))
-                         (format "\nMacro: %s" (format-kbd-macro def)))
+                        ((or (stringp real-def)
+                             (vectorp real-def))
+                         (format "\nMacro: %s" (format-kbd-macro real-def)))
                         (t "[Missing arglist.  Please make a bug report.]")))
                   (high (help-highlight-arguments use doc)))
              (let ((fill-begin (point)))
@@ -707,12 +750,19 @@ it is displayed along with the global value."
              (with-current-buffer standard-output
                (setq val-start-pos (point))
                (princ "value is ")
-               (let ((from (point)))
-                 (terpri)
-                 (pp val)
-                 (if (< (point) (+ 68 (line-beginning-position 0)))
-                     (delete-region from (1+ from))
-                   (delete-region (1- from) from))
+               (let ((from (point))
+                     (line-beg (line-beginning-position))
+                     ;;
+                     (print-rep
+                      (let ((print-quoted t))
+                        (prin1-to-string val))))
+                 (if (< (+ (length print-rep) (point) (- line-beg)) 68)
+                     (insert print-rep)
+                   (terpri)
+                   (pp val)
+                   (if (< (point) (+ 68 (line-beginning-position 0)))
+                       (delete-region from (1+ from))
+                     (delete-region (1- from) from)))
                  (let* ((sv (get variable 'standard-value))
                         (origval (and (consp sv)
                                       (condition-case nil
@@ -789,8 +839,12 @@ it is displayed along with the global value."
                    (obsolete (get variable 'byte-obsolete-variable))
                   (use (car obsolete))
                   (safe-var (get variable 'safe-local-variable))
-                   (doc (or (documentation-property variable 'variable-documentation)
-                            (documentation-property alias 'variable-documentation)))
+                   (doc (condition-case err
+                            (or (documentation-property
+                                 variable 'variable-documentation)
+                                (documentation-property
+                                 alias 'variable-documentation))
+                          (error (format "Doc not found: %S" err))))
                    (extra-line nil))
               ;; Add a note for variables that have been make-var-buffer-local.
               (when (and (local-variable-if-set-p variable)
@@ -798,7 +852,10 @@ it is displayed along with the global value."
                              (with-temp-buffer
                                (local-variable-if-set-p variable))))
                 (setq extra-line t)
-                (princ "  Automatically becomes buffer-local when set in any fashion.\n"))
+                (princ "  Automatically becomes ")
+               (if (get variable 'permanent-local)
+                   (princ "permanently "))
+               (princ "buffer-local when set.\n"))
 
               ;; Mention if it's an alias
               (unless (eq alias variable)