diff options
author | Jim Blandy <jimb@redhat.com> | 1991-12-21 08:23:15 +0000 |
---|---|---|
committer | Jim Blandy <jimb@redhat.com> | 1991-12-21 08:23:15 +0000 |
commit | 0231f2dce81e3f5118c5c2eecec6081ba888e03a (patch) | |
tree | b617bca3d0d129e768ab909df1a82151fcf4e845 /lisp/emacs-lisp/autoload.el | |
parent | 2b529dd25efceb5949eb53a6ee414d159d8a54e9 (diff) | |
download | emacs-0231f2dce81e3f5118c5c2eecec6081ba888e03a.tar.gz emacs-0231f2dce81e3f5118c5c2eecec6081ba888e03a.tar.bz2 emacs-0231f2dce81e3f5118c5c2eecec6081ba888e03a.zip |
Initial revision
Diffstat (limited to 'lisp/emacs-lisp/autoload.el')
-rw-r--r-- | lisp/emacs-lisp/autoload.el | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el new file mode 100644 index 00000000000..0a7c9dc74c7 --- /dev/null +++ b/lisp/emacs-lisp/autoload.el @@ -0,0 +1,290 @@ +;;; Maintain autoloads in loaddefs.el. +;;; Copyright (C) 1991 Free Software Foundation, Inc. +;;; Written by Roland McGrath. +;;; +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 1, or (at your option) +;;; any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; A copy of the GNU General Public License can be obtained from this +;;; program's author (send electronic mail to roland@ai.mit.edu) or from +;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA +;;; 02139, USA. +;;; + +(defun make-autoload (form file) + "Turn FORM, a defun or defmacro, into an autoload for source file FILE. +Returns nil if FORM is not a defun or defmacro." + (let ((car (car-safe form))) + (if (or (eq car 'defun) (eq car 'defmacro)) + (let (name doc macrop) + (setq macrop (eq car 'defmacro)) + (setq form (cdr form)) + (setq name (car form)) + ;; Ignore the arguments. + (setq form (cdr (cdr form))) + (setq doc (car form)) + (if (stringp doc) + (setq form (cdr form)) + (setq doc nil)) + (list 'autoload (list 'quote name) file doc + (eq (car-safe (car form)) 'interactive) macrop)) + nil))) + +(defconst generate-autoload-cookie ";;;###autoload" + "Magic comment that tells \\[update-file-autoloads] +to make the following form into an autoload. This string should be +meaningless to Lisp (e.g., a comment). + +This string is used: + +;;;###autoload +\(defun function-to-be-autoloaded () ...) + +If this string appears alone on a line, the following form will be +read and an autoload made for it. If there is further text on the line, +that text will be copied verbatim to `generated-autoload-file'.") + +(defconst generate-autoload-section-header "\f\n;;;### " + "String inserted before the form identifying +the section of autoloads for a file.") + +(defconst generate-autoload-section-trailer "\n;;;***\n" + "String which indicates the end of the section of autoloads for a file.") + +;; Forms which have doc-strings which should be printed specially. +;; A doc-string-elt property of ELT says that (nth ELT FORM) is +;; the doc-string in FORM. +;; Note: defconst and defvar should NOT be marked in this way. +;; We don't want to produce defconsts and defvars that make-docfile can +;; grok, because then it would grok them twice, once in foo.el (where they +;; are given with ;;;###autoload) and once in loaddefs.el. +(put 'autoload 'doc-string-elt 3) + +(defun generate-file-autoloads (file) + "Insert at point a loaddefs autoload section for FILE. +autoloads are generated for defuns and defmacros in FILE +marked by `generate-autoload-regexp' (which see). +If FILE is being visited in a buffer, the contents of the buffer +are used." + (interactive "fGenerate autoloads for file: ") + (let ((outbuf (current-buffer)) + (inbuf (find-file-noselect file)) + (autoloads-done '()) + (load-name (let ((name (file-name-nondirectory file))) + (if (string-match "\\.elc?$" name) + (substring name 0 (match-beginning 0)) + name))) + (print-length nil) + (floating-output-format "%20e") + (done-any nil) + output-end) + (message "Generating autoloads for %s..." file) + (save-excursion + (set-buffer inbuf) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (while (not (eobp)) + (skip-chars-forward " \t\n\f") + (cond ((looking-at (regexp-quote generate-autoload-cookie)) + (search-forward generate-autoload-cookie) + (skip-chars-forward " \t") + (setq done-any t) + (if (eolp) + ;; Read the next form and make an autoload. + (let* ((form (prog1 (read (current-buffer)) + (forward-line 1))) + (autoload (make-autoload form load-name)) + (doc-string-elt (get (car-safe form) + 'doc-string-elt))) + (if autoload + (setq autoloads-done (cons (nth 1 form) + autoloads-done)) + (setq autoload form)) + (if (and doc-string-elt + (stringp (nth doc-string-elt autoload))) + ;; We need to hack the printing because the + ;; doc-string must be printed specially for + ;; make-docfile (sigh). + (let* ((p (nthcdr (1- doc-string-elt) autoload)) + (elt (cdr p))) + (setcdr p nil) + (princ "\n(" outbuf) + (mapcar (function (lambda (elt) + (prin1 elt outbuf) + (princ " " outbuf))) + autoload) + (princ "\"\\\n" outbuf) + (princ (substring (prin1-to-string (car elt)) 1) + outbuf) + (if (null (cdr elt)) + (princ ")" outbuf) + (princ " " outbuf) + (princ (substring (prin1-to-string (cdr elt)) + 1) + outbuf)) + (terpri outbuf)) + (print autoload outbuf))) + ;; Copy the rest of the line to the output. + (let ((begin (point))) + (forward-line 1) + (princ (buffer-substring begin (point)) outbuf)))) + ((looking-at ";") + ;; Don't read the comment. + (forward-line 1)) + (t + (forward-sexp 1) + (forward-line 1)))))) + (set-buffer outbuf) + (setq output-end (point-marker))) + (if done-any + (progn + (insert generate-autoload-section-header) + (prin1 (list 'autoloads autoloads-done load-name file + (nth 5 (file-attributes file))) + outbuf) + (terpri outbuf) + (insert ";;; Generated autoloads from " file "\n") + (goto-char output-end) + (insert generate-autoload-section-trailer))) + (message "Generating autoloads for %s...done" file))) + +(defconst generated-autoload-file "loaddefs.el" + "*File \\[update-file-autoloads] puts autoloads into. +A .el file can set this in its local variables section to make its +autoloads go somewhere else.") + +;;;###autoload +(defun update-file-autoloads (file) + "Update the autoloads for FILE in `generated-autoload-file' +\(which FILE might bind in its local variables)." + (interactive "fUpdate autoloads for file: ") + (let ((load-name (let ((name (file-name-nondirectory file))) + (if (string-match "\\.elc?$" name) + (substring name 0 (match-beginning 0)) + name))) + (done nil) + (existing-buffer (get-file-buffer file))) + (save-excursion + ;; We want to get a value for generated-autoload-file from + ;; the local variables section if it's there. + (set-buffer (find-file-noselect file)) + (set-buffer (find-file-noselect generated-autoload-file)) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (while (search-forward generate-autoload-section-header nil t) + (let ((form (condition-case () + (read (current-buffer)) + (end-of-file nil)))) + (if (string= (nth 2 form) load-name) + (let ((begin (match-beginning 0)) + (last-time (nth 4 form)) + (file-time (nth 5 (file-attributes file)))) + (if (and (or (null existing-buffer) + (not (buffer-modified-p existing-buffer))) + (listp last-time) (= (length last-time) 2) + (or (> (car last-time) (car file-time)) + (and (= (car last-time) (car file-time)) + (>= (nth 1 last-time) + (nth 1 file-time))))) + (message "Autoload section for %s is up to date." + file) + (search-forward generate-autoload-section-trailer) + (delete-region begin (point)) + (generate-file-autoloads file)) + (setq done t)))))) + (if done + () + ;; Have the user tell us where to put the section. + (save-window-excursion + (switch-to-buffer (current-buffer)) + (with-output-to-temp-buffer "*Help*" + (princ (substitute-command-keys + (format "\ +Move point to where the autoload section +for %s should be inserted. +Then do \\[exit-recursive-edit]." + file)))) + (recursive-edit)) + (generate-file-autoloads file))) + (if (and (null existing-buffer) + (setq existing-buffer (get-file-buffer file))) + (kill-buffer existing-buffer))))) + +;;;###autoload +(defun update-autoloads-here () + "Update the sections of the current buffer generated by +\\[update-file-autoloads]." + (interactive) + (let ((generated-autoload-file (buffer-file-name))) + (save-excursion + (goto-char (point-min)) + (while (search-forward generate-autoload-section-header nil t) + (let* ((form (condition-case () + (read (current-buffer)) + (end-of-file nil))) + (file (nth 3 form))) + (if (and (stringp file) + (or (get-file-buffer file) + (file-exists-p file))) + () + (setq file (if (y-or-n-p (format "Library \"%s\" (load \ +file \"%s\") doesn't exist. Remove its autoload section? " + (nth 2 form) file)) + t + (condition-case () + (read-file-name (format "Find \"%s\" load file: " + (nth 2 form)) + nil nil t) + (quit nil))))) + (if file + (let ((begin (match-beginning 0))) + (search-forward generate-autoload-section-trailer) + (delete-region begin (point)))) + (if (stringp file) + (generate-file-autoloads file))))))) + +;;;###autoload +(defun update-directory-autoloads (dir) + "Run \\[update-file-autoloads] on each .el file in DIR." + (interactive "DUpdate autoloads for directory: ") + (mapcar 'update-file-autoloads + (directory-files dir nil "\\.el$"))) + +;;;###autoload +(defun batch-update-autoloads () + "Update the autoloads for the files or directories on the command line. +Runs \\[update-file-autoloads] on files and \\[update-directory-autoloads] +on directories. Must be used only with -batch, and kills Emacs on completion. +Each file will be processed even if an error occurred previously. +For example, invoke \"emacs -batch -f batch-byte-compile *.el\"" + (if (not noninteractive) + (error "batch-update-file-autoloads is to be used only with -batch")) + (let ((lost nil) + (args command-line-args-left)) + (while args + (catch 'file + (condition-case lossage + (if (file-directory-p (expand-file-name (car args))) + (update-directory-autoloads (car args)) + (update-file-autoloads (car args))) + (error (progn (message ">>Error processing %s: %s" + (car args) lossage) + (setq lost t) + (throw 'file nil))))) + (setq args (cdr args))) + (save-some-buffers t) + (message "Done") + (kill-emacs (if lost 1 0)))) + +(provide 'autoload) |