* mh-alias.el (mh-alias-gecos-name): Use replace-regexp-in-string
[bpt/emacs.git] / lisp / mh-e / mh-init.el
CommitLineData
cee9f5c6 1;;; mh-init.el --- MH-E initialization
863e5e39 2
d49ed7d4 3;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
863e5e39
BW
4
5;; Author: Peter S. Galbraith <psg@debian.org>
6;; Maintainer: Bill Wohler <wohler@newt.com>
7;; Keywords: mail
8;; See: mh-e.el
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
3a35cf56
LK
24;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25;; Boston, MA 02110-1301, USA.
863e5e39
BW
26
27;;; Commentary:
28
6b19bd82 29;; Sets up the MH variant (currently nmh, MH, or GNU mailutils).
863e5e39
BW
30;;
31;; Users may customize `mh-variant' to switch between available variants.
32;; Available MH variants are described in the variable `mh-variants'.
33;; Developers may check which variant is currently in use with the
34;; variable `mh-variant-in-use' or the function `mh-variant-p'.
6b19bd82
BW
35;;
36;; Also contains code that is used at load or initialization time only.
863e5e39
BW
37
38;;; Change Log:
39
40;;; Code:
41
42(eval-when-compile (require 'mh-acros))
43(mh-require-cl)
44(require 'mh-utils)
45
cee9f5c6
BW
46;; Set for local environment:
47;; mh-progs and mh-lib used to be set in paths.el, which tried to
48;; figure out at build time which of several possible directories MH
49;; was installed into. But if you installed MH after building Emacs,
50;; this would almost certainly be wrong, so now we do it at run time.
863e5e39
BW
51
52(defvar mh-progs nil
53 "Directory containing MH commands, such as inc, repl, and rmm.")
54
55(defvar mh-lib nil
56 "Directory containing the MH library.
57This directory contains, among other things, the components file.")
58
59(defvar mh-lib-progs nil
60 "Directory containing MH helper programs.
61This directory contains, among other things, the mhl program.")
62
63(defvar mh-flists-present-flag nil
5a4aad03 64 "Non-nil means that we have \"flists\".")
863e5e39
BW
65
66;;;###autoload
67(put 'mh-progs 'risky-local-variable t)
68;;;###autoload
69(put 'mh-lib 'risky-local-variable t)
70;;;###autoload
71(put 'mh-lib-progs 'risky-local-variable t)
72
97c688ed
BW
73(defvar mh-variants nil
74 "List describing known MH variants.
75Created by the function `mh-variants'")
76
77;;;###mh-autoload
78(defun mh-variants ()
79 "Return a list of installed variants of MH on the system.
80This function looks for MH in `mh-sys-path', `mh-path' and
2dcf34f9
BW
81`exec-path'. The format of the list of variants that is returned
82is described by the variable `mh-variants'."
97c688ed
BW
83 (if mh-variants
84 mh-variants
85 (let ((list-unique))
86 ;; Make a unique list of directories, keeping the given order.
87 ;; We don't want the same MH variant to be listed multiple times.
88 (loop for dir in (append mh-path mh-sys-path exec-path) do
89 (setq dir (file-chase-links (directory-file-name dir)))
90 (add-to-list 'list-unique dir))
91 (loop for dir in (nreverse list-unique) do
92 (when (and dir (file-directory-p dir) (file-readable-p dir))
93 (let ((variant (mh-variant-info dir)))
94 (if variant
95 (add-to-list 'mh-variants variant)))))
96 mh-variants)))
97
863e5e39
BW
98(defvar mh-variant-in-use nil
99 "The MH variant currently in use; a string with variant and version number.
2dcf34f9 100This differs from `mh-variant' when the latter is set to
5a4aad03 101\"autodetect\".")
863e5e39
BW
102
103;;;###mh-autoload
104(defun mh-variant-set (variant)
105 "Set the MH variant to VARIANT.
2dcf34f9
BW
106Sets `mh-progs', `mh-lib', `mh-lib-progs' and
107`mh-flists-present-flag'.
5a4aad03 108If the VARIANT is \"autodetect\", then first try nmh, then MH and
2dcf34f9 109finally GNU mailutils."
863e5e39
BW
110 (interactive
111 (list (completing-read
112 "MH Variant: "
113 (mapcar (lambda (x) (list (car x))) (mh-variants))
114 nil t)))
115 (let ((valid-list (mapcar (lambda (x) (car x)) (mh-variants))))
116 (cond
117 ((eq variant 'none))
118 ((eq variant 'autodetect)
119 (cond
120 ((mh-variant-set-variant 'nmh)
121 (message "%s installed as MH variant" mh-variant-in-use))
eccf9613 122 ((mh-variant-set-variant 'mh)
863e5e39
BW
123 (message "%s installed as MH variant" mh-variant-in-use))
124 ((mh-variant-set-variant 'mu-mh)
125 (message "%s installed as MH variant" mh-variant-in-use))
126 (t
f9c53c97 127 (message "No MH variant found on the system"))))
863e5e39
BW
128 ((member variant valid-list)
129 (when (not (mh-variant-set-variant variant))
f9c53c97 130 (message "Warning: %s variant not found. Autodetecting..." variant)
863e5e39
BW
131 (mh-variant-set 'autodetect)))
132 (t
f9c53c97 133 (message "Unknown variant; use %s"
863e5e39
BW
134 (mapconcat '(lambda (x) (format "%s" (car x)))
135 mh-variants " or "))))))
136
137(defun mh-variant-set-variant (variant)
138 "Setup the system variables for the MH variant named VARIANT.
139If VARIANT is a string, use that key in the variable `mh-variants'.
2dcf34f9
BW
140If VARIANT is a symbol, select the first entry that matches that
141variant."
863e5e39
BW
142 (cond
143 ((stringp variant) ;e.g. "nmh 1.1-RC1"
144 (when (assoc variant mh-variants)
145 (let* ((alist (cdr (assoc variant mh-variants)))
146 (lib-progs (cadr (assoc 'mh-lib-progs alist)))
147 (lib (cadr (assoc 'mh-lib alist)))
148 (progs (cadr (assoc 'mh-progs alist)))
149 (flists (cadr (assoc 'flists alist))))
150 ;;(set-default mh-variant variant)
151 (setq mh-x-mailer-string nil
152 mh-flists-present-flag flists
153 mh-lib-progs lib-progs
154 mh-lib lib
155 mh-progs progs
156 mh-variant-in-use variant))))
157 ((symbolp variant) ;e.g. 'nmh (pick the first match)
158 (loop for variant-list in mh-variants
159 when (eq variant (cadr (assoc 'variant (cdr variant-list))))
160 return (let* ((version (car variant-list))
161 (alist (cdr variant-list))
162 (lib-progs (cadr (assoc 'mh-lib-progs alist)))
163 (lib (cadr (assoc 'mh-lib alist)))
164 (progs (cadr (assoc 'mh-progs alist)))
165 (flists (cadr (assoc 'flists alist))))
166 ;;(set-default mh-variant flavor)
167 (setq mh-x-mailer-string nil
168 mh-flists-present-flag flists
169 mh-lib-progs lib-progs
170 mh-lib lib
171 mh-progs progs
172 mh-variant-in-use version)
173 t)))))
174
175;;;###mh-autoload
176(defun mh-variant-p (&rest variants)
177 "Return t if variant is any of VARIANTS.
eccf9613 178Currently known variants are 'MH, 'nmh, and 'mu-mh."
863e5e39
BW
179 (let ((variant-in-use
180 (cadr (assoc 'variant (assoc mh-variant-in-use mh-variants)))))
181 (not (null (member variant-in-use variants)))))
182
183(defvar mh-sys-path
184 '("/usr/local/nmh/bin" ; nmh default
185 "/usr/local/bin/mh/"
186 "/usr/local/mh/"
187 "/usr/bin/mh/" ; Ultrix 4.2, Linux
188 "/usr/new/mh/" ; Ultrix < 4.2
189 "/usr/contrib/mh/bin/" ; BSDI
190 "/usr/pkg/bin/" ; NetBSD
191 "/usr/local/bin/"
192 "/usr/local/bin/mu-mh/" ; GNU mailutils - default
193 "/usr/bin/mu-mh/") ; GNU mailutils - packaged
194 "List of directories to search for variants of the MH variant.
195The list `exec-path' is searched in addition to this list.
2dcf34f9 196There's no need for users to modify this list. Instead add extra
863e5e39
BW
197directories to the customizable variable `mh-path'.")
198
863e5e39
BW
199(defun mh-variant-mh-info (dir)
200 "Return info for MH variant in DIR assuming a temporary buffer is setup."
201 ;; MH does not have the -version option.
5a4aad03 202 ;; Its version number is included in the output of "-help" as:
863e5e39
BW
203 ;;
204 ;; version: MH 6.8.4 #2[UCI] (burrito) of Fri Jan 15 20:01:39 EST 1999
205 ;; options: [ATHENA] [BIND] [DUMB] [LIBLOCKFILE] [LOCALE] [MAILGROUP] [MHE]
206 ;; [MHRC] [MIME] [MORE='"/usr/bin/sensible-pager"'] [NLINK_HACK]
207 ;; [NORUSERPASS] [OVERHEAD] [POP] [POPSERVICE='"pop-3"'] [RENAME]
208 ;; [RFC1342] [RPATHS] [RPOP] [SENDMTS] [SMTP] [SOCKETS]
209 ;; [SPRINTFTYPE=int] [SVR4] [SYS5] [SYS5DIR] [TERMINFO]
210 ;; [TYPESIG=void] [UNISTD] [UTK] [VSPRINTF]
211 (let ((mhparam (expand-file-name "mhparam" dir)))
212 (when (and (file-exists-p mhparam) (file-executable-p mhparam))
213 (erase-buffer)
214 (call-process mhparam nil '(t nil) nil "-help")
215 (goto-char (point-min))
216 (when (search-forward-regexp "version: MH \\(\\S +\\)" nil t)
217 (let ((version (format "MH %s" (match-string 1))))
218 (erase-buffer)
219 (call-process mhparam nil '(t nil) nil "libdir")
220 (goto-char (point-min))
221 (when (search-forward-regexp "^.*$" nil t)
222 (let ((libdir (match-string 0)))
223 `(,version
224 (variant mh)
225 (mh-lib-progs ,libdir)
226 (mh-lib ,libdir)
227 (mh-progs ,dir)
228 (flists nil)))))))))
229
230(defun mh-variant-mu-mh-info (dir)
231 "Return info for GNU mailutils variant in DIR.
232This assumes that a temporary buffer is setup."
233 ;; 'mhparam -version' output:
234 ;; mhparam (GNU mailutils 0.3.2)
235 (let ((mhparam (expand-file-name "mhparam" dir)))
236 (when (and (file-exists-p mhparam) (file-executable-p mhparam))
237 (erase-buffer)
238 (call-process mhparam nil '(t nil) nil "-version")
239 (goto-char (point-min))
240 (when (search-forward-regexp "mhparam (\\(GNU [Mm]ailutils \\S +\\))"
241 nil t)
242 (let ((version (match-string 1)))
243 (erase-buffer)
244 (call-process mhparam nil '(t nil) nil "libdir" "etcdir")
245 (goto-char (point-min))
246 (when (search-forward-regexp "^libdir:\\s-\\(\\S-+\\)\\s-*$" nil t)
247 (let ((libdir (match-string 1)))
248 (goto-char (point-min))
249 (when (search-forward-regexp
250 "^etcdir:\\s-\\(\\S-+\\)\\s-*$" nil t)
251 (let ((etcdir (match-string 1))
252 (flists (file-exists-p (expand-file-name "flists" dir))))
253 `(,version
254 (variant mu-mh)
255 (mh-lib-progs ,libdir)
256 (mh-lib ,etcdir)
257 (mh-progs ,dir)
258 (flists ,flists)))))))))))
259
260(defun mh-variant-nmh-info (dir)
261 "Return info for nmh variant in DIR assuming a temporary buffer is setup."
262 ;; `mhparam -version' outputs:
263 ;; mhparam -- nmh-1.1-RC1 [compiled on chaak at Fri Jun 20 11:03:28 PDT 2003]
264 (let ((mhparam (expand-file-name "mhparam" dir)))
265 (when (and (file-exists-p mhparam) (file-executable-p mhparam))
266 (erase-buffer)
267 (call-process mhparam nil '(t nil) nil "-version")
268 (goto-char (point-min))
269 (when (search-forward-regexp "mhparam -- nmh-\\(\\S +\\)" nil t)
270 (let ((version (format "nmh %s" (match-string 1))))
271 (erase-buffer)
272 (call-process mhparam nil '(t nil) nil "libdir" "etcdir")
273 (goto-char (point-min))
274 (when (search-forward-regexp "^libdir:\\s-\\(\\S-+\\)\\s-*$" nil t)
275 (let ((libdir (match-string 1)))
276 (goto-char (point-min))
277 (when (search-forward-regexp
278 "^etcdir:\\s-\\(\\S-+\\)\\s-*$" nil t)
279 (let ((etcdir (match-string 1))
280 (flists (file-exists-p (expand-file-name "flists" dir))))
281 `(,version
282 (variant nmh)
283 (mh-lib-progs ,libdir)
284 (mh-lib ,etcdir)
285 (mh-progs ,dir)
286 (flists ,flists)))))))))))
287
288(defun mh-variant-info (dir)
289 "Return MH variant found in DIR, or nil if none present."
290 (save-excursion
291 (let ((tmp-buffer (get-buffer-create mh-temp-buffer)))
292 (set-buffer tmp-buffer)
293 (cond
294 ((mh-variant-mh-info dir))
295 ((mh-variant-nmh-info dir))
296 ((mh-variant-mu-mh-info dir))))))
297
6b19bd82
BW
298\f
299
7094eefe
BW
300(eval-when-compile (defvar image-load-path)) ;shush compiler
301
2416ec64
SD
302(defvar mh-image-load-path-called-flag nil)
303
a05fcb7d
BW
304;;;###mh-autoload
305(defun mh-image-load-path ()
306 "Ensure that the MH-E images are accessible by `find-image'.
2dcf34f9 307Images for MH-E are found in ../../etc/images relative to the
5a4aad03 308files in \"lisp/mh-e\". If `image-load-path' exists (since Emacs
2dcf34f9
BW
30922), then the images directory is added to it if isn't already
310there. Otherwise, the images directory is added to the
311`load-path' if it isn't already there."
2416ec64 312 (unless mh-image-load-path-called-flag
8f552dc8 313 (let (mh-library-name mh-image-load-path)
2416ec64 314 ;; First, find mh-e in the load-path.
8f552dc8
BW
315 (setq mh-library-name (locate-library "mh-e"))
316 (if (not mh-library-name)
317 (error "Can not find MH-E in load-path"))
318 (setq mh-image-load-path
319 (expand-file-name (concat (file-name-directory mh-library-name)
320 "../../etc/images")))
321 (if (not (file-exists-p mh-image-load-path))
322 (error "Can not find image directory %s" mh-image-load-path))
323 (if (boundp 'image-load-path)
324 (add-to-list 'image-load-path mh-image-load-path)
325 (add-to-list 'load-path mh-image-load-path)))
2416ec64 326 (setq mh-image-load-path-called-flag t)))
a05fcb7d 327
6b19bd82
BW
328\f
329
7094eefe
BW
330;;; Support routines for mh-customize.el
331
6b19bd82
BW
332(defvar mh-min-colors-defined-flag (and (not mh-xemacs-flag)
333 (>= emacs-major-version 22))
334 "Non-nil means defface supports min-colors display requirement.")
335
336(defun mh-defface-compat (spec)
1a18223e 337 "Convert SPEC for defface if necessary to run on older platforms.
af435184 338Modifies SPEC in place and returns it. See `defface' for the spec definition.
6b19bd82 339
355ebcbf
BW
340When `mh-min-colors-defined-flag' is nil, this function finds
341display entries with \"min-colors\" requirements and either
342removes the \"min-colors\" requirement or strips the display
343entirely if the display does not support the number of specified
344colors."
345 (if mh-min-colors-defined-flag
346 spec
347 (let ((cells (display-color-cells))
348 new-spec)
349 ;; Remove entries with min-colors, or delete them if we have fewer colors
350 ;; than they specify.
351 (loop for entry in (reverse spec) do
352 (let ((requirement (if (eq (car entry) t)
353 nil
354 (assoc 'min-colors (car entry)))))
355 (if requirement
356 (when (>= cells (nth 1 requirement))
357 (setq new-spec (cons (cons (delq requirement (car entry))
358 (cdr entry))
359 new-spec)))
360 (setq new-spec (cons entry new-spec)))))
361 new-spec)))
1a18223e 362
863e5e39
BW
363(provide 'mh-init)
364
cee9f5c6
BW
365;; Local Variables:
366;; indent-tabs-mode: nil
367;; sentence-end-double-space: nil
368;; End:
863e5e39 369
b22103fe 370;; arch-tag: e8372aeb-d803-42b1-9c95-3c93ad22f63c
863e5e39 371;;; mh-init.el ends here