comparison lisp/emacs-lisp/autoload.el @ 81622:9d32dd7131c3

(autoload-find-destination): Return nil rather than throwing `up-to-date'. (autoload-generate-file-autoloads): Adjust correspondingly. (update-file-autoloads): Be careful to let-bind autoload-modified-buffers and adjust to new calling conventions. (autoload-modified-buffers): Make it a dynamically scoped var. (update-directory-autoloads): Use file-relative-name instead of autoload-trim-file-name. (autoload-insert-section-header): Don't use autoload-trim-file-name since the file is already relative now. (autoload-trim-file-name): Remove.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Tue, 26 Jun 2007 19:07:14 +0000
parents 56b815dd1abb
children 835baa7a130c
comparison
equal deleted inserted replaced
81621:6683a94d3fcb 81622:9d32dd7131c3
65 (defconst generate-autoload-section-trailer "\n;;;***\n" 65 (defconst generate-autoload-section-trailer "\n;;;***\n"
66 "String which indicates the end of the section of autoloads for a file.") 66 "String which indicates the end of the section of autoloads for a file.")
67 67
68 (defconst generate-autoload-section-continuation ";;;;;; " 68 (defconst generate-autoload-section-continuation ";;;;;; "
69 "String to add on each continuation of the section header form.") 69 "String to add on each continuation of the section header form.")
70
71 (defvar autoload-modified-buffers) ;Dynamically scoped var.
70 72
71 (defun make-autoload (form file) 73 (defun make-autoload (form file)
72 "Turn FORM into an autoload or defvar for source file FILE. 74 "Turn FORM into an autoload or defvar for source file FILE.
73 Returns nil if FORM is not a special autoload form (i.e. a function definition 75 Returns nil if FORM is not a special autoload form (i.e. a function definition
74 or macro definition or a defcustom)." 76 or macro definition or a defcustom)."
154 156
155 (defun autoload-generated-file () 157 (defun autoload-generated-file ()
156 (expand-file-name generated-autoload-file 158 (expand-file-name generated-autoload-file
157 (expand-file-name "lisp" 159 (expand-file-name "lisp"
158 source-directory))) 160 source-directory)))
159
160 (defun autoload-trim-file-name (file)
161 ;; Returns a relative file path for FILE
162 ;; starting from the directory that loaddefs.el is in.
163 ;; That is normally a directory in load-path,
164 ;; which means Emacs will be able to find FILE when it looks.
165 ;; Any extra directory names here would prevent finding the file.
166 (setq file (expand-file-name file))
167 (file-relative-name file
168 (file-name-directory generated-autoload-file)))
169 161
170 (defun autoload-read-section-header () 162 (defun autoload-read-section-header ()
171 "Read a section header form. 163 "Read a section header form.
172 Since continuation lines have been marked as comments, 164 Since continuation lines have been marked as comments,
173 we must copy the text of the form and remove those comment 165 we must copy the text of the form and remove those comment
258 250
259 (defun autoload-insert-section-header (outbuf autoloads load-name file time) 251 (defun autoload-insert-section-header (outbuf autoloads load-name file time)
260 "Insert the section-header line, 252 "Insert the section-header line,
261 which lists the file name and which functions are in it, etc." 253 which lists the file name and which functions are in it, etc."
262 (insert generate-autoload-section-header) 254 (insert generate-autoload-section-header)
263 (prin1 (list 'autoloads autoloads load-name 255 (prin1 (list 'autoloads autoloads load-name file time)
264 (if (stringp file) (autoload-trim-file-name file) file)
265 time)
266 outbuf) 256 outbuf)
267 (terpri outbuf) 257 (terpri outbuf)
268 ;; Break that line at spaces, to avoid very long lines. 258 ;; Break that line at spaces, to avoid very long lines.
269 ;; Make each sub-line into a comment. 259 ;; Make each sub-line into a comment.
270 (with-current-buffer outbuf 260 (with-current-buffer outbuf
316 Autoloads are generated for defuns and defmacros in FILE 306 Autoloads are generated for defuns and defmacros in FILE
317 marked by `generate-autoload-cookie' (which see). 307 marked by `generate-autoload-cookie' (which see).
318 If FILE is being visited in a buffer, the contents of the buffer are used. 308 If FILE is being visited in a buffer, the contents of the buffer are used.
319 OUTBUF is the buffer in which the autoload statements will be inserted. 309 OUTBUF is the buffer in which the autoload statements will be inserted.
320 If OUTBUF is nil, it will be determined by `autoload-generated-file'. 310 If OUTBUF is nil, it will be determined by `autoload-generated-file'.
321 Return non-nil in the case where no autoloads were added to OUTBUF. 311
322 312 Return non-nil iff FILE adds no autoloads to OUTBUF."
323 Can throw `up-to-date' to mean that the entries were found already and are 313 (catch 'done
324 up-to-date. Of course, this can only be the case if OUTBUF is not used." 314 (let ((autoloads-done '())
325 (let ((autoloads-done '()) 315 (load-name (autoload-file-load-name file))
326 (load-name (autoload-file-load-name file)) 316 (print-length nil)
327 (print-length nil) 317 (print-readably t) ; This does something in Lucid Emacs.
328 (print-readably t) ; This does something in Lucid Emacs. 318 (float-output-format nil)
329 (float-output-format nil) 319 (visited (get-file-buffer file))
330 (visited (get-file-buffer file)) 320 (absfile (expand-file-name file))
331 (absfile (expand-file-name file)) 321 relfile
332 relfile 322 ;; nil until we found a cookie.
333 ;; nil until we found a cookie. 323 output-start)
334 output-start) 324
335 325 (with-current-buffer (or visited
336 (with-current-buffer (or visited 326 ;; It is faster to avoid visiting the file.
337 ;; It is faster to avoid visiting the file. 327 (autoload-find-file file))
338 (autoload-find-file file)) 328 ;; Obey the no-update-autoloads file local variable.
339 ;; Obey the no-update-autoloads file local variable. 329 (unless no-update-autoloads
340 (unless no-update-autoloads 330 (message "Generating autoloads for %s..." file)
341 (message "Generating autoloads for %s..." file) 331 (save-excursion
342 (save-excursion 332 (save-restriction
343 (save-restriction 333 (widen)
344 (widen) 334 (goto-char (point-min))
345 (goto-char (point-min)) 335 (while (not (eobp))
346 (while (not (eobp)) 336 (skip-chars-forward " \t\n\f")
347 (skip-chars-forward " \t\n\f") 337 (cond
348 (cond 338 ((looking-at (regexp-quote generate-autoload-cookie))
349 ((looking-at (regexp-quote generate-autoload-cookie)) 339 ;; If not done yet, figure out where to insert this text.
350 ;; If not done yet, figure out where to insert this text. 340 (unless output-start
351 (unless output-start 341 (unless outbuf
352 (unless outbuf 342 (setq outbuf (autoload-find-destination absfile))
353 (setq outbuf (autoload-find-destination absfile))) 343 (unless outbuf
354 (with-current-buffer outbuf 344 ;; The file has autoload cookies, but they're
355 (setq relfile (file-relative-name absfile)) 345 ;; already up-to-date.
356 (setq output-start (point))) 346 (throw 'done t)))
357 ;; (message "file=%S, relfile=%S, dest=%S" 347 (with-current-buffer outbuf
358 ;; file relfile (autoload-generated-file)) 348 (setq relfile (file-relative-name absfile))
359 ) 349 (setq output-start (point)))
360 (search-forward generate-autoload-cookie) 350 ;; (message "file=%S, relfile=%S, dest=%S"
361 (skip-chars-forward " \t") 351 ;; file relfile (autoload-generated-file))
362 (if (eolp) 352 )
363 (condition-case err 353 (search-forward generate-autoload-cookie)
364 ;; Read the next form and make an autoload. 354 (skip-chars-forward " \t")
365 (let* ((form (prog1 (read (current-buffer)) 355 (if (eolp)
366 (or (bolp) (forward-line 1)))) 356 (condition-case err
367 (autoload (make-autoload form load-name))) 357 ;; Read the next form and make an autoload.
368 (if autoload 358 (let* ((form (prog1 (read (current-buffer))
369 (push (nth 1 form) autoloads-done) 359 (or (bolp) (forward-line 1))))
370 (setq autoload form)) 360 (autoload (make-autoload form load-name)))
371 (let ((autoload-print-form-outbuf outbuf)) 361 (if autoload
372 (autoload-print-form autoload))) 362 (push (nth 1 form) autoloads-done)
373 (error 363 (setq autoload form))
374 (message "Error in %s: %S" file err))) 364 (let ((autoload-print-form-outbuf outbuf))
375 365 (autoload-print-form autoload)))
376 ;; Copy the rest of the line to the output. 366 (error
377 (princ (buffer-substring 367 (message "Error in %s: %S" file err)))
378 (progn 368
379 ;; Back up over whitespace, to preserve it. 369 ;; Copy the rest of the line to the output.
380 (skip-chars-backward " \f\t") 370 (princ (buffer-substring
381 (if (= (char-after (1+ (point))) ? ) 371 (progn
382 ;; Eat one space. 372 ;; Back up over whitespace, to preserve it.
383 (forward-char 1)) 373 (skip-chars-backward " \f\t")
384 (point)) 374 (if (= (char-after (1+ (point))) ? )
385 (progn (forward-line 1) (point))) 375 ;; Eat one space.
386 outbuf))) 376 (forward-char 1))
387 ((looking-at ";") 377 (point))
388 ;; Don't read the comment. 378 (progn (forward-line 1) (point)))
389 (forward-line 1)) 379 outbuf)))
390 (t 380 ((looking-at ";")
391 (forward-sexp 1) 381 ;; Don't read the comment.
392 (forward-line 1)))))) 382 (forward-line 1))
393 383 (t
394 (when output-start 384 (forward-sexp 1)
395 (with-current-buffer outbuf 385 (forward-line 1))))))
396 (save-excursion 386
397 ;; Insert the section-header line which lists the file name 387 (when output-start
398 ;; and which functions are in it, etc. 388 (with-current-buffer outbuf
399 (goto-char output-start) 389 (save-excursion
400 (autoload-insert-section-header 390 ;; Insert the section-header line which lists the file name
401 outbuf autoloads-done load-name relfile 391 ;; and which functions are in it, etc.
402 (nth 5 (file-attributes relfile))) 392 (goto-char output-start)
403 (insert ";;; Generated autoloads from " relfile "\n")) 393 (autoload-insert-section-header
404 (insert generate-autoload-section-trailer))) 394 outbuf autoloads-done load-name relfile
405 (message "Generating autoloads for %s...done" file)) 395 (nth 5 (file-attributes relfile)))
406 (or visited 396 (insert ";;; Generated autoloads from " relfile "\n"))
407 ;; We created this buffer, so we should kill it. 397 (insert generate-autoload-section-trailer)))
408 (kill-buffer (current-buffer)))) 398 (message "Generating autoloads for %s...done" file))
409 (not output-start))) 399 (or visited
400 ;; We created this buffer, so we should kill it.
401 (kill-buffer (current-buffer))))
402 (not output-start))))
410 403
411 (defvar autoload-modified-buffers nil)
412
413 (defun autoload-save-buffers () 404 (defun autoload-save-buffers ()
414 (while autoload-modified-buffers 405 (while autoload-modified-buffers
415 (with-current-buffer (pop autoload-modified-buffers) 406 (with-current-buffer (pop autoload-modified-buffers)
416 (save-buffer)))) 407 (save-buffer))))
417 408
422 If SAVE-AFTER is non-nil (which is always, when called interactively), 413 If SAVE-AFTER is non-nil (which is always, when called interactively),
423 save the buffer too. 414 save the buffer too.
424 415
425 Return FILE if there was no autoload cookie in it, else nil." 416 Return FILE if there was no autoload cookie in it, else nil."
426 (interactive "fUpdate autoloads for file: \np") 417 (interactive "fUpdate autoloads for file: \np")
427 (let ((no-autoloads nil)) 418 (let* ((autoload-modified-buffers nil)
428 (if (catch 'up-to-date 419 (no-autoloads (autoload-generate-file-autoloads file)))
429 (progn 420 (if autoload-modified-buffers
430 (setq no-autoloads (autoload-generate-file-autoloads file))
431 t))
432 (if save-after (autoload-save-buffers)) 421 (if save-after (autoload-save-buffers))
433 (if (interactive-p) 422 (if (interactive-p)
434 (message "Autoload section for %s is up to date." file))) 423 (message "Autoload section for %s is up to date." file)))
435 ;; If we caught `up-to-date', it means there are autoload entries, since
436 ;; otherwise we wouldn't have detected their up-to-dateness.
437 (if no-autoloads file))) 424 (if no-autoloads file)))
438 425
439 (defun autoload-find-destination (file) 426 (defun autoload-find-destination (file)
440 "Find the destination point of the current buffer's autoloads. 427 "Find the destination point of the current buffer's autoloads.
441 FILE is the file name of the current buffer. 428 FILE is the file name of the current buffer.
442 Returns a buffer whose point is placed at the requested location. 429 Returns a buffer whose point is placed at the requested location.
443 Throws `up-to-date' if the file's autoloads are uptodate, otherwise 430 Returns nil if the file's autoloads are uptodate, otherwise
444 removes any prior now out-of-date autoload entries. 431 removes any prior now out-of-date autoload entries.
445 The current buffer only matters if it is visiting a file or if it has a buffer-local 432 The current buffer only matters if it is visiting a file or if it has a buffer-local
446 value for some variables such as `generated-autoload-file', so it's OK 433 value for some variables such as `generated-autoload-file', so it's OK
447 to call it from a dummy buffer if FILE is not currently visited." 434 to call it from a dummy buffer if FILE is not currently visited."
448 ;; (message "autoload-find-destination %S" file) 435 (catch 'up-to-date
449 (let ((load-name (autoload-file-load-name file)) 436 (let ((load-name (autoload-file-load-name file))
450 (existing-buffer (if buffer-file-name (current-buffer))) 437 (existing-buffer (if buffer-file-name (current-buffer)))
451 (found nil)) 438 (found nil))
452 (with-current-buffer 439 (with-current-buffer
453 ;; We must read/write the file without any code conversion, 440 ;; We must read/write the file without any code conversion,
454 ;; but still decode EOLs. 441 ;; but still decode EOLs.
455 (let ((coding-system-for-read 'raw-text)) 442 (let ((coding-system-for-read 'raw-text))
456 (find-file-noselect 443 (find-file-noselect
457 (autoload-ensure-default-file (autoload-generated-file)))) 444 (autoload-ensure-default-file (autoload-generated-file))))
458 ;; This is to make generated-autoload-file have Unix EOLs, so 445 ;; This is to make generated-autoload-file have Unix EOLs, so
459 ;; that it is portable to all platforms. 446 ;; that it is portable to all platforms.
460 (setq buffer-file-coding-system 'raw-text-unix) 447 (setq buffer-file-coding-system 'raw-text-unix)
461 (or (> (buffer-size) 0) 448 (or (> (buffer-size) 0)
462 (error "Autoloads file %s does not exist" buffer-file-name)) 449 (error "Autoloads file %s does not exist" buffer-file-name))
463 (or (file-writable-p buffer-file-name) 450 (or (file-writable-p buffer-file-name)
464 (error "Autoloads file %s is not writable" buffer-file-name)) 451 (error "Autoloads file %s is not writable" buffer-file-name))
465 (widen) 452 (widen)
466 (goto-char (point-min)) 453 (goto-char (point-min))
467 ;; Look for the section for LOAD-NAME. 454 ;; Look for the section for LOAD-NAME.
468 (while (and (not found) 455 (while (and (not found)
469 (search-forward generate-autoload-section-header nil t)) 456 (search-forward generate-autoload-section-header nil t))
470 (let ((form (autoload-read-section-header))) 457 (let ((form (autoload-read-section-header)))
471 (cond ((string= (nth 2 form) load-name) 458 (cond ((string= (nth 2 form) load-name)
472 ;; We found the section for this file. 459 ;; We found the section for this file.
473 ;; Check if it is up to date. 460 ;; Check if it is up to date.
474 (let ((begin (match-beginning 0)) 461 (let ((begin (match-beginning 0))
475 (last-time (nth 4 form)) 462 (last-time (nth 4 form))
476 (file-time (nth 5 (file-attributes file)))) 463 (file-time (nth 5 (file-attributes file))))
477 (if (and (or (null existing-buffer) 464 (if (and (or (null existing-buffer)
478 (not (buffer-modified-p existing-buffer))) 465 (not (buffer-modified-p existing-buffer)))
479 (listp last-time) (= (length last-time) 2) 466 (listp last-time) (= (length last-time) 2)
480 (not (time-less-p last-time file-time))) 467 (not (time-less-p last-time file-time)))
481 (throw 'up-to-date nil) 468 (throw 'up-to-date nil)
482 (autoload-remove-section begin) 469 (autoload-remove-section begin)
483 (setq found t)))) 470 (setq found t))))
484 ((string< load-name (nth 2 form)) 471 ((string< load-name (nth 2 form))
485 ;; We've come to a section alphabetically later than 472 ;; We've come to a section alphabetically later than
486 ;; LOAD-NAME. We assume the file is in order and so 473 ;; LOAD-NAME. We assume the file is in order and so
487 ;; there must be no section for LOAD-NAME. We will 474 ;; there must be no section for LOAD-NAME. We will
488 ;; insert one before the section here. 475 ;; insert one before the section here.
489 (goto-char (match-beginning 0)) 476 (goto-char (match-beginning 0))
490 (setq found t))))) 477 (setq found t)))))
491 (or found 478 (or found
492 (progn 479 (progn
493 ;; No later sections in the file. Put before the last page. 480 ;; No later sections in the file. Put before the last page.
494 (goto-char (point-max)) 481 (goto-char (point-max))
495 (search-backward "\f" nil t))) 482 (search-backward "\f" nil t)))
496 (unless (memq (current-buffer) autoload-modified-buffers) 483 (unless (memq (current-buffer) autoload-modified-buffers)
497 (push (current-buffer) autoload-modified-buffers)) 484 (push (current-buffer) autoload-modified-buffers))
498 (current-buffer)))) 485 (current-buffer)))))
499 486
500 (defun autoload-remove-section (begin) 487 (defun autoload-remove-section (begin)
501 (goto-char begin) 488 (goto-char begin)
502 (search-forward generate-autoload-section-trailer) 489 (search-forward generate-autoload-section-trailer)
503 (delete-region begin (point))) 490 (delete-region begin (point)))
531 (with-current-buffer 518 (with-current-buffer
532 (find-file-noselect (autoload-ensure-default-file autoloads-file)) 519 (find-file-noselect (autoload-ensure-default-file autoloads-file))
533 (save-excursion 520 (save-excursion
534 521
535 ;; Canonicalize file names and remove the autoload file itself. 522 ;; Canonicalize file names and remove the autoload file itself.
536 (setq files (delete (autoload-trim-file-name buffer-file-name) 523 (setq files (delete (file-relative-name buffer-file-name)
537 (mapcar 'autoload-trim-file-name files))) 524 (mapcar 'file-relative-name files)))
538 525
539 (goto-char (point-min)) 526 (goto-char (point-min))
540 (while (search-forward generate-autoload-section-header nil t) 527 (while (search-forward generate-autoload-section-header nil t)
541 (let* ((form (autoload-read-section-header)) 528 (let* ((form (autoload-read-section-header))
542 (file (nth 3 form))) 529 (file (nth 3 form)))