1 ;;; gnus-uu.el --- extract, view or save (uu)encoded files from gnus
3 ;; Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
5 ;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
8 ;; Last Modified: 1994/04/13
11 ;; This file is part of GNU Emacs.
13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING. If not, write to
25 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29 ;; All gnus-uu commands start with `C-c C-v'.
31 ;; Typing `C-c C-v C-v' (`gnus-uu-decode-and-view') in the summary
32 ;; buffer will try to find all articles in the same series, uudecode
33 ;; them and view the resulting file(s).
35 ;; gnus-uu guesses what articles are in the series according to the
36 ;; following simple rule: The subjects must be identical, except for
37 ;; the last two numbers of the line.
39 ;; For example: If you choose a subject called "cat.gif (2/3)" gnus-uu
40 ;; will find all the articles that matches "^cat.gif
41 ;; ([0-9]+/[0-9]+).*$". Subjects that are nonstandard, like "cat.gif
42 ;; (2/3) Part 6 of a series", will not be properly recognized by 'C-c
43 ;; C-v C-v', and you have to mark the articles manually with '#'.
45 ;; Typing `C-c C-v v' (`gnus-uu-decode-and-save') will do the same as
46 ;; `C-c C-v C-v', except that it will not display the resulting file,
47 ;; but save it instead.
49 ;; Typing `C-c C-v s' (`gnus-uu-shar-and-save') does the same as `C-c
50 ;; C-v v', and `C-c C-v C-s' (`gnus-uu-shar-and-view') does the same
51 ;; as `C-c C-v C-v', except that they unshar files instead, i. e. run
52 ;; them through /bin/sh. Most shar files can be viewed and/or saved
53 ;; with the normal uudecode commands, which is much safer, as no
54 ;; foreign code is run.
56 ;; `#' (`gnus-uu-mark-article') marks an article for later
57 ;; decoding/unsharing/saving/viewing. The files will be decoded in the
58 ;; sequence they were marked. To decode the files after you've marked
59 ;; the articles you are interested in, type the corresponding key
60 ;; strokes as the normal decoding commands, but put a `M-' in the last
61 ;; keystroke. For instance, to perform a standard uudecode and view,
62 ;; you would type `C-c C-v C-v'. To perform a marked uudecode and
63 ;; view, say `C-v C-v M-C-v'. All the other view and save commands are
64 ;; handled the same way; marked uudecode and save is then `C-c C-v
67 ;; `M-#' (`gnus-uu-unmark-article') will remove the mark from a
68 ;; previosly marked article.
70 ;; `C-c C-v C-u' (`gnus-uu-unmark-all-articles') will remove the mark from
71 ;; all marked articles.
73 ;; `C-c C-v C-r' (`gnus-uu-mark-by-regexp') will prompt for a regular
74 ;; expression and mark (forward) all articles matching that regular
77 ;; There's an additional way to reach the decoding functions to make
78 ;; future expansions easier: `C-c C-v C-m'
79 ;; (`gnus-uu-multi-decode-and-view') and the corresponding save, marked
80 ;; view and marked save keystrokes, `C-c C-v m', `C-c C-v M-C-m' and
81 ;; `C-c C-v M-m' respectively. You will be prompted for decoding
82 ;; method, like uudecode, shar, binhex or plain save. Note that
83 ;; methods like binhex and save doesn't have view modes; even if you
84 ;; issue a view command (`C-c C-v C-m' and "binhex"), gnus-uu will
85 ;; just save the resulting binhex file.
87 ;; `C-c C-v C-b' (`gnus-uu-decode-and-show-in-buffer') will decode the
88 ;; current article and display the results in an emacs buffer. This
89 ;; might be useful if there's jsut some text in the current article
90 ;; that has been uuencoded by some perverse poster.
92 ;; `C-c C-v a' (`gnus-uu-decode-and-save-all-articles') looks at all the
93 ;; articles in the current newsgroup and tries to uudecode everything
94 ;; it can find. The user will be prompted for a directory where the
95 ;; resulting files (if any) will be stored. `C-c C-v M-a' only looks
96 ;; at unread article. `C-c C-v w' does the same as `C-c C-v a', but
97 ;; also marks as read all articles it has peeked through, even if they
98 ;; weren't uuencoded articles. `C-c C-v M-w' is, as you might have
99 ;; guessed, similar to `C-c C-v M-a'.
101 ;; `C-c C-v C-l' (`gnus-uu-edit-begin-line') lets you edit the begin
102 ;; line of the current buffer. Useful to change an incorrect suffix or
103 ;; an incorrect begin line.
106 ;; When using the view commands, `C-c C-v C-v' for instance, gnus-uu
107 ;; will (normally, see below) try to view the file according to the
108 ;; rules given in `gnus-uu-default-view-rules' and
109 ;; `gnus-uu-user-view-rules'. If it recognises the file, it will
110 ;; display it immediately. If the file is some sort of archive,
111 ;; gnus-uu will attempt to unpack the archive and see if any of the
112 ;; files in the archive can be viewed. For instance, if you have a
113 ;; gzipped tar file "pics.tar.gz" containing the files "pic1.jpg" and
114 ;; "pic2.gif", gnus-uu will uncompress and detar the main file, and
115 ;; then view the two pictures. This unpacking process is recursive, so
116 ;; if the archive contains archives of archives, it'll all be
119 ;; If the view command doesn't recognise the file type, or can't view
120 ;; it because you don't have the viewer, or can't view *any* of the
121 ;; files in the archive, the user will be asked if she wishes to have
122 ;; the file saved somewhere. Note that if the decoded file is an
123 ;; archive, and gnus-uu manages to view some of the files in the
124 ;; archive, it won't tell the user that there were some files that
125 ;; were unviewable. See "Interactive view" for a different approach.
128 ;; Note that gnus-uu adds a function to `gnus-exit-group-hook' to
129 ;; clear the list of marked articles and check for any generated files
130 ;; that might have escaped deletion if the user typed `C-g'.
133 ;; `C-c C-v C-a' (`gnus-uu-toggle-asynchronous') toggles the
134 ;; `gnus-uu-asynchronous' variable. See below for explanation.
136 ;; `C-c C-v C-q' (`gnus-uu-toggle-query') toggles the
137 ;; `gnus-uu-ask-before-view' variable. See below for explanation.
139 ;; `C-c C-v C-p' (`gnus-uu-toggle-always-ask') toggles the
140 ;; `gnus-uu-view-and-save' variable. See below for explanation.
142 ;; `C-c C-v C-k' (`gnus-uu-toggle-kill-carriage-return') toggles the
143 ;; `gnus-uu-kill-carriage-return' variable. See below for explanation.
145 ;; `C-c C-v C-i' (`gnus-uu-toggle-interactive-view') toggles interactive
146 ;; mode. If it is turned on, gnus-uu won't view files immediately but
147 ;; give you a buffer with the default commands and files and lets you
148 ;; edit the commands and execute them at leisure.
150 ;; `C-c C-v C-t' (`gnus-uu-toggle-any-variable') is an interface to the
151 ;; five toggle commands listed above.
153 ;; `gnus-uu-toggle-correct-stripped-articles' toggles whether to check
154 ;; and correct uuencoded articles that may have had trailing spaces
155 ;; stripped by mailers.
160 ;; To load this file when starting gnus, put sumething like the
161 ;; following in your .emacs file:
163 ;; (setq gnus-group-mode-hook
164 ;; '(lambda () (load "gnus-uu")))
166 ;; To make gnus-uu use, for instance, "xli" to view JPEGs and GIFs,
167 ;; put this in your .emacs file:
169 ;; (setq gnus-uu-user-view-rules
171 ;; '("jpg$\\|gif$" "xli")
174 ;; This variable is a list where each list item is a list containing
175 ;; two strings. The first string is a regular expression. If the file
176 ;; name is matched by this expression, the command given in the
177 ;; second string is executed on this file. If the command contains
178 ;; "%s", the file will be inserted there in the command string. Eg.
179 ;; "giftoppm %s | xv -" will result in the file name being inserted at
182 ;; If you don't want to display certain file types, like if you
183 ;; haven't got sound capabilities, you could put something like
185 ;; (setq gnus-uu-user-view-rules
187 ;; '("au$\\|voc$\\|wav$" nil)
190 ;; in your .emacs file.
192 ;; There's a similar variable called `gnus-uu-user-archive-rules'
193 ;; which gives a list of unarcers to use when looking inside archives
194 ;; for files to display.
196 ;; If you don't want gnus-uu to look inside archives for files to
199 ;; (setq gnus-uu-do-not-unpack-archives t)
202 ;; If you want gnus-uu to ask you if you want to save a file after
205 ;; (setq gnus-uu-view-and-save t)
208 ;; If you don't want to wait for the viewing command to finish before
209 ;; returning to emacs, say
211 ;; (setq gnus-uu-asynchronous t)
214 ;; This can be useful if you're viewing long .mod files, for instance,
215 ;; which often takes several minutes. Note, however, that since
216 ;; gnus-uu doesn't ask, and if you are viewing an archive with lots of
217 ;; viewable files, you'll get them all up more or less at once, which
218 ;; can be confusing, to say the least. To get gnus-uu to ask you
219 ;; before viewing a file, say
221 ;; (setq gnus-uu-ask-before-view t)
223 ;; You can set this variable even if you're not using asynchronous
224 ;; viewing, of course.
226 ;; If the articles has been posted by some numbscull with a PC (isn't
227 ;; that a bit redundant, though?) and there's lots of carriage returns
230 ;; (setq gnus-uu-kill-carriage-return t)
232 ;; If you want gnus-uu to ignore the default file rules when viewing,
233 ;; for instance if there's several file types that you can't view, set
234 ;; `gnus-uu-ignore-default-view-rules' to t. There's a similar
235 ;; variable to disable the default unarchive rule list,
236 ;; `gnus-uu-ignore-default-archive-rules'.
238 ;; If you want a more interactive approach to file viewing, say
240 ;; (setq gnus-uu-use-interactive-view t)
242 ;; If this variable is set, whenever you type `C-c C-v C-v' (or any of
243 ;; the other view commands), gnus-uu will present you with a buffer
244 ;; with the default actions and file names after decoding. You can
245 ;; edit the command lines and execute them in a convenient fashion.
246 ;; The output from the commands will be displayed in a small window at
247 ;; the bottom of the emacs window. End interactive mode by typing `C-c
248 ;; C-c' in the view window.
250 ;; If you want gnus-uu to unmark articles that you have asked to
251 ;; decode, but can't be decoded (if, for instance, the articles aren't
252 ;; uuencoded files or the posting is incomplete), say
254 ;; (setq gnus-uu-unmark-articles-not-decoded t)
259 ;; v1.0: First version released Oct 2 1992.
261 ;; v1.1: Changed `C-c C-r' to `C-c C-e' and `C-c C-p' to `C-c C-k'.
262 ;; Changed (setq gnus-exit-group-hook) to (add-hook). Removed
263 ;; checking for "Re:" for finding parts.
265 ;; v2.2: Fixed handling of currupted archives. Changed uudecoding to
266 ;; an asynchronous process to avoid loading tons of data into emacs
267 ;; buffers. No longer reads articles emacs already have aboard. Fixed
268 ;; a firmer support for shar files. Made regexp searches for files
269 ;; more convenient. Added `C-c C-l' for editing uucode begin
270 ;; lines. Added multi-system decoder entry point. Added interactive
271 ;; view mode. Added function for decoding and saving all uuencoded
272 ;; articles in the current newsgroup.
274 ;; v2.3: After suggestions I have changed all the gnus-uu key bindings
275 ;; to avoid hogging all the user keys (C-c LETTER). Also added
276 ;; (provide) and fixed some saving stuff. First posted version to
277 ;; gnu.emacs.sources.
279 ;; v2.4: Fixed some more in the save-all category. Automatic fixing of
280 ;; uucode "begin" lines: names on the form of "dir/file" are
281 ;; translated into "dir-file". Added a function for fixing stripped
282 ;; uucode articles. Added binhex save.
284 ;; v2.5: First version copyrighted by FSF. Changed lots of
285 ;; documentation strings.
287 ;; v2.5.1: Added uuencode/posting code to post binary files.
290 ;; Default keymap overview:
292 ;; All commands start with `C-c C-v'. The difference is in the third
293 ;; keystroke. All view commands are `C-LETTER'. All save commands are
294 ;; just `LETTER'. All marked commands are the same as the unmarked
295 ;; commands, except that they have `M-' before in the last keystroke.
297 ;; `C-c C-v C-v' gnus-uu-decode-and-view
298 ;; `C-c C-v v' gnus-uu-decode-and-save
299 ;; `C-c C-v C-s' gnus-uu-shar-and-view
300 ;; `C-c C-v s' gnus-uu-shar-and-save
301 ;; `C-c C-v C-m' gnus-uu-multi-decode-and-view
302 ;; `C-c C-v m' gnus-uu-multi-decode-and-save
304 ;; `C-c C-v C-b' gnus-uu-decode-and-show-in-buffer
305 ;; `C-c C-v C-l' gnus-uu-edit-begin-line
306 ;; `C-c C-v M-a' gnus-uu-decode-and-save-all-unread-articles
307 ;; `C-c C-v a' gnus-uu-decode-and-save-all-articles
308 ;; `C-c C-v M-w' gnus-uu-decode-and-save-all-unread-articles-and-mark
309 ;; `C-c C-v w' gnus-uu-decode-and-save-all-articles-and-mark
311 ;; `#' gnus-uu-mark-article
312 ;; `M-#' gnus-uu-unmark-article
313 ;; `C-c C-v C-u' gnus-uu-unmark-all-articles
314 ;; `C-c C-v C-r' gnus-uu-mark-by-regexp
315 ;; `C-c C-v M-C-v' gnus-uu-marked-decode-and-view
316 ;; `C-c C-v M-v' gnus-uu-marked-decode-and-save
317 ;; `C-c C-v M-C-s' gnus-uu-marked-shar-and-view
318 ;; `C-c C-v M-s' gnus-uu-marked-shar-and-save
319 ;; `C-c C-v M-C-m' gnus-uu-marked-multi-decode-and-view
320 ;; `C-c C-v M-m' gnus-uu-marked-multi-decode-and-save
322 ;; `C-c C-v C-a' gnus-uu-toggle-asynchronous
323 ;; `C-c C-v C-q' gnus-uu-toggle-query
324 ;; `C-c C-v C-p' gnus-uu-toggle-always-ask
325 ;; `C-c C-v C-k' gnus-uu-toggle-kill-carriage-return
326 ;; `C-c C-v C-i' gnus-uu-toggle-interactive-view
327 ;; `C-c C-v C-t' gnus-uu-toggle-any-variable
334 ;; Binding of keys to the gnus-uu functions.
336 (defvar gnus-uu-ctl-map nil
)
337 (define-prefix-command 'gnus-uu-ctl-map
)
338 (define-key gnus-summary-mode-map
"\C-c\C-v" gnus-uu-ctl-map
)
340 (define-key gnus-uu-ctl-map
"\C-v" 'gnus-uu-decode-and-view
)
341 (define-key gnus-uu-ctl-map
"v" 'gnus-uu-decode-and-save
)
342 (define-key gnus-uu-ctl-map
"\C-s" 'gnus-uu-shar-and-view
)
343 (define-key gnus-uu-ctl-map
"s" 'gnus-uu-shar-and-save
)
344 (define-key gnus-uu-ctl-map
"\C-m" 'gnus-uu-multi-decode-and-view
)
345 (define-key gnus-uu-ctl-map
"m" 'gnus-uu-multi-decode-and-save
)
347 (define-key gnus-uu-ctl-map
"\C-b" 'gnus-uu-decode-and-show-in-buffer
)
349 (define-key gnus-summary-mode-map
"#" 'gnus-uu-mark-article
)
350 (define-key gnus-summary-mode-map
"\M-#" 'gnus-uu-unmark-article
)
351 (define-key gnus-uu-ctl-map
"\C-u" 'gnus-uu-unmark-all-articles
)
352 (define-key gnus-uu-ctl-map
"\C-r" 'gnus-uu-mark-by-regexp
)
354 (define-key gnus-uu-ctl-map
"\M-\C-v" 'gnus-uu-marked-decode-and-view
)
355 (define-key gnus-uu-ctl-map
"\M-v" 'gnus-uu-marked-decode-and-save
)
356 (define-key gnus-uu-ctl-map
"\M-\C-s" 'gnus-uu-marked-shar-and-view
)
357 (define-key gnus-uu-ctl-map
"\M-s" 'gnus-uu-marked-shar-and-save
)
358 (define-key gnus-uu-ctl-map
"\M-\C-m" 'gnus-uu-marked-multi-decode-and-view
)
359 (define-key gnus-uu-ctl-map
"\M-m" 'gnus-uu-marked-multi-decode-and-save
)
361 (define-key gnus-uu-ctl-map
"\C-a" 'gnus-uu-toggle-asynchronous
)
362 (define-key gnus-uu-ctl-map
"\C-q" 'gnus-uu-toggle-query
)
363 (define-key gnus-uu-ctl-map
"\C-p" 'gnus-uu-toggle-always-ask
)
364 (define-key gnus-uu-ctl-map
"\C-k" 'gnus-uu-toggle-kill-carriage-return
)
365 (define-key gnus-uu-ctl-map
"\C-i" 'gnus-uu-toggle-interactive-view
)
366 (define-key gnus-uu-ctl-map
"\C-t" 'gnus-uu-toggle-any-variable
)
368 (define-key gnus-uu-ctl-map
"\C-l" 'gnus-uu-edit-begin-line
)
370 (define-key gnus-uu-ctl-map
"\M-a" 'gnus-uu-decode-and-save-all-unread-articles
)
371 (define-key gnus-uu-ctl-map
"a" 'gnus-uu-decode-and-save-all-articles
)
372 (define-key gnus-uu-ctl-map
"\M-w" 'gnus-uu-decode-and-save-all-unread-articles-and-mark
)
373 (define-key gnus-uu-ctl-map
"w" 'gnus-uu-decode-and-save-all-articles-and-mark
)
376 ;(define-key news-reply-mode-map "\C-c\C-v" 'gnus-uu-uuencode-and-post)
378 ;; Dummy function gnus-uu
381 "gnus-uu is a package for uudecoding and viewing articles.
383 By default, all gnus-uu keystrokes begin with `C-c C-v'.
385 There four decoding commands categories:
386 All commands for viewing are `C-c C-v C-LETTER'.
387 All commands for saving are `C-c C-v LETTER'.
388 All commands for marked viewing are `C-c C-v C-M-LETTER'.
389 All commands for marked saving are `C-c C-v M-LETTER'.
391 \\<gnus-summary-mode-map>\\[gnus-uu-decode-and-view]\tDecode and view articles
392 \\[gnus-uu-decode-and-save]\tDecode and save articles
393 \\[gnus-uu-shar-and-view]\tUnshar and view articles
394 \\[gnus-uu-shar-and-save]\tUnshar and save articles
395 \\[gnus-uu-multi-decode-and-view]\tChoose a decoding method, decode and view articles
396 \\[gnus-uu-multi-decode-and-save]\tChoose a decoding method, decode and save articles
398 \\[gnus-uu-decode-and-show-in-buffer]\tDecode the current article and view the result in a buffer
399 \\[gnus-uu-edit-begin-line]\tEdit the 'begin' line of an uuencoded article
401 \\[gnus-uu-decode-and-save-all-unread-articles]\tDecode and save all unread articles
402 \\[gnus-uu-decode-and-save-all-articles]\tDecode and save all articles
403 \\[gnus-uu-decode-and-save-all-unread-articles-and-mark]\tDecode and save all unread articles and catch up
404 \\[gnus-uu-decode-and-save-all-articles-and-mark]\tDecode and save all articles and catch up
406 \\[gnus-uu-mark-article]\tMark the current article for decoding
407 \\[gnus-uu-unmark-article]\tUnmark the current article
408 \\[gnus-uu-unmark-all-articles]\tUnmark all articles
409 \\[gnus-uu-mark-by-regexp]\tMark articles for decoding by regexp
410 \\[gnus-uu-marked-decode-and-view]\tDecode and view marked articles
411 \\[gnus-uu-marked-decode-and-save]\tDecode and save marked articles
412 \\[gnus-uu-marked-shar-and-view]\tUnshar and view marked articles
413 \\[gnus-uu-marked-shar-and-save]\tUnshar and save marked articles
414 \\[gnus-uu-marked-multi-decode-and-view]\tChoose decoding method, decode and view marked articles
415 \\[gnus-uu-marked-multi-decode-and-save]\tChoose decoding method, decode and save marked articles
417 \\[gnus-uu-toggle-asynchronous]\tToggle asynchronous viewing mode
418 \\[gnus-uu-toggle-query]\tToggle whether to ask before viewing a file
419 \\[gnus-uu-toggle-always-ask]\tToggle whether to ask to save a file after viewing
420 \\[gnus-uu-toggle-kill-carriage-return]\tToggle whether to strip trailing carriage returns
421 \\[gnus-uu-toggle-interactive-view]\tToggle whether to use interactive viewing mode
422 \\[gnus-uu-toggle-any-variable]\tToggle any of the things above
424 User configurable variables:
428 gnus-uu uses \"rule\" variables to decide how to view a file. All
429 these variables are of the form
431 (list '(regexp1 command2)
435 `gnus-uu-user-view-rules'
436 This variable is consulted first when viewing files. If you wish
437 to use, for instance, sox to convert an .au sound file, you could
440 (setq gnus-uu-user-view-rules
441 (list '(\"\\\\.au$\" \"sox %s -t .aiff > /dev/audio\")))
443 `gnus-uu-user-view-rules-end'
444 This variable is consulted if gnus-uu couldn't make any matches
445 from the user and default view rules.
447 `gnus-uu-user-interactive-view-rules'
448 This is the variable used instead of `gnus-uu-user-view-rules'
449 when in interactive mode.
451 `gnus-uu-user-interactive-view-rules-end'
452 This variable is used instead of `gnus-uu-user-view-rules-end'
453 when in interactive mode.
455 `gnus-uu-user-archive-rules`
456 This variable can be used to say what comamnds should be used to
463 Where gnus-uu does its work.
465 `gnus-uu-do-not-unpack-archives'
466 Non-nil means that gnus-uu won't peek inside archives looking for
469 `gnus-uu-view-and-save'
470 Non-nil means that the user will always be asked to save a file
473 `gnus-uu-asynchronous'
474 Non-nil means that files will be viewed asynchronously.
476 `gnus-uu-ask-before-view'
477 Non-nil means that gnus-uu will ask you before viewing each file
479 `gnus-uu-ignore-default-view-rules'
480 Non-nil means that gnus-uu will ignore the default viewing rules.
482 `gnus-uu-ignore-default-archive-rules'
483 Non-nil means that gnus-uu will ignore the default archive
486 `gnus-uu-kill-carriage-return'
487 Non-nil means that gnus-uu will strip all carriage returns from
490 `gnus-uu-unmark-articles-not-decoded'
491 Non-nil means that gnus-uu will mark articles that were
492 unsuccessfully decoded as unread.
494 `gnus-uu-output-window-height'
495 This variable says how tall the output buffer window is to be
496 when using interactive view mode.
498 `gnus-uu-correct-stripped-uucode'
499 Non-nil means that gnus-uu will *try* to fix uuencoded files that
500 have had traling spaces deleted.
502 `gnus-uu-use-interactive-view'
503 Non-nil means that gnus-uu will use interactive viewing mode."
507 ;; Default viewing action rules
509 (defvar gnus-uu-default-view-rules
511 '("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv")
512 '("\\.tga$" "tgatoppm %s | xv -")
513 '("\\.te?xt$\\|\\.doc$\\|read.*me" "xterm -e less")
514 '("\\.fli$" "xflick")
515 '("\\.\\(wav\\|aiff\\|hcom\\|u[blw]\\|s[bfw]\\|voc\\|smp\\)$"
516 "sox -v .5 %s -t .au -u - > /dev/audio")
517 '("\\.au$" "cat %s > /dev/audio")
519 '("\\.ps$" "ghostview")
521 '("\\.1$" "xterm -e man -l")
522 '("\\.html$" "xmosaic")
523 '("\\.mpe?g$" "mpeg_play")
524 '("\\.\\(tar\\|arj\\|zip\\|zoo\\|arc\\|gz\\|Z\\|lzh\\|ar\\)$"
527 "Default actions to be taken when the user asks to view a file.
528 To change the behaviour, you can either edit this variable or set
529 `gnus-uu-user-view-rules' to something useful.
533 To make gnus-uu use 'xli' to display JPEG and GIF files, put the
534 following in your .emacs file
536 (setq gnus-uu-user-view-rules (list '(\"jpg$\\\\|gif$\" \"xli\")))
538 Both these variables are lists of lists with two string elements. The
539 first string is a regular expression. If the file name matches this
540 regular expression, the command in the second string is executed with
541 the file as an argument.
543 If the command string contains \"%s\", the file name will be inserted
544 at that point in the command string. If there's no \"%s\" in the
545 command string, the file name will be appended to the command string
548 There are several user variables to tailor the behaviour of gnus-uu to
549 your needs. First we have `gnus-uu-user-view-rules', which is the
550 variable gnus-uu first consults when trying to decide how to view a
551 file. If this variable contains no matches, gnus-uu examines the
552 default rule vaiable provided in this package. If gnus-uu finds no
553 match here, it uses `gnus-uu-user-view-rules-end' to try to make a
556 Unless, of course, you are using the interactive view mode. Then
557 `gnus-uu-user-interactive-view-rules' and
558 `gnus-uu-user-interactive-view-rules-end' will be used instead.")
560 (defvar gnus-uu-user-view-rules nil
561 "Variable detailing what actions are to be taken to view a file.
562 See the documentation on the `gnus-uu-default-view-rules' variable for
565 (defvar gnus-uu-user-view-rules-end nil
566 "Variable saying what actions are to be taken if no rule matched the file name.
567 See the documentation on the `gnus-uu-default-view-rules' variable for
570 (defvar gnus-uu-user-interactive-view-rules nil
571 "Variable detailing what actions are to be taken to view a file when using interactive mode.
572 See the documentation on the `gnus-uu-default-view-rules' variable for
575 (defvar gnus-uu-user-interactive-view-rules-end nil
576 "Variable saying what actions are to be taken if no rule matched the file name when using interactive mode.
577 See the documentation on the `gnus-uu-default-view-rules' variable for
580 (defvar gnus-uu-default-interactive-view-rules-begin
582 '("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed s/
584 '("\\.pas$" "cat %s | sed s/
589 ;; Default unpacking commands
591 (defvar gnus-uu-default-archive-rules
592 (list '("\\.tar$" "tar xf")
595 '("\\.arj$" "unarj x")
596 '("\\.zoo$" "zoo -e")
598 '("\\.Z$" "uncompress")
600 '("\\.arc$" "arc -x"))
603 (defvar gnus-uu-user-archive-rules nil
604 "A list that can be set to override the default archive unpacking commands.
605 To use, for instance, 'untar' to unpack tar files and 'zip -x' to
606 unpack zip files, say the following:
607 (setq gnus-uu-user-archive-rules
608 (list '(\"\\\\.tar$\" \"untar\")
609 '(\"\\\\.zip$\" \"zip -x\")))"
613 ;; Various variables users may set
615 (defvar gnus-uu-tmp-dir
"/tmp/"
616 "Variable saying where gnus-uu is to do its work.
617 Default is \"/tmp/\".")
619 (defvar gnus-uu-do-not-unpack-archives nil
620 "Non-nil means that gnus-uu won't peek inside archives looking for files to dispay.
623 (defvar gnus-uu-view-and-save nil
624 "Non-nil means that the user will always be asked to save a file after viewing it.
625 If the variable is nil, the suer will only be asked to save if the
626 viewing is unsuccessful. Default is nil.")
628 (defvar gnus-uu-asynchronous nil
629 "Non-nil means that files will be viewed asynchronously.
632 (defvar gnus-uu-ask-before-view nil
633 "Non-nil means that gnus-uu will ask you before viewing each file.
634 Especially useful when `gnus-uu-asynchronous' is set. Default is
637 (defvar gnus-uu-ignore-default-view-rules nil
638 "Non-nil means that gnus-uu will ignore the default viewing rules.
639 Only the user viewing rules will be consulted. Default is nil.")
641 (defvar gnus-uu-ignore-default-archive-rules nil
642 "Non-nil means that gnus-uu will ignore the default archive unpacking commands.
643 Only the user unpacking commands will be consulted. Default is nil.")
645 (defvar gnus-uu-kill-carriage-return t
646 "Non-nil means that gnus-uu will strip all carriage returns from articles.
649 (defvar gnus-uu-unmark-articles-not-decoded nil
650 "Non-nil means that gnus-uu will mark articles that were unsuccessfully decoded as unread.
653 (defvar gnus-uu-output-window-height
20
654 "This variable says how tall the output buffer window is to be when using interactive view mode.
655 Change it at your convenience. Default is 20.")
657 (defvar gnus-uu-correct-stripped-uucode nil
658 "Non-nil means that gnus-uu will *try* to fix uuencoded files that have had traling spaces deleted.
661 (defvar gnus-uu-use-interactive-view nil
662 "Non-nil means that gnus-uu will use interactive viewing mode.
663 Gnus-uu will create a special buffer where the user may choose
664 interactively which files to view and how. Default is nil.")
667 ;; Internal variables
669 (defconst gnus-uu-begin-string
"^begin[ \t]+[0-7][0-7][0-7][ \t]+\\(.*\\)$")
670 (defconst gnus-uu-end-string
"^end[ \t]*$")
671 (defconst gnus-uu-body-line
672 "^M.............................................................?$")
673 (defconst gnus-uu-shar-begin-string
"^#! */bin/sh")
675 (defvar gnus-uu-shar-file-name nil
)
676 (defconst gnus-uu-shar-name-marker
"begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)")
677 (defvar gnus-uu-shar-directory nil
)
679 (defvar gnus-uu-file-name nil
)
680 (defconst gnus-uu-uudecode-process nil
)
682 (defvar gnus-uu-interactive-file-list nil
)
683 (defvar gnus-uu-marked-article-list nil
)
684 (defvar gnus-uu-generated-file-list nil
)
686 (defconst gnus-uu-interactive-buffer-name
"*gnus-uu interactive*")
687 (defconst gnus-uu-output-buffer-name
"*Gnus UU Output*")
688 (defconst gnus-uu-result-buffer
"*Gnus UU Result Buffer*")
690 (defconst gnus-uu-error-during-unarching nil
)
692 ;; Interactive functions
696 (defun gnus-uu-decode-and-view ()
697 "UUdecodes and 'views' (if possible) the resulting file.
698 'Viewing' can be any action at all, as defined in the
699 `gnus-uu-file-action-list' variable. Running 'xv' on gifs and 'cat
700 >/dev/audio' on au files are popular actions. If the file can't be
701 viewed, the user is asked if she would like to save the file instead."
703 (gnus-uu-decode-and-view-or-save t nil
))
705 (defun gnus-uu-decode-and-save ()
706 "Decodes and saves the resulting file."
708 (gnus-uu-decode-and-view-or-save nil nil
))
710 (defun gnus-uu-marked-decode-and-view ()
711 "Decodes and views articles marked.
712 The marked equivalent to `gnus-uu-decode-and-view'."
714 (gnus-uu-decode-and-view-or-save t t
))
716 (defun gnus-uu-marked-decode-and-save ()
717 "Decodes and saves articles marked.
718 The marked equivalent to `gnus-uu-decode-and-save'."
720 (gnus-uu-decode-and-view-or-save nil t
))
725 (defun gnus-uu-shar-and-view ()
726 "Unshars and views articles.
727 The shar equivalent of `gnus-uu-decode-and-view'."
729 (gnus-uu-unshar-and-view-or-save t nil
))
731 (defun gnus-uu-shar-and-save ()
732 "Unshars and saves files.
733 The shar equivalent to `gnus-uu-decode-and-save'."
735 (gnus-uu-unshar-and-view-or-save nil nil
))
737 (defun gnus-uu-marked-shar-and-view ()
738 "Unshars and views articles marked.
739 The marked equivalent to `gnus-uu-shar-and-view'."
741 (gnus-uu-unshar-and-view-or-save t t
))
743 (defun gnus-uu-marked-shar-and-save ()
744 "Unshars and saves articles marked.
745 The marked equivalent to `gnus-uu-shar-and-save'."
747 (gnus-uu-unshar-and-view-or-save nil t
))
750 ;; Decode and show in buffer
752 (defun gnus-uu-decode-and-show-in-buffer ()
753 "Uudecodes the current article and displays the result in a buffer.
754 Might be useful if someone has, for instance, some text uuencoded in
755 their sigs. (Stranger things have happened.)"
757 (let ((uu-buffer (get-buffer-create gnus-uu-output-buffer-name
))
758 list-of-articles file-name
)
761 (setq list-of-articles
(list gnus-current-article
))
762 (gnus-uu-grab-articles list-of-articles
'gnus-uu-uustrip-article-as
)
763 (setq file-name
(gnus-uu-decode gnus-uu-tmp-dir
))
766 (set-buffer uu-buffer
)
768 (insert-file-contents file-name
))
769 (set-window-buffer (get-buffer-window gnus-article-buffer
)
771 (message (format "Showing file %s in buffer" file-name
))
772 (delete-file file-name
))))))
777 (defun gnus-uu-toggle-asynchronous ()
778 "This function toggles asynchronous viewing."
780 (if (setq gnus-uu-asynchronous
(not gnus-uu-asynchronous
))
781 (message "gnus-uu will now view files asynchronously")
782 (message "gnus-uu will now view files synchronously")))
784 (defun gnus-uu-toggle-query ()
785 "This function toggles whether to ask before viewing or not."
787 (if (setq gnus-uu-ask-before-view
(not gnus-uu-ask-before-view
))
788 (message "gnus-uu will now ask before viewing")
789 (message "gnus-uu will now view without asking first")))
791 (defun gnus-uu-toggle-always-ask ()
792 "This function toggles whether to always ask to save a file after viewing."
794 (if (setq gnus-uu-view-and-save
(not gnus-uu-view-and-save
))
795 (message "gnus-uu will now ask to save the file after viewing")
796 (message "gnus-uu will now not ask to save after successful viewing")))
798 (defun gnus-uu-toggle-interactive-view ()
799 "This function toggles whether to use interactive view."
801 (if (setq gnus-uu-use-interactive-view
(not gnus-uu-use-interactive-view
))
802 (message "gnus-uu will now use interactive view")
803 (message "gnus-uu will now use non-interactive view")))
805 (defun gnus-uu-toggle-unmark-undecoded ()
806 "This function toggles whether to unmark articles not decoded."
808 (if (setq gnus-uu-unmark-articles-not-decoded
809 (not gnus-uu-unmark-articles-not-decoded
))
810 (message "gnus-uu will now unmark articles not decoded")
811 (message "gnus-uu will now not unmark articles not decoded")))
813 (defun gnus-uu-toggle-kill-carriage-return ()
814 "This function toggles the stripping of carriage returns from the articles."
816 (if (setq gnus-uu-kill-carriage-return
(not gnus-uu-kill-carriage-return
))
817 (message "gnus-uu will now strip carriage returns")
818 (message "gnus-uu won't strip carriage returns")))
820 (defun gnus-uu-toggle-correct-stripped-uucode ()
821 "This function toggles whether to correct stripped uucode."
823 (if (setq gnus-uu-correct-stripped-uucode
824 (not gnus-uu-correct-stripped-uucode
))
825 (message "gnus-uu will now correct stripped uucode")
826 (message "gnus-uu won't check and correct stripped uucode")))
828 (defun gnus-uu-toggle-any-variable ()
829 "This function ask what variable the user wants to toggle."
832 (message "(a)sync, (q)uery, (p)ask, (k)ill CR, (i)nteractive, (u)nmark, (c)orrect")
833 (setq rep
(read-char))
835 (gnus-uu-toggle-asynchronous))
837 (gnus-uu-toggle-query))
839 (gnus-uu-toggle-always-ask))
841 (gnus-uu-toggle-kill-carriage-return))
843 (gnus-uu-toggle-unmark-undecoded))
845 (gnus-uu-toggle-correct-stripped-uucode))
847 (gnus-uu-toggle-interactive-view))))
852 (defun gnus-uu-edit-begin-line ()
853 "Edit the begin line of the current article."
855 (let ((buffer-read-only nil
)
858 (set-buffer gnus-article-buffer
)
860 (if (not (re-search-forward "begin " nil t
))
861 (progn (message "No begin line in the current article") (sit-for 2))
865 (setq begin
(buffer-substring b
(point)))
866 (setq begin
(read-string "" begin
))
867 (setq buffer-read-only nil
)
868 (delete-region b
(point))
869 (insert-string begin
)))))
873 (defun gnus-uu-multi-decode-and-view ()
874 "Choose a method of decoding and then decode and view.
875 This function lets the user decide what method to use for decoding.
876 Other than that, it's equivalent to the other decode-and-view
879 (gnus-uu-multi-decode-and-view-or-save t nil
))
881 (defun gnus-uu-multi-decode-and-save ()
882 "Choose a method of decoding and then decode and save.
883 This function lets the user decide what method to use for decoding.
884 Other than that, it's equivalent to the other decode-and-save
887 (gnus-uu-multi-decode-and-view-or-save nil nil
))
889 (defun gnus-uu-marked-multi-decode-and-view ()
890 "Choose a method of decoding and then decode and view the marked articles.
891 This function lets the user decide what method to use for decoding.
892 Other than that, it's equivalent to the other marked decode-and-view
895 (gnus-uu-multi-decode-and-view-or-save t t
))
897 (defun gnus-uu-marked-multi-decode-and-save ()
898 "Choose a method of decoding and then decode and save the marked articles.
899 This function lets the user decide what method to use for decoding.
900 Other than that, it's equivalent to the other marked decode-and-save
903 (gnus-uu-multi-decode-and-view-or-save t t
))
905 (defun gnus-uu-multi-decode-and-view-or-save (view marked
)
907 (message "(u)udecode, (s)har, s(a)ve, (b)inhex: ")
908 (setq decode-type
(read-char))
910 ) (setq decode-type ?u
))
911 (if (= decode-type ?u
)
912 (gnus-uu-decode-and-view-or-save view marked
)
913 (if (= decode-type ?s
)
914 (gnus-uu-unshar-and-view-or-save view marked
)
915 (if (= decode-type ?b
)
916 (gnus-uu-binhex-and-save view marked
)
917 (if (= decode-type ?a
)
918 (gnus-uu-save-articles view marked
)
919 (message (format "Unknown decode method '%c'." decode-type
))
925 (defconst gnus-uu-uuencode-post-length
90)
927 (defun gnus-uu-post ()
929 (let ((uuencode-buffer-name "*uuencode buffer*")
930 (send-buffer-name "*uuencode send buffer*")
931 (top-string "[ cut here %s (%s %d/%d) %s gnus-uu ]")
932 file uubuf short-file length parts header i end beg
933 beg-line minlen buf post-buf whole-len
)
934 (setq file
(read-file-name
935 "What file do you want to uuencode and post? " "~/Unrd.jpg"))
936 (if (not (file-exists-p file
))
937 (message "%s: No such file" file
)
939 (setq post-buf
(current-buffer))
940 (set-buffer (setq uubuf
(get-buffer-create uuencode-buffer-name
)))
942 (if (string-match "^~/" file
)
943 (setq file
(concat "$HOME" (substring file
1))))
944 (if (string-match "/[^/]*$" file
)
945 (setq short-file
(substring file
(1+ (match-beginning 0))))
946 (setq short-file file
))
947 (call-process "sh" nil uubuf nil
"-c"
948 (format "uuencode %s %s" file short-file
))
951 (while (re-search-forward " " nil t
)
953 (setq length
(count-lines 1 (point-max)))
954 (setq parts
(/ length gnus-uu-uuencode-post-length
))
955 (if (not (< (% length gnus-uu-uuencode-post-length
) 4))
956 (setq parts
(1+ parts
)))
957 (message "Det er %d parts" parts
))
959 (search-forward mail-header-separator nil t
)
962 (setq header
(buffer-substring 1 (point)))
964 (if (re-search-forward "^Subject: " nil t
)
967 (insert (format " (0/%d)" parts
))))
969 ; (set-buffer (get-buffer-create "*tull"))
971 ; (goto-char (point-max))
972 ; (insert-buffer send-buffer-name))
978 (while (not (> i parts
))
979 (set-buffer (get-buffer-create send-buffer-name
))
984 (- 62 (length (format top-string
"" short-file i parts
""))))
985 (setq minlen
(/ whole-len
2))
989 (make-string minlen ?-
)
991 (make-string (if (= 0 (% whole-len
2)) (1- minlen
) minlen
) ?-
)))
995 (if (re-search-forward "^Subject: " nil t
)
998 (insert (format " (%d/%d)" i parts
))))
999 (goto-char (point-max))
1004 (goto-char (point-max))
1005 (forward-line gnus-uu-uuencode-post-length
))
1007 (insert-buffer-substring uubuf beg end
)
1013 ; (set-buffer (get-buffer-create "*tull"))
1014 ; (goto-char (point-max))
1015 ; (insert-buffer send-buffer-name))
1018 (and (setq buf
(get-buffer send-buffer-name
))
1020 (and (setq buf
(get-buffer uuencode-buffer-name
))
1021 (kill-buffer buf
)))))
1025 ;; Decode and all files
1027 (defconst gnus-uu-rest-of-articles nil
)
1028 (defconst gnus-uu-do-sloppy-uudecode nil
)
1029 (defvar gnus-uu-current-save-dir nil
)
1031 (defun gnus-uu-decode-and-save-all-unread-articles ()
1032 "Try to decode all unread articles and saves the result.
1033 This function reads all unread articles in the current group and sees
1034 whether it can uudecode the articles. The user will be prompted for an
1035 directory to put the resulting (if any) files."
1037 (gnus-uu-decode-and-save-articles t t
))
1039 (defun gnus-uu-decode-and-save-all-articles ()
1040 "Try to decode all articles and saves the result.
1041 Does the same as `gnus-uu-decode-and-save-all-unread-articles', except
1042 that it grabs all articles visible, unread or not."
1044 (gnus-uu-decode-and-save-articles nil t
))
1046 (defun gnus-uu-decode-and-save-all-unread-articles-and-mark ()
1047 "Try to decode all unread articles and saves the result and marks everything as read.
1048 Does the same as `gnus-uu-decode-and-save-all-unread-articles', except that
1049 it marks everything as read, even if it couldn't decode the articles."
1051 (gnus-uu-decode-and-save-articles t nil
))
1053 (defun gnus-uu-decode-and-save-all-articles-and-mark ()
1054 "Try to decode all articles and saves the result and marks everything as read.
1055 Does the same as `gnus-uu-decode-and-save-all-articles', except that
1056 it marks everything as read, even if it couldn't decode the articles."
1058 (gnus-uu-decode-and-save-articles nil nil
))
1060 (defun gnus-uu-decode-and-save-articles (&optional unread unmark
)
1061 (let ((gnus-uu-unmark-articles-not-decoded unmark
)
1063 where dir did unmark saved-list
)
1064 (setq gnus-uu-do-sloppy-uudecode t
)
1065 (setq dir
(gnus-uu-read-directory "Where do you want the files? "))
1066 (message "Grabbing...")
1067 (setq gnus-uu-rest-of-articles
1068 (gnus-uu-get-list-of-articles "^." nil unread
))
1069 (setq gnus-uu-file-name nil
)
1070 (while (and gnus-uu-rest-of-articles
1071 (gnus-uu-grab-articles gnus-uu-rest-of-articles
1072 'gnus-uu-uustrip-article-as
))
1073 (if gnus-uu-file-name
1075 (setq saved-list
(cons gnus-uu-file-name saved-list
))
1076 (rename-file (concat gnus-uu-tmp-dir gnus-uu-file-name
)
1077 (concat dir gnus-uu-file-name
) t
)
1079 (setq gnus-uu-file-name nil
))))
1083 (setq filest
(concat filest
" " (car saved-list
)))
1084 (setq saved-list
(cdr saved-list
)))
1085 (message "Saved%s" filest
)))
1086 (setq gnus-uu-do-sloppy-uudecode nil
))
1091 (defun gnus-uu-decode-and-view-or-save (view marked
)
1092 (gnus-uu-initialize)
1095 (if (gnus-uu-decode-and-strip nil marked
)
1098 (setq file
(concat gnus-uu-tmp-dir gnus-uu-file-name
))
1100 (gnus-uu-view-file file
)
1101 (gnus-uu-save-file file
)))))
1103 (gnus-uu-summary-next-subject)
1105 (if gnus-uu-error-during-unarching
1107 (if (and gnus-uu-use-interactive-view view decoded
)
1108 (gnus-uu-do-interactive)))
1110 (if (or (not gnus-uu-use-interactive-view
) (not decoded
))
1111 (gnus-uu-clean-up))))
1114 ; Unshars and views/saves marked/unmarked articles.
1116 (defun gnus-uu-unshar-and-view-or-save (view marked
)
1117 (gnus-uu-initialize)
1118 (let (tar-file files decoded
)
1120 (setq gnus-uu-shar-directory
1121 (make-temp-name (concat gnus-uu-tmp-dir
"gnusuush")))
1122 (make-directory gnus-uu-shar-directory
)
1123 (gnus-uu-add-file gnus-uu-shar-directory
)
1124 (if (gnus-uu-decode-and-strip t marked
)
1127 (setq files
(directory-files gnus-uu-shar-directory t
))
1128 (setq gnus-uu-generated-file-list
1129 (append files gnus-uu-generated-file-list
))
1130 (if (> (length files
) 3)
1134 (make-temp-name (concat gnus-uu-tmp-dir
"gnusuuar"))
1136 (gnus-uu-add-file tar-file
)
1137 (call-process "sh" nil
1138 (get-buffer-create gnus-uu-output-buffer-name
)
1140 (format "cd %s ; tar cf %s * ; cd .. ; rm -r %s"
1141 gnus-uu-shar-directory
1143 gnus-uu-shar-directory
))
1145 (gnus-uu-view-file tar-file
)
1146 (gnus-uu-save-file tar-file
)))
1148 (gnus-uu-view-file (elt files
2))
1149 (gnus-uu-save-file (elt files
2)))))))
1151 (gnus-uu-summary-next-subject)
1153 (if (and gnus-uu-use-interactive-view view decoded
)
1154 (gnus-uu-do-interactive))
1156 (if (or (not gnus-uu-use-interactive-view
) (not decoded
))
1157 (gnus-uu-clean-up))))
1160 (defconst gnus-uu-saved-article-name nil
)
1161 (defun gnus-uu-save-articles (view marked
)
1162 (let (list-of-articles)
1165 (setq list-of-articles
(gnus-uu-get-list-of-articles))
1166 (setq list-of-articles
(reverse gnus-uu-marked-article-list
))
1167 (setq gnus-uu-marked-article-list nil
))
1168 (if (not list-of-articles
)
1170 (message "No list of articles")
1172 (setq gnus-uu-saved-article-name
1173 (concat gnus-uu-tmp-dir
1174 (read-file-name "Enter file name: " gnus-newsgroup-name
1175 gnus-newsgroup-name
)))
1176 (gnus-uu-add-file gnus-uu-saved-article-name
)
1177 (if (gnus-uu-grab-articles list-of-articles
'gnus-uu-save-article
)
1178 (gnus-uu-save-file gnus-uu-saved-article-name
))))))
1181 (defun gnus-uu-save-article (buffer in-state
)
1184 (call-process-region
1185 1 (point-max) "sh" nil
(get-buffer-create gnus-uu-output-buffer-name
)
1186 nil
"-c" (concat "cat >> " gnus-uu-saved-article-name
)))
1191 (defconst gnus-uu-binhex-body-line
1192 "^................................................................$")
1193 (defconst gnus-uu-binhex-begin-line
1194 "^:...............................................................$")
1195 (defconst gnus-uu-binhex-end-line
1197 (defvar gnus-uu-binhex-article-name nil
)
1200 (defun gnus-uu-binhex-and-save (view marked
)
1201 (let (list-of-articles)
1204 (setq list-of-articles
(gnus-uu-get-list-of-articles))
1205 (setq list-of-articles
(reverse gnus-uu-marked-article-list
))
1206 (setq gnus-uu-marked-article-list nil
))
1207 (if (not list-of-articles
)
1209 (message "No list of articles")
1211 (setq gnus-uu-binhex-article-name
1212 (concat gnus-uu-tmp-dir
1213 (read-file-name "Enter binhex file name: "
1215 gnus-newsgroup-name
)))
1216 (gnus-uu-add-file gnus-uu-binhex-article-name
)
1217 (if (gnus-uu-grab-articles list-of-articles
'gnus-uu-binhex-article
)
1218 (gnus-uu-save-file gnus-uu-binhex-article-name
))))))
1221 (defun gnus-uu-binhex-article (buffer in-state
)
1227 (if (not (re-search-forward (concat gnus-uu-binhex-begin-line
"\\|"
1228 gnus-uu-binhex-body-line
) nil t
))
1229 (setq state
'wrong-type
)
1231 (setq start-char
(point))
1232 (if (looking-at gnus-uu-binhex-begin-line
)
1234 (setq state
'middle
))
1235 (goto-char (point-max))
1236 (re-search-backward (concat gnus-uu-binhex-body-line
"\\|"
1237 gnus-uu-binhex-end-line
) nil t
)
1238 (if (looking-at gnus-uu-binhex-end-line
)
1239 (if (eq state
'begin
)
1240 (setq state
'begin-and-end
)
1244 (append-to-file start-char
(point) gnus-uu-binhex-article-name
)))
1248 ;; Internal view commands
1250 ; This function takes two parameters. The first is name of the file to
1251 ; be viewed. `gnus-uu-view-file' will look for an action associated
1252 ; with the file type of the file. If it finds an appropriate action,
1253 ; the file will be attempted displayed.
1255 ; The second parameter specifies if the user is to be asked whether to
1256 ; save the file if viewing is unsuccessful. t means "do not ask."
1258 ; Note that the file given will be deleted by this function, one way
1259 ; or another. If `gnus-uu-asynchronous' is set, it won't be deleted
1260 ; right away, but sometime later. If the user is offered to save the
1261 ; file, it'll be moved to wherever the user wants it.
1263 ; `gnus-uu-view-file' returns t if viewing is successful.
1265 (defun gnus-uu-view-file (file-name &optional dont-ask
)
1266 (let (action did-view
1270 (gnus-uu-choose-action
1273 (if (and gnus-uu-use-interactive-view
1274 gnus-uu-user-interactive-view-rules
)
1275 gnus-uu-user-interactive-view-rules
1276 gnus-uu-user-view-rules
)
1277 (if (or gnus-uu-ignore-default-view-rules
1278 (not gnus-uu-use-interactive-view
))
1280 gnus-uu-default-interactive-view-rules-begin
)
1281 (if gnus-uu-ignore-default-view-rules
1283 gnus-uu-default-view-rules
)
1284 (if (and gnus-uu-use-interactive-view
1285 gnus-uu-user-interactive-view-rules-end
)
1286 gnus-uu-user-interactive-view-rules-end
1287 gnus-uu-user-view-rules-end
))))
1289 (if (and gnus-uu-use-interactive-view
1290 (not (string= (or action
"") "gnus-uu-archive")))
1291 (gnus-uu-enter-interactive-file (or action
"") file-name
)
1294 (if (string= action
"gnus-uu-archive")
1295 (setq did-view
(gnus-uu-treat-archive file-name
))
1297 (if gnus-uu-ask-before-view
1302 (format "Do you want to view %s? "
1308 (if gnus-uu-asynchronous
1309 (gnus-uu-call-asynchronous file-name action
)
1310 (gnus-uu-call-synchronous file-name action
))))))
1312 (if (and (not dont-ask
) (not gnus-uu-use-interactive-view
))
1317 (and (string= action
"gnus-uu-archive")
1321 (format "Could find no rule for %s" file-name
))
1323 (and (or (not did-view
) gnus-uu-view-and-save
)
1325 (format "Do you want to save the file %s? "
1327 (gnus-uu-save-file file-name
))))
1329 (if (and (file-exists-p file-name
)
1330 (not gnus-uu-use-interactive-view
)
1332 (not (and gnus-uu-asynchronous did-view
))
1333 (string= action
"gnus-uu-archive")))
1334 (delete-file file-name
)))
1339 ; `gnus-uu-call-synchronous' takes two parameters: The name of the
1340 ; file to be displayed and the command to display it with. Returns t
1341 ; on success and nil if the file couldn't be displayed.
1343 (defun gnus-uu-call-synchronous (file-name action
)
1344 (let (did-view command
)
1346 (set-buffer (get-buffer-create gnus-uu-output-buffer-name
))
1348 (setq command
(gnus-uu-command action file-name
))
1349 (message (format "Viewing with '%s'" command
))
1350 (if (not (= 0 (call-process "sh" nil t nil
"-c" command
)))
1353 (while (re-search-forward "\n" nil t
)
1354 (replace-match " "))
1355 (message (concat "Error: " (buffer-substring 1 (point-max))))
1361 ; `gnus-uu-call-asyncronous' takes two parameters: The name of the
1362 ; file to be displayed and the command to display it with. Since the
1363 ; view command is executed asynchronously, it's kinda hard to decide
1364 ; whether the command succeded or not, so this function always returns
1365 ; t. It also adds "; rm -f file-name" to the end of the execution
1366 ; string, so the file will be removed after viewing has ended.
1368 (defun gnus-uu-call-asynchronous (file-name action
)
1369 (let (command file tmp-file start
)
1370 (while (string-match "/" file-name start
)
1371 (setq start
(1+ (match-beginning 0))))
1372 (setq file
(substring file-name start
))
1373 (setq tmp-file
(concat gnus-uu-tmp-dir file
))
1374 (if (string= tmp-file file-name
)
1376 (rename-file file-name tmp-file t
)
1377 (setq file-name tmp-file
))
1379 (setq command
(gnus-uu-command action file-name
))
1380 (setq command
(format "%s ; rm -f %s" command file-name
))
1381 (message (format "Viewing with %s" command
))
1382 (start-process "gnus-uu-view" nil
"sh" "-c" command
)
1386 ; `gnus-uu-decode-and-strip' does all the main work. It finds out what
1387 ; articles to grab, grabs them, strips the result and decodes. If any
1388 ; of these operations fail, it returns nil, t otherwise. If shar is
1389 ; t, it will pass this on to `gnus-uu-grab-articles', which will
1390 ; (probably) unshar the articles. If use-marked is non-nil, it won't
1391 ; try to find articles, but use the marked list.
1393 (defun gnus-uu-decode-and-strip (&optional shar use-marked
)
1394 (let (list-of-articles)
1398 (progn (if (eq gnus-uu-marked-article-list
())
1399 (message "No articles marked")
1400 (setq list-of-articles
(reverse gnus-uu-marked-article-list
))
1401 (gnus-uu-unmark-all-articles)))
1402 (setq list-of-articles
(gnus-uu-get-list-of-articles)))
1404 (and list-of-articles
1405 (gnus-uu-grab-articles list-of-articles
1407 'gnus-uu-unshar-article
1408 'gnus-uu-uustrip-article-as
))))))
1411 ; Takes a string and puts a \ in front of every special character;
1412 ; ignores any leading "version numbers" thingies that they use in the
1413 ; comp.binaries groups, and either replaces anything that looks like
1414 ; "2/3" with "[0-9]+/[0-9]+" or, if it can't find something like that,
1415 ; replaces the last two numbers with "[0-9]+". This, in my experience,
1416 ; should get most postings of a series."
1418 (defun gnus-uu-reginize-string (string)
1420 (vernum "v[0-9]+[a-z][0-9]+:")
1423 (set-buffer (get-buffer-create gnus-uu-output-buffer-name
))
1425 (insert (regexp-quote string
))
1428 (setq case-fold-search nil
)
1430 (if (looking-at vernum
)
1432 (replace-match vernum t t
)
1433 (setq beg
(length vernum
))))
1436 (if (re-search-forward "[ \t]*[0-9]+/[0-9]+" nil t
)
1437 (replace-match " [0-9]+/[0-9]+")
1440 (if (re-search-forward "[0-9]+[ \t]*of[ \t]*[0-9]+" nil t
)
1441 (replace-match "[0-9]+ of [0-9]+")
1444 (while (and (re-search-backward "[0-9]" nil t
) (> count
0))
1446 (looking-at "[0-9]")
1447 (< 1 (goto-char (1- (point))))))
1448 (re-search-forward "[0-9]+" nil t
)
1449 (replace-match "[0-9]+")
1451 (setq count
(1- count
)))))
1454 (while (re-search-forward "[ \t]+" nil t
)
1455 (replace-match "[ \t]*" t t
))
1457 (buffer-substring 1 (point-max)))))
1460 ; Finds all articles that matches the regular expression given.
1461 ; Returns the resulting list.
1463 (defun gnus-uu-get-list-of-articles (&optional subject mark-articles only-unread
)
1464 (let (beg end reg-subject list-of-subjects list-of-numbers art-num
)
1467 ; If the subject is not given, this function looks at the current subject
1471 (setq reg-subject subject
)
1475 (if (not (re-search-forward "\\] " end t
))
1476 (progn (message "No valid subject chosen") (sit-for 2))
1477 (setq subject
(buffer-substring (point) end
))
1479 (concat "\\[.*\\] " (gnus-uu-reginize-string subject
)))))
1481 ; (message reg-subject)(sleep-for 2)
1486 ; Collect all subjects matching reg-subject.
1488 (let ((case-fold-search t
))
1489 (setq case-fold-search t
)
1491 (while (re-search-forward reg-subject nil t
)
1494 (if (or (not only-unread
) (looking-at " \\|-"))
1497 (setq list-of-subjects
(cons
1498 (buffer-substring beg
(point))
1502 ; Expand all numbers in all the subjects: (hi9 -> hi0009, etc).
1504 (setq list-of-subjects
(gnus-uu-expand-numbers list-of-subjects
))
1506 ; Sort the subjects.
1508 (setq list-of-subjects
(sort list-of-subjects
'gnus-uu-string
<))
1510 ; Get the article numbers from the sorted list of subjects.
1512 (while list-of-subjects
1513 (setq art-num
(gnus-uu-article-number (car list-of-subjects
)))
1514 (if mark-articles
(gnus-summary-mark-as-read art-num ?
#))
1515 (setq list-of-numbers
(cons art-num list-of-numbers
))
1516 (setq list-of-subjects
(cdr list-of-subjects
)))
1518 (setq list-of-numbers
(nreverse list-of-numbers
))
1520 (if (not list-of-numbers
)
1522 (message (concat "No subjects matched " subject
))
1528 ; Takes a list of strings and "expands" all numbers in all the
1529 ; strings. That is, this function makes all numbers equal length by
1530 ; prepending lots of zeroes before each number. This is to ease later
1531 ; sorting to find out what sequence the articles are supposed to be
1532 ; decoded in. Returns the list of expanded strings.
1534 (defun gnus-uu-expand-numbers (string-list)
1535 (let (string out-list pos num
)
1537 (set-buffer (get-buffer-create gnus-uu-output-buffer-name
))
1540 (setq string
(car string-list
))
1541 (setq string-list
(cdr string-list
))
1544 (while (re-search-forward "[ \t]+" nil t
)
1545 (replace-match " "))
1547 (while (re-search-forward "[A-Za-z]" nil t
)
1548 (replace-match "a" t t
))
1551 (if (not (search-forward "] " nil t
))
1553 (while (re-search-forward "[0-9]+" nil t
)
1556 (string-to-int (buffer-substring
1557 (match-beginning 0) (match-end 0))))))
1558 (setq string
(buffer-substring 1 (point-max)))
1559 (setq out-list
(cons string out-list
)))))
1563 ; Used in a sort for finding out what string is bigger, but ignoring
1564 ; everything before the subject part.
1566 (defun gnus-uu-string< (string1 string2
)
1567 (string< (substring string1
(string-match "\\] " string1
))
1568 (substring string2
(string-match "\\] " string2
))))
1571 ;; gnus-uu-grab-article
1573 ; This is the general multi-article treatment function. It takes a
1574 ; list of articles to be grabbed and a function to apply to each
1575 ; article. It puts the result in `gnus-uu-result-buffer'.
1577 ; The function to be called should take two parameters. The first is
1578 ; the buffer that has the article that should be treated. The function
1579 ; should leave the result in this buffer as well. This result is then
1580 ; appended on to the `gnus-uu-result-buffer'.
1582 ; The second parameter is the state of the list of articles, and can
1583 ; have three values: 'start, 'middle and 'end.
1585 ; The function can have several return values:
1586 ; 'error if there was an error while treating.
1587 ; 'end if the last article has been sighted.
1588 ; 'begin-and-end if the article is both the beginning and
1589 ; the end. All these three return values results in
1590 ; `gnus-uu-grab-articles' stopping traversing of the list
1592 ; 'middle if the article is a "middle" article.
1593 ; 'ok if everything is ok.
1595 (defvar gnus-uu-has-been-grabbed nil
)
1597 (defun gnus-uu-unmark-list-of-grabbed (&optional dont-unmark-last-article
)
1599 (if (or (not gnus-uu-has-been-grabbed
)
1600 (not gnus-uu-unmark-articles-not-decoded
))
1602 (if dont-unmark-last-article
1604 (setq art
(car gnus-uu-has-been-grabbed
))
1605 (setq gnus-uu-has-been-grabbed
(cdr gnus-uu-has-been-grabbed
))))
1606 (while gnus-uu-has-been-grabbed
1607 (gnus-summary-mark-as-unread (car gnus-uu-has-been-grabbed
) t
)
1608 (setq gnus-uu-has-been-grabbed
(cdr gnus-uu-has-been-grabbed
)))
1609 (if dont-unmark-last-article
1610 (setq gnus-uu-has-been-grabbed
(list art
))))))
1613 ; This function takes a list of articles and a function to apply to
1614 ; each article grabbed. The result of the function is appended on to
1615 ; `gnus-uu-result-buffer'.
1617 ; This function returns t if the grabbing and the process-function
1618 ; has been successful and nil otherwise."
1620 (defun gnus-uu-grab-articles (list-of-articles process-function
)
1621 (let ((result-buffer (get-buffer-create gnus-uu-result-buffer
))
1626 (has-been-begin nil
)
1630 (set-buffer result-buffer
)
1632 (setq gnus-uu-has-been-grabbed nil
)
1633 (while (and list-of-articles
1634 (not (eq process-state
'end
))
1635 (not (eq process-state
'begin-and-end
))
1636 (not (eq process-state
'error
)))
1637 (setq article
(car list-of-articles
))
1638 (setq list-of-articles
(cdr list-of-articles
))
1639 (setq gnus-uu-has-been-grabbed
(cons article gnus-uu-has-been-grabbed
))
1641 (if (eq list-of-articles
()) (setq state
'last
))
1643 (message (format "Getting article %d" article
))
1644 (if (not (= (or gnus-current-article
0) article
))
1645 (gnus-summary-display-article article
))
1646 (gnus-summary-mark-as-read article
)
1649 (set-buffer gnus-article-buffer
)
1652 (setq process-state
(funcall process-function gnus-article-buffer state
))
1654 (if (or (eq process-state
'begin
) (eq process-state
'begin-and-end
)
1655 (eq process-state
'ok
))
1656 (setq has-been-begin t
))
1658 (if (not (eq process-state
'wrong-type
))
1659 (setq wrong-type nil
)
1660 (if gnus-uu-unmark-articles-not-decoded
1661 (gnus-summary-mark-as-unread article t
)))
1663 (if gnus-uu-do-sloppy-uudecode
1664 (setq wrong-type nil
))
1666 (if (and (not has-been-begin
)
1667 (not gnus-uu-do-sloppy-uudecode
)
1668 (or (eq process-state
'end
)
1669 (eq process-state
'middle
)))
1671 (setq process-state
'error
)
1672 (message "No begin part at the beginning")
1674 (setq state
'middle
)))
1676 (if (and (not has-been-begin
) (not gnus-uu-do-sloppy-uudecode
))
1679 (message "Wrong type file")
1681 (if (eq process-state
'error
)
1683 (if (not (or (eq process-state
'ok
)
1684 (eq process-state
'end
)
1685 (eq process-state
'begin-and-end
)))
1687 (if (not gnus-uu-do-sloppy-uudecode
)
1689 (message "End of articles reached before end of file")
1691 (gnus-uu-unmark-list-of-grabbed)
1692 (setq result nil
)))))
1693 (setq gnus-uu-rest-of-articles list-of-articles
)
1697 (defun gnus-uu-uudecode-sentinel (process event
)
1698 ; (message "Process '%s' has received event '%s'" process event)
1700 (delete-process (get-process process
)))
1703 (defun gnus-uu-uustrip-article-as (process-buffer in-state
)
1705 (process-connection-type nil
)
1706 start-char pst name-beg name-end buf-state
)
1708 (set-buffer process-buffer
)
1709 (setq buf-state buffer-read-only
)
1710 (setq buffer-read-only nil
)
1714 (if gnus-uu-kill-carriage-return
1716 (while (search-forward "
1718 (delete-backward-char 1))
1721 (if (not (re-search-forward gnus-uu-begin-string nil t
))
1722 (if (not (re-search-forward gnus-uu-body-line nil t
))
1723 (setq state
'wrong-type
)))
1725 (if (eq state
'wrong-type
)
1728 (setq start-char
(point))
1730 (if (looking-at gnus-uu-begin-string
)
1732 (setq name-end
(match-end 1))
1733 (goto-char (setq name-beg
(match-beginning 1)))
1734 (while (re-search-forward "/" name-end t
)
1735 (replace-match "-"))
1736 (setq gnus-uu-file-name
(buffer-substring name-beg name-end
))
1737 (and gnus-uu-uudecode-process
1738 (setq pst
(process-status
1739 (or gnus-uu-uudecode-process
"nevair")))
1740 (if (or (eq pst
'stop
) (eq pst
'run
))
1742 (delete-process gnus-uu-uudecode-process
)
1743 (gnus-uu-unmark-list-of-grabbed t
))))
1744 (setq gnus-uu-uudecode-process
1747 (get-buffer-create gnus-uu-output-buffer-name
)
1749 (format "cd %s ; uudecode" gnus-uu-tmp-dir
)))
1750 (set-process-sentinel
1751 gnus-uu-uudecode-process
'gnus-uu-uudecode-sentinel
)
1753 (gnus-uu-add-file (concat gnus-uu-tmp-dir gnus-uu-file-name
)))
1754 (setq state
'middle
))
1756 (goto-char (point-max))
1759 (concat gnus-uu-body-line
"\\|" gnus-uu-end-string
) nil t
)
1762 (if (looking-at gnus-uu-end-string
)
1763 (if (eq state
'begin
)
1764 (setq state
'begin-and-end
)
1768 ; (message "Ja: %s" state)(sit-for 0)(sleep-for 2)
1770 (and gnus-uu-uudecode-process
1771 (setq pst
(process-status (or gnus-uu-uudecode-process
"nevair")))
1772 (if (or (eq pst
'run
) (eq pst
'stop
))
1774 (if gnus-uu-correct-stripped-uucode
1776 (gnus-uu-check-correct-stripped-uucode
1778 (goto-char (point-max))
1780 (concat gnus-uu-body-line
"\\|" gnus-uu-end-string
)
1784 (process-send-region gnus-uu-uudecode-process
1788 (message "Her var en uuerror")
1790 (setq state
'wrong-type
)
1791 (delete-process gnus-uu-uudecode-process
)))))
1792 (setq state
'wrong-type
)))
1793 (if (not gnus-uu-uudecode-process
)
1794 (setq state
'wrong-type
)))
1796 (setq buffer-read-only buf-state
))
1800 ; This function is used by `gnus-uu-grab-articles' to treat
1803 (defun gnus-uu-unshar-article (process-buffer in-state
)
1807 (set-buffer process-buffer
)
1809 (if (not (re-search-forward gnus-uu-shar-begin-string nil t
))
1810 (setq state
'wrong-type
)
1812 (setq start-char
(point))
1813 (call-process-region
1814 start-char
(point-max) "sh" nil
1815 (get-buffer-create gnus-uu-output-buffer-name
) nil
1816 "-c" (concat "cd " gnus-uu-shar-directory
" ; sh"))))
1820 ; Returns the name of what the shar file is going to unpack.
1822 (defun gnus-uu-find-name-in-shar ()
1823 (let ((oldpoint (point))
1826 (if (re-search-forward gnus-uu-shar-name-marker nil t
)
1827 (setq res
(buffer-substring (match-beginning 1) (match-end 1))))
1828 (goto-char oldpoint
)
1832 ; Returns the article number of the given subject.
1834 (defun gnus-uu-article-number (subject)
1836 (string-match "[0-9]+[^0-9]" subject
1)
1837 (setq end
(match-end 0))
1839 (substring subject
(string-match "[0-9]" subject
1) end
))))
1842 ; UUdecodes everything in the buffer and returns the name of the
1845 (defun gnus-uu-decode (directory)
1846 (let ((command (concat "cd " directory
" ; uudecode"))
1849 (message "Uudecoding...")
1850 (set-buffer (get-buffer-create gnus-uu-result-buffer
))
1851 (setq file-name
(concat gnus-uu-tmp-dir gnus-uu-file-name
))
1852 (gnus-uu-add-file file-name
)
1853 (call-process-region 1 (point-max) "sh" nil t nil
"-c" command
)
1857 ; `gnus-uu-choose-action' chooses what action to perform given the name
1858 ; and `gnus-uu-file-action-list'. Returns either nil if no action is
1859 ; found, or the name of the command to run if such a rule is found.
1861 (defun gnus-uu-choose-action (file-name file-action-list
)
1862 (let ((action-list (copy-sequence file-action-list
))
1864 (while (not (or (eq action-list
()) action
))
1865 (setq rule
(car action-list
))
1866 (setq action-list
(cdr action-list
))
1867 (if (string-match (car rule
) file-name
)
1868 (setq action
(car (cdr rule
)))))
1872 ; Moves the file from the tmp directory to where the user wants it.
1874 (defun gnus-uu-save-file (from-file-name &optional default-dir ignore-existing
)
1875 (let (dir file-name command
)
1876 (string-match "/[^/]*$" from-file-name
)
1877 (setq file-name
(substring from-file-name
(1+ (match-beginning 0))))
1879 (setq dir default-dir
)
1880 (setq dir
(gnus-uu-read-directory "Where do you want the file? ")))
1881 (if (and (not ignore-existing
) (file-exists-p (concat dir file-name
)))
1883 (message (concat "There already is a file called " file-name
))
1886 (read-file-name "Give a new name: " dir
(concat dir file-name
)
1888 (setq file-name
(concat dir file-name
)))
1889 (rename-file from-file-name file-name t
)))
1892 (defun gnus-uu-read-directory (prompt &optional default
)
1893 (let (dir ok create
)
1896 (setq dir
(if default default
1897 (read-file-name prompt gnus-uu-current-save-dir
1898 gnus-uu-current-save-dir
)))
1899 (while (string-match "/$" dir
)
1900 (setq dir
(substring dir
0 (match-beginning 0))))
1901 (if (file-exists-p dir
)
1902 (if (not (file-directory-p dir
))
1905 (message "%s is a file" dir
)
1908 (while (not (or (= create ?y
) (= create ?n
)))
1909 (message "%s: No such directory. Do you want to create it? (y/n)"
1911 (setq create
(read-char)))
1912 (if (= create ?y
) (make-directory dir
))))
1913 (setq gnus-uu-current-save-dir
(concat dir
"/"))))
1916 ; Unpacks an archive and views all the files in it. Returns t if
1917 ; viewing one or more files is successful.
1919 (defun gnus-uu-treat-archive (file-name)
1920 (let ((arc-dir (make-temp-name
1921 (concat gnus-uu-tmp-dir
"gnusuu")))
1922 action command files file did-view short-file-name
)
1923 (setq action
(gnus-uu-choose-action
1924 file-name
(append gnus-uu-user-archive-rules
1925 (if gnus-uu-ignore-default-archive-rules
1927 gnus-uu-default-archive-rules
))))
1929 (progn (message (format "No unpackers for the file %s" file-name
))
1931 (string-match "/[^/]*$" file-name
)
1932 (setq short-file-name
(substring file-name
(1+ (match-beginning 0))))
1933 (setq command
(format "%s %s %s ; cd %s ; %s "
1934 (if (or (string= action
"uncompress")
1935 (string= action
"gunzip"))
1938 (gnus-uu-command "" file-name
) arc-dir
1940 (gnus-uu-command action short-file-name
)))
1942 (make-directory arc-dir
)
1943 (gnus-uu-add-file arc-dir
)
1946 (set-buffer (get-buffer-create gnus-uu-output-buffer-name
))
1949 (message (format "Unpacking with %s..." action
))
1952 (if (= 0 (call-process "sh" nil
1953 (get-buffer-create gnus-uu-output-buffer-name
)
1956 (message "Error during unpacking of archive")
1957 (sit-for 0) (sleep-for 2)
1958 (setq gnus-uu-error-during-unarching t
))
1960 (if (not (or (string= action
"uncompress")
1961 (string= action
"gunzip")))
1962 (call-process "sh" nil
(get-buffer gnus-uu-output-buffer-name
)
1963 nil
"-c" (format "mv %s %s"
1964 (gnus-uu-command "" (concat arc-dir
"/" short-file-name
))
1966 (gnus-uu-add-file (concat gnus-uu-tmp-dir short-file-name
))
1969 (or (gnus-uu-show-directory arc-dir gnus-uu-use-interactive-view
)
1972 (if (and (not gnus-uu-use-interactive-view
)
1973 (file-directory-p arc-dir
))
1974 (delete-directory arc-dir
)))
1979 ; Tries to view all the files in the given directory. Returns t if
1980 ; viewing one or more files is successful.
1982 (defun gnus-uu-show-directory (dir &optional dont-delete-files
)
1983 (let (files file did-view
)
1984 (setq files
(directory-files dir t
))
1985 (setq gnus-uu-generated-file-list
1986 (append files gnus-uu-generated-file-list
))
1988 (setq file
(car files
))
1989 (setq files
(cdr files
))
1990 (if (and (not (string-match "/\\.$" file
))
1991 (not (string-match "/\\.\\.$" file
)))
1993 (set-file-modes file
448)
1994 (if (file-directory-p file
)
1995 (setq did-view
(or (gnus-uu-show-directory file
1998 (setq did-view
(or (gnus-uu-view-file file t
) did-view
))
1999 (if (and (not dont-delete-files
) (file-exists-p file
))
2000 (delete-file file
))))))
2001 (if (not dont-delete-files
) (delete-directory dir
))
2007 (defun gnus-uu-enter-mark-in-list ()
2012 (setq article
(gnus-uu-article-number
2013 (buffer-substring beg
(point))))
2014 (message (format "Adding article %d to list" article
))
2015 (setq gnus-uu-marked-article-list
2016 (cons article gnus-uu-marked-article-list
))))
2018 (defun gnus-uu-mark-article ()
2019 "Marks the current article to be decoded later."
2021 (gnus-uu-enter-mark-in-list)
2022 (gnus-summary-mark-as-read nil ?
#)
2023 (gnus-summary-next-subject 1 nil
))
2025 (defun gnus-uu-unmark-article ()
2026 "Unmarks the current article."
2028 (let ((in (copy-sequence gnus-uu-marked-article-list
))
2029 out article beg found
2030 (old-point (point)))
2034 (setq article
(gnus-uu-article-number (buffer-substring beg
(point))))
2035 (message (format "Removing article %d" article
))
2037 (if (not (= (car in
) article
))
2038 (setq out
(cons (car in
) out
))
2040 (message (format "Removing article %d" article
)))
2042 (if (not found
) (message "Not a marked article."))
2043 (setq gnus-uu-marked-article-list
(reverse out
))
2044 (gnus-summary-mark-as-unread nil t
)
2045 (gnus-summary-next-subject 1 nil
)))
2048 (defun gnus-uu-unmark-all-articles ()
2049 "Removes the mark from all articles marked for decoding."
2051 (let ((articles (copy-sequence gnus-uu-marked-article-list
)))
2053 (gnus-summary-goto-subject (car articles
))
2054 (gnus-summary-mark-as-unread nil t
)
2055 (setq articles
(cdr articles
)))
2056 (setq gnus-uu-marked-article-list
())))
2058 (defun gnus-uu-mark-by-regexp ()
2059 "Asks for a regular expression and marks all articles that match."
2062 (setq exp
(read-from-minibuffer "Enter regular expression: "))
2063 (setq gnus-uu-marked-article-list
2064 (reverse (gnus-uu-get-list-of-articles exp t
)))
2070 (defun gnus-uu-check-correct-stripped-uucode (start end
)
2071 (let (found beg length short
)
2072 (if (not gnus-uu-correct-stripped-uucode
)
2076 (if (re-search-forward " \\|`" end t
)
2081 (if (looking-at "\n") (replace-match ""))
2085 (if (looking-at (concat gnus-uu-begin-string
"\\|"
2086 gnus-uu-end-string
))
2093 (setq length
(- (point) beg
))))
2098 (if (not (= length
(- (point) beg
)))
2099 (insert (make-string (- length
(- (point) beg
)) ?
))))
2100 (forward-line 1))))))
2102 (defun gnus-uu-initialize ()
2103 (setq gnus-uu-error-during-unarching nil
)
2104 (if (not gnus-uu-use-interactive-view
)
2107 (setq gnus-uu-interactive-file-list nil
)
2108 (set-buffer (get-buffer-create gnus-uu-interactive-buffer-name
))
2112 "# Press return to execute a command.
2113 # Press `C-c C-c' to exit interactive view.
2118 ; Kills the temporary uu buffers, kills any processes, etc.
2120 (defun gnus-uu-clean-up ()
2122 (setq gnus-uu-do-sloppy-uudecode nil
)
2123 (and gnus-uu-uudecode-process
2124 (setq pst
(process-status (or gnus-uu-uudecode-process
"nevair")))
2125 (if (or (eq pst
'stop
) (eq pst
'run
))
2126 (delete-process gnus-uu-uudecode-process
)))
2127 (and (not gnus-uu-asynchronous
)
2128 (setq buf
(get-buffer gnus-uu-output-buffer-name
))
2130 (and (setq buf
(get-buffer gnus-uu-result-buffer
))
2131 (kill-buffer buf
))))
2134 ; `gnus-uu-check-for-generated-files' deletes any generated files that
2135 ; hasn't been deleted, if, for instance, the user terminated decoding
2138 (defun gnus-uu-check-for-generated-files ()
2140 (while gnus-uu-generated-file-list
2141 (setq file
(car gnus-uu-generated-file-list
))
2142 (setq gnus-uu-generated-file-list
(cdr gnus-uu-generated-file-list
))
2143 (if (not (string-match "/\\.[\\.]?$" file
))
2145 (if (file-directory-p file
)
2146 (delete-directory file
)
2147 (if (file-exists-p file
)
2148 (delete-file file
))))))))
2151 ; Add a file to be checked (and deleted if it still exists upon
2152 ; exiting the newsgroup) to a list
2153 (defun gnus-uu-add-file (file)
2154 (setq gnus-uu-generated-file-list
2155 (cons file gnus-uu-generated-file-list
)))
2158 ; Go to the next unread subject. If there is no further unread
2159 ; subjects, go to the last subject in the buffer.
2160 (defun gnus-uu-summary-next-subject ()
2161 (if (not (gnus-summary-search-forward t
))
2165 (goto-char (point-max))
2168 (search-forward ":" nil t
)))
2170 (gnus-summary-recenter))
2172 ; Inputs an action and a file and returns a full command, putting
2173 ; ticks round the file name and escaping any ticks in the file name.
2174 (defun gnus-uu-command (action file
)
2176 (while (string-match "`\\|\"\\|\\$\\|\\\\" file
)
2179 (concat ofile
(substring file
0 (match-beginning 0)) "\\"
2180 (substring file
(match-beginning 0) (match-end 0))))
2181 (setq file
(substring file
(1+ (match-beginning 0))))))
2182 (setq ofile
(concat "\"" ofile file
"\""))
2183 (if (string-match "%s" action
)
2184 (format action ofile
)
2185 (concat action
" " ofile
))))
2190 (add-hook 'gnus-exit-group-hook
2193 (setq gnus-uu-marked-article-list nil
)
2194 (gnus-uu-check-for-generated-files)))
2197 ;; Interactive exec mode
2199 (defvar gnus-uu-output-window nil
)
2200 (defvar gnus-uu-mode-hook nil
)
2201 (defvar gnus-uu-mode-map nil
)
2203 (defun gnus-uu-do-interactive ()
2204 (let (int-buffer out-buf
)
2206 (setq int-buffer
(get-buffer gnus-uu-interactive-buffer-name
)))
2207 (switch-to-buffer-other-window int-buffer
)
2208 (pop-to-buffer int-buffer
)
2209 (setq gnus-uu-output-window
2210 (split-window nil
(- (window-height) gnus-uu-output-window-height
)))
2211 (set-window-buffer gnus-uu-output-window
2213 (get-buffer-create gnus-uu-output-buffer-name
)))
2214 (save-excursion (set-buffer out-buf
) (erase-buffer))
2217 (run-hooks 'gnus-uu-mode-hook
)))
2220 (defun gnus-uu-enter-interactive-file (action file
)
2223 (setq gnus-uu-interactive-file-list
2224 (cons file gnus-uu-interactive-file-list
))
2225 (set-buffer (get-buffer gnus-uu-interactive-buffer-name
))
2226 (setq command
(gnus-uu-command action file
))
2227 (insert (format "%s\n" command
)))))
2230 (defun gnus-uu-interactive-execute ()
2231 "Executes the command on the current line in interactive mode."
2233 (let (beg out-buf command
)
2237 (setq command
(buffer-substring beg
(point)))
2238 (setq out-buf
(get-buffer-create gnus-uu-output-buffer-name
))
2240 (set-buffer out-buf
)
2242 (insert (format "$ %s \n\n" command
)))
2243 (message "Executing...")
2244 (if gnus-uu-asynchronous
2245 (start-process "gnus-uu-view" out-buf
"sh" "-c" command
)
2246 (call-process "sh" nil out-buf nil
"-c" command
)
2249 (beginning-of-line)))
2252 (defun gnus-uu-interactive-end ()
2253 "This function exits interactive view mode and returns to summary mode."
2256 (delete-window gnus-uu-output-window
)
2258 (if (not gnus-uu-asynchronous
) (gnus-uu-check-for-generated-files))
2259 (setq buf
(get-buffer gnus-uu-interactive-buffer-name
))
2260 (if gnus-article-buffer
(switch-to-buffer gnus-article-buffer
))
2261 (if buf
(kill-buffer buf
))
2262 (pop-to-buffer gnus-summary-buffer
)))
2265 (if gnus-uu-mode-map
2267 (setq gnus-uu-mode-map
(make-sparse-keymap))
2268 (define-key gnus-uu-mode-map
"\C-c\C-x" 'gnus-uu-interactive-execute
)
2269 (define-key gnus-uu-mode-map
"\C-c\C-v" 'gnus-uu-interactive-execute
)
2270 (define-key gnus-uu-mode-map
"\C-m" 'gnus-uu-interactive-execute
)
2271 (define-key gnus-uu-mode-map
"\C-c\C-c" 'gnus-uu-interactive-end
)
2272 (define-key gnus-uu-mode-map
"\C-cs"
2273 'gnus-uu-interactive-save-current-file
)
2274 (define-key gnus-uu-mode-map
"\C-c\C-s"
2275 'gnus-uu-interactive-save-current-file-silent
)
2276 (define-key gnus-uu-mode-map
"\C-c\C-w" 'gnus-uu-interactive-save-all-files
)
2277 (define-key gnus-uu-mode-map
"\C-c\C-o" 'gnus-uu-interactive-save-original-file
))
2280 (defun gnus-uu-interactive-save-original-file ()
2281 "Saves the file from whence the file on the current line came from."
2285 (setq file
(concat gnus-uu-tmp-dir
2286 (or gnus-uu-file-name gnus-uu-shar-file-name
))))
2287 (gnus-uu-save-file file
)
2288 (message "Already saved."))))
2291 (defun gnus-uu-interactive-save-current-file-silent ()
2292 "Saves the file referred to on the current line in the current directory."
2294 (gnus-uu-interactive-save-current-file t
))
2296 (defun gnus-uu-interactive-save-current-file (&optional dont-ask silent
)
2297 "Saves the file referred to on the current line."
2299 (let (files beg line file
)
2300 (setq files
(copy-sequence gnus-uu-interactive-file-list
))
2304 (setq line
(buffer-substring beg
(point)))
2307 (concat "" (regexp-quote (setq file
(car files
))) "")
2309 (setq files
(cdr files
)))
2314 (progn (message "Could not find file") (sit-for 2)))
2315 (gnus-uu-save-file file
(if dont-ask gnus-uu-current-save-dir nil
) silent
)
2316 (delete-region beg
(point)))))
2319 (defun gnus-uu-interactive-save-all-files ()
2320 "Saves all files referred to in the interactive buffer."
2324 (setq dir
(gnus-uu-read-directory "Where do you want the files? "))
2326 (gnus-uu-interactive-save-current-file t t
))))
2328 (defun gnus-uu-mode ()
2329 "Major mode for editing view commands in gnus-uu.
2332 \\<gnus-uu-mode-map>Return, C-c C-v, C-c C-x Execute the current command
2333 \\[gnus-uu-interactive-end] End interactive mode
2334 \\[gnus-uu-interactive-save-current-file] Save the current file
2335 \\[gnus-uu-interactive-save-current-file-silent] Save the current file without asking
2337 \\[gnus-uu-interactive-save-all-files] Save all files
2338 \\[gnus-uu-interactive-save-original-file] Save the original file: If the files
2339 originated in an archive, the archive
2343 (kill-all-local-variables)
2344 (use-local-map gnus-uu-mode-map
)
2345 (setq mode-name
"gnus-uu")
2346 (setq major-mode
'gnus-uu-mode
)
2349 (define-key gnus-uu-mode-map
"\C-c\C-x" 'gnus-uu-interactive-execute
)
2350 (define-key gnus-uu-mode-map
"\C-c\C-v" 'gnus-uu-interactive-execute
)
2351 (define-key gnus-uu-mode-map
"\C-m" 'gnus-uu-interactive-execute
)
2352 (define-key gnus-uu-mode-map
"\C-c\C-c" 'gnus-uu-interactive-end
)
2353 (define-key gnus-uu-mode-map
"\C-cs"
2354 'gnus-uu-interactive-save-current-file
)
2355 (define-key gnus-uu-mode-map
"\C-c\C-s"
2356 'gnus-uu-interactive-save-current-file-silent
)
2357 (define-key gnus-uu-mode-map
"\C-c\C-a" 'gnus-uu-interactive-save-all-files
)
2358 (define-key gnus-uu-mode-map
"\C-c\C-o" 'gnus-uu-interactive-save-original-file
)
2362 ;; gnus-uu.el ends here