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"
83 (function (lambda (arg)
84 (initz-trim-separator arg)))
85 (cdr command-line-args)
86 initz-separator-string)))
87 ( flavor . ("flavor" ,initz-flavor))
88 (host . ("host" ,(system-name)))
89 (system . ("system" ,(symbol-name system-type)))
90 (misc . (,initz-null-string ,initz-null-string))))
92 (defun initz-get-init-value (sym type)
93 "Return the TYPE's value of SYM from `initz-init-alist'."
94 (let ((list (cdr (assq sym initz-init-alist)))
99 (function (lambda (temp)
101 (let ((elem (nth count list)))
102 (when (and (eq type 'prefix)
103 (not (string= elem initz-null-string)))
104 (setq elem (concat initz-separator-string
107 (setq count (incf count)))))
111 (defun initz-directory (kind)
112 "Return the directory of KIND."
114 ((eq kind 'startup) "startup")
115 ((eq kind 'flavor) initz-flavor)
116 (t initz-null-string))))
117 (expand-file-name dir initz-directory)))
119 (defun initz-startup-directory (sym)
120 "Return the startup directory of SYM."
122 (initz-get-init-value sym 'dir)
123 (initz-directory 'startup)))
125 (defun initz-flavor-directory (sym)
126 "Return the flavor directory of SYM."
128 (initz-get-init-value sym 'dir)
129 (initz-directory 'flavor)))
131 (defun initz-get-kind (file)
132 "Return the kind of FILE."
135 (function (lambda (kind)
136 (when (string-match (initz-directory kind) file)
137 (throw 'found kind))))
141 (defun initz-get-dir (file)
142 "Return dir of the FILE."
143 (let ((file (file-name-directory file))
144 (directory (initz-directory (initz-get-kind file))))
145 (when (string-match "/$" file)
146 (setq file (substring file 0 (1- (length file)))))
148 (if (string= file directory)
150 (when (string-match (concat directory "\\(.+\\)") file)
151 (let ((dir (substring (match-string 1 file) 1)))
153 (function (lambda (alist)
154 (when (string= (nth 0 (cdr alist)) dir)
155 (throw 'found (car alist)))))
159 (defun initz-get-correspondence-file (init-file)
160 "Return correspondence file of the INIT-FILE."
161 (let* ((file (file-name-nondirectory init-file))
162 (kind (if (eq (initz-get-kind init-file) 'startup)
165 (directory (expand-file-name
166 (initz-get-init-value (initz-get-dir init-file) 'dir)
167 (initz-directory kind))))
168 (expand-file-name (if (eq kind 'startup)
169 (substring file 0 (1- (length file)))
173 (defun initz-get-files (kind dir)
174 "Return files of the directory made by KIND and DIR."
175 (let ((directory (expand-file-name
176 (initz-get-init-value dir 'dir)
177 (initz-directory kind)))
178 (prefix (regexp-quote
180 (initz-get-init-value dir 'prefix))))
181 (ext (if (eq kind 'startup) "\\.el$" "\\.elc$")))
182 (unless (and (not (eq dir 'misc))
183 (string= prefix initz-prefix))
185 directory t (concat "^\\(" prefix "\\|"
186 prefix initz-separator-string
187 initz-module-regexp "\\)" ext)))))
189 (defun initz-make-directory (sym)
190 "Make SYM's directory."
192 (function (lambda (kind)
193 (let ((directory (expand-file-name
194 (initz-get-init-value sym 'dir)
195 (initz-directory kind))))
196 (unless (file-directory-p directory)
197 (make-directory directory t)))))
200 (defun initz-make-directories ()
201 "Make initz directories."
204 (function (lambda (alist)
205 (let ((sym (car alist)))
206 (initz-make-directory sym))))
209 (defun initz-delete-file (flavor-file)
210 "Delete the FLAVOR-FILE when startup-file was deleted."
211 (let ((startup-file (initz-get-correspondence-file flavor-file)))
212 (unless (file-exists-p startup-file)
213 (delete-file flavor-file))))
215 (defun initz-delete-files (sym)
216 "Delete files in the SYM's directory when startup-file was deleted."
217 (let ((flavor-files (initz-get-files 'flavor sym)))
219 (function (lambda (flavor-file)
220 (initz-delete-file flavor-file)))
223 (defun initz-delete ()
224 "Delete the initz startup files."
226 (initz-make-directories)
228 (function (lambda (alist)
229 (let ((sym (car alist)))
230 (initz-delete-files sym))))
233 (defun initz-compile-file (startup-file)
234 "Compile the STARTUP-FILE."
235 (let ((flavor-file (initz-get-correspondence-file startup-file)))
236 (when (file-newer-than-file-p startup-file flavor-file)
238 (unless (save-window-excursion
239 (byte-compile-file startup-file))
242 ;; Use `initz-ignore-list' instead of `initz-ignore-list-internal'
244 (unless (member (initz-get-module-name startup-file)
246 (add-to-list 'initz-compile-error-files startup-file))
249 (defun initz-compile-files (sym)
250 "Compile files in the SYM's directory."
251 (let ((startup-files (initz-get-files 'startup sym))
254 (function (lambda (startup-file)
255 (initz-compile-file startup-file)))
257 (setq compiled-files (directory-files
258 (initz-startup-directory sym) nil "\\.elc$"))
259 (install-files compiled-files (initz-startup-directory sym)
260 (initz-flavor-directory sym) t t)))
262 (defun initz-compile ()
263 "Compile the initz startup files."
266 (setq initz-compile-error-files nil)
268 (function (lambda (alist)
269 (let ((sym (car alist)))
270 (initz-compile-files sym))))
272 (and initz-compile-error-files (eq initz-verbose 'errors)
275 (defun initz-load-file (flavor-file &optional unload)
276 "Load the FLAVOR-FILE."
277 (let* ((module (initz-get-module-name flavor-file))
278 (mesg (format (if unload
279 initz-unload-module-message-format
280 initz-load-module-message-format)
282 (if (or (member module initz-ignore-list-internal)
283 (and initz-load-list-internal
284 (not (member module initz-load-list-internal))))
285 (initz-message (concat mesg "ignored"))
286 (unless (and initz-interactively
288 (format initz-load-module-ask-message-format
292 (let*((base-name (initz-get-base-name flavor-file))
293 (feature (intern base-name)))
295 (unload-feature feature t)
296 (when (memq feature features)
297 (unload-feature feature t))
299 (initz-message (concat mesg "done")))
300 (error (add-to-list 'initz-load-error-files
301 (initz-get-correspondence-file flavor-file))
302 (initz-message (concat mesg "failed"))
305 (defun initz-load-files (sym)
306 "Load files in the SYM's directory."
307 (let ((flavor-files (initz-get-files 'flavor sym)))
309 (function (lambda (flavor-file)
310 (initz-load-file flavor-file)))
314 "Load the initz startup files."
317 (setq initz-load-error-files nil)
318 (initz-add-to-load-path (initz-directory 'flavor))
320 (setq initz-load-list-internal initz-load-list)
321 (setq initz-ignore-list-internal initz-ignore-list)
323 (function (lambda (alist)
324 (let ((sym (car alist)))
325 (initz-load-files sym))))
327 (and initz-load-error-files (eq initz-verbose 'errors)
332 (initz-message (format initz-done-message-format
333 (initz-version) initz-flavor)))
336 (defun initz-startup ()
339 (unless noninteractive
345 ;;; initz.el ends here