]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/autoload.el
merge trunk
[gnu-emacs] / lisp / emacs-lisp / autoload.el
index c5316d06429a6c2faac9fa034268a0c10846be97..f8f8d9b00f2bdf6fc413375ed43272fde069462f 100644 (file)
@@ -1,11 +1,10 @@
 ;; autoload.el --- maintain autoloads in loaddefs.el
 
-;; Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2001, 2002, 2003,
-;;   2004, 2005, 2006, 2007, 2008, 2009, 2010
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1991-1997, 2001-2011  Free Software Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>
 ;; Keywords: maint
+;; Package: emacs
 
 ;; This file is part of GNU Emacs.
 
 (require 'help-fns)                    ;for help-add-fundoc-usage.
 (eval-when-compile (require 'cl))
 
-(defvar 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.  The autoload file is assumed to contain a
-trailer starting with a FormFeed character.")
+(defvar generated-autoload-file nil
+  "File into which to write autoload definitions.
+A Lisp file can set this in its local variables section to make
+its autoloads go somewhere else.
+
+If this is a relative file name, the directory is determined as
+follows:
+ - If a Lisp file defined `generated-autoload-file' as a
+   file-local variable, use its containing directory.
+ - Otherwise use the \"lisp\" subdirectory of `source-directory'.
+
+The autoload file is assumed to contain a trailer starting with a
+FormFeed character.")
 ;;;###autoload
 (put 'generated-autoload-file 'safe-local-variable 'stringp)
 
@@ -109,29 +116,48 @@ or macro definition or a defcustom)."
       (let* ((macrop (memq car '(defmacro defmacro*)))
             (name (nth 1 form))
             (args (case car
-                   ((defun defmacro defun* defmacro*
-                      define-overloadable-function) (nth 2 form))
-                   ((define-skeleton) '(&optional str arg))
-                   ((define-generic-mode define-derived-mode
-                       define-compilation-mode) nil)
-                   (t)))
+                     ((defun defmacro defun* defmacro*
+                        define-overloadable-function) (nth 2 form))
+                     ((define-skeleton) '(&optional str arg))
+                     ((define-generic-mode define-derived-mode
+                        define-compilation-mode) nil)
+                     (t)))
             (body (nthcdr (get car 'doc-string-elt) form))
             (doc (if (stringp (car body)) (pop body))))
        (when (listp args)
          ;; Add the usage form at the end where describe-function-1
          ;; can recover it.
          (setq doc (help-add-fundoc-usage doc args)))
-       ;; `define-generic-mode' quotes the name, so take care of that
-       (list 'autoload (if (listp name) name (list 'quote name)) file doc
-             (or (and (memq car '(define-skeleton define-derived-mode
-                                   define-generic-mode
-                                   easy-mmode-define-global-mode
-                                   define-global-minor-mode
-                                   define-globalized-minor-mode
-                                   easy-mmode-define-minor-mode
-                                   define-minor-mode)) t)
-                 (eq (car-safe (car body)) 'interactive))
-             (if macrop (list 'quote 'macro) nil))))
+        (let ((exp
+               ;; `define-generic-mode' quotes the name, so take care of that
+               (list 'autoload (if (listp name) name (list 'quote name))
+                     file doc
+                     (or (and (memq car '(define-skeleton define-derived-mode
+                                           define-generic-mode
+                                           easy-mmode-define-global-mode
+                                           define-global-minor-mode
+                                           define-globalized-minor-mode
+                                           easy-mmode-define-minor-mode
+                                           define-minor-mode)) t)
+                         (eq (car-safe (car body)) 'interactive))
+                     (if macrop (list 'quote 'macro) nil))))
+          (when macrop
+            ;; Special case to autoload some of the macro's declarations.
+            (let ((decls (nth (if (stringp (nth 3 form)) 4 3) form))
+                  (exps '()))
+              (when (eq (car-safe decls) 'declare)
+                ;; FIXME: We'd like to reuse macro-declaration-function,
+                ;; but we can't since it doesn't return anything.
+                (dolist (decl decls)
+                  (case (car-safe decl)
+                    (indent
+                     (push `(put ',name 'lisp-indent-function ',(cadr decl))
+                           exps))
+                    (doc-string
+                     (push `(put ',name 'doc-string-elt ',(cadr decl)) exps))))
+                (when exps
+                  (setq exp `(progn ,exp ,@exps))))))
+          exp)))
 
      ;; For defclass forms, use `eieio-defclass-autoload'.
      ((eq car 'defclass)
@@ -172,6 +198,15 @@ or macro definition or a defcustom)."
 ;; the doc-string in FORM.
 ;; Those properties are now set in lisp-mode.el.
 
+(defun autoload-find-generated-file ()
+  "Visit the autoload file for the current buffer, and return its buffer.
+If a buffer is visiting the desired autoload file, return it."
+  (let ((enable-local-variables :safe))
+    ;; We used to use `raw-text' to read this file, but this causes
+    ;; problems when the file contains non-ASCII characters.
+    (find-file-noselect
+     (autoload-ensure-default-file (autoload-generated-file)))))
+
 (defun autoload-generated-file ()
   (expand-file-name generated-autoload-file
                     ;; File-local settings of generated-autoload-file should
@@ -363,7 +398,8 @@ If FILE is being visited in a buffer, the contents of the buffer
 are used.
 Return non-nil in the case where no autoloads were added at point."
   (interactive "fGenerate autoloads for file: ")
-  (autoload-generate-file-autoloads file (current-buffer)))
+  (let ((generated-autoload-file buffer-file-name))
+    (autoload-generate-file-autoloads file (current-buffer))))
 
 (defvar print-readably)
 
@@ -453,7 +489,8 @@ Return non-nil if and only if FILE adds no autoloads to OUTFILE
                                    (marker-buffer output-start)))
                               (autoload-print-form autoload)))
                         (error
-                         (message "Error in %s: %S" file err)))
+                         (message "Autoload cookie error in %s:%s %S"
+                                  file (count-lines (point-min) (point)) err)))
 
                     ;; Copy the rest of the line to the output.
                     (princ (buffer-substring
@@ -519,18 +556,26 @@ Return non-nil if and only if FILE adds no autoloads to OUTFILE
 (defun autoload-save-buffers ()
   (while autoload-modified-buffers
     (with-current-buffer (pop autoload-modified-buffers)
-      (save-buffer))))
+      (let ((version-control 'never))
+       (save-buffer)))))
 
 ;;;###autoload
-(defun update-file-autoloads (file &optional save-after)
-  "Update the autoloads for FILE in `generated-autoload-file'
-\(which FILE might bind in its local variables).
-If SAVE-AFTER is non-nil (which is always, when called interactively),
-save the buffer too.
+(defun update-file-autoloads (file &optional save-after outfile)
+  "Update the autoloads for FILE.
+If prefix arg SAVE-AFTER is non-nil, save the buffer too.
+
+If FILE binds `generated-autoload-file' as a file-local variable,
+autoloads are written into that file.  Otherwise, the autoloads
+file is determined by OUTFILE.  If called interactively, prompt
+for OUTFILE; if called from Lisp with OUTFILE nil, use the
+existing value of `generated-autoload-file'.
 
 Return FILE if there was no autoload cookie in it, else nil."
-  (interactive "fUpdate autoloads for file: \np")
-  (let* ((autoload-modified-buffers nil)
+  (interactive (list (read-file-name "Update autoloads for file: ")
+                    current-prefix-arg
+                    (read-file-name "Write autoload definitions to file: ")))
+  (let* ((generated-autoload-file (or outfile generated-autoload-file))
+        (autoload-modified-buffers nil)
          (no-autoloads (autoload-generate-file-autoloads file)))
     (if autoload-modified-buffers
         (if save-after (autoload-save-buffers))
@@ -548,15 +593,11 @@ removes any prior now out-of-date autoload entries."
     (let* ((buf (current-buffer))
            (existing-buffer (if buffer-file-name buf))
            (found nil))
-      (with-current-buffer
-          ;; We used to use `raw-text' to read this file, but this causes
-          ;; problems when the file contains non-ASCII characters.
-          (find-file-noselect
-           (autoload-ensure-default-file (autoload-generated-file)))
+      (with-current-buffer (autoload-find-generated-file)
         ;; This is to make generated-autoload-file have Unix EOLs, so
         ;; that it is portable to all platforms.
-        (unless (zerop (coding-system-eol-type buffer-file-coding-system))
-          (set-buffer-file-coding-system 'unix))
+        (or (eq 0 (coding-system-eol-type buffer-file-coding-system))
+           (set-buffer-file-coding-system 'unix))
         (or (> (buffer-size) 0)
             (error "Autoloads file %s lacks boilerplate" buffer-file-name))
         (or (file-writable-p buffer-file-name)
@@ -611,15 +652,20 @@ removes any prior now out-of-date autoload entries."
 
 ;;;###autoload
 (defun update-directory-autoloads (&rest dirs)
-  "\
-Update loaddefs.el with all the current autoloads from DIRS, and no old ones.
-This uses `update-file-autoloads' (which see) to do its work.
-In an interactive call, you must give one argument, the name
-of a single directory.  In a call from Lisp, you can supply multiple
+  "Update autoload definitions for Lisp files in the directories DIRS.
+In an interactive call, you must give one argument, the name of a
+single directory.  In a call from Lisp, you can supply multiple
 directories as separate arguments, but this usage is discouraged.
 
 The function does NOT recursively descend into subdirectories of the
-directory or directories specified."
+directory or directories specified.
+
+In an interactive call, prompt for a default output file for the
+autoload definitions, and temporarily bind the variable
+`generated-autoload-file' to this value.  When called from Lisp,
+use the existing value of `generated-autoload-file'.  If any Lisp
+file binds `generated-autoload-file' as a file-local variable,
+write its autoloads into the specified file instead."
   (interactive "DUpdate autoloads from directory: ")
   (let* ((files-re (let ((tmp nil))
                     (dolist (suf (get-load-suffixes)
@@ -635,13 +681,14 @@ directory or directories specified."
          ;; Files with no autoload cookies or whose autoloads go to other
          ;; files because of file-local autoload-generated-file settings.
         (no-autoloads nil)
-         (autoload-modified-buffers nil))
+         (autoload-modified-buffers nil)
+        (generated-autoload-file
+         (if (called-interactively-p 'interactive)
+             (read-file-name "Write autoload definitions to file: ")
+           generated-autoload-file)))
 
-    (with-current-buffer
-       (find-file-noselect
-         (autoload-ensure-default-file (autoload-generated-file)))
+    (with-current-buffer (autoload-find-generated-file)
       (save-excursion
-
        ;; Canonicalize file names and remove the autoload file itself.
        (setq files (delete (file-relative-name buffer-file-name)
                            (mapcar 'file-relative-name files)))
@@ -703,7 +750,8 @@ directory or directories specified."
         (current-buffer) nil nil no-autoloads this-time)
        (insert generate-autoload-section-trailer))
 
-      (save-buffer)
+      (let ((version-control 'never))
+       (save-buffer))
       ;; In case autoload entries were added to other files because of
       ;; file-local autoload-generated-file settings.
       (autoload-save-buffers))))
@@ -717,7 +765,9 @@ directory or directories specified."
 ;;;###autoload
 (defun batch-update-autoloads ()
   "Update loaddefs.el autoloads in batch mode.
-Calls `update-directory-autoloads' on the command line arguments."
+Calls `update-directory-autoloads' on the command line arguments.
+Definitions are written to `generated-autoload-file' (which
+should be non-nil)."
   ;; For use during the Emacs build process only.
   (unless autoload-excludes
     (let* ((ldir (file-name-directory generated-autoload-file))
@@ -758,16 +808,17 @@ Calls `update-directory-autoloads' on the command line arguments."
          (with-temp-buffer
            (insert-file-contents mfile)
            (when (re-search-forward "^shortlisp= " nil t)
-             (setq lim (line-end-position))
-             (while (re-search-forward "\\.\\./lisp/\\([^ ]+\\.el\\)c?\\>"
-                                       lim t)
+             (while (and (not lim)
+                         (re-search-forward "\\.\\./lisp/\\([^ ]+\\.el\\)c?\\>"
+                                            nil t))
                (push (expand-file-name (match-string 1) ldir)
-                     autoload-excludes))))))))
+                     autoload-excludes)
+               (skip-chars-forward " \t")
+               (if (eolp) (setq lim t)))))))))
   (let ((args command-line-args-left))
     (setq command-line-args-left nil)
     (apply 'update-directory-autoloads args)))
 
 (provide 'autoload)
 
-;; arch-tag: 00244766-98f4-4767-bf42-8a22103441c6
 ;;; autoload.el ends here