;;; help-fns.el --- Complex help functions -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1993-1994, 1998-2012
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1993-1994, 1998-2014 Free Software
+;; Foundation, Inc.
;; Maintainer: FSF
;; Keywords: help, internal
;;; Code:
+(defvar help-fns-describe-function-functions nil
+ "List of functions to run in help buffer in `describe-function'.
+Those functions will be run after the header line and argument
+list was inserted, and before the documentation will be inserted.
+The functions will receive the function name as argument.")
+
;; Functions
;;;###autoload
(when (and docstring (string-match "\n\n(fn\\(\\( .*\\)?)\\)\\'" docstring))
(cons (format "(%s%s"
;; Replace `fn' with the actual function name.
- (if (consp def) "anonymous" def)
+ (if (symbolp def) def "anonymous")
(match-string 1 docstring))
(unless (zerop (match-beginning 0))
(substring docstring 0 (match-beginning 0))))))
;; If we don't have a file-name string by now, we lost.
nil)
;; Now, `file-name' should have become an absolute file name.
- ;; For files loaded from ~/.emacs.elc, try ~/.emacs.
+ ;; For files loaded from ~/.foo.elc, try ~/.foo.
+ ;; This applies to config files like ~/.emacs,
+ ;; which people sometimes compile.
((let (fn)
- (and (string-equal file-name
- (expand-file-name ".emacs.elc" "~"))
- (file-readable-p (setq fn (expand-file-name ".emacs" "~")))
+ (and (string-match "\\`\\..*\\.elc\\'"
+ (file-name-nondirectory file-name))
+ (string-equal (file-name-directory file-name)
+ (file-name-as-directory (expand-file-name "~")))
+ (file-readable-p (setq fn (file-name-sans-extension file-name)))
fn)))
;; When the Elisp source file can be found in the install
;; directory, return the name of that file.
(match-string 1 str))))
(and src-file (file-readable-p src-file) src-file))))))
-(declare-function ad-get-advice-info "advice" (function))
-
(defun help-fns--key-bindings (function)
(when (commandp function)
(let ((pt2 (with-current-buffer standard-output (point)))
(let ((handler (function-get function 'compiler-macro)))
(when handler
(insert "\nThis 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)
- (insert (format " in `%s'" lib))
- (save-excursion
- (re-search-backward "`\\([^`']+\\)'" nil t)
- (help-xref-button 1 'help-function-cmacro function lib))))
+ (if (symbolp handler)
+ (progn
+ (insert (format " `%s'" handler))
+ (save-excursion
+ (re-search-backward "`\\([^`']+\\)'" nil t)
+ (help-xref-button 1 'help-function handler)))
+ ;; FIXME: Obsolete since 24.4.
+ (let ((lib (get function 'compiler-macro-file)))
+ (when (stringp lib)
+ (insert (format " in `%s'" lib))
+ (save-excursion
+ (re-search-backward "`\\([^`']+\\)'" nil t)
+ (help-xref-button 1 'help-function-cmacro function lib)))))
(insert ".\n"))))
(defun help-fns--signature (function doc real-def real-function)
;;;###autoload
(defun describe-function-1 (function)
- (let* ((advised (and (symbolp function) (featurep 'advice)
- (ad-get-advice-info function)))
+ (let* ((advised (and (symbolp function)
+ (featurep 'nadvice)
+ (advice--p (advice--symbol-function function))))
;; If the function is advised, use the symbol that has the
;; real definition, if that symbol is already set up.
(real-function
(or (and advised
- (let ((origname (cdr (assq 'origname advised))))
- (and (fboundp origname) origname)))
+ (let* ((advised-fn (advice--cdr
+ (advice--symbol-function function))))
+ (while (advice--p advised-fn)
+ (setq advised-fn (advice--cdr advised-fn)))
+ advised-fn))
function))
;; Get the real definition.
(def (if (symbolp real-function)
(symbol-function real-function)
- function))
- (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))
+ real-function))
+ (aliased (or (symbolp def)
+ ;; Advised & aliased function.
+ (and advised (symbolp real-function))))
+ (real-def (cond
+ (aliased (let ((f real-function))
+ (while (and (fboundp f)
+ (symbolp (symbol-function f)))
+ (setq f (symbol-function f)))
+ f))
+ ((subrp def) (intern (subr-name def)))
+ (t def)))
(file-name (find-lisp-object-file-name function def))
(pt1 (with-current-buffer (help-buffer) (point)))
(beg (if (and (or (byte-code-function-p 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"))
+ ;; Aliases are Lisp functions, so we need to check
+ ;; aliases before functions.
(aliased
(format "an alias for `%s'" real-def))
+ ((or (eq (car-safe def) 'macro)
+ ;; For advised macros, def is a lambda
+ ;; expression or a byte-code-function-p, so we
+ ;; need to check macros before functions.
+ (macrop function))
+ (concat beg "Lisp macro"))
+ ((byte-code-function-p def)
+ (concat beg "compiled Lisp function"))
((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"))
((autoloadp def)
(point)))
(terpri)(terpri)
- (let* ((doc-raw (condition-case err
- (documentation function t)
- (error (format "No Doc! %S" err))))
+ (let* ((doc-raw (documentation function t))
;; If the function is autoloaded, and its docstring has
;; key substitution constructs, load the library.
(doc (progn
(help-fns--key-bindings function)
(with-current-buffer standard-output
(setq doc (help-fns--signature function doc real-def real-function))
-
- (help-fns--compiler-macro function)
- (help-fns--parent-mode function)
- (help-fns--obsolete function)
-
+ (run-hook-with-args 'help-fns-describe-function-functions function)
(insert "\n"
(or doc "Not documented.")))))))
+;; Add defaults to `help-fns-describe-function-functions'.
+(add-hook 'help-fns-describe-function-functions 'help-fns--obsolete)
+(add-hook 'help-fns-describe-function-functions 'help-fns--parent-mode)
+(add-hook 'help-fns-describe-function-functions 'help-fns--compiler-macro)
+
\f
;; Variables
(cond
((bufferp locus)
(princ (format "Local in buffer %s; "
- (buffer-name))))
+ (buffer-name buffer))))
((framep locus)
(princ (format "It is a frame-local variable; ")))
((terminal-live-p locus)
(obsolete (get variable 'byte-obsolete-variable))
(use (car obsolete))
(safe-var (get variable 'safe-local-variable))
- (doc (condition-case err
- (or (documentation-property
- variable 'variable-documentation)
- (documentation-property
- alias 'variable-documentation))
- (error (format "Doc not found: %S" err))))
+ (doc (or (documentation-property
+ variable 'variable-documentation)
+ (documentation-property
+ alias 'variable-documentation)))
(extra-line nil))
;; Mention if it's a local variable.
(princ "buffer-local when set.\n"))
((not permanent-local))
((bufferp locus)
+ (setq extra-line t)
(princ " This variable's buffer-local value is permanent.\n"))
(t
+ (setq extra-line t)
(princ " This variable's value is permanent \
if it is given a local binding.\n")))