diff --git a/etc/NEWS b/etc/NEWS index 585a91decab..e804805c8d0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -64,6 +64,18 @@ been adding them there, put them somewhere else, eg site-lisp. * Changes in Emacs 24.2 +** Help changes + +*** `C-h f' (describe-function) can now perform autoloading. +When this command is called for an autoloaded function whose docstring +contains a key substitution construct, that function's library is +automatically loaded, so that the documentation can be shown +correctly. To disable this, set `help-enable-auto-load' to nil. + +*** `C-h f' now reports previously-autoloaded functions as "autoloaded", +even after their associated libraries have been loaded (and the +autoloads have been redefined as functions). + ** The function `current-time' now returns extended-format time stamps (HIGH LOW USEC PSEC) that use picosecond resolution; the PSEC component is new. PSEC is typically a multiple of 1000 on current diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 602c79854fa..c52891af605 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,12 @@ +2012-06-27 Chong Yidong + + * help.el (help-enable-auto-load): New variable. + + * help-fns.el (help-fns--autoloaded-p): New function. + (describe-function-1): Refer to a function as "autoloaded" if it + was autoloaded at any time in the past. Perform autoloading if + help-enable-auto-load is non-nil. + 2012-06-26 Eli Zaretskii * makefile.w32-in (compile, compile-always): Depend on diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 555bdbb69ce..52f1fe26056 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -401,6 +401,21 @@ suitable file is found, return nil." (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) @@ -416,59 +431,66 @@ 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))) + (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, @@ -531,11 +553,21 @@ suitable file is found, return nil." (unless (looking-back "\n\n") (terpri))))) (help-fns--compiler-macro function) - (let* ((advertised (gethash def advertised-signature-table t)) + (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. @@ -556,9 +588,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))) diff --git a/lisp/help.el b/lisp/help.el index 2dbb31de97b..c02b058fef9 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1030,6 +1030,16 @@ by `with-help-window'" :group 'help :version "23.1") +(defcustom help-enable-auto-load t + "Whether Help commands can perform autoloading. +If non-nil, whenever \\[describe-function] is called for an +autoloaded function whose docstring contains any key substitution +construct (see `substitute-command-keys'), the library is loaded, +so that the documentation can show the right key bindings." + :type 'boolean + :group 'help + :version "24.2") + (defun help-window-display-message (quit-part window &optional scroll) "Display message telling how to quit and scroll help window. QUIT-PART is a string telling how to quit the help window WINDOW. diff --git a/src/ChangeLog b/src/ChangeLog index bef3bbd4c83..4614ba09b3d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2012-06-27 Chong Yidong + + * doc.c (Fsubstitute_command_keys): Fix punctuation. + 2012-06-26 John Wiegley * unexmacosx.c (copy_data_segment): Added two section names used diff --git a/src/doc.c b/src/doc.c index 223741c3bf5..cbfeb06756e 100644 --- a/src/doc.c +++ b/src/doc.c @@ -897,11 +897,11 @@ Otherwise, return a new string, without any text properties. */) if (NILP (tem)) { name = Fsymbol_name (name); - insert_string ("\nUses keymap \""); + insert_string ("\nUses keymap `"); insert_from_string (name, 0, 0, SCHARS (name), SBYTES (name), 1); - insert_string ("\", which is not currently defined.\n"); + insert_string ("', which is not currently defined.\n"); if (start[-1] == '<') keymap = Qnil; } else if (start[-1] == '<')