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 ,(let ((args initz-null-string))
84 (function (lambda (arg)
85 (unless (string= args initz-null-string)
86 (setq args (concat args
87 initz-separator-string)))
88 (setq arg (initz-trim-separator arg))
89 (setq args (concat args arg))))
90 (cdr command-line-args))
92 (flavor . ("flavor" ,initz-flavor))
93 (host . ("host" ,(system-name)))
94 (system . ("system" ,(symbol-name system-type)))
95 (misc . (,initz-null-string ,initz-null-string))))
97 (defun initz-get-init-value (sym type)
98 "Return the TYPE's value of SYM from `initz-init-alist'."
99 (let ((list (cdr (assq sym initz-init-alist)))
104 (function (lambda (temp)
106 (let ((elem (nth count list)))
107 (when (and (eq type 'prefix)
108 (not (string= elem initz-null-string)))
109 (setq elem (concat initz-separator-string
112 (setq count (incf count)))))
116 (defun initz-directory (kind)
117 "Return the directory of KIND."
119 ((eq kind 'startup) "startup")
120 ((eq kind 'flavor) initz-flavor)
121 (t initz-null-string))))
122 (expand-file-name dir initz-directory)))
124 (defun initz-startup-directory (sym)
125 "Return the startup directory of SYM."
127 (initz-get-init-value sym 'dir)
128 (initz-directory 'startup)))
130 (defun initz-flavor-directory (sym)
131 "Return the flavor directory of SYM."
133 (initz-get-init-value sym 'dir)
134 (initz-directory 'flavor)))
136 (defun initz-get-kind (file)
137 "Return the kind of FILE."
140 (function (lambda (kind)
141 (when (string-match (initz-directory kind) file)
142 (throw 'found kind))))
146 (defun initz-get-dir (file)
147 "Return dir of the FILE."
148 (let ((file (file-name-directory file))
149 (directory (initz-directory (initz-get-kind file))))
150 (when (string-match "/$" file)
151 (setq file (substring file 0 (1- (length file)))))
153 (if (string= file directory)
155 (when (string-match (concat directory "\\(.+\\)") file)
156 (let ((dir (substring (match-string 1 file) 1)))
158 (function (lambda (alist)
159 (when (string= (nth 0 (cdr alist)) dir)
160 (throw 'found (car alist)))))
164 (defun initz-get-correspondence-file (init-file)
165 "Return correspondence file of the INIT-FILE."
166 (let* ((file (file-name-nondirectory init-file))
167 (kind (if (eq (initz-get-kind init-file) 'startup)
170 (directory (expand-file-name
171 (initz-get-init-value (initz-get-dir init-file) 'dir)
172 (initz-directory kind))))
173 (expand-file-name (if (eq kind 'startup)
174 (substring file 0 (1- (length file)))
178 (defun initz-get-files (kind dir)
179 "Return files of the directory made by KIND and DIR."
180 (let ((directory (expand-file-name
181 (initz-get-init-value dir 'dir)
182 (initz-directory kind)))
183 (prefix (regexp-quote
185 (initz-get-init-value dir 'prefix))))
186 (ext (if (eq kind 'startup) "\\.el$" "\\.elc$")))
187 (unless (and (not (eq dir 'misc))
188 (string= prefix initz-prefix))
190 directory t (concat "^\\(" prefix "\\|"
191 prefix initz-separator-string
192 initz-module-regexp "\\)" ext)))))
194 (defun initz-make-directory (sym)
195 "Make SYM's directory."
197 (function (lambda (kind)
198 (let ((directory (expand-file-name
199 (initz-get-init-value sym 'dir)
200 (initz-directory kind))))
201 (unless (file-directory-p directory)
202 (make-directory directory t)))))
205 (defun initz-make-directories ()
206 "Make initz directories."
209 (function (lambda (alist)
210 (let ((sym (car alist)))
211 (initz-make-directory sym))))
214 (defun initz-delete-file (flavor-file)
215 "Delete the FLAVOR-FILE when startup-file was deleted."
216 (let ((startup-file (initz-get-correspondence-file flavor-file)))
217 (unless (file-exists-p startup-file)
218 (delete-file flavor-file))))
220 (defun initz-delete-files (sym)
221 "Delete files in the SYM's directory when startup-file was deleted."
222 (let ((flavor-files (initz-get-files 'flavor sym)))
224 (function (lambda (flavor-file)
225 (initz-delete-file flavor-file)))
228 (defun initz-delete ()
229 "Delete the initz startup files."
231 (initz-make-directories)
233 (function (lambda (alist)
234 (let ((sym (car alist)))
235 (initz-delete-files sym))))
238 (defun initz-compile-file (startup-file)
239 "Compile the STARTUP-FILE."
240 (let ((flavor-file (initz-get-correspondence-file startup-file)))
241 (when (file-newer-than-file-p startup-file flavor-file)
243 (unless (save-window-excursion
244 (byte-compile-file startup-file))
247 ;; Use `initz-ignore-list' instead of `initz-ignore-list-internal'
249 (unless (member (initz-get-module-name startup-file)
251 (add-to-list 'initz-compile-error-files startup-file))
254 (defun initz-compile-files (sym)
255 "Compile files in the SYM's directory."
256 (let ((startup-files (initz-get-files 'startup sym))
259 (function (lambda (startup-file)
260 (initz-compile-file startup-file)))
262 (setq compiled-files (directory-files
263 (initz-startup-directory sym) nil "\\.elc$"))
264 (install-files compiled-files (initz-startup-directory sym)
265 (initz-flavor-directory sym) t t)))
267 (defun initz-compile ()
268 "Compile the initz startup files."
271 (setq initz-compile-error-files nil)
273 (function (lambda (alist)
274 (let ((sym (car alist)))
275 (initz-compile-files sym))))
277 (and initz-compile-error-files (eq initz-verbose 'errors)
280 (defun initz-load-file (flavor-file &optional unload)
281 "Load the FLAVOR-FILE."
282 (let* ((module (initz-get-module-name flavor-file))
283 (mesg (format (if unload
284 initz-unload-module-message-format
285 initz-load-module-message-format)
287 (if (or (member module initz-ignore-list-internal)
288 (and initz-load-list-internal
289 (not (member module initz-load-list-internal))))
290 (initz-message (concat mesg "ignored"))
291 (unless (and initz-interactively
293 (format initz-load-module-ask-message-format
297 (let*((base-name (initz-get-base-name flavor-file))
298 (feature (intern base-name)))
300 (unload-feature feature t)
301 (when (memq feature features)
302 (unload-feature feature t))
304 (initz-message (concat mesg "done")))
305 (error (add-to-list 'initz-load-error-files
306 (initz-get-correspondence-file flavor-file))
307 (initz-message (concat mesg "failed"))
310 (defun initz-load-files (sym)
311 "Load files in the SYM's directory."
312 (let ((flavor-files (initz-get-files 'flavor sym)))
314 (function (lambda (flavor-file)
315 (initz-load-file flavor-file)))
319 "Load the initz startup files."
322 (setq initz-load-error-files nil)
323 (initz-add-to-load-path (initz-directory 'flavor))
325 (setq initz-load-list-internal initz-load-list)
326 (setq initz-ignore-list-internal initz-ignore-list)
328 (function (lambda (alist)
329 (let ((sym (car alist)))
330 (initz-load-files sym))))
332 (and initz-load-error-files (eq initz-verbose 'errors)
337 (initz-message (format initz-done-message-format
338 (initz-version) initz-flavor)))
341 (defun initz-startup ()
344 (unless noninteractive
350 ;;; initz.el ends here