Commit | Line | Data |
---|---|---|
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. | |
57 | This directory contains, among other things, the components file.") | |
58 | ||
59 | (defvar mh-lib-progs nil | |
60 | "Directory containing MH helper programs. | |
61 | This 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. | |
75 | Created 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. | |
80 | This 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 |
82 | is 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 | 100 | This 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 |
106 | Sets `mh-progs', `mh-lib', `mh-lib-progs' and |
107 | `mh-flists-present-flag'. | |
5a4aad03 | 108 | If the VARIANT is \"autodetect\", then first try nmh, then MH and |
2dcf34f9 | 109 | finally 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. | |
139 | If VARIANT is a string, use that key in the variable `mh-variants'. | |
2dcf34f9 BW |
140 | If VARIANT is a symbol, select the first entry that matches that |
141 | variant." | |
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 | 178 | Currently 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. | |
195 | The list `exec-path' is searched in addition to this list. | |
2dcf34f9 | 196 | There's no need for users to modify this list. Instead add extra |
863e5e39 BW |
197 | directories 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. | |
232 | This 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 | 307 | Images for MH-E are found in ../../etc/images relative to the |
5a4aad03 | 308 | files in \"lisp/mh-e\". If `image-load-path' exists (since Emacs |
2dcf34f9 BW |
309 | 22), then the images directory is added to it if isn't already |
310 | there. 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 | 338 | Modifies SPEC in place and returns it. See `defface' for the spec definition. |
6b19bd82 | 339 | |
355ebcbf BW |
340 | When `mh-min-colors-defined-flag' is nil, this function finds |
341 | display entries with \"min-colors\" requirements and either | |
342 | removes the \"min-colors\" requirement or strips the display | |
343 | entirely if the display does not support the number of specified | |
344 | colors." | |
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 |