diff options
| author | Stefan Monnier | 2004-04-07 19:38:54 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2004-04-07 19:38:54 +0000 |
| commit | 154ee9b7377983dcb37d84a1b39b145ae32fc16a (patch) | |
| tree | a9217e2f1b735d223c04718323ce0666141ad6fd | |
| parent | 0728ab11962b050a55d91872b149a9d86677e715 (diff) | |
| download | emacs-154ee9b7377983dcb37d84a1b39b145ae32fc16a.tar.gz emacs-154ee9b7377983dcb37d84a1b39b145ae32fc16a.zip | |
(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.
| -rw-r--r-- | lisp/help-fns.el | 74 |
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 @@ | |||
| 1 | ;;; help-fns.el --- Complex help functions | 1 | ;;; help-fns.el --- Complex help functions |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1985, 1986, 1993, 1994, 1998, 1999, 2000, 2001, 2002, 2003 | 3 | ;; Copyright (C) 1985, 86, 93, 94, 98, 1999, 2000, 01, 02, 03, 2004 |
| 4 | ;; Free Software Foundation, Inc. | 4 | ;; Free Software Foundation, Inc. |
| 5 | 5 | ||
| 6 | ;; Maintainer: FSF | 6 | ;; Maintainer: FSF |
| @@ -215,6 +215,61 @@ ARGLIST can also be t or a string of the form \"(fun ARG1 ARG2 ...)\"." | |||
| 215 | (intern (upcase name)))))) | 215 | (intern (upcase name)))))) |
| 216 | arglist))) | 216 | arglist))) |
| 217 | 217 | ||
| 218 | (defvar help-C-source-directory | ||
| 219 | (let ((dir (expand-file-name "src" source-directory))) | ||
| 220 | (when (and (file-directory-p dir) (file-readable-p dir)) | ||
| 221 | dir)) | ||
| 222 | "Directory where the C source files of Emacs can be found. | ||
| 223 | If nil, do not try to find the source code of functions and variables | ||
| 224 | defined in C.") | ||
| 225 | |||
| 226 | (defun help-subr-name (subr) | ||
| 227 | (let ((name (prin1-to-string subr))) | ||
| 228 | (if (string-match "\\`#<subr \\(.*\\)>\\'" name) | ||
| 229 | (match-string 1 name) | ||
| 230 | (error "Unexpected subroutine print name: %s" name)))) | ||
| 231 | |||
| 232 | (defun help-C-file-name (subr-or-var kind) | ||
| 233 | "Return the name of the C file where SUBR-OR-VAR is defined. | ||
| 234 | KIND should be `var' for a variable or `subr' for a subroutine." | ||
| 235 | (let ((docbuf (get-buffer-create " *DOC*")) | ||
| 236 | (name (if (eq 'var kind) | ||
| 237 | (concat "V" (symbol-name subr-or-var)) | ||
| 238 | (concat "F" (help-subr-name subr-or-var))))) | ||
| 239 | (with-current-buffer docbuf | ||
| 240 | (goto-char (point-min)) | ||
| 241 | (if (eobp) | ||
| 242 | (insert-file-contents-literally | ||
| 243 | (expand-file-name internal-doc-file-name doc-directory))) | ||
| 244 | (search-forward (concat "" name "\n")) | ||
| 245 | (re-search-backward "S\\(.*\\)") | ||
| 246 | (let ((file (match-string 1))) | ||
| 247 | (if (string-match "\\.\\(o\\|obj\\)\\'" file) | ||
| 248 | (replace-match ".c" t t file) | ||
| 249 | file))))) | ||
| 250 | |||
| 251 | (defun help-find-C-source (fun-or-var file kind) | ||
| 252 | "Find the source location where SUBR-OR-VAR is defined in FILE. | ||
| 253 | KIND should be `var' for a variable or `subr' for a subroutine." | ||
| 254 | (setq file (expand-file-name file help-C-source-directory)) | ||
| 255 | (unless (file-readable-p file) | ||
| 256 | (error "The C source file %s is not available" | ||
| 257 | (file-name-nondirectory file))) | ||
| 258 | (if (eq 'fun kind) | ||
| 259 | (setq fun-or-var (indirect-function fun-or-var))) | ||
| 260 | (with-current-buffer (find-file-noselect file) | ||
| 261 | (goto-char (point-min)) | ||
| 262 | (unless (re-search-forward | ||
| 263 | (if (eq 'fun kind) | ||
| 264 | (concat "DEFUN[ \t\n]*([ \t\n]*\"" | ||
| 265 | (regexp-quote (help-subr-name fun-or-var)) | ||
| 266 | "\"") | ||
| 267 | (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\"" | ||
| 268 | (regexp-quote (symbol-name fun-or-var)))) | ||
| 269 | nil t) | ||
| 270 | (error "Can't find source for %s" fun)) | ||
| 271 | (cons (current-buffer) (match-beginning 0)))) | ||
| 272 | |||
| 218 | ;;;###autoload | 273 | ;;;###autoload |
| 219 | (defun describe-function-1 (function) | 274 | (defun describe-function-1 (function) |
| 220 | (let* ((def (if (symbolp function) | 275 | (let* ((def (if (symbolp function) |
| @@ -280,8 +335,10 @@ ARGLIST can also be t or a string of the form \"(fun ARG1 ARG2 ...)\"." | |||
| 280 | (when (re-search-backward | 335 | (when (re-search-backward |
| 281 | "^;;; Generated autoloads from \\(.*\\)" nil t) | 336 | "^;;; Generated autoloads from \\(.*\\)" nil t) |
| 282 | (setq file-name (match-string 1))))))) | 337 | (setq file-name (match-string 1))))))) |
| 283 | (cond | 338 | (when (and (null file-name) (subrp def) help-C-source-directory) |
| 284 | (file-name | 339 | ;; Find the C source file name. |
| 340 | (setq file-name (concat "src/" (help-C-file-name def 'subr)))) | ||
| 341 | (when file-name | ||
| 285 | (princ " in `") | 342 | (princ " in `") |
| 286 | ;; We used to add .el to the file name, | 343 | ;; We used to add .el to the file name, |
| 287 | ;; but that's completely wrong when the user used load-file. | 344 | ;; 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 ...)\"." | |||
| 289 | (princ "'") | 346 | (princ "'") |
| 290 | ;; Make a hyperlink to the library. | 347 | ;; Make a hyperlink to the library. |
| 291 | (with-current-buffer standard-output | 348 | (with-current-buffer standard-output |
| 292 | (save-excursion | 349 | (save-excursion |
| 293 | (re-search-backward "`\\([^`']+\\)'" nil t) | 350 | (re-search-backward "`\\([^`']+\\)'" nil t) |
| 294 | (help-xref-button 1 'help-function-def function file-name))))) | 351 | (help-xref-button 1 'help-function-def function file-name)))) |
| 295 | (princ ".") | 352 | (princ ".") |
| 296 | (terpri) | 353 | (terpri) |
| 297 | (when (commandp function) | 354 | (when (commandp function) |
| @@ -500,6 +557,13 @@ it is displayed along with the global value." | |||
| 500 | (when (re-search-backward | 557 | (when (re-search-backward |
| 501 | "^;;; Generated autoloads from \\(.*\\)" nil t) | 558 | "^;;; Generated autoloads from \\(.*\\)" nil t) |
| 502 | (setq file-name (match-string 1))))))) | 559 | (setq file-name (match-string 1))))))) |
| 560 | (when (and (null file-name) | ||
| 561 | (integerp (get variable 'variable-documentation))) | ||
| 562 | ;; It's a variable not defined in Elisp but in C. | ||
| 563 | (if help-C-source-directory | ||
| 564 | (setq file-name | ||
| 565 | (concat "src/" (help-C-file-name variable 'var))) | ||
| 566 | (princ "\n\nDefined in core C code."))) | ||
| 503 | (when file-name | 567 | (when file-name |
| 504 | (princ "\n\nDefined in `") | 568 | (princ "\n\nDefined in `") |
| 505 | (princ file-name) | 569 | (princ file-name) |