(easy-menu-create-keymaps): Add menu-alias property.
[bpt/emacs.git] / lisp / emacs-lisp / autoload.el
CommitLineData
c0274f38
ER
1;;; autoload.el --- maintain autoloads in loaddefs.el.
2
b578f267
EN
3;; Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
4
e5167999 5;; Author: Roland McGrath <roland@gnu.ai.mit.edu>
e9571d2a 6;; Keywords: maint
e5167999 7
b578f267
EN
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 2, or (at your option)
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
0231f2dc 24
07b3798c 25;;; Commentary:
e41b2db1 26
00ee57f3 27;; This code helps GNU Emacs maintainers keep the loaddefs.el file up to
e41b2db1
ER
28;; date. It interprets magic cookies of the form ";;;###autoload" in
29;; lisp source files in various useful ways. To learn more, read the
30;; source; if you're going to use this, you'd better be able to.
31
e5167999
ER
32;;; Code:
33
0231f2dc
JB
34(defun make-autoload (form file)
35 "Turn FORM, a defun or defmacro, into an autoload for source file FILE.
5950a4fc 36Returns nil if FORM is not a defun, define-skeleton or defmacro."
0231f2dc 37 (let ((car (car-safe form)))
5950a4fc 38 (if (memq car '(defun define-skeleton defmacro))
327ab40d
RM
39 (let ((macrop (eq car 'defmacro))
40 name doc)
5950a4fc
KH
41 (setq form (cdr form)
42 name (car form)
43 ;; Ignore the arguments.
44 form (cdr (if (eq car 'define-skeleton)
45 form
46 (cdr form)))
47 doc (car form))
0231f2dc
JB
48 (if (stringp doc)
49 (setq form (cdr form))
50 (setq doc nil))
51 (list 'autoload (list 'quote name) file doc
5950a4fc
KH
52 (or (eq car 'define-skeleton)
53 (eq (car-safe (car form)) 'interactive))
44893360 54 (if macrop (list 'quote 'macro) nil)))
0231f2dc
JB
55 nil)))
56
5950a4fc
KH
57(put 'define-skeleton 'doc-string-elt 3)
58
0231f2dc 59(defconst generate-autoload-cookie ";;;###autoload"
d08589bf
RM
60 "Magic comment indicating the following form should be autoloaded.
61Used by \\[update-file-autoloads]. This string should be
0231f2dc
JB
62meaningless to Lisp (e.g., a comment).
63
64This string is used:
65
66;;;###autoload
67\(defun function-to-be-autoloaded () ...)
68
69If this string appears alone on a line, the following form will be
70read and an autoload made for it. If there is further text on the line,
71that text will be copied verbatim to `generated-autoload-file'.")
72
73(defconst generate-autoload-section-header "\f\n;;;### "
74 "String inserted before the form identifying
75the section of autoloads for a file.")
76
77(defconst generate-autoload-section-trailer "\n;;;***\n"
78 "String which indicates the end of the section of autoloads for a file.")
79
daa37602
JB
80;;; Forms which have doc-strings which should be printed specially.
81;;; A doc-string-elt property of ELT says that (nth ELT FORM) is
82;;; the doc-string in FORM.
83;;;
84;;; There used to be the following note here:
85;;; ;;; Note: defconst and defvar should NOT be marked in this way.
86;;; ;;; We don't want to produce defconsts and defvars that
87;;; ;;; make-docfile can grok, because then it would grok them twice,
88;;; ;;; once in foo.el (where they are given with ;;;###autoload) and
89;;; ;;; once in loaddefs.el.
90;;;
91;;; Counter-note: Yes, they should be marked in this way.
92;;; make-docfile only processes those files that are loaded into the
93;;; dumped Emacs, and those files should never have anything
94;;; autoloaded here. The above-feared problem only occurs with files
95;;; which have autoloaded entries *and* are processed by make-docfile;
96;;; there should be no such files.
97
0231f2dc 98(put 'autoload 'doc-string-elt 3)
daa37602
JB
99(put 'defun 'doc-string-elt 3)
100(put 'defvar 'doc-string-elt 3)
101(put 'defconst 'doc-string-elt 3)
102(put 'defmacro 'doc-string-elt 3)
0231f2dc 103
72c19d97 104(defun autoload-trim-file-name (file)
1eb0a345
RS
105 ;; Returns a relative pathname of FILE
106 ;; starting from the directory that loaddefs.el is in.
107 ;; That is normally a directory in load-path,
108 ;; which means Emacs will be able to find FILE when it looks.
109 ;; Any extra directory names here would prevent finding the file.
72c19d97
RM
110 (setq file (expand-file-name file))
111 (file-relative-name file
1eb0a345 112 (file-name-directory generated-autoload-file)))
72c19d97 113
0231f2dc
JB
114(defun generate-file-autoloads (file)
115 "Insert at point a loaddefs autoload section for FILE.
116autoloads are generated for defuns and defmacros in FILE
da8826b4 117marked by `generate-autoload-cookie' (which see).
0231f2dc
JB
118If FILE is being visited in a buffer, the contents of the buffer
119are used."
120 (interactive "fGenerate autoloads for file: ")
121 (let ((outbuf (current-buffer))
0231f2dc
JB
122 (autoloads-done '())
123 (load-name (let ((name (file-name-nondirectory file)))
124 (if (string-match "\\.elc?$" name)
125 (substring name 0 (match-beginning 0))
126 name)))
127 (print-length nil)
72c19d97 128 (print-readably t) ; This does something in Lucid Emacs.
aa7ea8bd 129 (float-output-format nil)
0231f2dc 130 (done-any nil)
7e4263eb 131 (visited (get-file-buffer file))
0231f2dc 132 output-end)
daa37602
JB
133
134 ;; If the autoload section we create here uses an absolute
135 ;; pathname for FILE in its header, and then Emacs is installed
136 ;; under a different path on another system,
137 ;; `update-autoloads-here' won't be able to find the files to be
138 ;; autoloaded. So, if FILE is in the same directory or a
e5d77022 139 ;; subdirectory of the current buffer's directory, we'll make it
daa37602
JB
140 ;; relative to the current buffer's directory.
141 (setq file (expand-file-name file))
1265394f
RM
142 (let* ((source-truename (file-truename file))
143 (dir-truename (file-name-as-directory
144 (file-truename default-directory)))
145 (len (length dir-truename)))
146 (if (and (< len (length source-truename))
147 (string= dir-truename (substring source-truename 0 len)))
148 (setq file (substring source-truename len))))
daa37602 149
0231f2dc 150 (message "Generating autoloads for %s..." file)
6798a385
JB
151 (save-excursion
152 (unwind-protect
153 (progn
66fc2bf5
RM
154 (if visited
155 (set-buffer visited)
156 ;; It is faster to avoid visiting the file.
157 (set-buffer (get-buffer-create " *generate-autoload-file*"))
158 (kill-all-local-variables)
159 (erase-buffer)
b59c7256
RM
160 (setq buffer-undo-list t
161 buffer-read-only nil)
162 (emacs-lisp-mode)
66fc2bf5 163 (insert-file-contents file nil))
6798a385
JB
164 (save-excursion
165 (save-restriction
166 (widen)
167 (goto-char (point-min))
168 (while (not (eobp))
169 (skip-chars-forward " \t\n\f")
170 (cond
171 ((looking-at (regexp-quote generate-autoload-cookie))
172 (search-forward generate-autoload-cookie)
173 (skip-chars-forward " \t")
174 (setq done-any t)
9ed4d64f
RM
175 (if (eolp)
176 ;; Read the next form and make an autoload.
177 (let* ((form (prog1 (read (current-buffer))
ad9c7f2b 178 (or (bolp) (forward-line 1))))
9ed4d64f
RM
179 (autoload (make-autoload form load-name))
180 (doc-string-elt (get (car-safe form)
181 'doc-string-elt)))
182 (if autoload
183 (setq autoloads-done (cons (nth 1 form)
184 autoloads-done))
185 (setq autoload form))
186 (if (and doc-string-elt
187 (stringp (nth doc-string-elt autoload)))
188 ;; We need to hack the printing because the
189 ;; doc-string must be printed specially for
190 ;; make-docfile (sigh).
191 (let* ((p (nthcdr (1- doc-string-elt)
192 autoload))
193 (elt (cdr p)))
194 (setcdr p nil)
195 (princ "\n(" outbuf)
196 (let ((print-escape-newlines t))
197 (mapcar (function (lambda (elt)
198 (prin1 elt outbuf)
199 (princ " " outbuf)))
200 autoload))
201 (princ "\"\\\n" outbuf)
202 (let ((begin (save-excursion
203 (set-buffer outbuf)
204 (point))))
6798a385 205 (princ (substring
72c19d97
RM
206 (prin1-to-string (car elt)) 1)
207 outbuf)
208 ;; Insert a backslash before each ( that
209 ;; appears at the beginning of a line in
210 ;; the doc string.
211 (save-excursion
212 (set-buffer outbuf)
213 (save-excursion
214 (while (search-backward "\n(" begin t)
215 (forward-char 1)
216 (insert "\\"))))
217 (if (null (cdr elt))
218 (princ ")" outbuf)
219 (princ " " outbuf)
220 (princ (substring
221 (prin1-to-string (cdr elt))
222 1)
223 outbuf))
9ed4d64f
RM
224 (terpri outbuf)))
225 (let ((print-escape-newlines t))
52859db8 226 (print autoload outbuf))))
9ed4d64f 227 ;; Copy the rest of the line to the output.
6e21af56
RM
228 (princ (buffer-substring
229 (progn
230 ;; Back up over whitespace, to preserve it.
231 (skip-chars-backward " \f\t")
232 (if (= (char-after (1+ (point))) ? )
233 ;; Eat one space.
234 (forward-char 1))
235 (point))
236 (progn (forward-line 1) (point)))
237 outbuf)))
72c19d97
RM
238 ((looking-at ";")
239 ;; Don't read the comment.
240 (forward-line 1))
241 (t
242 (forward-sexp 1)
243 (forward-line 1)))))))
6798a385
JB
244 (or visited
245 ;; We created this buffer, so we should kill it.
246 (kill-buffer (current-buffer)))
247 (set-buffer outbuf)
248 (setq output-end (point-marker))))
0231f2dc
JB
249 (if done-any
250 (progn
251 (insert generate-autoload-section-header)
72c19d97
RM
252 (prin1 (list 'autoloads autoloads-done load-name
253 (autoload-trim-file-name file)
0231f2dc
JB
254 (nth 5 (file-attributes file)))
255 outbuf)
256 (terpri outbuf)
72c19d97
RM
257 (insert ";;; Generated autoloads from "
258 (autoload-trim-file-name file) "\n")
d0cb5e04
RS
259 ;; Warn if we put a line in loaddefs.el
260 ;; that is long enough to cause trouble.
261 (while (< (point) output-end)
262 (let ((beg (point)))
263 (end-of-line)
264 (if (> (- (point) beg) 900)
265 (progn
266 (message "A line is too long--over 900 characters")
267 (sleep-for 2)
268 (goto-char output-end))))
269 (forward-line 1))
0231f2dc
JB
270 (goto-char output-end)
271 (insert generate-autoload-section-trailer)))
272 (message "Generating autoloads for %s...done" file)))
e2b6138f 273\f
0231f2dc
JB
274(defconst generated-autoload-file "loaddefs.el"
275 "*File \\[update-file-autoloads] puts autoloads into.
276A .el file can set this in its local variables section to make its
277autoloads go somewhere else.")
278
279;;;###autoload
280(defun update-file-autoloads (file)
281 "Update the autoloads for FILE in `generated-autoload-file'
282\(which FILE might bind in its local variables)."
283 (interactive "fUpdate autoloads for file: ")
284 (let ((load-name (let ((name (file-name-nondirectory file)))
285 (if (string-match "\\.elc?$" name)
286 (substring name 0 (match-beginning 0))
287 name)))
d55e3ff0 288 (found nil)
0231f2dc
JB
289 (existing-buffer (get-file-buffer file)))
290 (save-excursion
291 ;; We want to get a value for generated-autoload-file from
292 ;; the local variables section if it's there.
b59c7256
RM
293 (if existing-buffer
294 (set-buffer existing-buffer))
0231f2dc
JB
295 (set-buffer (find-file-noselect generated-autoload-file))
296 (save-excursion
297 (save-restriction
298 (widen)
299 (goto-char (point-min))
d55e3ff0
RM
300 ;; Look for the section for LOAD-NAME.
301 (while (and (not found)
302 (search-forward generate-autoload-section-header nil t))
0231f2dc
JB
303 (let ((form (condition-case ()
304 (read (current-buffer))
305 (end-of-file nil))))
d55e3ff0
RM
306 (cond ((string= (nth 2 form) load-name)
307 ;; We found the section for this file.
308 ;; Check if it is up to date.
309 (let ((begin (match-beginning 0))
310 (last-time (nth 4 form))
311 (file-time (nth 5 (file-attributes file))))
312 (if (and (or (null existing-buffer)
313 (not (buffer-modified-p existing-buffer)))
314 (listp last-time) (= (length last-time) 2)
315 (or (> (car last-time) (car file-time))
316 (and (= (car last-time) (car file-time))
317 (>= (nth 1 last-time)
318 (nth 1 file-time)))))
319 (progn
d5aa62ec
RM
320 (if (interactive-p)
321 (message "\
322Autoload section for %s is up to date."
323 file))
d55e3ff0
RM
324 (setq found 'up-to-date))
325 (search-forward generate-autoload-section-trailer)
326 (delete-region begin (point))
327 (setq found t))))
328 ((string< load-name (nth 2 form))
329 ;; We've come to a section alphabetically later than
330 ;; LOAD-NAME. We assume the file is in order and so
331 ;; there must be no section for LOAD-NAME. We will
332 ;; insert one before the section here.
333 (goto-char (match-beginning 0))
72c19d97 334 (setq found 'new)))))
0f09bac6
RM
335 (or found
336 (progn
337 (setq found 'new)
338 ;; No later sections in the file. Put before the last page.
339 (goto-char (point-max))
340 (search-backward "\f")))
72c19d97 341 (or (eq found 'up-to-date)
0f09bac6 342 (and (eq found 'new)
72c19d97
RM
343 ;; Check that FILE has any cookies before generating a
344 ;; new section for it.
345 (save-excursion
b59c7256
RM
346 (if existing-buffer
347 (set-buffer existing-buffer)
348 ;; It is faster to avoid visiting the file.
349 (set-buffer (get-buffer-create " *autoload-file*"))
350 (kill-all-local-variables)
351 (erase-buffer)
352 (setq buffer-undo-list t
353 buffer-read-only nil)
354 (emacs-lisp-mode)
355 (insert-file-contents file nil))
72c19d97 356 (save-excursion
b59c7256
RM
357 (save-restriction
358 (widen)
359 (goto-char (point-min))
360 (prog1
361 (if (search-forward
362 (concat "\n" generate-autoload-cookie)
363 nil t)
364 nil
365 (if (interactive-p)
75632953 366 (message "%s has no autoloads" file))
b59c7256
RM
367 t)
368 (or existing-buffer
369 (kill-buffer (current-buffer))))))))
57cf354d 370 (generate-file-autoloads file))))
b59c7256 371 (if (interactive-p) (save-buffer)))))
0231f2dc
JB
372
373;;;###autoload
b59c7256 374(defun update-autoloads-from-directory (dir)
d08589bf 375 "\
b59c7256
RM
376Update loaddefs.el with all the current autoloads from DIR, and no old ones.
377This uses `update-file-autoloads' (which see) do its work."
378 (interactive "DUpdate autoloads from directory: ")
d5aa62ec 379 (setq dir (expand-file-name dir))
b59c7256 380 (let ((files (directory-files dir nil "^[^=].*\\.el$")))
0231f2dc 381 (save-excursion
b59c7256
RM
382 (set-buffer (find-file-noselect
383 (if (file-exists-p generated-autoload-file)
384 generated-autoload-file
385 (expand-file-name generated-autoload-file
386 dir))))
e2b6138f 387 (save-excursion
b59c7256
RM
388 (goto-char (point-min))
389 (while (search-forward generate-autoload-section-header nil t)
390 (let* ((form (condition-case ()
391 (read (current-buffer))
392 (end-of-file nil)))
393 (file (nth 3 form)))
394 (cond ((not (stringp file)))
395 ((not (file-exists-p (expand-file-name file dir)))
396 ;; Remove the obsolete section.
397 (let ((begin (match-beginning 0)))
398 (search-forward generate-autoload-section-trailer)
399 (delete-region begin (point))))
400 (t
401 (update-file-autoloads file)))
402 (setq files (delete file files)))))
403 ;; Elements remaining in FILES have no existing autoload sections.
404 (mapcar 'update-file-autoloads files)
405 (save-buffer))))
0231f2dc
JB
406
407;;;###autoload
408(defun batch-update-autoloads ()
b59c7256
RM
409 "Update loaddefs.el autoloads in batch mode.
410Calls `update-autoloads-from-directory' on each command line argument."
411 (mapcar 'update-autoloads-from-directory command-line-args-left)
412 (setq command-line-args-left nil))
0231f2dc
JB
413
414(provide 'autoload)
ffd56f97 415
c0274f38 416;;; autoload.el ends here