summaryrefslogtreecommitdiff
path: root/lisp/help-fns.el
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2004-04-07 19:38:54 +0000
committerStefan Monnier <monnier@iro.umontreal.ca>2004-04-07 19:38:54 +0000
commit154ee9b7377983dcb37d84a1b39b145ae32fc16a (patch)
treea9217e2f1b735d223c04718323ce0666141ad6fd /lisp/help-fns.el
parent0728ab11962b050a55d91872b149a9d86677e715 (diff)
downloademacs-154ee9b7377983dcb37d84a1b39b145ae32fc16a.tar.gz
(help-C-source-directory): New var.
(help-subr-name, help-C-file-name, help-find-C-source): New funs. (describe-function-1, describe-variable): Use them.
Diffstat (limited to 'lisp/help-fns.el')
-rw-r--r--lisp/help-fns.el74
1 files changed, 69 insertions, 5 deletions
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 4201a3de1a5..ab76b5eb232 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1,6 +1,6 @@
;;; help-fns.el --- Complex help functions
-;; Copyright (C) 1985, 1986, 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003
+;; Copyright (C) 1985, 86, 93, 94, 98, 1999, 2000, 01, 02, 03, 2004
;; Free Software Foundation, Inc.
;; Maintainer: FSF
@@ -215,6 +215,61 @@ ARGLIST can also be t or a string of the form \"(fun ARG1 ARG2 ...)\"."
(intern (upcase name))))))
arglist)))
+(defvar help-C-source-directory
+ (let ((dir (expand-file-name "src" source-directory)))
+ (when (and (file-directory-p dir) (file-readable-p dir))
+ dir))
+ "Directory where the C source files of Emacs can be found.
+If nil, do not try to find the source code of functions and variables
+defined in C.")
+
+(defun help-subr-name (subr)
+ (let ((name (prin1-to-string subr)))
+ (if (string-match "\\`#<subr \\(.*\\)>\\'" name)
+ (match-string 1 name)
+ (error "Unexpected subroutine print name: %s" name))))
+
+(defun help-C-file-name (subr-or-var kind)
+ "Return the name of the C file where SUBR-OR-VAR is defined.
+KIND should be `var' for a variable or `subr' for a subroutine."
+ (let ((docbuf (get-buffer-create " *DOC*"))
+ (name (if (eq 'var kind)
+ (concat "V" (symbol-name subr-or-var))
+ (concat "F" (help-subr-name subr-or-var)))))
+ (with-current-buffer docbuf
+ (goto-char (point-min))
+ (if (eobp)
+ (insert-file-contents-literally
+ (expand-file-name internal-doc-file-name doc-directory)))
+ (search-forward (concat "" name "\n"))
+ (re-search-backward "S\\(.*\\)")
+ (let ((file (match-string 1)))
+ (if (string-match "\\.\\(o\\|obj\\)\\'" file)
+ (replace-match ".c" t t file)
+ file)))))
+
+(defun help-find-C-source (fun-or-var file kind)
+ "Find the source location where SUBR-OR-VAR is defined in FILE.
+KIND should be `var' for a variable or `subr' for a subroutine."
+ (setq file (expand-file-name file help-C-source-directory))
+ (unless (file-readable-p file)
+ (error "The C source file %s is not available"
+ (file-name-nondirectory file)))
+ (if (eq 'fun kind)
+ (setq fun-or-var (indirect-function fun-or-var)))
+ (with-current-buffer (find-file-noselect file)
+ (goto-char (point-min))
+ (unless (re-search-forward
+ (if (eq 'fun kind)
+ (concat "DEFUN[ \t\n]*([ \t\n]*\""
+ (regexp-quote (help-subr-name fun-or-var))
+ "\"")
+ (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\""
+ (regexp-quote (symbol-name fun-or-var))))
+ nil t)
+ (error "Can't find source for %s" fun))
+ (cons (current-buffer) (match-beginning 0))))
+
;;;###autoload
(defun describe-function-1 (function)
(let* ((def (if (symbolp function)
@@ -280,8 +335,10 @@ ARGLIST can also be t or a string of the form \"(fun ARG1 ARG2 ...)\"."
(when (re-search-backward
"^;;; Generated autoloads from \\(.*\\)" nil t)
(setq file-name (match-string 1)))))))
- (cond
- (file-name
+ (when (and (null file-name) (subrp def) help-C-source-directory)
+ ;; Find the C source file name.
+ (setq file-name (concat "src/" (help-C-file-name def 'subr))))
+ (when file-name
(princ " in `")
;; We used to add .el to the file name,
;; but that's completely wrong when the user used load-file.
@@ -289,9 +346,9 @@ ARGLIST can also be t or a string of the form \"(fun ARG1 ARG2 ...)\"."
(princ "'")
;; Make a hyperlink to the library.
(with-current-buffer standard-output
- (save-excursion
+ (save-excursion
(re-search-backward "`\\([^`']+\\)'" nil t)
- (help-xref-button 1 'help-function-def function file-name)))))
+ (help-xref-button 1 'help-function-def function file-name))))
(princ ".")
(terpri)
(when (commandp function)
@@ -500,6 +557,13 @@ it is displayed along with the global value."
(when (re-search-backward
"^;;; Generated autoloads from \\(.*\\)" nil t)
(setq file-name (match-string 1)))))))
+ (when (and (null file-name)
+ (integerp (get variable 'variable-documentation)))
+ ;; It's a variable not defined in Elisp but in C.
+ (if help-C-source-directory
+ (setq file-name
+ (concat "src/" (help-C-file-name variable 'var)))
+ (princ "\n\nDefined in core C code.")))
(when file-name
(princ "\n\nDefined in `")
(princ file-name)