comparison lisp/utils/autoload.el @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents d620409f5eb8
children c7528f8e288d
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
1 ;;; autoload.el --- maintain autoloads in loaddefs.el. 1 ;;; autoload.el --- maintain autoloads in loaddefs.el.
2
2 ;;; Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. 3 ;;; Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3 ;;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. 4 ;;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
4 ;;; Copyright (C) 1996 Ben Wing. 5 ;;; Copyright (C) 1996 Ben Wing.
5 6
6 ;; Author: Roland McGrath <roland@gnu.ai.mit.edu> 7 ;; Author: Roland McGrath <roland@gnu.ai.mit.edu>
7 ;; Keywords: maint 8 ;; Keywords: maint
8 9
9 ;; This file is part of XEmacs. 10 ;;; This program is free software; you can redistribute it and/or modify
10 11 ;;; it under the terms of the GNU General Public License as published by
11 ;; XEmacs is free software; you can redistribute it and/or modify it 12 ;;; the Free Software Foundation; either version 2, or (at your option)
12 ;; under the terms of the GNU General Public License as published by 13 ;;; any later version.
13 ;; the Free Software Foundation; either version 2, or (at your option) 14 ;;;
14 ;; any later version. 15 ;;; This program is distributed in the hope that it will be useful,
15 16 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; XEmacs is distributed in the hope that it will be useful, but 17 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of 18 ;;; GNU General Public License for more details.
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 ;;;
19 ;; General Public License for more details. 20 ;;; A copy of the GNU General Public License can be obtained from this
20 21 ;;; program's author (send electronic mail to roland@ai.mit.edu) or from
21 ;; You should have received a copy of the GNU General Public License 22 ;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
22 ;; along with XEmacs; see the file COPYING. If not, write to the Free 23 ;;; 02139, USA.
23 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 24 ;;;
24 ;; 02111-1307, USA. 25
25 26 ;;; Synched up with: FSF 19.30.
26 ;;; Synched up with: Not synched with FSF.
27 27
28 ;;; Commentary: 28 ;;; Commentary:
29 29
30 ;; This code helps GNU Emacs maintainers keep the loaddefs.el file up to 30 ;; This code helps GNU Emacs maintainers keep the loaddefs.el file up to
31 ;; date. It interprets magic cookies of the form ";;;###autoload" in 31 ;; date. It interprets magic cookies of the form ";;;###autoload" in
57 (if macrop (list 'quote 'macro) nil))) 57 (if macrop (list 'quote 'macro) nil)))
58 nil))) 58 nil)))
59 59
60 (put 'define-skeleton 'doc-string-elt 3) 60 (put 'define-skeleton 'doc-string-elt 3)
61 61
62 (defvar generate-autoload-cookie ";;;###autoload" 62 (defconst generate-autoload-cookie ";;;###autoload"
63 "Magic comment indicating the following form should be autoloaded. 63 "Magic comment indicating the following form should be autoloaded.
64 Used by `update-file-autoloads'. This string should be 64 Used by \\[update-file-autoloads]. This string should be
65 meaningless to Lisp (e.g., a comment). 65 meaningless to Lisp (e.g., a comment).
66 66
67 This string is used: 67 This string is used:
68 68
69 ;;;###autoload 69 ;;;###autoload
70 \(defun function-to-be-autoloaded () ...) 70 \(defun function-to-be-autoloaded () ...)
71 71
72 If this string appears alone on a line, the following form will be 72 If this string appears alone on a line, the following form will be read and
73 read and an autoload made for it. If it is followed by the string 73 an autoload made for it. If it is followed by the string \"immediate\",
74 \"immediate\", then the form on the following line will be copied 74 then the form on the following will be copied verbatim. If there is further
75 verbatim. If there is further text on the line, that text will be 75 text on the line, that text will be copied verbatim to
76 copied verbatim to `generated-autoload-file'.") 76 `generated-autoload-file'.")
77 77
78 (defvar generate-autoload-section-header "\f\n;;;### " 78 (defconst generate-autoload-section-header "\f\n;;;### "
79 "String inserted before the form identifying 79 "String inserted before the form identifying
80 the section of autoloads for a file.") 80 the section of autoloads for a file.")
81 81
82 (defvar generate-autoload-section-trailer "\n;;;***\n" 82 (defconst generate-autoload-section-trailer "\n;;;***\n"
83 "String which indicates the end of the section of autoloads for a file.") 83 "String which indicates the end of the section of autoloads for a file.")
84 84
85 ;;; Forms which have doc-strings which should be printed specially. 85 ;;; Forms which have doc-strings which should be printed specially.
86 ;;; A doc-string-elt property of ELT says that (nth ELT FORM) is 86 ;;; A doc-string-elt property of ELT says that (nth ELT FORM) is
87 ;;; the doc-string in FORM. 87 ;;; the doc-string in FORM.
105 (put 'defvar 'doc-string-elt 3) 105 (put 'defvar 'doc-string-elt 3)
106 (put 'defconst 'doc-string-elt 3) 106 (put 'defconst 'doc-string-elt 3)
107 (put 'defmacro 'doc-string-elt 3) 107 (put 'defmacro 'doc-string-elt 3)
108 108
109 (defun autoload-trim-file-name (file) 109 (defun autoload-trim-file-name (file)
110 "Returns a relative pathname of FILE including the last directory." 110 ;; returns a relative pathname of FILE including the last directory.
111 (setq file (expand-file-name file)) 111 (setq file (expand-file-name file))
112 (file-relative-name file (file-name-directory 112 (file-relative-name file
113 (directory-file-name 113 (file-name-directory
114 (file-name-directory file))))) 114 (directory-file-name
115 (file-name-directory file)))))
115 116
116 ;;;###autoload 117 ;;;###autoload
117 (defun generate-file-autoloads (file &optional funlist) 118 (defun generate-file-autoloads (file &optional funlist)
118 "Insert at point a loaddefs autoload section for FILE. 119 "Insert at point a loaddefs autoload section for FILE.
119 autoloads are generated for defuns and defmacros in FILE 120 autoloads are generated for defuns and defmacros in FILE
120 marked by `generate-autoload-cookie' (which see). 121 marked by `generate-autoload-cookie' (which see).
121 If FILE is being visited in a buffer, the contents of the buffer 122 If FILE is being visited in a buffer, the contents of the buffer
122 are used." 123 are used."
123 (interactive "fGenerate autoloads for file: ") 124 (interactive "fGenerate autoloads for file: ")
124 (generate-file-autoloads-1 file funlist))
125
126 (defun* generate-file-autoloads-1 (file funlist)
127 "Insert at point a loaddefs autoload section for FILE.
128 autoloads are generated for defuns and defmacros in FILE
129 marked by `generate-autoload-cookie' (which see).
130 If FILE is being visited in a buffer, the contents of the buffer
131 are used."
132 (let ((outbuf (current-buffer)) 125 (let ((outbuf (current-buffer))
133 (autoloads-done '()) 126 (autoloads-done '())
134 (load-name (replace-in-string (file-name-nondirectory file) 127 (load-name (let ((name (file-name-nondirectory file)))
135 "\\.elc?$" 128 (if (string-match "\\.elc?$" name)
136 "")) 129 (substring name 0 (match-beginning 0))
137 (trim-name (autoload-trim-file-name file)) 130 name)))
138 (dofiles (not (null funlist))) 131 (dofiles (not (null funlist)))
139 (print-length nil) 132 (print-length nil)
140 (print-readably t) ; XEmacs 133 (print-readably t) ; XEmacs
141 (float-output-format nil) 134 (float-output-format nil)
142 ;; (done-any nil) 135 (done-any nil)
143 (visited (get-file-buffer file)) 136 (visited (get-file-buffer file))
144 output-end) 137 output-end)
145 138
146 ;; If the autoload section we create here uses an absolute 139 ;; If the autoload section we create here uses an absolute
147 ;; pathname for FILE in its header, and then Emacs is installed 140 ;; pathname for FILE in its header, and then Emacs is installed
149 ;; `update-autoloads-here' won't be able to find the files to be 142 ;; `update-autoloads-here' won't be able to find the files to be
150 ;; autoloaded. So, if FILE is in the same directory or a 143 ;; autoloaded. So, if FILE is in the same directory or a
151 ;; subdirectory of the current buffer's directory, we'll make it 144 ;; subdirectory of the current buffer's directory, we'll make it
152 ;; relative to the current buffer's directory. 145 ;; relative to the current buffer's directory.
153 (setq file (expand-file-name file)) 146 (setq file (expand-file-name file))
154 147 (let* ((source-truename (file-truename file))
148 (dir-truename (file-name-as-directory
149 (file-truename default-directory)))
150 (len (length dir-truename)))
151 (if (and (< len (length source-truename))
152 (string= dir-truename (substring source-truename 0 len)))
153 (setq file (substring source-truename len))))
154
155 (message "Generating autoloads for %s..." file)
155 (save-excursion 156 (save-excursion
156 (unwind-protect 157 (unwind-protect
157 (progn 158 (progn
158 (let ((find-file-hooks nil)) 159 (set-buffer (find-file-noselect file))
159 (set-buffer (or visited (find-file-noselect file))))
160 (save-excursion 160 (save-excursion
161 (save-restriction 161 (save-restriction
162 (widen) 162 (widen)
163 (goto-char (point-min))
164 (unless (search-forward generate-autoload-cookie nil t)
165 (message "No autoloads found in %s" trim-name)
166 (return-from generate-file-autoloads-1))
167
168 (message "Generating autoloads for %s..." trim-name)
169 (goto-char (point-min)) 163 (goto-char (point-min))
170 (while (if dofiles funlist (not (eobp))) 164 (while (if dofiles funlist (not (eobp)))
171 (if (not dofiles) 165 (if (not dofiles)
172 (skip-chars-forward " \t\n\f") 166 (skip-chars-forward " \t\n\f")
173 (goto-char (point-min)) 167 (goto-char (point-min))
181 (looking-at (regexp-quote generate-autoload-cookie))) 175 (looking-at (regexp-quote generate-autoload-cookie)))
182 (if dofiles 176 (if dofiles
183 nil 177 nil
184 (search-forward generate-autoload-cookie) 178 (search-forward generate-autoload-cookie)
185 (skip-chars-forward " \t")) 179 (skip-chars-forward " \t"))
186 ;; (setq done-any t) 180 (setq done-any t)
187 (if (or dofiles (eolp)) 181 (if (or dofiles (eolp))
188 ;; Read the next form and make an autoload. 182 ;; Read the next form and make an autoload.
189 (let* ((form (prog1 (read (current-buffer)) 183 (let* ((form (prog1 (read (current-buffer))
190 (or (bolp) (forward-line 1)))) 184 (or (bolp) (forward-line 1))))
191 (autoload (make-autoload form load-name)) 185 (autoload (make-autoload form load-name))
290 (t 284 (t
291 (forward-sexp 1) 285 (forward-sexp 1)
292 (forward-line 1))) 286 (forward-line 1)))
293 (if dofiles 287 (if dofiles
294 (setq funlist (cdr funlist))))))) 288 (setq funlist (cdr funlist)))))))
295 ;;(unless visited 289 (or visited
296 ;; We created this buffer, so we should kill it. 290 ;; We created this buffer, so we should kill it.
297 ;; Customize needs it later, we don't want to read the file 291 (kill-buffer (current-buffer)))
298 ;; in twice.
299 ;;(kill-buffer (current-buffer)))
300 (set-buffer outbuf) 292 (set-buffer outbuf)
301 (setq output-end (point-marker)))) 293 (setq output-end (point-marker))))
302 (if t ;; done-any 294 (if t ;; done-any
303 ;; XEmacs -- always do this so that we cache the information 295 ;; XEmacs -- always do this so that we cache the information
304 ;; that we've processed the file already. 296 ;; that we've processed the file already.
305 (progn 297 (progn
306 (insert generate-autoload-section-header) 298 (insert generate-autoload-section-header)
307 (prin1 (list 'autoloads autoloads-done load-name trim-name) 299 (prin1 (list 'autoloads autoloads-done load-name
300 (autoload-trim-file-name file)
301 (nth 5 (file-attributes file)))
308 outbuf) 302 outbuf)
309 (terpri outbuf) 303 (terpri outbuf)
310 ;;;; (insert ";;; Generated autoloads from " 304 (insert ";;; Generated autoloads from "
311 ;;;; (autoload-trim-file-name file) "\n") 305 (autoload-trim-file-name file) "\n")
312 ;; Warn if we put a line in loaddefs.el 306 ;; Warn if we put a line in loaddefs.el
313 ;; that is long enough to cause trouble. 307 ;; that is long enough to cause trouble.
314 (when (< output-end (point))
315 (setq output-end (point-marker)))
316 (while (< (point) output-end) 308 (while (< (point) output-end)
317 (let ((beg (point))) 309 (let ((beg (point)))
318 (end-of-line) 310 (end-of-line)
319 (if (> (- (point) beg) 900) 311 (if (> (- (point) beg) 900)
320 (progn 312 (progn
324 (forward-line 1)) 316 (forward-line 1))
325 (goto-char output-end) 317 (goto-char output-end)
326 (insert generate-autoload-section-trailer))) 318 (insert generate-autoload-section-trailer)))
327 (or noninteractive ; XEmacs: only need one line in -batch mode. 319 (or noninteractive ; XEmacs: only need one line in -batch mode.
328 (message "Generating autoloads for %s...done" file)))) 320 (message "Generating autoloads for %s...done" file))))
329
330 321
331 (defvar generated-autoload-file 322 (defconst generated-autoload-file (expand-file-name "../lisp/prim/loaddefs.el"
332 (expand-file-name "../lisp/prim/auto-autoloads.el" data-directory) 323 data-directory)
333 "*File `update-file-autoloads' puts autoloads into. 324 "*File \\[update-file-autoloads] puts autoloads into.
334 A .el file can set this in its local variables section to make its 325 A .el file can set this in its local variables section to make its
335 autoloads go somewhere else.") 326 autoloads go somewhere else.")
336 327
337 (defvar generated-custom-file 328 (defvar generate-autoload-dynamic-but-inefficient nil
338 (expand-file-name "../lisp/prim/custom-load.el" data-directory) 329 "If non-nil, `update-file-autoloads' will always read in its files.
339 "*File `update-file-autoloads' puts customization into.") 330 This allows you to bind `generated-autoload-file' in your local variables
340 331 (do you really want to do that?) but makes it very slow in updating
341 ;; Written by Per Abrahamsen 332 lots of files.")
342 (defun autoload-snarf-defcustom (file)
343 "Snarf all customizations in the current buffer."
344 (let ((visited (get-file-buffer file)))
345 (save-excursion
346 (set-buffer (or visited (find-file-noselect file)))
347 (when (and file
348 (string-match "\\`\\(.*\\)\\.el\\'" file)
349 (not (buffer-modified-p)))
350 (goto-char (point-min))
351 (condition-case nil
352 (let ((name (file-name-nondirectory (match-string 1 file))))
353 (while t
354 (let ((expr (read (current-buffer))))
355 (when (and (listp expr)
356 (memq (car expr) '(defcustom defface defgroup)))
357 (eval expr)
358 (put (nth 1 expr) 'custom-where name)))))
359 (error nil)))
360 (unless (buffer-modified-p)
361 (kill-buffer (current-buffer))))))
362 333
363 ;;;###autoload 334 ;;;###autoload
364 (defun update-file-autoloads (file) 335 (defun update-file-autoloads (file)
365 "Update the autoloads for FILE in `generated-autoload-file' 336 "Update the autoloads for FILE in `generated-autoload-file'
366 \(which FILE might bind in its local variables)." 337 \(which FILE might bind in its local variables)."
367 (interactive "fUpdate autoloads for file: ") 338 (interactive "fUpdate autoloads for file: ")
368 (setq file (expand-file-name file)) 339 ;; avoid horrid horrid problems with relative filenames.
369 (let ((load-name (replace-in-string (file-name-nondirectory file) 340 (setq file (expand-file-name file default-directory))
370 "\\.elc?$" 341 (let ((load-name (let ((name (file-name-nondirectory file)))
371 "")) 342 (if (string-match "\\.elc?$" name)
343 (substring name 0 (match-beginning 0))
344 name)))
372 (trim-name (autoload-trim-file-name file)) 345 (trim-name (autoload-trim-file-name file))
373 section-begin form) 346 (found nil)
347 (pass 'first)
348 (existing-buffer (get-file-buffer file)))
374 (save-excursion 349 (save-excursion
375 (let ((find-file-hooks nil)) 350 ;; We want to get a value for generated-autoload-file from
376 (set-buffer (or (get-file-buffer generated-autoload-file) 351 ;; the local variables section if it's there.
377 (find-file-noselect generated-autoload-file)))) 352 (and generate-autoload-dynamic-but-inefficient
378 ;; First delete all sections for this file. 353 (set-buffer (find-file-noselect file)))
379 (goto-char (point-min)) 354 (set-buffer (or (get-file-buffer generated-autoload-file)
380 (while (search-forward generate-autoload-section-header nil t) 355 (find-file-noselect generated-autoload-file)))
381 (setq section-begin (match-beginning 0)) 356 (save-excursion
382 (setq form (read (current-buffer))) 357 (save-restriction
383 (when (string= (nth 2 form) load-name) 358 (widen)
384 (search-forward generate-autoload-section-trailer) 359 (while pass
385 (delete-region section-begin (point)))) 360 ;; This is done in two passes:
386 361 ;; 1st pass: Look for the section for LOAD-NAME anywhere in the file.
387 ;; Now find insertion point for new section 362 ;; 2st pass: Find a place to insert it. Use alphabetical order.
388 (block find-insertion-point 363 (goto-char (point-min))
389 (goto-char (point-min)) 364 (while (and (not found)
390 (while (search-forward generate-autoload-section-header nil t) 365 (search-forward generate-autoload-section-header nil t))
391 (setq form (read (current-buffer))) 366 (let ((form (condition-case ()
392 (when (string< trim-name (nth 3 form)) 367 (read (current-buffer))
393 ;; Found alphabetically correct insertion point 368 (end-of-file nil))))
394 (goto-char (match-beginning 0)) 369 (cond ((and (eq pass 'first)
395 (return-from find-insertion-point)) 370 (string= (nth 2 form) load-name))
396 (search-forward generate-autoload-section-trailer)) 371 ;; We found the section for this file.
397 (when (eq (point) (point-min)) ; No existing entries? 372 ;; Check if it is up to date.
398 (goto-char (point-max)))) ; Append. 373 (let ((begin (match-beginning 0))
399 374 (last-time (nth 4 form))
400 ;; Add in new sections for file 375 (file-time (nth 5 (file-attributes file))))
401 (generate-file-autoloads file) 376 (if (and (or (null existing-buffer)
402 (autoload-snarf-defcustom file)) 377 (not (buffer-modified-p existing-buffer)))
403 378 (listp last-time) (= (length last-time) 2)
404 (when (interactive-p) (save-buffer)))) 379 (or (> (car last-time) (car file-time))
380 (and (= (car last-time) (car file-time))
381 (>= (nth 1 last-time)
382 (nth 1 file-time)))))
383 (progn
384 (or noninteractive
385 ;; jwz: too loud in -batch mode
386 (message
387 "Autoload section for %s is up to date."
388 file))
389 (setq found 'up-to-date))
390 ;; Okay, we found it and it's not up to date...
391 (search-forward generate-autoload-section-trailer)
392 (delete-region begin (point))
393 ;; if the file has moved, then act like it hasn't
394 ;; been found and then reinsert it alphabetically.
395 (setq found (string= trim-name (nth 3 form)))
396 )))
397 ;; XEmacs change -- we organize by sub-directories
398 ;; so inserting new autoload entries is a bit tricky...
399 ((and (eq pass 'last)
400 (string< trim-name (nth 3 form)))
401 ;; We've come to a section alphabetically later than
402 ;; LOAD-NAME. We assume the file is in order and so
403 ;; there must be no section for LOAD-NAME. We will
404 ;; insert one before the section here.
405 (goto-char (match-beginning 0))
406 (setq found 'new))
407 )))
408 (cond (found
409 (setq pass nil)) ; success -- exit loop
410 ((eq pass 'first)
411 (setq pass 'last))
412 (t
413 ;; failure -- exit loop
414 (setq pass nil))))
415 (or (eq found 'up-to-date)
416 ;; XEmacs -- don't do the following. If we do, then
417 ;; every time we update autoloads we have to search
418 ;; the whole file (yuck).
419 ; (and (eq found 'new)
420 ; ;; Check that FILE has any cookies before generating a
421 ; ;; new section for it.
422 ; (save-excursion
423 ; (set-buffer (find-file-noselect file))
424 ; (save-excursion
425 ; (widen)
426 ; (goto-char (point-min))
427 ; (if (search-forward (concat "\n"
428 ; generate-autoload-cookie)
429 ; nil t)
430 ; nil
431 ; (if (interactive-p)
432 ; (message file " has no autoloads"))
433 ; t))))
434 (generate-file-autoloads file))))
435 (if (interactive-p) (save-buffer))
436 (if (and (null existing-buffer)
437 (setq existing-buffer (get-file-buffer file)))
438 (kill-buffer existing-buffer)))))
405 439
406 ;;;###autoload 440 ;;;###autoload
407 (defun update-autoloads-here () 441 (defun update-autoloads-here ()
408 "Update sections of the current buffer generated by `update-file-autoloads'." 442 "\
443 Update sections of the current buffer generated by \\[update-file-autoloads]."
409 (interactive) 444 (interactive)
410 (let ((generated-autoload-file (buffer-file-name))) 445 (let ((generated-autoload-file (buffer-file-name)))
411 (save-excursion 446 (save-excursion
412 (goto-char (point-min)) 447 (goto-char (point-min))
413 (while (search-forward generate-autoload-section-header nil t) 448 (while (search-forward generate-autoload-section-header nil t)
432 (if (or (get-file-buffer loc) 467 (if (or (get-file-buffer loc)
433 (file-exists-p loc)) 468 (file-exists-p loc))
434 (setq file loc) 469 (setq file loc)
435 nil)))))) 470 nil))))))
436 (t 471 (t
437 (setq file 472 (setq file (if (y-or-n-p (format "Can't find library `%s'; remove its autoloads? "
438 (if (y-or-n-p 473 (nth 2 form) file))
439 (format 474 t
440 "Can't find library `%s'; remove its autoloads? " 475 (condition-case ()
441 (nth 2 form) file)) 476 (read-file-name
442 t 477 (format "Find `%s' load file: "
443 (condition-case () 478 (nth 2 form))
444 (read-file-name 479 nil nil t)
445 (format "Find `%s' load file: " 480 (quit nil))))))
446 (nth 2 form))
447 nil nil t)
448 (quit nil))))))
449 (if file 481 (if file
450 (let ((begin (match-beginning 0))) 482 (let ((begin (match-beginning 0)))
451 (search-forward generate-autoload-section-trailer) 483 (search-forward generate-autoload-section-trailer)
452 (delete-region begin (point)))) 484 (delete-region begin (point))))
453 (if (stringp file) 485 (if (stringp file)
454 (generate-file-autoloads file))))))) 486 (generate-file-autoloads file)))))))
455 487
456 ;;;###autoload 488 ;;;###autoload
457 (defun update-autoloads-from-directory (dir) 489 (defun update-directory-autoloads (dir)
458 "Update `generated-autoload-file' with all the current autoloads from DIR. 490 "Run \\[update-file-autoloads] on each .el file in DIR."
459 This runs `update-file-autoloads' on each .el file in DIR.
460 Obsolete autoload entries for files that no longer exist are deleted."
461 (interactive "DUpdate autoloads for directory: ") 491 (interactive "DUpdate autoloads for directory: ")
462 (setq dir (expand-file-name dir)) 492 (let ((enable-local-eval nil))
463 (let ((simple-dir (file-name-as-directory 493 (mapcar 'update-file-autoloads
464 (file-name-nondirectory 494 (directory-files dir t "^[^=].*\\.el$")))
465 (directory-file-name dir)))) 495 (if (interactive-p)
466 (enable-local-eval nil)) 496 (save-excursion
467 (save-excursion 497 (set-buffer (find-file-noselect generated-autoload-file))
468 (let ((find-file-hooks nil)) 498 (save-buffer))))
469 (set-buffer (find-file-noselect generated-autoload-file)))
470 (goto-char (point-min))
471 (while (search-forward generate-autoload-section-header nil t)
472 (let* ((begin (match-beginning 0))
473 (form (condition-case ()
474 (read (current-buffer))
475 (end-of-file nil)))
476 (file (nth 3 form)))
477 (when (and (stringp file)
478 (string= (file-name-directory file) simple-dir)
479 (not (file-exists-p
480 (expand-file-name
481 (file-name-nondirectory file) dir))))
482 ;; Remove the obsolete section.
483 (search-forward generate-autoload-section-trailer)
484 (delete-region begin (point)))))
485 ;; Update or create autoload sections for existing files.
486 (mapcar 'update-file-autoloads (directory-files dir t "^[^=].*\\.el$"))
487 (unless noninteractive
488 (save-buffer)))))
489
490 ;; Based on code from Per Abrahamsen
491 (defun autoload-save-customization ()
492 (save-excursion
493 (set-buffer (find-file-noselect generated-custom-file))
494 (erase-buffer)
495 (insert
496 (with-output-to-string
497 (mapatoms (lambda (symbol)
498 (let ((members (get symbol 'custom-group))
499 item where found)
500 (when members
501 (princ "(put '")
502 (princ symbol)
503 (princ " 'custom-loads '(")
504 (while members
505 (setq item (car (car members))
506 members (cdr members)
507 where (get item 'custom-where))
508 (unless (or (null where)
509 (member where found))
510 (when found
511 (princ " "))
512 (prin1 where)
513 (push where found)))
514 (princ "))\n")))))))))
515 499
516 ;;;###autoload 500 ;;;###autoload
517 (defun batch-update-autoloads () 501 (defun batch-update-autoloads ()
518 "Update the autoloads for the files or directories on the command line. 502 "Update the autoloads for the files or directories on the command line.
519 Runs `update-file-autoloads' on files and `update-directory-autoloads' 503 Runs \\[update-file-autoloads] on files and \\[update-directory-autoloads]
520 on directories. Must be used only with -batch, and kills Emacs on completion. 504 on directories. Must be used only with -batch, and kills Emacs on completion.
521 Each file will be processed even if an error occurred previously. 505 Each file will be processed even if an error occurred previously.
522 For example, invoke `xemacs -batch -f batch-update-autoloads *.el'." 506 For example, invoke `emacs -batch -f batch-update-autoloads *.el'."
523 (unless noninteractive 507 (if (not noninteractive)
524 (error "batch-update-autoloads is to be used only with -batch")) 508 (error "batch-update-autoloads is to be used only with -batch"))
525 (let ((defdir default-directory) 509 (let ((lost nil)
526 (enable-local-eval nil)) ; Don't query in batch mode. 510 (args command-line-args-left)
511 (defdir default-directory)
512 (enable-local-eval nil)) ;Don't query in batch mode.
527 (message "Updating autoloads in %s..." generated-autoload-file) 513 (message "Updating autoloads in %s..." generated-autoload-file)
528 (dolist (arg command-line-args-left) 514 (let ((frob (function
529 (setq arg (expand-file-name arg defdir)) 515 (lambda (file)
530 (cond 516 (condition-case lossage
531 ((file-directory-p arg) 517 (let ((default-directory defdir))
532 (message "Updating autoloads for directory %s..." arg) 518 (update-file-autoloads file))
533 (update-autoloads-from-directory arg)) 519 (error
534 ((file-exists-p arg) 520 (princ ">>Error processing ")
535 (update-file-autoloads arg)) 521 (princ file)
536 (t (error "No such file or directory: %s" arg)))) 522 (princ ": ")
537 (autoload-save-customization) 523 (if (fboundp 'display-error)
524 (display-error lossage nil)
525 (prin1 lossage))
526 (princ "\n")
527 (setq lost t)))))))
528 (while args
529 (if (file-directory-p (expand-file-name (car args)))
530 (let ((rest (directory-files (car args) t "\\.el$")))
531 (if noninteractive
532 (message "Processing directory %s..." (car args)))
533 (while rest
534 (funcall frob (car rest))
535 (setq rest (cdr rest))))
536 (funcall frob (car args)))
537 (setq args (cdr args))))
538 (save-some-buffers t) 538 (save-some-buffers t)
539 (message "Done") 539 (message "Done")
540 (kill-emacs 0))) 540 (kill-emacs (if lost 1 0))))
541 541
542 (provide 'autoload) 542 (provide 'autoload)
543 543
544 ;;; autoload.el ends here 544 ;;; autoload.el ends here