Mercurial > emacs
comparison lisp/mail/rmailout.el @ 88128:b621daa96824
Attempt to minimize byte compilation warnings.
(rmail-output-to-rmail-file): Eliminate Babyl 5 code by using
(rmail-output).
(rmail-output): Generalize the use by GNUS; rewrite to reflect mbox as
the default format.
(rmail-output-body-to-file): Use the rmail message descriptor in
setting the "stored" attribute.
author | Paul Reilly <pmr@pajato.com> |
---|---|
date | Sat, 15 Feb 2003 15:38:18 +0000 |
parents | e82b3fe06d4c |
children | d7ddb3e565de |
comparison
equal
deleted
inserted
replaced
88127:9c783aa2b379 | 88128:b621daa96824 |
---|---|
1 ;;; rmailout.el --- "RMAIL" mail reader for Emacs: output message to a file | 1 ;;; rmailout.el --- "RMAIL" mail reader for Emacs: output message to a file. |
2 | 2 |
3 ;; Copyright (C) 1985, 1987, 1993, 1994, 2001 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1985, 1987, 1993, 1994, 2001 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Maintainer: FSF | 5 ;; Maintainer: FSF |
6 ;; Keywords: mail | 6 ;; Keywords: mail |
24 | 24 |
25 ;;; Commentary: | 25 ;;; Commentary: |
26 | 26 |
27 ;;; Code: | 27 ;;; Code: |
28 | 28 |
29 (require 'rmail) | |
30 (provide 'rmailout) | 29 (provide 'rmailout) |
30 | |
31 (eval-when-compile | |
32 (require 'rmail) | |
33 (require 'rmaildesc)) | |
34 | |
31 | 35 |
32 ;;;###autoload | 36 ;;;###autoload |
33 (defcustom rmail-output-file-alist nil | 37 (defcustom rmail-output-file-alist nil |
34 "*Alist matching regexps to suggested output Rmail files. | 38 "*Alist matching regexps to suggested output Rmail files. |
35 This is a list of elements of the form (REGEXP . NAME-EXP). | 39 This is a list of elements of the form (REGEXP . NAME-EXP). |
60 ;; If no suggestions, use same file as last time. | 64 ;; If no suggestions, use same file as last time. |
61 (expand-file-name (or answer rmail-default-rmail-file))))) | 65 (expand-file-name (or answer rmail-default-rmail-file))))) |
62 (let ((read-file | 66 (let ((read-file |
63 (expand-file-name | 67 (expand-file-name |
64 (read-file-name | 68 (read-file-name |
65 (concat "Output message to Rmail file: (default " | 69 (concat "Output message to Rmail (mbox) file: (default " |
66 (file-name-nondirectory default-file) | 70 (file-name-nondirectory default-file) |
67 ") ") | 71 ") ") |
68 (file-name-directory default-file) | 72 (file-name-directory default-file) |
69 (abbreviate-file-name default-file)) | 73 (abbreviate-file-name default-file)) |
70 (file-name-directory default-file)))) | 74 (file-name-directory default-file)))) |
74 (if (file-directory-p read-file) | 78 (if (file-directory-p read-file) |
75 (expand-file-name (file-name-nondirectory default-file) | 79 (expand-file-name (file-name-nondirectory default-file) |
76 read-file) | 80 read-file) |
77 read-file))))) | 81 read-file))))) |
78 | 82 |
83 ;;; mbox: deprecated | |
79 (defun rmail-output-read-file-name () | 84 (defun rmail-output-read-file-name () |
80 "Read the file name to use for `rmail-output'. | 85 "Read the file name to use for `rmail-output'. |
81 Set `rmail-default-file' to this name as well as returning it." | 86 Set `rmail-default-file' to this name as well as returning it." |
82 (let ((default-file | 87 (let ((default-file |
83 (let (answer tail) | 88 (let (answer tail) |
106 read-file) | 111 read-file) |
107 (expand-file-name | 112 (expand-file-name |
108 (or read-file (file-name-nondirectory default-file)) | 113 (or read-file (file-name-nondirectory default-file)) |
109 (file-name-directory default-file))))))) | 114 (file-name-directory default-file))))))) |
110 | 115 |
116 ;;; mbox: ready | |
111 ;;; There are functions elsewhere in Emacs that use this function; | 117 ;;; There are functions elsewhere in Emacs that use this function; |
112 ;;; look at them before you change the calling method. | 118 ;;; look at them before you change the calling method. |
113 ;;;###autoload | 119 ;;;###autoload |
114 (defun rmail-output-to-rmail-file (file-name &optional count stay) | 120 (defun rmail-output-to-rmail-file (file-name &optional count stay) |
115 "Append the current message to an Rmail file named FILE-NAME. | 121 "Append the current message to an Rmail (mbox) file named FILE-NAME. |
116 If the file does not exist, ask if it should be created. | 122 If the file does not exist, ask if it should be created. |
117 If file is being visited, the message is appended to the Emacs | 123 If file is being visited, the message is appended to the Emacs |
118 buffer visiting that file. | 124 buffer visiting that file. |
119 If the file exists and is not an Rmail file, the message is | 125 If the file exists and is not an Rmail file, the message is |
120 appended in inbox format, the same way `rmail-output' does it. | 126 appended in inbox format, the same way `rmail-output' does it. |
128 If optional argument STAY is non-nil, then leave the last filed | 134 If optional argument STAY is non-nil, then leave the last filed |
129 mesasge up instead of moving forward to the next non-deleted message." | 135 mesasge up instead of moving forward to the next non-deleted message." |
130 (interactive | 136 (interactive |
131 (list (rmail-output-read-rmail-file-name) | 137 (list (rmail-output-read-rmail-file-name) |
132 (prefix-numeric-value current-prefix-arg))) | 138 (prefix-numeric-value current-prefix-arg))) |
133 (or count (setq count 1)) | 139 |
134 (setq file-name | 140 ;; Use the 'rmail-output function to perform the output. |
135 (expand-file-name file-name | 141 (rmail-output file-name count nil nil) |
136 (file-name-directory rmail-default-rmail-file))) | 142 |
137 (if (and (file-readable-p file-name) (not (mail-file-babyl-p file-name))) | 143 ;; Deal with the next message |
138 (rmail-output file-name count) | 144 (if rmail-delete-after-output |
139 (rmail-maybe-set-message-counters) | 145 (unless |
140 (setq file-name (abbreviate-file-name file-name)) | 146 (if (and (= count 0) stay) |
141 (or (find-buffer-visiting file-name) | 147 (rmail-delete-message) |
142 (file-exists-p file-name) | 148 (rmail-delete-forward)) |
143 (if (yes-or-no-p | 149 (setq count 0)) |
144 (concat "\"" file-name "\" does not exist, create it? ")) | 150 (if (> count 0) |
145 (let ((file-buffer (create-file-buffer file-name))) | 151 (unless |
146 (save-excursion | 152 (if (not stay) (rmail-next-undeleted-message 1)) |
147 (set-buffer file-buffer) | 153 (setq count 0))))) |
148 (rmail-insert-rmail-file-header) | 154 |
149 (let ((require-final-newline nil) | 155 ;;; mbox: deprecated |
150 (coding-system-for-write | |
151 (or rmail-file-coding-system | |
152 'emacs-mule-unix))) | |
153 (write-region (point-min) (point-max) file-name t 1))) | |
154 (kill-buffer file-buffer)) | |
155 (error "Output file does not exist"))) | |
156 (while (> count 0) | |
157 (let (redelete) | |
158 (unwind-protect | |
159 (progn | |
160 (set-buffer rmail-buffer) | |
161 ;; Temporarily turn off Deleted attribute. | |
162 ;; Do this outside the save-restriction, since it would | |
163 ;; shift the place in the buffer where the visible text starts. | |
164 (if (rmail-message-deleted-p rmail-current-message) | |
165 (progn (setq redelete t) | |
166 (rmail-set-attribute "deleted" nil))) | |
167 (save-restriction | |
168 (widen) | |
169 ;; Decide whether to append to a file or to an Emacs buffer. | |
170 (save-excursion | |
171 (let ((buf (find-buffer-visiting file-name)) | |
172 (cur (current-buffer)) | |
173 (beg (1+ (rmail-msgbeg rmail-current-message))) | |
174 (end (1+ (rmail-msgend rmail-current-message))) | |
175 (coding-system-for-write | |
176 (or rmail-file-coding-system | |
177 'emacs-mule-unix))) | |
178 (if (not buf) | |
179 ;; Output to a file. | |
180 (if rmail-fields-not-to-output | |
181 ;; Delete some fields while we output. | |
182 (let ((obuf (current-buffer))) | |
183 (set-buffer (get-buffer-create " rmail-out-temp")) | |
184 (insert-buffer-substring obuf beg end) | |
185 (rmail-delete-unwanted-fields) | |
186 (append-to-file (point-min) (point-max) file-name) | |
187 (set-buffer obuf) | |
188 (kill-buffer (get-buffer " rmail-out-temp"))) | |
189 (append-to-file beg end file-name)) | |
190 (if (eq buf (current-buffer)) | |
191 (error "Can't output message to same file it's already in")) | |
192 ;; File has been visited, in buffer BUF. | |
193 (set-buffer buf) | |
194 (let ((buffer-read-only nil) | |
195 (msg (and (boundp 'rmail-current-message) | |
196 rmail-current-message))) | |
197 ;; If MSG is non-nil, buffer is in RMAIL mode. | |
198 (if msg | |
199 (progn | |
200 ;; Turn on auto save mode, if it's off in this | |
201 ;; buffer but enabled by default. | |
202 (and (not buffer-auto-save-file-name) | |
203 auto-save-default | |
204 (auto-save-mode t)) | |
205 (rmail-maybe-set-message-counters) | |
206 (widen) | |
207 (narrow-to-region (point-max) (point-max)) | |
208 (insert-buffer-substring cur beg end) | |
209 (goto-char (point-min)) | |
210 (widen) | |
211 (search-backward "\n\^_") | |
212 (narrow-to-region (point) (point-max)) | |
213 (rmail-delete-unwanted-fields) | |
214 (rmail-count-new-messages t) | |
215 (if (rmail-summary-exists) | |
216 (rmail-select-summary | |
217 (rmail-update-summary))) | |
218 (rmail-show-message msg)) | |
219 ;; Output file not in rmail mode => just insert at the end. | |
220 (narrow-to-region (point-min) (1+ (buffer-size))) | |
221 (goto-char (point-max)) | |
222 (insert-buffer-substring cur beg end) | |
223 (rmail-delete-unwanted-fields))))))) | |
224 (rmail-set-attribute "filed" t)) | |
225 (if redelete (rmail-set-attribute "deleted" t)))) | |
226 (setq count (1- count)) | |
227 (if rmail-delete-after-output | |
228 (unless | |
229 (if (and (= count 0) stay) | |
230 (rmail-delete-message) | |
231 (rmail-delete-forward)) | |
232 (setq count 0)) | |
233 (if (> count 0) | |
234 (unless | |
235 (if (not stay) (rmail-next-undeleted-message 1)) | |
236 (setq count 0))))))) | |
237 | |
238 ;;;###autoload | 156 ;;;###autoload |
239 (defcustom rmail-fields-not-to-output nil | 157 (defcustom rmail-fields-not-to-output nil |
240 "*Regexp describing fields to exclude when outputting a message to a file." | 158 "*Regexp describing fields to exclude when outputting a message to a file." |
241 :type '(choice (const :tag "None" nil) | 159 :type '(choice (const :tag "None" nil) |
242 regexp) | 160 regexp) |
243 :group 'rmail-output) | 161 :group 'rmail-output) |
244 | 162 |
163 ;;; mbox: deprecated | |
245 ;; Delete from the buffer header fields we don't want output. | 164 ;; Delete from the buffer header fields we don't want output. |
246 ;; NOT-RMAIL if t means this buffer does not have the full header | 165 ;; NOT-RMAIL if t means this buffer does not have the full header |
247 ;; and *** EOOH *** that a message in an Rmail file has. | 166 ;; and *** EOOH *** that a message in an Rmail file has. |
248 (defun rmail-delete-unwanted-fields (&optional not-rmail) | 167 (defun rmail-delete-unwanted-fields (&optional not-rmail) |
249 (if rmail-fields-not-to-output | 168 (if rmail-fields-not-to-output |
257 (while (re-search-forward rmail-fields-not-to-output end t) | 176 (while (re-search-forward rmail-fields-not-to-output end t) |
258 (beginning-of-line) | 177 (beginning-of-line) |
259 (delete-region (point) | 178 (delete-region (point) |
260 (progn (forward-line 1) (point))))))))) | 179 (progn (forward-line 1) (point))))))))) |
261 | 180 |
181 ;;; mbox: ready | |
262 ;;; There are functions elsewhere in Emacs that use this function; | 182 ;;; There are functions elsewhere in Emacs that use this function; |
263 ;;; look at them before you change the calling method. | 183 ;;; look at them before you change the calling method. |
264 ;;;###autoload | 184 ;;;###autoload |
265 (defun rmail-output (file-name &optional count noattribute from-gnus) | 185 (defun rmail-output (file-name &optional count noattribute ext) |
266 "Append this message to system-inbox-format mail file named FILE-NAME. | 186 "Append an mbox formatted message to the mbox formatted file named |
267 A prefix argument N says to output N consecutive messages | 187 FILE-NAME. A prefix argument COUNT says to output COUNT consecutive |
268 starting with the current one. Deleted messages are skipped and don't count. | 188 messages starting with the current one. Deleted messages are skipped |
269 When called from lisp code, N may be omitted. | 189 and don't count. When called from lisp code, COUNT may be omitted. |
270 | |
271 If the pruned message header is shown on the current message, then | |
272 messages will be appended with pruned headers; otherwise, messages | |
273 will be appended with their original headers. | |
274 | 190 |
275 The default file name comes from `rmail-default-file', | 191 The default file name comes from `rmail-default-file', |
276 which is updated to the name you use in this command. | 192 which is updated to the name you use in this command. |
277 | 193 |
278 The optional third argument NOATTRIBUTE, if non-nil, says not | 194 The optional third argument NOATTRIBUTE, if non-nil, says not |
279 to set the `filed' attribute, and not to display a message. | 195 to set the `filed' attribute, and not to display a message. |
280 | 196 |
281 The optional fourth argument FROM-GNUS is set when called from GNUS." | 197 The optional fourth argument EXT is set when called from outside of an |
198 Rmail function, for example by GNUS or Sendmail." | |
282 (interactive | 199 (interactive |
283 (list (rmail-output-read-file-name) | 200 (list (rmail-output-read-file-name) |
284 (prefix-numeric-value current-prefix-arg))) | 201 (prefix-numeric-value current-prefix-arg))) |
285 (or count (setq count 1)) | 202 (or count (setq count 1)) |
286 (setq file-name | 203 (setq file-name |
287 (expand-file-name file-name | 204 (expand-file-name file-name |
288 (and rmail-default-file | 205 (and rmail-default-file |
289 (file-name-directory rmail-default-file)))) | 206 (file-name-directory rmail-default-file)))) |
290 (if (and (file-readable-p file-name) (mail-file-babyl-p file-name)) | 207 |
291 (rmail-output-to-rmail-file file-name count) | 208 ;; Use the Rmail buffer, likely narrowed, as the message source |
292 (set-buffer rmail-buffer) | 209 ;; unless being called from an external party, such as GNUS or |
293 (let ((orig-count count) | 210 ;; Sendmail. |
294 (rmailbuf (current-buffer)) | 211 (unless ext |
295 (case-fold-search t) | 212 (set-buffer rmail-buffer)) |
296 (tembuf (get-buffer-create " rmail-output")) | 213 |
297 (original-headers-p | 214 (let ((orig-count count) |
298 (and (not from-gnus) | 215 (src-buf (current-buffer)) |
299 (save-excursion | 216 (dst-buf (find-buffer-visiting file-name)) |
300 (save-restriction | 217 (current-message rmail-current-message) |
301 (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max)) | 218 (tembuf (get-buffer-create " rmail-output")) |
302 (goto-char (point-min)) | 219 (original-headers-p |
303 (forward-line 1) | 220 (and (not ext) (not (rmail-msg-is-pruned))))) |
304 (= (following-char) ?0))))) | 221 |
305 header-beginning | 222 ;; Output each message to the destination file. |
306 mail-from mime-version content-type) | 223 (while (> count 0) |
307 (while (> count 0) | 224 (save-excursion |
308 ;; Preserve the Mail-From and MIME-Version fields | 225 |
309 ;; even if they have been pruned. | 226 ;; Copy the message, including all headers, to the temporary |
310 (or from-gnus | 227 ;; buffer. |
311 (save-excursion | 228 (set-buffer tembuf) |
312 (save-restriction | 229 (erase-buffer) |
313 (widen) | 230 (insert-buffer-substring src-buf) |
314 (goto-char (rmail-msgbeg rmail-current-message)) | 231 |
315 (setq header-beginning (point)) | 232 ;; Deal with MIME --- tbd. |
316 (search-forward "\n*** EOOH ***\n") | 233 ;;(when rmail-enable-mime ... |
317 (narrow-to-region header-beginning (point)) | 234 |
318 (setq mail-from (mail-fetch-field "Mail-From")) | 235 ;; Determine whether a buffer is already visiting the output |
319 (unless rmail-enable-mime | 236 ;; file. |
320 (setq mime-version (mail-fetch-field "MIME-Version") | 237 (if dst-buf |
321 content-type (mail-fetch-field "Content-type")))))) | 238 |
322 (save-excursion | 239 ;; The destination file is being visited. Update it. |
323 (set-buffer tembuf) | 240 (progn |
324 (erase-buffer) | 241 (set-buffer dst-buf) |
325 (insert-buffer-substring rmailbuf) | 242 |
326 (when rmail-enable-mime | 243 ;; Determine if the destination file is an Rmail file. |
327 (if original-headers-p | 244 (let ((buffer-read-only nil) |
328 (delete-region (goto-char (point-min)) | 245 (dst-current-message (and (boundp 'rmail-current-message) |
329 (if (search-forward "\n*** EOOH ***\n") | 246 rmail-current-message))) |
330 (match-end 0))) | 247 (if dst-current-message |
331 (goto-char (point-min)) | 248 |
332 (forward-line 2) | 249 ;; The buffer is an Rmail buffer. Append the message. |
333 (delete-region (point-min)(point)) | 250 (progn |
334 (search-forward "\n*** EOOH ***\n") | 251 (widen) |
335 (delete-region (match-beginning 0) | 252 (narrow-to-region (point-max) (point-max)) |
336 (if (search-forward "\n\n") | 253 (insert-buffer-substring src-buf) |
337 (1- (match-end 0))))) | 254 (insert "\n") |
338 (setq buffer-file-coding-system (or rmail-file-coding-system | 255 (rmail-process-new-messages) |
339 'raw-text))) | 256 (rmail-show-message dst-current-message)) |
340 (rmail-delete-unwanted-fields t) | 257 |
341 (or (bolp) (insert "\n")) | 258 ;; The destination file is not an Rmail file, just |
342 (goto-char (point-min)) | 259 ;; insert at the end. |
343 (if mail-from | 260 (goto-char (point-max)) |
344 (insert mail-from "\n") | 261 (insert-buffer-substring src-buf)))) |
345 (insert "From " | 262 |
346 (mail-strip-quoted-names (or (mail-fetch-field "from") | 263 ;; The destination file is not being visited, just write out |
347 (mail-fetch-field "really-from") | 264 ;; the processed message. |
348 (mail-fetch-field "sender") | 265 (write-region (point-min) (point-max) file-name t |
349 "unknown")) | 266 (if noattribute 'nomsg)))) |
350 " " (current-time-string) "\n")) | 267 |
351 (if mime-version | 268 ;; Do housekeeping, such as setting the "Filed" attribute, if |
352 (insert "MIME-Version: " mime-version | 269 ;; necessary and moving to the next message. |
353 "\nContent-type: " content-type "\n")) | 270 (or noattribute |
354 ;; ``Quote'' "\nFrom " as "\n>From " | 271 (if (equal major-mode 'rmail-mode) |
355 ;; (note that this isn't really quoting, as there is no requirement | 272 (progn |
356 ;; that "\n[>]+From " be quoted in the same transparent way.) | 273 (rmail-set-attribute "filed" t current-message) |
357 (let ((case-fold-search nil)) | 274 (setq current-message (1+ current-message))))) |
358 (while (search-forward "\nFrom " nil t) | 275 |
359 (forward-char -5) | 276 ;; Determine if Rmail post output operations need to be handled. |
360 (insert ?>))) | 277 (or ext |
361 (write-region (point-min) (point-max) file-name t | 278 |
362 (if noattribute 'nomsg))) | 279 ;; They do. Move to the next non-deleted message. |
363 (or noattribute | 280 (let ((next-message-p |
364 (if (equal major-mode 'rmail-mode) | 281 (if rmail-delete-after-output |
365 (rmail-set-attribute "filed" t))) | 282 (rmail-delete-forward) |
366 (setq count (1- count)) | 283 (if (> count 1) |
367 (or from-gnus | 284 (rmail-next-undeleted-message 1)))) |
368 (let ((next-message-p | 285 (num-appended (- orig-count count))) |
369 (if rmail-delete-after-output | 286 (if (and (> count 1) (not next-message-p)) |
370 (rmail-delete-forward) | 287 (progn |
371 (if (> count 0) | 288 (error |
372 (rmail-next-undeleted-message 1)))) | 289 (save-excursion |
373 (num-appended (- orig-count count))) | 290 (set-buffer src-buf) |
374 (if (and next-message-p original-headers-p) | 291 (format "Only %d message%s appended" num-appended |
375 (rmail-toggle-header)) | 292 (if (= num-appended 1) "" "s")))) |
376 (if (and (> count 0) (not next-message-p)) | 293 (setq count 0))))) |
377 (progn | 294 |
378 (error | 295 ;; Decrement the count for the next iteration. If an error has |
379 (save-excursion | 296 ;; occurred, then count will be -1, which is every bit as good |
380 (set-buffer rmailbuf) | 297 ;; as 0. |
381 (format "Only %d message%s appended" num-appended | 298 (setq count (1- count))) |
382 (if (= num-appended 1) "" "s")))) | 299 (kill-buffer tembuf))) |
383 (setq count 0)))))) | 300 |
384 (kill-buffer tembuf)))) | 301 ;;; mbox: ready |
385 | |
386 ;;;###autoload | 302 ;;;###autoload |
387 (defun rmail-output-body-to-file (file-name) | 303 (defun rmail-output-body-to-file (file-name) |
388 "Write this message body to the file FILE-NAME. | 304 "Write this message body to the file FILE-NAME. |
389 FILE-NAME defaults, interactively, from the Subject field of the message." | 305 FILE-NAME defaults, interactively, from the Subject field of the message." |
390 (interactive | 306 (interactive |
407 (and (file-exists-p file-name) | 323 (and (file-exists-p file-name) |
408 (not (y-or-n-p (message "File %s exists; overwrite? " file-name))) | 324 (not (y-or-n-p (message "File %s exists; overwrite? " file-name))) |
409 (error "Operation aborted")) | 325 (error "Operation aborted")) |
410 (write-region (point) (point-max) file-name) | 326 (write-region (point) (point-max) file-name) |
411 (if (equal major-mode 'rmail-mode) | 327 (if (equal major-mode 'rmail-mode) |
412 (rmail-set-attribute "stored" t))) | 328 (rmail-desc-set-attribute rmail-desc-stored-index t rmail-current-message))) |
413 (if rmail-delete-after-output | 329 (if rmail-delete-after-output |
414 (rmail-delete-forward))) | 330 (rmail-delete-forward))) |
415 | 331 |
416 ;;; rmailout.el ends here | 332 ;;; rmailout.el ends here |