Merge branch 'master' of ssh://dio.dreamhost.com/~/repos.nelsonferreira.com/git/sxema...
[sxemacs] / lisp / lisp-initd.el
1 ;; lisp-initd.el - rc.d inspired configuration management for
2 ;;                 SXEmacs-lisp
3 ;;
4 ;; Copyright (C) 2007, Nelson Ferreira
5 ;; Maintainer: Nelson Ferreira
6 ;;
7 ;; This file is part of SXEmacs
8 ;;
9 ;; All rights reserved.
10 ;;
11 ;; Redistribution and use in source and binary forms, with or without
12 ;; modification, are permitted provided that the following conditions
13 ;; are met:
14 ;;
15 ;; Redistributions of source code must retain the above copyright
16 ;; notice, this list of conditions and the following disclaimer.
17 ;;
18 ;; Redistributions in binary form must reproduce the above copyright
19 ;; notice, this list of conditions and the following disclaimer in the
20 ;; documentation and/or other materials provided with the
21 ;; distribution.
22 ;;
23 ;; Neither the name of the <ORGANIZATION> nor the names of its
24 ;; contributors may be used to endorse or promote products derived
25 ;; from this software without specific prior written permission.
26 ;;
27 ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 ;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 ;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 ;; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 ;; COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 ;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 ;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 ;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 ;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 ;; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 ;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
38 ;; OF THE POSSIBILITY OF SUCH DAMAGE.
39
40 ;; This file is dumped with SXEmacs
41
42 (require 'cl-extra)
43 ;(require 'bytecomp)
44 ;(require 'byte-optimize)
45 ;(require 'bytecomp-runtime)
46
47 (defvar lisp-initd-basename  "init.d"
48   "The default prefix for the compiled init file.")
49
50
51 (defvar lisp-initd-dir 
52   (concat user-init-directory lisp-initd-basename)
53   "The default directory for the init files.")
54
55
56 (defvar lisp-initd-keep-elisp t
57   "If TRUE the initd resulting lisp file is kept.
58 Only takes effect when `lisp-initd-byte-compile-elisp' is non-nil.")
59
60 (defvar lisp-initd-byte-compile-elisp t
61   "If TRUE the initd lisp is byte-compiled.")
62
63 (defvar lisp-initd-kill-compile-log nil
64   "Kill the byte-compile Compile Log buffers")
65
66
67 (defvar lisp-initd-gather-func #'directory-files 
68   "Function used to gather the files used in init.  For acceptable
69 arguments see `directory-files'.  The function is expected to return a
70 sorted list of absolute pathnames, accept and honor the MATCH argument
71 and return files only.")
72
73 (defun lisp-initd-compile (&optional dir file do-init)
74   "Compile the lisp files in DIR into a file named {DIR}/{PREFIX}init.d.el.
75 If DIR is nil `lisp-initd-dir' is used.
76 If FILE is nil `lisp-initd-basename' is used.
77 If DO-INIT is non-nil the file is loaded."
78   (let* ((initd-dir    (file-name-as-directory
79                         (expand-file-name
80                          (or dir lisp-initd-dir))))
81          (initd-file   (or file lisp-initd-basename))
82          (initd-el     (expand-file-name (concat initd-file ".el")
83                                          (paths-construct-path 
84                                           (list initd-dir ".."))))
85          (initd-elc    (concat initd-el "c"))
86          (initd-files  (funcall lisp-initd-gather-func initd-dir
87                                 t "^.*\.el$" nil t))
88          (init-file     (if lisp-initd-byte-compile-elisp initd-elc initd-el))
89          init-buffer)
90
91     ;; No use in keeping an outdate byte-compiled file...
92     (when (and (file-exists-p initd-el)
93                (file-exists-p initd-elc)
94                (file-newer-than-file-p initd-el initd-elc))
95       (delete-file initd-elc))
96
97     ;; If a file (or the directory itself) is newer than the existing
98     ;; file then
99     (when (some #'(lambda (file) (file-newer-than-file-p file init-file))
100                 (cons initd-dir initd-files))
101       ;; No matter what the elc is outdated now..
102       (when (file-exists-p initd-elc) (delete-file initd-elc))
103       (when (file-exists-p initd-elc) (delete-file initd-el))
104       (message "Recompiling init files....")
105       (setq init-buffer (generate-new-buffer (concat "*" initd-el "*")))
106       (with-current-buffer init-buffer
107         (set-visited-file-name initd-el)
108         (insert ";; This is an automatically generated file.\n"
109                 ";; DO NOT EDIT\n"
110                 ";;\n")
111         (insert "(message \"Compiled " initd-dir " loading started\")\n")
112         (mapc 
113          #'(lambda (current)
114              (condition-case err
115                  (insert "(condition-case err (progn\n"
116                          ";; ------------------------------------\n"
117                          ";; " current "\n"
118                          (save-excursion        
119                            (save-restriction 
120                              (with-temp-buffer
121                                (insert-file-contents current)
122                                (eval-buffer)
123                                (buffer-substring))))
124                          "\n"
125                          ";; ----------------------------------\n"
126                          ")\n"
127                          "(error (message \"Error loading " current 
128                          ": \\\"%S\\\" (signal:\'%S\' . data:\'%S\')\" "
129                          "err (car err) (cdr err))))\n"
130                          ";; ----------------------------------\n\n")
131                (error
132                 (progn
133                   (insert "(warn \"\\\"" current 
134                           "\\\" not inserted "
135                           (replace-regexp-in-string 
136                            "\"" "\\\""
137                            (format (concat "due to syntax error: %S"
138                                            " (signal:%S . data:%S)")
139                                    err (car err) (cdr err)))
140                           "\")\n")
141                   (message
142                    "\"%S\" not inserted due to syntax error: %S (signal:%S . data:%S)"
143                    current err (car err) (cdr err))))))
144          initd-files)
145         (insert "(message \"Compiled " initd-dir " loading finished\")\n")
146         (save-buffer init-buffer)))
147     (when (and lisp-initd-byte-compile-elisp
148                (file-newer-than-file-p initd-el initd-elc))
149       (ignore-errors
150         (progn
151           (byte-compile-file initd-el)
152           (when lisp-initd-kill-compile-log
153             (kill-buffer (get-buffer "*Compile-Log*"))
154             (kill-buffer (get-buffer "*Compile-Log-Show*")))
155           (delete-other-windows)
156           (unless lisp-initd-keep-elisp
157             (delete-file initd-el)))))
158     (when (and do-init (null init-buffer))
159       (load init-file nil nil t))))
160
161
162 (defun lisp-initd-compile-and-load (&optional dir file)
163   "Compile and load the lisp files in DIR into a file named {DIR}/{FILE}.el.
164
165 If DIR, a string, is omitted `lisp-initd-dir' is used.  DIR can be
166 either a complete path, or the last element of a path.  If the latter,
167 DIR is expanded against the _parent_ directory of `lisp-initd-dir'.
168
169 Optional file arg, FILE is the name of the file to be loaded.  
170 If it is omitted, `lisp-initd-basename' is used.
171
172 See `lisp-initd-compile'."
173   (interactive (list (expand-file-name (read-directory-name
174                                         "initd directory: " user-init-directory
175                                         lisp-initd-dir t))))
176   (when dir
177     (unless (string-match "/" dir)
178       (setq dir (file-name-as-directory
179                  (expand-file-name dir (paths-construct-path 
180                                         (list lisp-initd-dir "..")))))))
181   (when current-prefix-arg
182     (setq file (read-string "File: ")))
183     
184   (lisp-initd-compile dir file t))
185
186 (provide 'lisp-initd)
187