comparison lisp/help-fns.el @ 54749:f7424850240d

(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.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Wed, 07 Apr 2004 19:38:54 +0000
parents bce4d57a18d7
children 8041d88f98b5
comparison
equal deleted inserted replaced
54748:8143853620d8 54749:f7424850240d
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
7 ;; Keywords: help, internal 7 ;; Keywords: help, internal
8 8
212 arg) 212 arg)
213 (let ((name (symbol-name arg))) 213 (let ((name (symbol-name arg)))
214 (if (string-match "\\`&" name) arg 214 (if (string-match "\\`&" name) arg
215 (intern (upcase name)))))) 215 (intern (upcase name))))))
216 arglist))) 216 arglist)))
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))))
217 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)
221 (symbol-function function) 276 (symbol-function function)
278 (with-current-buffer (car location) 333 (with-current-buffer (car location)
279 (goto-char (cdr location)) 334 (goto-char (cdr location))
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.
288 (princ file-name) 345 (princ file-name)
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)
298 (let* ((remapped (command-remapping function)) 355 (let* ((remapped (command-remapping function))
299 (keys (where-is-internal 356 (keys (where-is-internal
498 (with-current-buffer (car location) 555 (with-current-buffer (car location)
499 (goto-char (cdr location)) 556 (goto-char (cdr location))
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)
506 (princ "'.") 570 (princ "'.")
507 (with-current-buffer standard-output 571 (with-current-buffer standard-output