(autoload-ensure-default-file, autoload-insert-section-header)
authorGerd Moellmann <gerd@gnu.org>
Fri, 5 Oct 2001 09:29:11 +0000 (09:29 +0000)
committerGerd Moellmann <gerd@gnu.org>
Fri, 5 Oct 2001 09:29:11 +0000 (09:29 +0000)
(autoload-before-p, autoload-remove-section): New functions.
(generate-file-autoloads): Use them.
(update-file-autoloads): Use them.  Return FILE if there's no cookie.
Make sure the autoload file is properly formatted when creating it.
(update-autoloads-from-directories): Use them as well.
Only update autoloads for files whose timestamp has changed.
Add a dummy entry to remember the files which had no autoload cookies.

lisp/emacs-lisp/autoload.el

index 37bc21f..f29cd3e 100644 (file)
@@ -230,6 +230,44 @@ markers before we call `read'."
              (print-escape-nonascii t))
          (print form outbuf)))))))
 
              (print-escape-nonascii t))
          (print form outbuf)))))))
 
+(defun autoload-ensure-default-file (file)
+  "Make sure that the autoload file FILE exists and if not create it."
+  (unless (file-exists-p file)
+    (write-region
+     (concat ";;; " (file-name-nondirectory file)
+            " --- automatically extracted autoloads\n"
+            ";;\n"
+            ";;; Code:\n\n"
+            "\f\n;; Local Variables:\n"
+            ";; version-control: never\n"
+            ";; no-byte-compile: t\n"
+            ";; no-update-autoloads: t\n"
+            ";; End:\n"
+            ";;; " (file-name-nondirectory file)
+            "ends here\n")
+     nil file))
+  file)
+
+(defun autoload-insert-section-header (outbuf autoloads load-name file time)
+  "Insert the section-header line,
+which lists the file name and which functions are in it, etc."
+  (insert generate-autoload-section-header)
+  (prin1 (list 'autoloads autoloads load-name
+              (if (stringp file) (autoload-trim-file-name file) file)
+              time)
+        outbuf)
+  (terpri outbuf)
+  ;; Break that line at spaces, to avoid very long lines.
+  ;; Make each sub-line into a comment.
+  (with-current-buffer outbuf
+    (save-excursion
+      (forward-line -1)
+      (while (not (eolp))
+       (move-to-column 64)
+       (skip-chars-forward "^ \n")
+       (or (eolp)
+           (insert "\n" generate-autoload-section-continuation))))))
+
 (defun generate-file-autoloads (file)
   "Insert at point a loaddefs autoload section for FILE.
 autoloads are generated for defuns and defmacros in FILE
 (defun generate-file-autoloads (file)
   "Insert at point a loaddefs autoload section for FILE.
 autoloads are generated for defuns and defmacros in FILE
@@ -328,22 +366,8 @@ are used."
        (progn
          ;; Insert the section-header line
          ;; which lists the file name and which functions are in it, etc.
        (progn
          ;; Insert the section-header line
          ;; which lists the file name and which functions are in it, etc.
-         (insert generate-autoload-section-header)
-         (prin1 (list 'autoloads autoloads-done load-name
-                      (autoload-trim-file-name file)
-                      (nth 5 (file-attributes file)))
-                outbuf)
-         (terpri outbuf)
-         ;; Break that line at spaces, to avoid very long lines.
-         ;; Make each sub-line into a comment.
-         (with-current-buffer outbuf
-           (save-excursion
-             (forward-line -1)
-             (while (not (eolp))
-               (move-to-column 64)
-               (skip-chars-forward "^ \n")
-               (or (eolp)
-                   (insert "\n" generate-autoload-section-continuation)))))
+         (autoload-insert-section-header outbuf autoloads-done load-name file
+                                         (nth 5 (file-attributes file)))
          (insert ";;; Generated autoloads from "
                  (autoload-trim-file-name file) "\n")
          (goto-char output-end)
          (insert ";;; Generated autoloads from "
                  (autoload-trim-file-name file) "\n")
          (goto-char output-end)
@@ -353,14 +377,16 @@ are used."
 ;;;###autoload
 (defun update-file-autoloads (file)
   "Update the autoloads for FILE in `generated-autoload-file'
 ;;;###autoload
 (defun update-file-autoloads (file)
   "Update the autoloads for FILE in `generated-autoload-file'
-\(which FILE might bind in its local variables)."
+\(which FILE might bind in its local variables).
+Return FILE if there was no autoload cookie in it."
   (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)))
        (found nil)
   (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)))
        (found nil)
-       (existing-buffer (get-file-buffer file)))
+       (existing-buffer (get-file-buffer file))
+       (no-autoloads nil))
     (save-excursion
       ;; We want to get a value for generated-autoload-file from
       ;; the local variables section if it's there.
     (save-excursion
       ;; We want to get a value for generated-autoload-file from
       ;; the local variables section if it's there.
@@ -370,9 +396,10 @@ are used."
       ;; but still decode EOLs.
       (let ((coding-system-for-read 'raw-text))
        (set-buffer (find-file-noselect
       ;; but still decode EOLs.
       (let ((coding-system-for-read 'raw-text))
        (set-buffer (find-file-noselect
-                    (expand-file-name generated-autoload-file
-                                      (expand-file-name "lisp"
-                                                        source-directory))))
+                    (autoload-ensure-default-file
+                     (expand-file-name generated-autoload-file
+                                       (expand-file-name "lisp"
+                                                         source-directory)))))
        ;; This is to make generated-autoload-file have Unix EOLs, so
        ;; that it is portable to all platforms.
        (setq buffer-file-coding-system 'raw-text-unix))
        ;; This is to make generated-autoload-file have Unix EOLs, so
        ;; that it is portable to all platforms.
        (setq buffer-file-coding-system 'raw-text-unix))
@@ -397,10 +424,7 @@ are used."
                       (if (and (or (null existing-buffer)
                                    (not (buffer-modified-p existing-buffer)))
                                (listp last-time) (= (length last-time) 2)
                       (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)))))
+                               (not (autoload-before-p last-time file-time)))
                           (progn
                             (if (interactive-p)
                                 (message "\
                           (progn
                             (if (interactive-p)
                                 (message "\
@@ -450,13 +474,26 @@ Autoload section for %s is up to date."
                                 nil
                               (if (interactive-p)
                                   (message "%s has no autoloads" file))
                                 nil
                               (if (interactive-p)
                                   (message "%s has no autoloads" file))
+                              (setq no-autoloads t)
                               t)
                           (or existing-buffer
                               (kill-buffer (current-buffer))))))))
              (generate-file-autoloads file))))
       (and (interactive-p)
           (buffer-modified-p)
                               t)
                           (or existing-buffer
                               (kill-buffer (current-buffer))))))))
              (generate-file-autoloads file))))
       (and (interactive-p)
           (buffer-modified-p)
-          (save-buffer)))))
+          (save-buffer))
+
+      (if no-autoloads file))))
+
+(defun autoload-before-p (time1 time2)
+  (or (< (car time1) (car time2))
+      (and (= (car time1) (car time2))
+          (< (nth 1 time1) (nth 1 time2)))))
+
+(defun autoload-remove-section (begin)
+  (goto-char begin)
+  (search-forward generate-autoload-section-trailer)
+  (delete-region begin (point)))
 
 ;;;###autoload
 (defun update-autoloads-from-directories (&rest dirs)
 
 ;;;###autoload
 (defun update-autoloads-from-directories (&rest dirs)
@@ -464,37 +501,67 @@ Autoload section for %s is up to date."
 Update loaddefs.el with all the current autoloads from DIRS, and no old ones.
 This uses `update-file-autoloads' (which see) do its work."
   (interactive "DUpdate autoloads from directory: ")
 Update loaddefs.el with all the current autoloads from DIRS, and no old ones.
 This uses `update-file-autoloads' (which see) do its work."
   (interactive "DUpdate autoloads from directory: ")
-  (let ((files (apply 'nconc
-                     (mapcar (function (lambda (dir)
-                                         (directory-files (expand-file-name dir)
-                                                          t
-                                                          "^[^=.].*\\.el$")))
-                             dirs)))
-       autoloads-file
-       top-dir)
-    (setq autoloads-file
+  (let* ((files (apply 'nconc
+                      (mapcar (lambda (dir)
+                                (directory-files (expand-file-name dir)
+                                                 ;; FIXME: add .gz etc...
+                                                 t "^[^=.].*\\.el\\'"))
+                              dirs)))
+        (this-time (current-time))
+        (no-autoloads nil)             ;files with no autoload cookies.
+        (autoloads-file
          (expand-file-name generated-autoload-file
          (expand-file-name generated-autoload-file
-                           (expand-file-name "lisp"
-                                             source-directory)))
-    (setq top-dir (file-name-directory autoloads-file))
-    (save-excursion
-      (set-buffer (find-file-noselect autoloads-file))
+                           (expand-file-name "lisp" source-directory)))
+        (top-dir (file-name-directory autoloads-file)))
+
+    (with-current-buffer
+       (find-file-noselect (autoload-ensure-default-file autoloads-file))
       (save-excursion
       (save-excursion
+
+       ;; Canonicalize file names and remove the autoload file itself.
+       (setq files (delete (autoload-trim-file-name buffer-file-name)
+                           (mapcar 'autoload-trim-file-name files)))
+
        (goto-char (point-min))
        (while (search-forward generate-autoload-section-header nil t)
          (let* ((form (autoload-read-section-header))
                 (file (nth 3 form)))
        (goto-char (point-min))
        (while (search-forward generate-autoload-section-header nil t)
          (let* ((form (autoload-read-section-header))
                 (file (nth 3 form)))
-           (cond ((not (stringp file)))
+           (cond ((and (consp file) (stringp (car file)))
+                  ;; This is a list of files that have no autoload cookies.
+                  ;; There shouldn't be more than one such entry.
+                  ;; Remove the obsolete section.
+                  (autoload-remove-section (match-beginning 0))
+                  (let ((last-time (nth 4 form)))
+                    (dolist (file file)
+                      (let ((file-time (nth 5 (file-attributes file))))
+                        (when (and file-time
+                                   (not (autoload-before-p last-time
+                                                           file-time)))
+                          ;; file unchanged
+                          (push file no-autoloads)
+                          (setq files (delete file files)))))))
+                 ((not (stringp file)))
                  ((not (file-exists-p (expand-file-name file top-dir)))
                   ;; Remove the obsolete section.
                  ((not (file-exists-p (expand-file-name file top-dir)))
                   ;; Remove the obsolete section.
-                  (let ((begin (match-beginning 0)))
-                    (search-forward generate-autoload-section-trailer)
-                    (delete-region begin (point))))
+                  (autoload-remove-section (match-beginning 0)))
+                 ((equal (nth 4 form) (nth 5 (file-attributes file)))
+                  ;; File hasn't changed.
+                  nil)
                  (t
                   (update-file-autoloads file)))
            (setq files (delete file files)))))
                  (t
                   (update-file-autoloads file)))
            (setq files (delete file files)))))
-      ;; Elements remaining in FILES have no existing autoload sections.
-      (mapcar 'update-file-autoloads files)
+      ;; Elements remaining in FILES have no existing autoload sections yet.
+      (setq no-autoloads
+           (append no-autoloads
+                   (delq nil (mapcar 'update-file-autoloads files))))
+      (when no-autoloads
+       ;; Add the `no-autoloads' section.
+       (goto-char (point-max))
+       (search-backward "\f" nil t)
+       (autoload-insert-section-header
+        (current-buffer) nil nil no-autoloads this-time)
+       (insert generate-autoload-section-trailer))
+
       (save-buffer))))
 
 ;;;###autoload
       (save-buffer))))
 
 ;;;###autoload