1 ;;; initz.el --- Handles the switching of various startup initialization files
3 ;; Copyright (C) 2001-2002 OHASHI Akira <bg66@koka-in.org>
5 ;; Author: OHASHI Akira <bg66@koka-in.org>
6 ;; Keywords: startup, init
8 ;; This file is part of Initz.
10 ;; This program 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)
15 ;; This program 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.
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.
34 (require 'initz-globals)
36 (eval-when-compile (require 'cl))
38 (autoload 'initz-error "initz-error" nil t)
39 (autoload 'initz-list "initz-list" nil t)
40 (autoload 'initz-list-new-file "initz-list" nil t))
42 (product-provide 'initz
43 (product-define "Initz" nil '(0 0 11)))
45 (defun initz-version (&optional arg)
46 "Return Initz version.
47 If it is called interactively, version string is appeared on minibuffer.
48 If ARG is specified, don't display code name."
50 (let ((product-info (product-string-1 'initz (not arg))))
52 (message "%s" product-info)
55 (defconst initz-done-message-format
56 "Loading %s init files for %s...done")
58 (defun initz-message (mesg)
59 "If `initz-verbose' is non-nil, print MESG."
60 (when initz-verbose (message mesg)))
62 (defmacro initz-message-no-log (string &rest args)
63 "Like `message', except that message logging is disabled."
64 (if (featurep 'xemacs)
66 `(display-message 'no-log (format ,string ,@args))
67 `(display-message 'no-log ,string))
68 `(let (message-log-max)
69 (message ,string ,@args))))
71 (defun initz-trim-separator (string)
72 "Trim `initz-separator-string' from STRING."
74 (when (string-match (concat "^" initz-separator-string "+") temp)
75 (setq temp (substring temp (match-end 0))))
76 (when (string-match (concat initz-separator-string "+$") temp)
77 (setq temp (substring temp 0 (match-beginning 0))))
80 (defconst initz-init-alist
81 `((argument . ("argument"
82 ,(mapconcat #'(lambda (arg)
83 (initz-trim-separator arg))
84 (cdr command-line-args)
85 initz-separator-string)))
86 ( flavor . ("flavor" ,initz-flavor))
87 (host . ("host" ,(system-name)))
88 (system . ("system" ,(symbol-name system-type)))
89 (misc . (,initz-null-string ,initz-null-string))))
91 (defun initz-get-init-value (sym type)
92 "Return the TYPE's value of SYM from `initz-init-alist'."
93 (let ((list (cdr (assq sym initz-init-alist)))
97 (mapc #'(lambda (temp)
99 (let ((elem (nth count list)))
100 (when (and (eq type 'prefix)
101 (not (string= elem initz-null-string)))
102 (setq elem (concat initz-separator-string elem)))
104 (setq count (incf count))))
108 (defun initz-directory (kind)
109 "Return the directory of KIND."
111 ((eq kind 'startup) "startup")
112 ((eq kind 'flavor) initz-flavor)
113 (t initz-null-string))))
114 (expand-file-name dir initz-directory)))
116 (defun initz-startup-directory (sym)
117 "Return the startup directory of SYM."
119 (initz-get-init-value sym 'dir)
120 (initz-directory 'startup)))
122 (defun initz-flavor-directory (sym)
123 "Return the flavor directory of SYM."
125 (initz-get-init-value sym 'dir)
126 (initz-directory 'flavor)))
128 (defun initz-get-kind (file)
129 "Return the kind of FILE."
131 (mapc #'(lambda (kind)
132 (when (string-match (initz-directory kind) file)
133 (throw 'found kind)))
137 (defun initz-get-dir (file)
138 "Return dir of the FILE."
139 (let ((file (file-name-directory file))
140 (directory (initz-directory (initz-get-kind file))))
141 (when (string-match "/$" file)
142 (setq file (substring file 0 (1- (length file)))))
144 (if (string= file directory)
146 (when (string-match (concat directory "\\(.+\\)") file)
147 (let ((dir (substring (match-string 1 file) 1)))
148 (mapc #'(lambda (alist)
149 (when (string= (nth 0 (cdr alist)) dir)
150 (throw 'found (car alist))))
154 (defun initz-get-correspondence-file (init-file)
155 "Return correspondence file of the INIT-FILE."
156 (let* ((file (file-name-nondirectory init-file))
157 (kind (if (eq (initz-get-kind init-file) 'startup)
160 (directory (expand-file-name
161 (initz-get-init-value (initz-get-dir init-file) 'dir)
162 (initz-directory kind))))
163 (expand-file-name (if (eq kind 'startup)
164 (substring file 0 (1- (length file)))
168 (defun initz-get-files (kind dir)
169 "Return files of the directory made by KIND and DIR."
170 (let ((directory (expand-file-name
171 (initz-get-init-value dir 'dir)
172 (initz-directory kind)))
173 (prefix (regexp-quote
175 (initz-get-init-value dir 'prefix))))
176 (ext (if (eq kind 'startup) "\\.el$" "\\.elc$")))
177 (unless (and (not (eq dir 'misc))
178 (string= prefix initz-prefix))
180 directory t (concat "^\\(" prefix "\\|"
181 prefix initz-separator-string
182 initz-module-regexp "\\)" ext)))))
184 (defun initz-make-directory (sym)
185 "Make SYM's directory."
186 (mapc #'(lambda (kind)
187 (let ((directory (expand-file-name
188 (initz-get-init-value sym 'dir)
189 (initz-directory kind))))
190 (unless (file-directory-p directory)
191 (make-directory directory t))))
194 (defun initz-make-directories ()
195 "Make initz directories."
197 (mapc #'(lambda (alist)
198 (let ((sym (car alist)))
199 (initz-make-directory sym)))
202 (defun initz-delete-file (flavor-file)
203 "Delete the FLAVOR-FILE when startup-file was deleted."
204 (let ((startup-file (initz-get-correspondence-file flavor-file)))
205 (unless (file-exists-p startup-file)
206 (delete-file flavor-file))))
208 (defun initz-delete-files (sym)
209 "Delete files in the SYM's directory when startup-file was deleted."
210 (let ((flavor-files (initz-get-files 'flavor sym)))
211 (mapc #'(lambda (flavor-file)
212 (initz-delete-file flavor-file))
215 (defun initz-delete ()
216 "Delete the initz startup files."
218 (initz-make-directories)
219 (mapc #'(lambda (alist)
220 (let ((sym (car alist)))
221 (initz-delete-files sym)))
224 (defun initz-compile-file (startup-file)
225 "Compile the STARTUP-FILE."
226 (let ((flavor-file (initz-get-correspondence-file startup-file)))
227 (when (file-newer-than-file-p startup-file flavor-file)
229 (unless (save-window-excursion
230 (byte-compile-file startup-file))
233 ;; Use `initz-ignore-list' instead of `initz-ignore-list-internal'
235 (unless (member (initz-get-module-name startup-file)
237 (add-to-list 'initz-compile-error-files startup-file))
240 (defun initz-compile-files (sym)
241 "Compile files in the SYM's directory."
242 (let ((startup-files (initz-get-files 'startup sym))
244 (mapc #'(lambda (startup-file)
245 (initz-compile-file startup-file))
247 (setq compiled-files (directory-files
248 (initz-startup-directory sym) nil "\\.elc$"))
249 (install-files compiled-files (initz-startup-directory sym)
250 (initz-flavor-directory sym) t t)))
252 (defun initz-compile ()
253 "Compile the initz startup files."
256 (setq initz-compile-error-files nil)
257 (mapc #'(lambda (alist)
258 (let ((sym (car alist)))
259 (initz-compile-files sym)))
261 (and initz-compile-error-files (eq initz-verbose 'errors)
264 (defun initz-load-file (flavor-file &optional unload)
265 "Load the FLAVOR-FILE."
266 (let* ((module (initz-get-module-name flavor-file))
267 (mesg (format (if unload
268 initz-unload-module-message-format
269 initz-load-module-message-format)
271 (if (or (member module initz-ignore-list-internal)
272 (and initz-load-list-internal
273 (not (member module initz-load-list-internal))))
274 (initz-message (concat mesg "ignored"))
275 (unless (and initz-interactively
277 (format initz-load-module-ask-message-format
281 (let*((base-name (initz-get-base-name flavor-file))
282 (feature (intern base-name)))
284 (unload-feature feature t)
285 (when (memq feature features)
286 (unload-feature feature t))
288 (initz-message (concat mesg "done")))
289 (error (add-to-list 'initz-load-error-files
290 (initz-get-correspondence-file flavor-file))
291 (initz-message (concat mesg "failed"))
294 (defun initz-load-files (sym)
295 "Load files in the SYM's directory."
296 (let ((flavor-files (initz-get-files 'flavor sym)))
297 (mapc #'(lambda (flavor-file)
298 (initz-load-file flavor-file))
302 "Load the initz startup files."
305 (setq initz-load-error-files nil)
306 (initz-add-to-load-path (initz-directory 'flavor))
308 (setq initz-load-list-internal initz-load-list)
309 (setq initz-ignore-list-internal initz-ignore-list)
310 (mapc #'(lambda (alist)
311 (let ((sym (car alist)))
312 (initz-load-files sym)))
314 (and initz-load-error-files (eq initz-verbose 'errors)
319 (when initz-delete-compile-log-buffer
320 (mapc #'(lambda (buffer)
321 (when (string-match "^\\*Compile-Log\\*$" (buffer-name buffer))
322 (kill-buffer buffer)))
324 (initz-message (format initz-done-message-format
325 (initz-version) initz-flavor)))
328 (defun initz-startup ()
331 (unless noninteractive
337 ;;; initz.el ends here