Mercurial > emacs
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 |