comparison lisp/mh-e/mh-funcs.el @ 88155:d7ddb3e565de

sync with trunk
author Henrik Enberg <henrik.enberg@telia.com>
date Mon, 16 Jan 2006 00:03:54 +0000
parents 0d8b17d428b5
children
comparison
equal deleted inserted replaced
88154:8ce476d3ba36 88155:d7ddb3e565de
1 ;;; mh-funcs.el --- MH-E functions not everyone will use right away 1 ;;; mh-funcs.el --- MH-E functions not everyone will use right away
2 2
3 ;; Copyright (C) 1993, 1995, 2001, 2002 Free Software Foundation, Inc. 3 ;; Copyright (C) 1993, 1995,
4 ;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4 5
5 ;; Author: Bill Wohler <wohler@newt.com> 6 ;; Author: Bill Wohler <wohler@newt.com>
6 ;; Maintainer: Bill Wohler <wohler@newt.com> 7 ;; Maintainer: Bill Wohler <wohler@newt.com>
7 ;; Keywords: mail 8 ;; Keywords: mail
8 ;; See: mh-e.el 9 ;; See: mh-e.el
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details. 21 ;; GNU General Public License for more details.
21 22
22 ;; You should have received a copy of the GNU General Public License 23 ;; 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 24 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 25 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02111-1307, USA. 26 ;; Boston, MA 02110-1301, USA.
26 27
27 ;;; Commentary: 28 ;;; Commentary:
28 29
29 ;; Internal support for MH-E package. 30 ;; Internal support for MH-E package.
30 ;; Putting these functions in a separate file lets MH-E start up faster, 31 ;; Putting these functions in a separate file lets MH-E start up faster,
31 ;; since less Lisp code needs to be loaded all at once. 32 ;; since less Lisp code needs to be loaded all at once.
32 33
33 ;;; Change Log: 34 ;;; Change Log:
34 35
35 ;; $Id: mh-funcs.el,v 1.2 2003/02/03 20:55:30 wohler Exp $
36
37 ;;; Code: 36 ;;; Code:
38 37
38 ;;(message "> mh-funcs")
39 (eval-when-compile (require 'mh-acros))
40 (mh-require-cl)
41 (require 'mh-buffers)
39 (require 'mh-e) 42 (require 'mh-e)
40 43 ;;(message "< mh-funcs")
41 ;;; Customization 44
42 45
43 (defvar mh-sortm-args nil 46
44 "Extra arguments to have \\[mh-sort-folder] pass to the \"sortm\" command. 47 ;;; Scan Line Formats
45 The arguments are passed to sortm if \\[mh-sort-folder] is given a
46 prefix argument. Normally default arguments to sortm are specified in the
47 MH profile.
48 For example, '(\"-nolimit\" \"-textfield\" \"subject\") is a useful setting.")
49 48
50 (defvar mh-note-copied "C" 49 (defvar mh-note-copied "C"
51 "String whose first character is used to notate copied messages.") 50 "Messages that have been copied are marked by this character.")
52 51
53 (defvar mh-note-printed "P" 52 (defvar mh-note-printed "P"
54 "String whose first character is used to notate printed messages.") 53 "Messages that have been printed are marked by this character.")
54
55
55 56
56 ;;; Functions 57 ;;; Functions
57 58
58 ;;;###mh-autoload 59 ;;;###mh-autoload
59 (defun mh-burst-digest () 60 (defun mh-burst-digest ()
60 "Burst apart the current message, which should be a digest. 61 "Break up digest into separate messages\\<mh-folder-mode-map>.
61 The message is replaced by its table of contents and the messages from the 62
62 digest are inserted into the folder after that message." 63 This command uses the MH command \"burst\" to break out each
64 message in the digest into its own message. Using this command,
65 you can quickly delete unwanted messages, like this: Once the
66 digest is split up, toggle out of MH-Folder Show mode with
67 \\[mh-toggle-showing] so that the scan lines fill the screen and
68 messages aren't displayed. Then use \\[mh-delete-msg] to quickly
69 delete messages that you don't want to read (based on the
70 \"Subject:\" header field). You can also burst the digest to
71 reply directly to the people who posted the messages in the
72 digest. One problem you may encounter is that the \"From:\"
73 header fields are preceded with a \">\" so that your reply can't
74 create the \"To:\" field correctly. In this case, you must
75 correct the \"To:\" field yourself."
63 (interactive) 76 (interactive)
64 (let ((digest (mh-get-msg-num t))) 77 (let ((digest (mh-get-msg-num t)))
65 (mh-process-or-undo-commands mh-current-folder) 78 (mh-process-or-undo-commands mh-current-folder)
66 (mh-set-folder-modified-p t) ; lock folder while bursting 79 (mh-set-folder-modified-p t) ; lock folder while bursting
67 (message "Bursting digest...") 80 (message "Bursting digest...")
72 (mh-regenerate-headers (format "%d-last" digest) t) 85 (mh-regenerate-headers (format "%d-last" digest) t)
73 (mh-goto-cur-msg) 86 (mh-goto-cur-msg)
74 (message "Bursting digest...done"))) 87 (message "Bursting digest...done")))
75 88
76 ;;;###mh-autoload 89 ;;;###mh-autoload
77 (defun mh-copy-msg (msg-or-seq folder) 90 (defun mh-copy-msg (range folder)
78 "Copy the specified MSG-OR-SEQ to another FOLDER without deleting them. 91 "Copy RANGE to FOLDER\\<mh-folder-mode-map>.
79 Default is the displayed message. If optional prefix argument is provided, 92
80 then prompt for the message sequence." 93 If you wish to copy a message to another folder, you can use this
81 (interactive (list (cond 94 command (see the \"-link\" argument to \"refile\"). Like the
82 ((mh-mark-active-p t) 95 command \\[mh-refile-msg], this command prompts you for the name
83 (cons (region-beginning) (region-end))) 96 of the target folder and you can specify a range. Note that
84 (current-prefix-arg 97 unlike the command \\[mh-refile-msg], the copy takes place
85 (mh-read-seq-default "Copy" t)) 98 immediately. The original copy remains in the current folder.
86 (t 99
87 (cons (line-beginning-position) (line-end-position)))) 100 Check the documentation of `mh-interactive-range' to see how
101 RANGE is read in interactive use."
102 (interactive (list (mh-interactive-range "Copy")
88 (mh-prompt-for-folder "Copy to" "" t))) 103 (mh-prompt-for-folder "Copy to" "" t)))
89 (let ((msg-list (cond ((numberp msg-or-seq) (list msg-or-seq)) 104 (let ((msg-list (let ((result ()))
90 ((symbolp msg-or-seq) (mh-seq-to-msgs msg-or-seq)) 105 (mh-iterate-on-range msg range
91 ((and (consp msg-or-seq) (numberp (car msg-or-seq)) 106 (mh-notate nil mh-note-copied mh-cmd-note)
92 (numberp (cdr msg-or-seq))) 107 (push msg result))
93 (let ((result ())) 108 result)))
94 (mh-iterate-on-messages-in-region msg
95 (car msg-or-seq) (cdr msg-or-seq)
96 (mh-notate nil mh-note-copied mh-cmd-note)
97 (push msg result))
98 result))
99 (t msg-or-seq))))
100 (mh-exec-cmd "refile" (mh-coalesce-msg-list msg-list) 109 (mh-exec-cmd "refile" (mh-coalesce-msg-list msg-list)
101 "-link" "-src" mh-current-folder folder) 110 "-link" "-src" mh-current-folder folder)))
102 (cond ((numberp msg-or-seq)
103 (mh-notate msg-or-seq mh-note-copied mh-cmd-note))
104 ((symbolp msg-or-seq)
105 (mh-notate-seq msg-or-seq mh-note-copied mh-cmd-note)))))
106 111
107 ;;;###mh-autoload 112 ;;;###mh-autoload
108 (defun mh-kill-folder () 113 (defun mh-kill-folder ()
109 "Remove the current folder and all included messages. 114 "Remove folder.
110 Removes all of the messages (files) within the specified current folder, 115
111 and then removes the folder (directory) itself." 116 Remove all of the messages (files) within the current folder, and
112 (interactive) 117 then remove the folder (directory) itself.
113 (if (or mh-index-data 118
114 (yes-or-no-p (format "Remove folder %s (and all included messages)?" 119 Run the abnormal hook `mh-kill-folder-suppress-prompt-hooks'. The
120 hook functions are called with no arguments and should return a
121 non-nil value to suppress the normal prompt when you remove a
122 folder. This is useful for folders that are easily regenerated."
123 (interactive)
124 (if (or (run-hook-with-args-until-success
125 'mh-kill-folder-suppress-prompt-hooks)
126 (yes-or-no-p (format "Remove folder %s (and all included messages)? "
115 mh-current-folder))) 127 mh-current-folder)))
116 (let ((folder mh-current-folder) 128 (let ((folder mh-current-folder)
117 (window-config mh-previous-window-config)) 129 (window-config mh-previous-window-config))
118 (mh-set-folder-modified-p t) ; lock folder to kill it 130 (mh-set-folder-modified-p t) ; lock folder to kill it
119 (mh-exec-cmd-daemon "rmf" 'mh-rmf-daemon folder) 131 (mh-exec-cmd-daemon "rmf" 'mh-rmf-daemon folder)
134 "The rmf PROCESS puts OUTPUT in temporary buffer. 146 "The rmf PROCESS puts OUTPUT in temporary buffer.
135 Display the results only if something went wrong." 147 Display the results only if something went wrong."
136 (set-buffer (get-buffer-create mh-temp-buffer)) 148 (set-buffer (get-buffer-create mh-temp-buffer))
137 (insert-before-markers output) 149 (insert-before-markers output)
138 (when (save-excursion 150 (when (save-excursion
139 (beginning-of-buffer) 151 (goto-char (point-min))
140 (re-search-forward "^rmf: " (point-max) t)) 152 (re-search-forward "^rmf: " (point-max) t))
141 (display-buffer mh-temp-buffer))) 153 (display-buffer mh-temp-buffer)))
142 154
143 ;; Avoid compiler warning... 155 ;; Shush compiler.
144 (defvar view-exit-action) 156 (eval-when-compile (defvar view-exit-action))
145 157
146 ;;;###mh-autoload 158 ;;;###mh-autoload
147 (defun mh-list-folders () 159 (defun mh-list-folders ()
148 "List mail folders." 160 "List mail folders."
149 (interactive) 161 (interactive)
155 (message "Listing folders...") 167 (message "Listing folders...")
156 (mh-exec-cmd-output "folders" t (if mh-recursive-folders-flag 168 (mh-exec-cmd-output "folders" t (if mh-recursive-folders-flag
157 "-recurse" 169 "-recurse"
158 "-norecurse")) 170 "-norecurse"))
159 (goto-char (point-min)) 171 (goto-char (point-min))
160 (view-mode 1) 172 (view-mode-enter)
161 (setq view-exit-action 'kill-buffer) 173 (setq view-exit-action 'kill-buffer)
162 (message "Listing folders...done"))))) 174 (message "Listing folders...done")))))
163 175
164 ;;;###mh-autoload 176 ;;;###mh-autoload
165 (defun mh-pack-folder (range) 177 (defun mh-pack-folder (range)
166 "Renumber the messages of a folder to be 1..n. 178 "Pack folder\\<mh-folder-mode-map>.
167 First, offer to execute any outstanding commands for the current folder. If 179
168 optional prefix argument provided, prompt for the RANGE of messages to display 180 This command packs the folder, removing gaps from the numbering
169 after packing. Otherwise, show the entire folder." 181 sequence. If you don't want to rescan the entire folder
182 afterward, this command will accept a RANGE. Check the
183 documentation of `mh-interactive-range' to see how RANGE is read
184 in interactive use.
185
186 This command will ask if you want to process refiles or deletes
187 first and then either run \\[mh-execute-commands] for you or undo
188 the pending refiles and deletes, which are lost."
170 (interactive (list (if current-prefix-arg 189 (interactive (list (if current-prefix-arg
171 (mh-read-msg-range mh-current-folder t) 190 (mh-read-range "Scan" mh-current-folder t nil t
191 mh-interpret-number-as-range-flag)
172 '("all")))) 192 '("all"))))
173 (let ((threaded-flag (memq 'unthread mh-view-ops))) 193 (let ((threaded-flag (memq 'unthread mh-view-ops)))
174 (mh-pack-folder-1 range) 194 (mh-pack-folder-1 range)
175 (mh-goto-cur-msg) 195 (mh-goto-cur-msg)
176 (when mh-index-data 196 (when mh-index-data
179 (mh-index-data (mh-index-insert-folder-headers)))) 199 (mh-index-data (mh-index-insert-folder-headers))))
180 (message "Packing folder...done")) 200 (message "Packing folder...done"))
181 201
182 (defun mh-pack-folder-1 (range) 202 (defun mh-pack-folder-1 (range)
183 "Close and pack the current folder. 203 "Close and pack the current folder.
184 Display the given RANGE of messages after packing. If RANGE is nil, show the 204
185 entire folder." 205 Display RANGE after packing, or the entire folder if RANGE is nil."
186 (mh-process-or-undo-commands mh-current-folder) 206 (mh-process-or-undo-commands mh-current-folder)
187 (message "Packing folder...") 207 (message "Packing folder...")
188 (mh-set-folder-modified-p t) ; lock folder while packing 208 (mh-set-folder-modified-p t) ; lock folder while packing
189 (save-excursion 209 (save-excursion
190 (mh-exec-cmd-quiet t "folder" mh-current-folder "-pack" 210 (mh-exec-cmd-quiet t "folder" mh-current-folder "-pack"
191 "-norecurse" "-fast")) 211 "-norecurse" "-fast"))
192 (mh-reset-threads-and-narrowing) 212 (mh-reset-threads-and-narrowing)
193 (mh-regenerate-headers range)) 213 (mh-regenerate-headers range))
194 214
195 ;;;###mh-autoload 215 ;;;###mh-autoload
196 (defun mh-pipe-msg (command include-headers) 216 (defun mh-pipe-msg (command include-header)
197 "Pipe the current message through the given shell COMMAND. 217 "Pipe message through shell command COMMAND.
198 If INCLUDE-HEADERS (prefix argument) is provided, send the entire message. 218
199 Otherwise just send the message's body without the headers." 219 You are prompted for the Unix command through which you wish to
220 run your message. If you give a prefix argument INCLUDE-HEADER to
221 this command, the message header is included in the text passed
222 to the command."
200 (interactive 223 (interactive
201 (list (read-string "Shell command on message: ") current-prefix-arg)) 224 (list (read-string "Shell command on message: ") current-prefix-arg))
202 (let ((msg-file-to-pipe (mh-msg-filename (mh-get-msg-num t))) 225 (let ((msg-file-to-pipe (mh-msg-filename (mh-get-msg-num t)))
203 (message-directory default-directory)) 226 (message-directory default-directory))
204 (save-excursion 227 (save-excursion
205 (set-buffer (get-buffer-create mh-temp-buffer)) 228 (set-buffer (get-buffer-create mh-temp-buffer))
206 (erase-buffer) 229 (erase-buffer)
207 (insert-file-contents msg-file-to-pipe) 230 (insert-file-contents msg-file-to-pipe)
208 (goto-char (point-min)) 231 (goto-char (point-min))
209 (if (not include-headers) (search-forward "\n\n")) 232 (if (not include-header) (search-forward "\n\n"))
210 (let ((default-directory message-directory)) 233 (let ((default-directory message-directory))
211 (shell-command-on-region (point) (point-max) command nil))))) 234 (shell-command-on-region (point) (point-max) command nil)))))
212 235
213 ;;;###mh-autoload 236 ;;;###mh-autoload
214 (defun mh-page-digest () 237 (defun mh-page-digest ()
215 "Advance displayed message to next digested message." 238 "Display next message in digest."
216 (interactive) 239 (interactive)
217 (mh-in-show-buffer (mh-show-buffer) 240 (mh-in-show-buffer (mh-show-buffer)
218 ;; Go to top of screen (in case user moved point). 241 ;; Go to top of screen (in case user moved point).
219 (move-to-window-line 0) 242 (move-to-window-line 0)
220 (let ((case-fold-search nil)) 243 (let ((case-fold-search nil))
227 (forward-line 2) 250 (forward-line 2)
228 (mh-recenter 0))) 251 (mh-recenter 0)))
229 252
230 ;;;###mh-autoload 253 ;;;###mh-autoload
231 (defun mh-page-digest-backwards () 254 (defun mh-page-digest-backwards ()
232 "Back up displayed message to previous digested message." 255 "Display previous message in digest."
233 (interactive) 256 (interactive)
234 (mh-in-show-buffer (mh-show-buffer) 257 (mh-in-show-buffer (mh-show-buffer)
235 ;; Go to top of screen (in case user moved point). 258 ;; Go to top of screen (in case user moved point).
236 (move-to-window-line 0) 259 (move-to-window-line 0)
237 (let ((case-fold-search nil)) 260 (let ((case-fold-search nil))
243 (if (search-backward "\n\n" nil t) 266 (if (search-backward "\n\n" nil t)
244 (forward-line 2)) 267 (forward-line 2))
245 (mh-recenter 0))) 268 (mh-recenter 0)))
246 269
247 ;;;###mh-autoload 270 ;;;###mh-autoload
248 (defun mh-print-msg (msg-or-seq)
249 "Print MSG-OR-SEQ (default: displayed message) on printer.
250 If optional prefix argument provided, then prompt for the message sequence.
251 The variable `mh-lpr-command-format' is used to generate the print command.
252 The messages are formatted by mhl. See the variable `mhl-formfile'."
253 (interactive (list (if current-prefix-arg
254 (reverse (mh-seq-to-msgs
255 (mh-read-seq-default "Print" t)))
256 (mh-get-msg-num t))))
257 (if (numberp msg-or-seq)
258 (message "Printing message...")
259 (message "Printing sequence..."))
260 (let ((print-command
261 (if (numberp msg-or-seq)
262 (format "%s -nobell -clear %s %s | %s"
263 (expand-file-name "mhl" mh-lib-progs)
264 (mh-msg-filename msg-or-seq)
265 (if (stringp mhl-formfile)
266 (format "-form %s" mhl-formfile)
267 "")
268 (format mh-lpr-command-format
269 (if (numberp msg-or-seq)
270 (format "%s/%d" mh-current-folder
271 msg-or-seq)
272 (format "Sequence from %s" mh-current-folder))))
273 (format "(scan -clear %s ; %s -nobell -clear %s %s) | %s"
274 (mapconcat (function (lambda (msg) msg)) msg-or-seq " ")
275 (expand-file-name "mhl" mh-lib-progs)
276 (if (stringp mhl-formfile)
277 (format "-form %s" mhl-formfile)
278 "")
279 (mh-msg-filenames msg-or-seq)
280 (format mh-lpr-command-format
281 (if (numberp msg-or-seq)
282 (format "%s/%d" mh-current-folder
283 msg-or-seq)
284 (format "Sequence from %s"
285 mh-current-folder)))))))
286 (if mh-print-background-flag
287 (mh-exec-cmd-daemon shell-file-name nil "-c" print-command)
288 (call-process shell-file-name nil nil nil "-c" print-command))
289 (if (numberp msg-or-seq)
290 (mh-notate msg-or-seq mh-note-printed mh-cmd-note)
291 (mh-notate-seq msg-or-seq mh-note-printed mh-cmd-note))
292 (mh-add-msgs-to-seq msg-or-seq 'printed t)
293 (if (numberp msg-or-seq)
294 (message "Printing message...done")
295 (message "Printing sequence...done"))))
296
297 (defun mh-msg-filenames (msgs &optional folder)
298 "Return a list of file names for MSGS in FOLDER (default current folder)."
299 (mapconcat (function (lambda (msg) (mh-msg-filename msg folder))) msgs " "))
300
301 ;;;###mh-autoload
302 (defun mh-sort-folder (&optional extra-args) 271 (defun mh-sort-folder (&optional extra-args)
303 "Sort the messages in the current folder by date. 272 "Sort folder.
304 Calls the MH program sortm to do the work. 273
305 The arguments in the list `mh-sortm-args' are passed to sortm if the optional 274 By default, messages are sorted by date. The option
306 argument EXTRA-ARGS is given." 275 `mh-sortm-args' holds extra arguments to pass on to the command
276 \"sortm\" when a prefix argument EXTRA-ARGS is used."
307 (interactive "P") 277 (interactive "P")
308 (mh-process-or-undo-commands mh-current-folder) 278 (mh-process-or-undo-commands mh-current-folder)
309 (setq mh-next-direction 'forward) 279 (setq mh-next-direction 'forward)
310 (mh-set-folder-modified-p t) ; lock folder while sorting 280 (mh-set-folder-modified-p t) ; lock folder while sorting
311 (message "Sorting folder...") 281 (message "Sorting folder...")
312 (let ((threaded-flag (memq 'unthread mh-view-ops))) 282 (let ((threaded-flag (memq 'unthread mh-view-ops)))
313 (mh-exec-cmd "sortm" mh-current-folder (if extra-args mh-sortm-args)) 283 (mh-exec-cmd "sortm" mh-current-folder (if extra-args mh-sortm-args))
314 (when mh-index-data 284 (when mh-index-data
315 (mh-index-update-maps mh-current-folder)) 285 (mh-index-update-maps mh-current-folder))
316 (message "Sorting folder...done") 286 (message "Sorting folder...done")
317 (mh-reset-threads-and-narrowing)
318 (mh-scan-folder mh-current-folder "all") 287 (mh-scan-folder mh-current-folder "all")
319 (cond (threaded-flag (mh-toggle-threads)) 288 (cond (threaded-flag (mh-toggle-threads))
320 (mh-index-data (mh-index-insert-folder-headers))))) 289 (mh-index-data (mh-index-insert-folder-headers)))))
321 290
322 ;;;###mh-autoload 291 ;;;###mh-autoload
323 (defun mh-undo-folder (&rest ignore) 292 (defun mh-undo-folder ()
324 "Undo all pending deletes and refiles in current folder. 293 "Undo all refiles and deletes in the current folder."
325 Argument IGNORE is deprecated."
326 (interactive) 294 (interactive)
327 (cond ((or mh-do-not-confirm-flag 295 (cond ((or mh-do-not-confirm-flag
328 (yes-or-no-p "Undo all commands in folder? ")) 296 (yes-or-no-p "Undo all commands in folder? "))
329 (setq mh-delete-list nil 297 (setq mh-delete-list nil
330 mh-refile-list nil 298 mh-refile-list nil
331 mh-seq-list nil 299 mh-seq-list nil
332 mh-next-direction 'forward) 300 mh-next-direction 'forward)
333 (with-mh-folder-updating (nil) 301 (with-mh-folder-updating (nil)
334 (mh-unmark-all-headers t))) 302 (mh-remove-all-notation)))
335 (t 303 (t
336 (message "Commands not undone.") 304 (message "Commands not undone"))))
337 (sit-for 2))))
338 305
339 ;;;###mh-autoload 306 ;;;###mh-autoload
340 (defun mh-store-msg (directory) 307 (defun mh-store-msg (directory)
341 "Store the file(s) contained in the current message into DIRECTORY. 308 "Unpack message created with \"uudecode\" or \"shar\".
342 The message can contain a shar file or uuencoded file. 309
343 Default directory is the last directory used, or initially the value of 310 The default DIRECTORY for extraction is the current directory;
344 `mh-store-default-directory' or the current directory." 311 however, you have a chance to specify a different extraction
312 directory. The next time you use this command, the default
313 directory is the last directory you used. If you would like to
314 change the initial default directory, customize the option
315 `mh-store-default-directory', change the value from \"Current\"
316 to \"Directory\", and then enter the name of the directory for
317 storing the content of these messages."
345 (interactive (list (let ((udir (or mh-store-default-directory 318 (interactive (list (let ((udir (or mh-store-default-directory
346 default-directory))) 319 default-directory)))
347 (read-file-name "Store message in directory: " 320 (read-file-name "Store message in directory: "
348 udir udir nil)))) 321 udir udir nil))))
349 (let ((msg-file-to-store (mh-msg-filename (mh-get-msg-num t)))) 322 (let ((msg-file-to-store (mh-msg-filename (mh-get-msg-num t))))
353 (insert-file-contents msg-file-to-store) 326 (insert-file-contents msg-file-to-store)
354 (mh-store-buffer directory)))) 327 (mh-store-buffer directory))))
355 328
356 ;;;###mh-autoload 329 ;;;###mh-autoload
357 (defun mh-store-buffer (directory) 330 (defun mh-store-buffer (directory)
358 "Store the file(s) contained in the current buffer into DIRECTORY. 331 "Unpack buffer created with \"uudecode\" or \"shar\".
359 The buffer can contain a shar file or uuencoded file. 332
360 Default directory is the last directory used, or initially the value of 333 See `mh-store-msg' for a description of DIRECTORY."
361 `mh-store-default-directory' or the current directory."
362 (interactive (list (let ((udir (or mh-store-default-directory 334 (interactive (list (let ((udir (or mh-store-default-directory
363 default-directory))) 335 default-directory)))
364 (read-file-name "Store buffer in directory: " 336 (read-file-name "Store buffer in directory: "
365 udir udir nil)))) 337 udir udir nil))))
366 (let ((store-directory (expand-file-name directory)) 338 (let ((store-directory (expand-file-name directory))
376 (forward-line 1)) 348 (forward-line 1))
377 (beginning-of-line) 349 (beginning-of-line)
378 (if (looking-at "^[#:]....+\n\\( ?\n\\)?end$") 350 (if (looking-at "^[#:]....+\n\\( ?\n\\)?end$")
379 nil ;most likely end of a uuencode 351 nil ;most likely end of a uuencode
380 (point)))))) 352 (point))))))
381 (log-buffer (get-buffer-create "*Store Output*"))
382 (command "sh") 353 (command "sh")
383 (uudecode-filename "(unknown filename)")) 354 (uudecode-filename "(unknown filename)")
355 log-begin)
384 (if (not sh-start) 356 (if (not sh-start)
385 (save-excursion 357 (save-excursion
386 (goto-char (point-min)) 358 (goto-char (point-min))
387 (if (re-search-forward "^begin [0-7]+ " nil t) 359 (if (re-search-forward "^begin [0-7]+ " nil t)
388 (setq uudecode-filename 360 (setq uudecode-filename
389 (buffer-substring (point) 361 (buffer-substring (point)
390 (progn (end-of-line) (point))))))) 362 (progn (end-of-line) (point)))))))
391 (save-excursion 363 (save-excursion
392 (set-buffer log-buffer) 364 (set-buffer (get-buffer-create mh-log-buffer))
393 (erase-buffer) 365 (setq log-begin (mh-truncate-log-buffer))
394 (if (not (file-directory-p store-directory)) 366 (if (not (file-directory-p store-directory))
395 (progn 367 (progn
396 (insert "mkdir " directory "\n") 368 (insert "mkdir " directory "\n")
397 (call-process "mkdir" nil log-buffer t store-directory))) 369 (call-process "mkdir" nil mh-log-buffer t store-directory)))
398 (insert "cd " directory "\n") 370 (insert "cd " directory "\n")
399 (setq mh-store-default-directory directory) 371 (setq mh-store-default-directory directory)
400 (if (not sh-start) 372 (if (not sh-start)
401 (progn 373 (progn
402 (setq command "uudecode") 374 (setq command "uudecode")
403 (insert uudecode-filename " being uudecoded...\n")))) 375 (insert uudecode-filename " being uudecoded...\n"))))
404 (set-window-start (display-buffer log-buffer) 0) ;watch progress 376 (set-window-start (display-buffer mh-log-buffer) log-begin) ;watch progress
405 (let (value) 377 (let ((default-directory (file-name-as-directory store-directory)))
406 (let ((default-directory (file-name-as-directory store-directory))) 378 (if (equal (call-process-region sh-start (point-max) command
407 (setq value (call-process-region sh-start (point-max) command 379 nil mh-log-buffer t)
408 nil log-buffer t))) 380 0)
409 (set-buffer log-buffer) 381 (save-excursion
410 (mh-handle-process-error command value)) 382 (set-buffer mh-log-buffer)
411 (insert "\n(mh-store finished)\n"))) 383 (insert "\n(mh-store finished)\n"))
384 (error "Error occurred during execution of %s" command)))))
412 385
413 386
414 387
415 ;;; Help Functions 388 ;;; Help Functions
416 389
390 ;;;###mh-autoload
417 (defun mh-ephem-message (string) 391 (defun mh-ephem-message (string)
418 "Display STRING in the minibuffer momentarily." 392 "Display STRING in the minibuffer momentarily."
419 (message "%s" string) 393 (message "%s" string)
420 (sit-for 5) 394 (sit-for 5)
421 (message "")) 395 (message ""))
422 396
423 ;;;###mh-autoload 397 ;;;###mh-autoload
424 (defun mh-help () 398 (defun mh-help ()
425 "Display cheat sheet for the MH-Folder commands in minibuffer." 399 "Display cheat sheet for the MH-E commands."
426 (interactive) 400 (interactive)
427 (mh-ephem-message 401 (with-electric-help
428 (substitute-command-keys 402 (function
429 (mapconcat 'identity (cdr (assoc nil mh-help-messages)) "")))) 403 (lambda ()
404 (insert
405 (substitute-command-keys
406 (mapconcat 'identity (cdr (assoc nil mh-help-messages)) ""))))
407 mh-help-buffer)))
430 408
431 ;;;###mh-autoload 409 ;;;###mh-autoload
432 (defun mh-prefix-help () 410 (defun mh-prefix-help ()
433 "Display cheat sheet for the commands of the current prefix in minibuffer." 411 "Display cheat sheet for the commands of the current prefix in minibuffer."
434 (interactive) 412 (interactive)
435 ;; We got here because the user pressed a `?', but he pressed a prefix key 413 ;; We got here because the user pressed a "?", but he pressed a prefix key
436 ;; before that. Since the the key vector starts at index 0, the index of the 414 ;; before that. Since the the key vector starts at index 0, the index of the
437 ;; last keystroke is length-1 and thus the second to last keystroke is at 415 ;; last keystroke is length-1 and thus the second to last keystroke is at
438 ;; length-2. We use that information to obtain a suitable prefix character 416 ;; length-2. We use that information to obtain a suitable prefix character
439 ;; from the recent keys. 417 ;; from the recent keys.
440 (let* ((keys (recent-keys)) 418 (let* ((keys (recent-keys))
441 (prefix-char (elt keys (- (length keys) 2)))) 419 (prefix-char (elt keys (- (length keys) 2))))
442 (mh-ephem-message 420 (with-electric-help
443 (substitute-command-keys 421 (function
444 (mapconcat 'identity (cdr (assoc prefix-char mh-help-messages)) ""))))) 422 (lambda ()
423 (insert
424 (substitute-command-keys
425 (mapconcat 'identity
426 (cdr (assoc prefix-char mh-help-messages)) "")))))
427 mh-help-buffer)))
445 428
446 (provide 'mh-funcs) 429 (provide 'mh-funcs)
447 430
448 ;;; Local Variables: 431 ;; Local Variables:
449 ;;; indent-tabs-mode: nil 432 ;; indent-tabs-mode: nil
450 ;;; sentence-end-double-space: nil 433 ;; sentence-end-double-space: nil
451 ;;; End: 434 ;; End:
452 435
436 ;; arch-tag: 1936c4f1-4843-438e-bc4b-a63bb75a7762
453 ;;; mh-funcs.el ends here 437 ;;; mh-funcs.el ends here