comparison lisp/cus-dep.el @ 209:41ff10fd062f r20-4b3

Import from CVS: tag r20-4b3
author cvs
date Mon, 13 Aug 2007 10:04:58 +0200
parents
children 2c611d1463a6
comparison
equal deleted inserted replaced
208:f427b8ec4379 209:41ff10fd062f
1 ;;; cus-dep.el --- Find customization dependencies.
2 ;;
3 ;; Copyright (C) 1997 Free Software Foundation, Inc.
4 ;;
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>, then
6 ;; Richar Stallman <rms@gnu.ai.mit.edu>, then
7 ;; Hrvoje Niksic <hniksic@srce.hr> (rewritten for XEmacs)
8 ;; Maintainer: Hrvoje Niksic <hniksic@srce.hr>
9 ;; Keywords: internal
10
11 ;; This file is part of XEmacs.
12
13 ;; XEmacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; any later version.
17
18 ;; XEmacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with XEmacs; see the file COPYING. If not, write to the
25 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 ;; Boston, MA 02111-1307, USA.
27
28 ;;; Synched up with: Not synched with FSF.
29
30
31 ;;; Commentary:
32
33 ;; This file generates the custom-load files, loaded by cus-load.el.
34 ;; The only entry point is `Custom-make-dependencies'.
35
36 ;; It works by scanning all the `.el' files in a directory, and
37 ;; evaluates any `defcustom', `defgroup', or `defface' expression that
38 ;; it finds. The symbol changed by this expression is stored to a
39 ;; hash table as the hash key, file name being the value.
40
41 ;; After all the files have been examined, custom-loads.el is
42 ;; generated by mapping all the atoms, and seeing if any of them
43 ;; contains a `custom-group' property. This property is a list whose
44 ;; each element's car is the "child" group symbol. If that property
45 ;; is in the hash-table, the file name will be looked up from the
46 ;; hash-table, and added to cusload-file. Because the hash-table is
47 ;; cleared whenever we process a new directory, we cannot get confused
48 ;; by custom-loads from another directory, or from a previous
49 ;; installation. This is also why it is perfectly safe to have old
50 ;; custom-loads around, and have them loaded by `cus-load.el' (as
51 ;; invoked by `cus-edit.el').
52
53 ;; A trivial, but useful optimization is that if cusload-file exists,
54 ;; and no .el files in the directory are newer than cusload-file, it
55 ;; will not be generated. This means that the directories where
56 ;; nothing has changed will be skipped.
57
58 ;; The `custom-put' function, used by files generated by
59 ;; `Custom-make-dependencies', is a specialized function that updates
60 ;; a property (which must be a list of strings) with a new list of
61 ;; strings, eliminating the duplicates. As it also adds an
62 ;; appropriate entry to a custom hash-table, *do not* use it outside
63 ;; of custom. Its inner workings can change anytime, without prior
64 ;; notice. `custom-put' is defined in `cus-load.el'.
65
66 ;; Example:
67
68 ;; (custom-put 'foo 'custom-loads '("bar" "baz"))
69 ;; (get 'foo 'custom-loads)
70 ;; => ("bar" "baz")
71 ;;
72 ;; (custom-put 'foo 'custom-loads '("hmph" "baz" "quz"))
73 ;; (get 'foo 'custom-loads)
74 ;; => ("bar" "baz" "hmph" "qux")
75
76 ;; Obviously, this allows correct incremental loading of custom-load
77 ;; files. This is not necessary under FSF (they use a simple `put'),
78 ;; since they have only *one* file. With the advent of packages, we
79 ;; cannot afford the same luxury.
80
81
82 ;;; Code:
83
84 (require 'cl)
85 (require 'widget)
86 (require 'cus-face)
87
88 ;; Don't change this, unless you plan to change the code in
89 ;; cus-start.el, too.
90 (defconst cusload-base-file "custom-load.el")
91
92 ;; Be very careful when changing this function. It looks easy to
93 ;; understand, but is in fact very easy to break. Be sure to read and
94 ;; understand the commentary above!
95
96 ;;;###autoload
97 (defun Custom-make-dependencies (&optional subdirs)
98 "Extract custom dependencies from .el files in SUBDIRS.
99 SUBDIRS is a list of directories. If it is nil, the command-line
100 arguments are used. If it is a string, only that directory is
101 processed. This function is especially useful in batch mode.
102
103 Batch usage: xemacs -batch -l cus-dep.el -f Custom-make-dependencies DIRS"
104 (interactive "DDirectory: ")
105 (and (stringp subdirs)
106 (setq subdirs (list subdirs)))
107 (or subdirs
108 ;; Usurp the command-line-args
109 (setq subdirs command-line-args-left
110 command-line-args-left nil))
111 (setq subdirs (mapcar #'expand-file-name subdirs))
112 (with-temp-buffer
113 (let ((enable-local-eval nil)
114 (hash (make-hash-table :test 'eq)))
115 (dolist (dir subdirs)
116 (princ (format "Processing %s\n" dir))
117 (let ((cusload-file (expand-file-name cusload-base-file dir))
118 (files (directory-files dir t "\\`[^=].*\\.el\\'")))
119 ;; A trivial optimization: if no file in the directory is
120 ;; newer than custom-load.el, no need to do anything!
121 (if (and (file-exists-p cusload-file)
122 (dolist (file files t)
123 (when (file-newer-than-file-p file cusload-file)
124 (return nil))))
125 (princ "(No changes need to be written)\n")
126 ;; Process directory
127 (dolist (file files)
128 (when (file-exists-p file)
129 (erase-buffer)
130 (insert-file-contents file)
131 (goto-char (point-min))
132 (let ((name (file-name-sans-extension
133 (file-name-nondirectory file))))
134 ;; Search for defcustom/defface/defgroup
135 ;; expressions, and evaluate them.
136 (ignore-errors
137 (while (re-search-forward
138 "^(defcustom\\|^(defface\\|^(defgroup"
139 nil t)
140 (beginning-of-line)
141 (let ((expr (read (current-buffer))))
142 (eval expr)
143 ;; Hash the file of the affected symbol.
144 (setf (gethash (nth 1 expr) hash) name)))))))
145 (cond
146 ((zerop (hash-table-count hash))
147 (princ "(No customization dependencies")
148 (when (file-exists-p cusload-file)
149 (princ (format ", deleting %s" cusload-file))
150 (delete-file cusload-file))
151 (princ ")\n"))
152 (t
153 (princ (format "Generating %s...\n" cusload-base-file))
154 (with-temp-file cusload-file
155 (insert ";;; " cusload-base-file
156 " --- automatically extracted custom dependencies\n"
157 "\n\n;;; Code:\n\n")
158 (mapatoms
159 (lambda (sym)
160 (let ((members (get sym 'custom-group))
161 item where found)
162 (when members
163 (while members
164 (setq item (car (car members))
165 members (cdr members)
166 where (gethash item hash))
167 (unless (or (null where)
168 (member where found))
169 (if found
170 (insert " ")
171 (insert "(custom-add-loads '"
172 (symbol-name sym) " '("))
173 (prin1 where (current-buffer))
174 (push where found)))
175 (when found
176 (insert "))\n"))))))
177 (insert "\n;;; custom-load.el ends here\n"))
178 (clrhash hash)))))))))
179
180 (provide 'cus-dep)
181
182 ;;; cus-dep.el ends here