From f1206324939866662415ab655e7c134369f46c63 Mon Sep 17 00:00:00 2001 From: yamaoka Date: Tue, 21 Jan 2003 06:21:45 +0000 Subject: [PATCH] Import Oort Gnus v0.13. --- ChangeLog | 18 + GNUS-NEWS | 55 ++- lisp/ChangeLog | 263 ++++++++++++++ lisp/deuglify.el | 43 +-- lisp/gnus-agent.el | 74 ++-- lisp/gnus-art.el | 31 +- lisp/gnus-audio.el | 6 +- lisp/gnus-ems.el | 6 +- lisp/gnus-fun.el | 34 +- lisp/gnus-group.el | 77 ++-- lisp/gnus-int.el | 20 +- lisp/gnus-msg.el | 4 +- lisp/gnus-score.el | 14 + lisp/gnus-sum.el | 976 +++++++++++++++++++++++++------------------------- lisp/gnus-win.el | 2 +- lisp/gnus-xmas.el | 3 +- lisp/gnus.el | 271 +++++++------- lisp/mailcap.el | 55 +-- lisp/message.el | 33 +- lisp/messagexmas.el | 5 +- lisp/nnfolder.el | 2 +- lisp/nnheader.el | 6 +- lisp/nnimap.el | 17 +- lisp/nnmail.el | 8 +- lisp/nnsoup.el | 2 +- lisp/nnspool.el | 2 +- lisp/spam.el | 370 ++++++------------- make-x.bat | 28 +- make.bat | 27 +- texi/ChangeLog | 81 +++++ texi/dir | 1 + texi/emacs-mime.texi | 16 +- texi/gnus.texi | 377 ++++++++++++------- texi/message.texi | 22 +- 34 files changed, 1782 insertions(+), 1167 deletions(-) diff --git a/ChangeLog b/ChangeLog index ceccd8c..3b79a97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2003-01-15 Simon Josefsson + + * GNUS-NEWS: Add. Fix from Reiner Steib + <4uce.02.r.steib@gmx.net>. + +2003-01-10 Reiner Steib + + * make.bat: Removed "-no-init-file" (it's the same as "-q"). Use + new variables EMACSBATCH and GNUS_INFO_DIR. Install gnus-?, + message-?, sieve and pgg (in texi). Added hint for dir entries. + + * make-x.bat: Ditto. + +2003-01-13 Simon Josefsson + + * GNUS-NEWS: Add smileys, Sender:, message-utils. + Expand anti-spam. Fixes. + 2003-01-09 Simon Josefsson * etc/gnus/preview.xpm: Add. diff --git a/GNUS-NEWS b/GNUS-NEWS index 4a963c3..7206c50 100644 --- a/GNUS-NEWS +++ b/GNUS-NEWS @@ -8,10 +8,55 @@ For older news, see Gnus info node "New Features". * Changes in Oort Gnus +** The new variable `gnus-parameters' can be used to set group parameters. + +Earlier this was done only via `G p' (or `G c'), which stored the +parameters in ~/.newsrc.eld, but via this variable you can enjoy the +powers of customize, and simplified backups since you set the variable +in ~/.emacs instead of ~/.newsrc.eld. The variable maps regular +expressions matching group names to group parameters, a'la: + + (setq gnus-parameters + '(("mail\\..*" + (gnus-show-threads nil) + (gnus-use-scoring nil)) + ("^nnimap:\\(foo.bar\\)$" + (to-group . "\\1")))) + +** Smileys (":-)", ";-)" etc) are now iconized for Emacs too. + +Put (setq gnus-treat-display-smileys nil) in ~/.emacs to disable it. + +** Gnus no longer generate the Sender: header automatically. + +Earlier it was generated iff the user configurable email address was +different from the Gnus guessed default user address. As the guessing +algorithm is rarely correct these days, and (more controversally) the +only use of the Sender: header was to check if you are entitled to +cancel/supersede news (which is now solved by Cancel Locks instead, +see another entry), generation of the header has been disabled by +default. See the variables `message-required-headers', +`message-required-news-headers', and `message-required-mail-headers'. + +** Features from third party message-utils.el added to message.el. + +Message now asks if you wish to remove "(was: )" from +subject lines (see `message-subject-trailing-was-query'). C-c M-m and +C-c M-f inserts markers indicating included text. C-c C-f a adds a +X-No-Archive: header. C-c C-f x inserts appropriate headers and a +note in the body for cross-postings and followups (see the variables +`message-cross-post-*'). + ** References and X-Draft-Headers are no longer generated when you start composing messages. -** Improved anti-speam features. +** Improved anti-spam features. + +Gnus is now able to take out spam from your mail and news streams +using a wide variety of programs and filter rules. Among the supported +methods are RBL blocklists, bogofilter and white/blacklists. Hooks +for easy use of external packages such as SpamAssassin and Hashcash +are also new. ** Easy inclusion of X-Faces headers. @@ -127,7 +172,7 @@ Add a new format of match like ((header "to" "larsi.*org") (Organization "Somewhere, Inc.")) -The old format like the lines below is obsolete. +The old format like the lines below is obsolete, but still accepted. (header "to" "larsi.*org" (Organization "Somewhere, Inc.")) @@ -215,10 +260,10 @@ the .marks or .mrk file instead of the information in .newsrc.eld. The new server variables `nnml-marks-is-evil' and `nnfolder-marks-is-evil' can be used to disable this feature. -** The menu bar (in Group and Summary buffer) named "Misc" has been -renamed to "Gnus". +** The menu bar item (in Group and Summary buffer) named "Misc" has +been renamed to "Gnus". -** The menu bar (in Message mode) named "MML" has been renamed to +** The menu bar item (in Message mode) named "MML" has been renamed to "Attachments". ** gnus-group-charset-alist and gnus-group-ignored-charsets-alist. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4f86b0f..84f6e5f 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,266 @@ +2003-01-21 07:15:41 Lars Magne Ingebrigtsen + + * gnus.el: Oort Gnus v0.13 is released. + +2003-01-21 Lars Magne Ingebrigtsen + + * gnus-art.el (gnus-button-url-regexp): Removed |. + + * message.el (message-send-hook): Doc fix. + + * gnus-win.el (gnus-buffer-configuration): Display article + instead of article-copy when `reply'. + +2003-01-21 Jesper Harder + + * gnus.el (gnus-format): Change customize group to gnus. + (gnus-cache): Add link. + (gnus-group-charter-alist): Fix docstring. + +2003-01-20 Jesper Harder + + * mailcap.el (mailcap-print-command): lpr-command might be + unbound in XEmacs. + +2002-01-18 Kevin Greiner + + * gnus-agent.el (gnus-agent-regenerate-group): Added interactive form. + + * gnus-sum.el (gnus-summary-update-article-line): Fixed + calculation of net characters added for use in the gnus-data + structure. + +2003-01-18 Kai Gro,A_(Bjohann + + * nnmail.el (nnmail-process-unix-mail-format): Improve error + message. Suggested by Jari Aalto. + +2003-01-17 Lars Magne Ingebrigtsen + + * gnus-art.el (gnus-article-followup-with-original): Clean up. + (gnus-article-reply-with-original): Ditto. + + * gnus-sum.el (gnus-summary-catchup): Make sure downloadable, + read articles don't become unread. + +2003-01-17 Simon Josefsson + + * gnus-fun.el (gnus-x-face-from-file): + (gnus-face-from-file): Suggest image format in minibuffer prompt. + + * gnus-fun.el (gnus-convert-image-to-x-face-command) + (gnus-convert-image-to-face-command): Doc fix. + +2003-01-17 Lars Magne Ingebrigtsen + + * gnus-fun.el (gnus-convert-face-to-png): Protect against errors. + +2003-01-17 Jesper Harder + + * gnus-art.el (gnus-mime-print-part): Use mm-save-part-to-file to + avoid encoding problems. + + * mailcap.el (mailcap-ps-command): New variable. + (mailcap-mime-data): Add print entry where applicable. Use + pdftotext on a tty. + +2003-01-16 ShengHuo ZHU + + * gnus-sum.el (gnus-alter-header-function): Add type and group. + +2003-01-16 Simon Josefsson + + * gnus-fun.el (gnus-convert-image-to-x-face-command) + (gnus-convert-image-to-face-command, gnus-x-face-from-file) + (gnus-face-from-file): Doc fix; don't mention image format. + +2003-01-16 Teodor Zlatanov + + * spam.el (spam-get-article-as-filename): new function (unused for now) + (spam-get-article-as-buffer): new function + (spam-get-article-as-string): use spam-get-article-as-buffer + (spam-summary-prepare-exit): fixed bug, noticed by Malcolm Purvis + +2003-01-15 ShengHuo ZHU + + * gnus-agent.el: Don't use `path'. + From the GNU coding standards: + + Please do not use the term ``pathname'' that is used in Unix + documentation; use ``file name'' (two words) instead. We use + the term ``path'' only for search paths, which are lists of + directory names. + + * nnsoup.el (nnsoup-file-name): Ditto. + + * nnmail.el (nnmail-pathname-coding-system): Ditto. + (nnmail-group-pathname): Ditto. + + * nnimap.el (nnimap-group-overview-filename): Ditto. + + * nnheader.el (nnheader-pathname-coding-system): Ditto. + (nnheader-group-pathname): Ditto. + + * nnfolder.el (nnfolder-group-pathname): Ditto. + + * gnus.el (gnus-home-directory): Ditto. + + * gnus-group.el (gnus-group-icon-list): Ditto. + +2003-01-16 Jesper Harder + + * gnus-art.el (gnus-mime-print-part): Use mm-handle-media-type. + + * message.el (message-mode-menu): Use it. + (message-mode-menu): Deactivate "Yank Original" if there's no + reply buffer. + + * messagexmas.el (message-xmas-redefine): Redefine in XEmacs. + + * message.el (message-mark-active-p): New function. + +2003-01-15 Teodor Zlatanov + + * spam.el (spam-use-bogofilter-headers, spam-bogofilter-header) + (spam-bogofilter-database-directory): new variables + (spam-check-bogofilter-headers, spam-check-bogofilter) + (spam-bogofilter-register-with-bogofilter) + (spam-bogofilter-register-spam-routine) + (spam-bogofilter-register-ham-routine) + (spam-group-ham-processor-bogofilter-p): new functions for the new + Bogofilter interface + (spam-summary-prepare-exit): use the new Bogofilter functions + (spam-list-of-checks): added spam-use-bogofilter-headers + (spam-bogofilter-score): rewrote function + (spam-check-bogofilter): optional score parameter, uses + spam-check-bogofilter-headers better + (spam-check-bogofilter-headers): optional score parameter + + * gnus.el (gnus-install-group-spam-parameters): new variable, t by + default, in the gnus-start customization group. Used to disable + the spam-*/ham-* parameters. + (gnus-group-ham-exit-processor-bogofilter): new ham processor + +2003-01-15 Jesper Harder + + * gnus-xmas.el (gnus-xmas-redefine): Use region-exists-p in + XEmacs. + + * gnus-ems.el (gnus-mark-active-p): do. + +2003-01-15 Kevin Ryde + + * gnus.texi (Using MIME): Mention auto-compression-mode with + gnus-mime-copy-part. + +2003-01-15 Lars Magne Ingebrigtsen + + * message.el (message-send): Don't warn about duplicates when + superseding. + +2003-01-15 Simon Josefsson + + * nnimap.el (nnimap-split-download-body): New variable. + (nnimap-split-articles): Use it. + +2002-01-14 Kevin Greiner + + * gnus-agent.el (gnus-agent-check-overview-buffer): This data + integrity checker was incorrectly flagging, and removing, articles + whose article number was negative. + (gnus-agent-fetch-group-1): When executed in the group's summary + buffer, refresh each downloaded line to update the status flag and + font. Preserve the value of gnus-newsgroup-headers so that + gnus-agent-fetch-articles can split the requests by size. + (gnus-agent-expire): Corrected day calculation for when + gnus-agent-expire-days contains a list. + +2003-01-14 Lars Magne Ingebrigtsen + + * gnus-audio.el (gnus-audio-au-player): Use executable-find. + +2003-01-13 Jhair Tocancipa Triana + + * gnus-audio.el (gnus-audio-au-player, gnus-audio-wav-player): Use + /usr/bin/play as default player. + (gnus-audio-play): Added ARG-DESCRIPTOR to prompt for a file to play. + +2003-01-14 Katsumi Yamaoka + + * gnus-msg.el (gnus-inews-add-send-actions): Allow a list of + articles to be marked as well. + +2002-01-14 Kevin Greiner + * gnus-agent.el (gnus-agent-get-undownloaded-list): Include the + fictious headers generated by nnagent (ie. Undownloaded Article + ####) in the list of articles that have not been downloaded. + + * gnus-int.el (): Added require declarations to resolve + compile-time warnings. + (gnus-open-server): If the server status is set to offline, + recursively execute gnus-open-server to open the offline backend + (e.g. nnagent). + +2003-01-14 Jesper Harder + + * gnus-art.el (gnus-article-reply-with-original): Use + gnus-mark-active-p. + (gnus-article-followup-with-original): do. + +2003-01-13 Reiner Steib + + * gnus-sum.el: Removed `(when t ...)' around `gnus-define-keys'. + +2003-01-13 Reiner Steib + + * gnus-score.el (gnus-score-edit-file-at-point): New function. + (gnus-score-find-trace): Bind it to `e' key. Added `q' for quit. + +2003-01-13 Romain FRANCOISE + + * gnus-fun.el (gnus-x-face-from-file): Quote file name. + (gnus-face-from-file): Ditto. + +2003-01-13 Lars Magne Ingebrigtsen + + * gnus-sum.el (gnus-articles-to-read): Don't just apply + gnus-alter-articles-to-read-function to the unread articles. + +2003-01-13 Reiner Steib + + * deuglify.el (gnus-article-outlook-unwrap-lines) + (gnus-article-outlook-repair-attribution) + (gnus-article-outlook-rearrange-citation): New function names, + renamed from "gnus-outlook-" to "gnus-article-outlook-". Changed + doc-string. + + * gnus-sum.el (gnus-summary-mode-map): Use new function names, + removed `W k' key binding (use `W Y f' instead). + (gnus-summary-make-menu-bar): Use new function names. + +2003-01-13 Simon Josefsson + + * gnus-fun.el (gnus-random-x-face): Doc fix. + (gnus-insert-random-x-face-header): New function. + +2003-01-13 Jesper Harder + + * gnus-sum.el (gnus-summary-make-menu-bar): Deactivate items if + mark is not active. + + * gnus-msg.el (gnus-inews-do-gcc): Comment. + + * gnus-ems.el (gnus-mark-active-p): New function. + + * gnus-group.el (gnus-topic-mode-p): New function. + (gnus-group-make-menu-bar): Show more key bindings in topic mode. + Deactivate items if mark is not active. + +2003-01-12 Lars Magne Ingebrigtsen + + * gnus.el (gnus-version-number): Bumped version. + (gnus-summary-line-format): Doc fix. + 2003-01-12 22:02:49 Lars Magne Ingebrigtsen * gnus.el: Oort Gnus v0.12 is released. diff --git a/lisp/deuglify.el b/lisp/deuglify.el index 915a625..33635de 100644 --- a/lisp/deuglify.el +++ b/lisp/deuglify.el @@ -47,7 +47,7 @@ ;; > verb. This sentence no verb. This sentence no verb. This ;; > sentence no verb. ;; -;; The function `gnus-outlook-unwrap-lines' tries to recognize those +;; The function `gnus-article-outlook-unwrap-lines' tries to recognize those ;; erroneously wrapped lines and will unwrap them. I.e. putting the ;; wrapped parts ("no" in this example) back where they belong (at the ;; end of the cited line above). @@ -70,7 +70,7 @@ ;; ;; Unwrapping "You forgot in all your sentences." would be illegal as ;; this part wasn't intended to be cited text. -;; `gnus-outlook-unwrap-lines' will only unwrap lines if the resulting +;; `gnus-article-outlook-unwrap-lines' will only unwrap lines if the resulting ;; citation line will be of a certain maximum length. You can control ;; this by adjusting `gnus-outlook-deuglify-unwrap-max'. Also ;; unwrapping will only be done if the line above the (possibly) @@ -113,7 +113,7 @@ ;; > Bye, John ;; ;; Repairing the attribution line will be done by function -;; `gnus-outlook-repair-attribution' which calls other function that +;; `gnus-article-outlook-repair-attribution which calls other function that ;; try to recognize and repair broken attribution lines. See variable ;; `gnus-outlook-deuglify-attrib-cut-regexp' for stuff that should be ;; cut off from the beginning of an attribution line and variable @@ -123,8 +123,8 @@ ;; ;; Rearranging the article so that the cited text appears above the ;; new text will be done by function -;; `gnus-outlook-rearrange-citation'. This function calls -;; `gnus-outlook-repair-attribution' to find and repair an attribution +;; `gnus-article-outlook-rearrange-citation'. This function calls +;; `gnus-article-outlook-repair-attribution to find and repair an attribution ;; line. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -158,15 +158,15 @@ ;; To automatically invoke deuglification on every article you read, ;; put something like that in your .gnus: ;; -;; (add-hook 'gnus-article-decode-hook 'gnus-outlook-unwrap-lines) +;; (add-hook 'gnus-article-decode-hook 'gnus-article-outlook-unwrap-lines) ;; ;; or _one_ of the following lines: ;; ;; ;; repair broken attribution lines -;; (add-hook 'gnus-article-decode-hook 'gnus-outlook-repair-attribution) +;; (add-hook 'gnus-article-decode-hook 'gnus-article-outlook-repair-attribution) ;; ;; ;; repair broken attribution lines and citations -;; (add-hook 'gnus-article-decode-hook 'gnus-outlook-rearrange-citation) +;; (add-hook 'gnus-article-decode-hook 'gnus-article-outlook-rearrange-citation) ;; ;; Note that there always may be some false positives, so I suggest ;; using the manual invocation. After deuglification you may want to @@ -178,16 +178,16 @@ ;; ----------- ;; ;; As I said before there may (or will) be a few false positives on -;; unwrapping cited lines with `gnus-outlook-unwrap-lines'. +;; unwrapping cited lines with `gnus-article-outlook-unwrap-lines'. ;; -;; `gnus-outlook-repair-attribution' will only fix the first +;; `gnus-article-outlook-repair-attribution will only fix the first ;; attribution line found in the article. Furthermore it fixed to ;; certain kinds of attributions. And there may be horribly many ;; false positives, vanishing lines and so on -- so don't trust your ;; eyes. Again I recommend manual invocation. ;; -;; `gnus-outlook-rearrange-citation' carries all the limitations of -;; `gnus-outlook-repair-attribution'. +;; `gnus-article-outlook-rearrange-citation' carries all the limitations of +;; `gnus-article-outlook-repair-attribution. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -299,7 +299,7 @@ It is run after `gnus-article-prepare-hook'." 'gnus-outlook-display-hook))) ;;;###autoload -(defun gnus-outlook-unwrap-lines (&optional nodisplay) +(defun gnus-article-outlook-unwrap-lines (&optional nodisplay) "Unwrap lines that appear to be wrapped citation lines. You can control what lines will be unwrapped by frobbing `gnus-outlook-deuglify-unwrap-min' and `gnus-outlook-deuglify-unwrap-max', @@ -419,7 +419,7 @@ NODISPLAY is non-nil, don't redisplay the article buffer." (match-beginning 0))))))) ;;;###autoload -(defun gnus-outlook-repair-attribution (&optional nodisplay) +(defun gnus-article-outlook-repair-attribution (&optional nodisplay) "Repair a broken attribution line. If NODISPLAY is non-nil, don't redisplay the article buffer." (interactive "P") @@ -431,11 +431,11 @@ If NODISPLAY is non-nil, don't redisplay the article buffer." (unless nodisplay (gnus-outlook-display-article-buffer)) attrib-start)) -(defun gnus-outlook-rearrange-citation (&optional nodisplay) +(defun gnus-article-outlook-rearrange-citation (&optional nodisplay) "Repair broken citations. If NODISPLAY is non-nil, don't redisplay the article buffer." (interactive "P") - (let ((attrib-start (gnus-outlook-repair-attribution 'nodisplay))) + (let ((attrib-start (gnus-article-outlook-repair-attribution 'nodisplay))) ;; rearrange citations if an attribution line has been recognized (if attrib-start (gnus-outlook-rearrange-article attrib-start))) @@ -443,15 +443,16 @@ If NODISPLAY is non-nil, don't redisplay the article buffer." ;;;###autoload (defun gnus-outlook-deuglify-article (&optional nodisplay) - "Deuglify broken Outlook (Express) articles. -If NODISPLAY is non-nil, don't redisplay the article buffer." + "Full deuglify of broken Outlook (Express) articles. +Treat dumbquotes, unwrap lines, repair attribution and rearrange citation. If +NODISPLAY is non-nil, don't redisplay the article buffer." (interactive "P") ;; apply treatment of dumb quotes (gnus-article-treat-dumbquotes) ;; repair wrapped cited lines - (gnus-outlook-unwrap-lines 'nodisplay) - ;; repair attribution line - (gnus-outlook-rearrange-citation 'nodisplay) + (gnus-article-outlook-unwrap-lines 'nodisplay) + ;; repair attribution line and rearrange citation. + (gnus-article-outlook-rearrange-citation 'nodisplay) (unless nodisplay (gnus-outlook-display-article-buffer))) ;;;###autoload diff --git a/lisp/gnus-agent.el b/lisp/gnus-agent.el index f4f3cca..2f773f3 100644 --- a/lisp/gnus-agent.el +++ b/lisp/gnus-agent.el @@ -234,12 +234,12 @@ node `(gnus)Server Buffer'.") (cadr gnus-command-method)))) (defsubst gnus-agent-directory () - "Path of the Gnus agent directory." + "The name of the Gnus agent directory." (nnheader-concat gnus-agent-directory (nnheader-translate-file-chars (gnus-agent-method)) "/")) (defun gnus-agent-lib-file (file) - "The full path of the Gnus agent library FILE." + "The full name of the Gnus agent library FILE." (expand-file-name file (file-name-as-directory (expand-file-name "agent.lib" (gnus-agent-directory))))) @@ -757,7 +757,11 @@ article's mark is toggled." (cond ((< a h) (pop alist)) ; ignore IDs in the alist that are not being displayed in the summary ((> a h) - (pop headers)) ; ignore headers that are not in the alist as these should be fictious (see nnagent-retrieve-headers). + ;; headers that are not in the alist should be + ;; fictious (see nnagent-retrieve-headers); they + ;; imply that this article isn't in the agent. + (gnus-agent-append-to-list tail h) + (pop headers)) ((cdar alist) (pop alist) (pop headers) @@ -767,6 +771,9 @@ article's mark is toggled." (pop alist) (pop headers) (gnus-agent-append-to-list tail a))))) + + (while headers + (gnus-agent-append-to-list tail (mail-header-number (pop headers)))) (setq gnus-newsgroup-undownloaded (cdr undownloaded)))))) (defun gnus-agent-catchup () @@ -926,7 +933,7 @@ This can be added to `gnus-select-article-hook' or (delete-char 1)))))) (defun gnus-agent-group-path (group) - "Translate GROUP into a path." + "Translate GROUP into a file name." (if nnmail-use-long-file-names (gnus-group-real-name group) (nnheader-translate-file-chars @@ -1167,18 +1174,13 @@ and that there are no duplicates." (gnus-message 1 "Duplicate overview line for %d" cur) (delete-region (point) (progn (forward-line 1) (point)))) - ((< cur 0) + ((< cur prev-num) (or backed-up (setq backed-up (gnus-agent-backup-overview-buffer))) - (gnus-message 1 "Junk article number %d" cur) - (delete-region (point) (progn (forward-line 1) (point)))) - ((< cur prev-num) + (gnus-message 1 "Overview buffer not sorted!") (sort-numeric-fields 1 (point-min) (point-max)) (goto-char (point-min)) - (setq prev-num -1) - (or backed-up - (setq backed-up (gnus-agent-backup-overview-buffer))) - (gnus-message 1 "Overview buffer not sorted!")) + (setq prev-num -1)) (t (setq prev-num cur))) (forward-line 1))))))) @@ -1577,7 +1579,6 @@ of FILE placing the combined headers in nntp-server-buffer." (setq gnus-newsgroup-dependencies (or gnus-newsgroup-dependencies (make-vector (length articles) 0))) - (setq gnus-newsgroup-headers (or gnus-newsgroup-headers (gnus-get-newsgroup-headers-xover articles nil nil @@ -1615,7 +1616,8 @@ of FILE placing the combined headers in nntp-server-buffer." (let ((arts (list nil))) (let ((arts-tail arts) (alist (gnus-agent-load-alist group)) - (marked-articles marked-articles)) + (marked-articles marked-articles) + (gnus-newsgroup-headers gnus-newsgroup-headers)) (while (setq gnus-headers (pop gnus-newsgroup-headers)) (let ((num (mail-header-number gnus-headers))) ;; Determine if this article is already in the cache @@ -1649,15 +1651,21 @@ of FILE placing the combined headers in nntp-server-buffer." (let ((unfetched-articles (gnus-sorted-ndifference (cdr arts) fetched-articles))) (if gnus-newsgroup-active + ;; Update the summary buffer (progn (dolist (article marked-articles) (when (gnus-summary-goto-subject article nil t) (gnus-summary-set-agent-mark article t))) (dolist (article fetched-articles) (if gnus-agent-mark-unread-after-downloaded - (gnus-summary-mark-article article gnus-unread-mark))) + (gnus-summary-mark-article article gnus-unread-mark)) + (when (gnus-summary-goto-subject article nil t) + (gnus-summary-update-download-mark article))) (dolist (article unfetched-articles) (gnus-summary-mark-article article gnus-canceled-mark))) + + ;; Update the group buffer. + ;; When some, or all, of the marked articles came ;; from the download mark. Remove that mark. I ;; didn't do this earlier as I only want to remove @@ -2078,7 +2086,20 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)." (gnus-agent-directory) (gnus-agent-group-path expiring-group) "/")) (active - (gnus-gethash-safe expiring-group orig))) + (gnus-gethash-safe expiring-group orig)) + (day (if (numberp day) + day + (let (found + (days gnus-agent-expire-days)) + (catch 'found + (while (and (not found) + days) + (when (eq 0 (string-match (caar days) expiring-group)) + (throw 'found (- (time-to-days (current-time)) (cadar days)))) + (pop days)) + ;; No regexp matched so set a limit that will block expiration in this group + 0))))) + (when active (gnus-agent-load-alist expiring-group) (gnus-message 5 "Expiring articles in %s" expiring-group) @@ -2232,17 +2253,7 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)." ;; We now have the arrival day, so we see ;; whether it's old enough to be expired. - ((< fetch-date - (if (numberp day) - day - (let (found - (days gnus-agent-expire-days)) - (while (and (not found) - days) - (when (eq 0 (string-match (caar days) expiring-group)) - (setq found (cadar days))) - (pop days)) - found))) + ((< fetch-date day) 'expired) (force 'forced))) @@ -2493,6 +2504,15 @@ FORCE is equivalent to setting gnus-agent-expire-days to zero(0)." (defun gnus-agent-regenerate-group (group &optional reread) "Regenerate GROUP. If REREAD is t, all articles in the .overview are marked as unread. If REREAD is not nil, downloaded articles are marked as unread." + (interactive (list (let ((def (or (gnus-group-group-name) + gnus-newsgroup-name))) + (let ((select (read-string (if def (concat "Group Name (" def "): ") + "Group Name: ")))) + (if (and (equal "" select) + def) + def + select))) + (intern-soft (read-string "Reread (nil)? (t=>all, nil=>none, some=>all downloaded): ")))) (gnus-message 5 "Regenerating in %s" group) (let* ((gnus-command-method (or gnus-command-method (gnus-find-method-for-group group))) diff --git a/lisp/gnus-art.el b/lisp/gnus-art.el index 9c53e8b..04f524b 100644 --- a/lisp/gnus-art.el +++ b/lisp/gnus-art.el @@ -3986,7 +3986,9 @@ The uncompress method used is derived from `buffer-file-name'." (jka-compr-delete-temp-file err-file))))))) (defun gnus-mime-copy-part (&optional handle) - "Put the MIME part under point into a new buffer." + "Put the MIME part under point into a new buffer. +If `auto-compression-mode' is enabled, compressed files like .gz and .bz2 +are decompressed." (interactive) (gnus-article-check-buffer) (let* ((handle (or handle (get-text-property (point) 'gnus-data))) @@ -4018,13 +4020,12 @@ The uncompress method used is derived from `buffer-file-name'." (let* ((handle (or handle (get-text-property (point) 'gnus-data))) (contents (and handle (mm-get-part handle))) (file (mm-make-temp-file (expand-file-name "mm." mm-tmp-directory))) - (printer (mailcap-mime-info (mm-handle-type handle) "print"))) + (printer (mailcap-mime-info (mm-handle-media-type handle) "print"))) (when contents (if printer (unwind-protect (progn - (with-temp-file file - (insert contents)) + (mm-save-part-to-file handle file) (call-process shell-file-name nil (generate-new-buffer " *mm*") nil @@ -4996,36 +4997,38 @@ Argument LINES specifies lines to be scrolled down." The text in the region will be yanked. If the region isn't active, the entire article will be yanked." (interactive "P") - (let ((article (cdr gnus-article-current)) cont) - (if (not (mark t)) + (let ((article (cdr gnus-article-current)) + contents) + (if (not (gnus-mark-active-p)) (with-current-buffer gnus-summary-buffer (gnus-summary-reply (list (list article)) wide)) - (setq cont (buffer-substring (point) (mark t))) + (setq contents (buffer-substring (point) (mark t))) ;; Deactivate active regions. (when (and (boundp 'transient-mark-mode) transient-mark-mode) (setq mark-active nil)) (with-current-buffer gnus-summary-buffer (gnus-summary-reply - (list (list article cont)) wide))))) + (list (list article contents)) wide))))) (defun gnus-article-followup-with-original () "Compose a followup to the current article. The text in the region will be yanked. If the region isn't active, the entire article will be yanked." (interactive) - (let ((article (cdr gnus-article-current)) cont) - (if (not (mark t)) + (let ((article (cdr gnus-article-current)) + contents) + (if (not (gnus-mark-active-p)) (with-current-buffer gnus-summary-buffer (gnus-summary-followup (list (list article)))) - (setq cont (buffer-substring (point) (mark t))) + (setq contents (buffer-substring (point) (mark t))) ;; Deactivate active regions. (when (and (boundp 'transient-mark-mode) transient-mark-mode) (setq mark-active nil)) (with-current-buffer gnus-summary-buffer (gnus-summary-followup - (list (list article cont))))))) + (list (list article contents))))))) (defun gnus-article-hide (&optional arg force) "Hide all the gruft in the current article. @@ -5429,8 +5432,8 @@ groups." (defcustom gnus-button-url-regexp (if (string-match "[[:digit:]]" "1") ;; support POSIX? - "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)\\(//[-a-z0-9_.]+:[0-9]*\\)?[-a-z0-9_=!?#$@~`%&*+|\\/:;.,[:word:]]+[-a-z0-9_=#$@~`%&*+|\\/[:word:]]\\)" - "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)\\(//[-a-z0-9_.]+:[0-9]*\\)?\\([-a-z0-9_=!?#$@~`%&*+|\\/:;.,]\\|\\w\\)+\\([-a-z0-9_=#$@~`%&*+|\\/]\\|\\w\\)\\)") + "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)\\(//[-a-z0-9_.]+:[0-9]*\\)?[-a-z0-9_=!?#$@~`%&*+\\/:;.,[:word:]]+[-a-z0-9_=#$@~`%&*+\\/[:word:]]\\)" + "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)\\(//[-a-z0-9_.]+:[0-9]*\\)?\\([-a-z0-9_=!?#$@~`%&*+\\/:;.,]\\|\\w\\)+\\([-a-z0-9_=#$@~`%&*+\\/]\\|\\w\\)\\)") "Regular expression that matches URLs." :group 'gnus-article-buttons :type 'regexp) diff --git a/lisp/gnus-audio.el b/lisp/gnus-audio.el index 8906745..af10d58 100644 --- a/lisp/gnus-audio.el +++ b/lisp/gnus-audio.el @@ -47,12 +47,12 @@ :type '(choice directory (const nil)) :group 'gnus-audio) -(defcustom gnus-audio-au-player "/usr/bin/showaudio" +(defcustom gnus-audio-au-player (executable-find "play") "Executable program for playing sun AU format sound files." :group 'gnus-audio :type 'string) -(defcustom gnus-audio-wav-player "/usr/local/bin/play" +(defcustom gnus-audio-wav-player (executable-find "play") "Executable program for playing WAV files." :group 'gnus-audio :type 'string) @@ -93,7 +93,7 @@ ;;;###autoload (defun gnus-audio-play (file) "Play a sound FILE through the speaker." - (interactive) + (interactive "fSound file name: ") (let ((sound-file (if (file-exists-p file) file (expand-file-name file gnus-audio-directory)))) diff --git a/lisp/gnus-ems.el b/lisp/gnus-ems.el index fb4107e..58e5cbb 100644 --- a/lisp/gnus-ems.el +++ b/lisp/gnus-ems.el @@ -1,5 +1,5 @@ ;;; gnus-ems.el --- functions for making Gnus work under different Emacsen -;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 ;; Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen @@ -148,6 +148,10 @@ (boundp 'mark-active) mark-active)) +(defun gnus-mark-active-p () + "Non-nil means the mark and region are currently active in this buffer." + mark-active) ; aliased to region-exists-p in XEmacs. + (if (fboundp 'add-minor-mode) (defalias 'gnus-add-minor-mode 'add-minor-mode) (defun gnus-add-minor-mode (mode name map &rest rest) diff --git a/lisp/gnus-fun.el b/lisp/gnus-fun.el index 5e9d79a..b2cf411 100644 --- a/lisp/gnus-fun.el +++ b/lisp/gnus-fun.el @@ -36,12 +36,16 @@ :type 'string) (defcustom gnus-convert-image-to-x-face-command "giftopnm %s | ppmnorm | pnmscale -width 48 -height 48 | ppmtopgm | pgmtopbm | pbmtoxbm | compface" - "Command for converting a GIF to an X-Face." + "Command for converting an image to an X-Face. +By default it takes a GIF filename and output the X-Face header data +on stdout." :group 'gnus-fun :type 'string) (defcustom gnus-convert-image-to-face-command "djpeg %s | ppmnorm | pnmscale -width 48 -height 48 | ppmquant %d | pnmtopng" - "Command for converting a GIF to an X-Face." + "Command for converting an image to an Face. +By default it takes a JPEG filename and output the Face header data +on stdout." :group 'gnus-fun :type 'string) @@ -60,7 +64,7 @@ Output to the current buffer, replace text, and don't mingle error." ;;;###autoload (defun gnus-random-x-face () - "Insert a random X-Face header from `gnus-x-face-directory'." + "Return X-Face header data chosen randomly from `gnus-x-face-directory'." (interactive) (when (file-exists-p gnus-x-face-directory) (let* ((files (directory-files gnus-x-face-directory t "\\.pbm$")) @@ -71,18 +75,31 @@ Output to the current buffer, replace text, and don't mingle error." (shell-quote-argument file))))))) ;;;###autoload +(defun gnus-insert-random-x-face-header () + "Insert a random X-Face header from `gnus-x-face-directory'." + (interactive) + (let ((data (gnus-random-x-face))) + (save-excursion + (message-goto-eoh) + (if data + (insert "X-Face: " data) + (message + "No face returned by `gnus-random-x-face'. Does %s/*.pbm exist?" + gnus-x-face-directory))))) + +;;;###autoload (defun gnus-x-face-from-file (file) "Insert an X-Face header based on an image file." - (interactive "fImage file name:" ) + (interactive "fImage file name (by default GIF): ") (when (file-exists-p file) (gnus-shell-command-to-string (format gnus-convert-image-to-x-face-command - (shell-quote-argument file))))) + (shell-quote-argument (expand-file-name file)))))) ;;;###autoload (defun gnus-face-from-file (file) "Return an Face header based on an image file." - (interactive "fImage file name:" ) + (interactive "fImage file name (by default JPEG): ") (when (file-exists-p file) (let ((done nil) (attempt "") @@ -93,7 +110,7 @@ Output to the current buffer, replace text, and don't mingle error." (setq attempt (gnus-shell-command-to-string (format gnus-convert-image-to-face-command - (shell-quote-argument file) + (shell-quote-argument (expand-file-name file)) quant))) (if (> (length attempt) 740) (progn @@ -121,7 +138,8 @@ Output to the current buffer, replace text, and don't mingle error." (defun gnus-convert-face-to-png (face) (mm-with-unibyte-buffer (insert face) - (base64-decode-region (point-min) (point-max)) + (ignore-errors + (base64-decode-region (point-min) (point-max))) (buffer-string))) (defun gnus-convert-image-to-gray-x-face (file depth) diff --git a/lisp/gnus-group.el b/lisp/gnus-group.el index bbfe4db..2cca870 100644 --- a/lisp/gnus-group.el +++ b/lisp/gnus-group.el @@ -388,7 +388,7 @@ particular group line should be displayed, each form is evaluated. The icon from the file field after the first true form is used. You can change how those group lines are displayed by editing the file field. The File will either be found in the -`gnus-group-glyph-directory' or by designating absolute path to the +`gnus-group-glyph-directory' or by designating absolute name of the file. It is also possible to change and add form fields, but currently that @@ -726,6 +726,11 @@ simple manner.") "\C-k" gnus-group-kill-level "z" gnus-group-kill-all-zombies)) +(defun gnus-topic-mode-p () + "Return non-nil in `gnus-topic-mode'." + (and (boundp 'gnus-topic-mode) + gnus-topic-mode)) + (defun gnus-group-make-menu-bar () (gnus-turn-off-edit-menu 'group) (unless (boundp 'gnus-group-reading-menu) @@ -733,19 +738,38 @@ simple manner.") (easy-menu-define gnus-group-reading-menu gnus-group-mode-map "" `("Group" - ["Read" gnus-group-read-group (gnus-group-group-name)] - ["Select" gnus-group-select-group (gnus-group-group-name)] + ["Read" gnus-group-read-group + :included (not (gnus-topic-mode-p)) + :active (gnus-group-group-name)] + ["Read " gnus-topic-read-group + :included (gnus-topic-mode-p)] + ["Select" gnus-group-select-group + :included (not (gnus-topic-mode-p)) + :active (gnus-group-group-name)] + ["Select " gnus-topic-select-group + :included (gnus-topic-mode-p)] ["See old articles" (gnus-group-select-group 'all) :keys "C-u SPC" :active (gnus-group-group-name)] - ["Catch up" gnus-group-catchup-current :active (gnus-group-group-name) + ["Catch up" gnus-group-catchup-current + :included (not (gnus-topic-mode-p)) + :active (gnus-group-group-name) ,@(if (featurep 'xemacs) nil '(:help "Mark unread articles in the current group as read"))] + ["Catch up " gnus-topic-catchup-articles + :included (gnus-topic-mode-p) + ,@(if (featurep 'xemacs) nil + '(:help "Mark unread articles in the current group or topic as read"))] ["Catch up all articles" gnus-group-catchup-current-all (gnus-group-group-name)] ["Check for new articles" gnus-group-get-new-news-this-group + :included (not (gnus-topic-mode-p)) :active (gnus-group-group-name) ,@(if (featurep 'xemacs) nil '(:help "Check for new messages in current group"))] + ["Check for new articles " gnus-topic-get-new-news-this-topic + :included (gnus-topic-mode-p) + ,@(if (featurep 'xemacs) nil + '(:help "Check for new messages in current group or topic"))] ["Toggle subscription" gnus-group-unsubscribe-current-group (gnus-group-group-name)] ["Kill" gnus-group-kill-group :active (gnus-group-group-name) @@ -756,26 +780,34 @@ simple manner.") ,@(if (featurep 'xemacs) nil '(:help "Display description of the current group"))] ["Fetch FAQ" gnus-group-fetch-faq (gnus-group-group-name)] - ["Fetch charter" gnus-group-fetch-charter :active (gnus-group-group-name) + ["Fetch charter" gnus-group-fetch-charter + :active (gnus-group-group-name) ,@(if (featurep 'xemacs) nil '(:help "Display the charter of the current group"))] - ["Fetch control message" gnus-group-fetch-control :active (gnus-group-group-name) + ["Fetch control message" gnus-group-fetch-control + :active (gnus-group-group-name) ,@(if (featurep 'xemacs) nil '(:help "Display the archived control message for the current group"))] ;; Actually one should check, if any of the marked groups gives t for ;; (gnus-check-backend-function 'request-expire-articles ...) - ["Expire articles" gnus-group-expire-articles - (or (and (gnus-group-group-name) - (gnus-check-backend-function - 'request-expire-articles - (gnus-group-group-name))) gnus-group-marked)] + ["Expire articles" gnus-group-expire-articles + :included (not (gnus-topic-mode-p)) + :active (or (and (gnus-group-group-name) + (gnus-check-backend-function + 'request-expire-articles + (gnus-group-group-name))) gnus-group-marked)] + ["Expire articles " gnus-topic-expire-articles + :included (gnus-topic-mode-p)] ["Set group level..." gnus-group-set-current-level (gnus-group-group-name)] ["Select quick" gnus-group-quick-select-group (gnus-group-group-name)] ["Customize" gnus-group-customize (gnus-group-group-name)] ("Edit" ["Parameters" gnus-group-edit-group-parameters - (gnus-group-group-name)] + :included (not (gnus-topic-mode-p)) + :active (gnus-group-group-name)] + ["Parameters " gnus-topic-edit-parameters + :included (gnus-topic-mode-p)] ["Select method" gnus-group-edit-group-method (gnus-group-group-name)] ["Info" gnus-group-edit-group (gnus-group-group-name)] @@ -810,21 +842,21 @@ simple manner.") ["Sort by real name" gnus-group-sort-groups-by-real-name t]) ("Sort process/prefixed" ["Default sort" gnus-group-sort-selected-groups - (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))] + (not (gnus-topic-mode-p))] ["Sort by method" gnus-group-sort-selected-groups-by-method - (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))] + (not (gnus-topic-mode-p))] ["Sort by rank" gnus-group-sort-selected-groups-by-rank - (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))] + (not (gnus-topic-mode-p))] ["Sort by score" gnus-group-sort-selected-groups-by-score - (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))] + (not (gnus-topic-mode-p))] ["Sort by level" gnus-group-sort-selected-groups-by-level - (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))] + (not (gnus-topic-mode-p))] ["Sort by unread" gnus-group-sort-selected-groups-by-unread - (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))] + (not (gnus-topic-mode-p))] ["Sort by name" gnus-group-sort-selected-groups-by-alphabet - (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))] + (not (gnus-topic-mode-p))] ["Sort by real name" gnus-group-sort-selected-groups-by-real-name - (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]) + (not (gnus-topic-mode-p))]) ("Mark" ["Mark group" gnus-group-mark-group (and (gnus-group-group-name) @@ -834,13 +866,14 @@ simple manner.") (memq (gnus-group-group-name) gnus-group-marked))] ["Unmark all" gnus-group-unmark-all-groups gnus-group-marked] ["Mark regexp..." gnus-group-mark-regexp t] - ["Mark region" gnus-group-mark-region t] + ["Mark region" gnus-group-mark-region :active (gnus-mark-active-p)] ["Mark buffer" gnus-group-mark-buffer t] ["Execute command" gnus-group-universal-argument (or gnus-group-marked (gnus-group-group-name))]) ("Subscribe" ["Subscribe to a group..." gnus-group-unsubscribe-group t] - ["Kill all newsgroups in region" gnus-group-kill-region t] + ["Kill all newsgroups in region" gnus-group-kill-region + :active (gnus-mark-active-p)] ["Kill all zombie groups" gnus-group-kill-all-zombies gnus-zombie-list] ["Kill all groups on level..." gnus-group-kill-level t]) diff --git a/lisp/gnus-int.el b/lisp/gnus-int.el index e52bb5e..3536822 100644 --- a/lisp/gnus-int.el +++ b/lisp/gnus-int.el @@ -29,6 +29,11 @@ (eval-when-compile (require 'cl)) (require 'gnus) +(require 'message) +(require 'gnus-range) + +(eval-when-compile + (defun gnus-agent-expire (a b c))) (defcustom gnus-open-server-hook nil "Hook called just before opening connection to the news server." @@ -219,12 +224,21 @@ If it is down, start it up (again)." (format "Unable to open %s:%s, go offline? " (car gnus-command-method) (cadr gnus-command-method))) - 'offline + 'offline 'denied)) 'denied))) ;; Return the result from the "open" call. - (or (eq (cadr elem) 'offline) - result))))) + (cond ((eq (cadr elem) 'offline) + ;; I'm avoiding infinite recursion by binding unopen + ;; status to denied (The logic of this routine + ;; guarantees that I can't get to this point with + ;; unopen status already bound to denied). + (unless (eq gnus-server-unopen-status 'denied) + (let ((gnus-server-unopen-status 'denied)) + (gnus-open-server gnus-command-method))) + t) + (t + result)))))) (defun gnus-close-server (gnus-command-method) "Close the connection to GNUS-COMMAND-METHOD." diff --git a/lisp/gnus-msg.el b/lisp/gnus-msg.el index 5aebc44..286e8f1 100644 --- a/lisp/gnus-msg.el +++ b/lisp/gnus-msg.el @@ -518,7 +518,7 @@ Gcc: header for archiving purposes." `(set-window-configuration ,winconf) 'exit 'postpone 'kill) (let ((to-be-marked (cond (yanked yanked) - (article (list article)) + (article (if (listp article) article (list article))) (t nil)))) (message-add-action `(when (gnus-buffer-exists-p ,buffer) @@ -1639,6 +1639,8 @@ this is a reply." group (gnus-status-message method)) (sit-for 2)) (when (and group-art + ;; FIXME: Should gcc-mark-as-read work when + ;; Gnus is not running? (gnus-alive-p) (or gnus-gcc-mark-as-read gnus-inews-mark-gcc-as-read)) diff --git a/lisp/gnus-score.el b/lisp/gnus-score.el index 9882bad..e1a6120 100644 --- a/lisp/gnus-score.el +++ b/lisp/gnus-score.el @@ -36,6 +36,8 @@ (require 'message) (require 'score-mode) +(autoload 'ffap-string-at-point "ffap") + (defcustom gnus-global-score-files nil "List of global score files and directories. Set this variable if you want to use people's score files. One entry @@ -1101,6 +1103,11 @@ EXTRA is the possible non-standard header." 4 (substitute-command-keys "\\\\[gnus-score-edit-exit] to save edits"))) +(defun gnus-score-edit-file-at-point () + "Edit score file at point. Useful especially after `V t'." + (interactive) + (gnus-score-edit-file (ffap-string-at-point))) + (defun gnus-score-load-file (file) ;; Load score file FILE. Returns a list a retrieved score-alists. (let* ((file (expand-file-name @@ -2343,6 +2350,13 @@ score in `gnus-newsgroup-scored' by SCORE." 1 "No score rules apply to the current article (default score %d)." gnus-summary-default-score) (set-buffer "*Score Trace*") + ;; ToDo: Use a keymap instead? + (local-set-key "q" + (lambda () + (interactive) + (kill-buffer nil) + (gnus-article-show-summary))) + (local-set-key "e" 'gnus-score-edit-file-at-point) (setq truncate-lines t) (while trace (insert (format "%S -> %s\n" (cdar trace) diff --git a/lisp/gnus-sum.el b/lisp/gnus-sum.el index 9ccfe4f..fd2f4fe 100644 --- a/lisp/gnus-sum.el +++ b/lisp/gnus-sum.el @@ -1,5 +1,5 @@ ;;; gnus-sum.el --- summary mode commands for Gnus -;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 +;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 ;; Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen @@ -46,9 +46,9 @@ (autoload 'gnus-article-outlook-deuglify-article "deuglify" "Deuglify broken Outlook (Express) articles and redisplay." t) -(autoload 'gnus-outlook-unwrap-lines "deuglify" nil t) -(autoload 'gnus-outlook-repair-attribution "deuglify" nil t) -(autoload 'gnus-outlook-rearrange-citation "deuglify" nil t) +(autoload 'gnus-article-outlook-unwrap-lines "deuglify" nil t) +(autoload 'gnus-article-outlook-repair-attribution "deuglify" nil t) +(autoload 'gnus-article-outlook-rearrange-citation "deuglify" nil t) (defcustom gnus-kill-summary-on-exit t "*If non-nil, kill the summary buffer when you exit from it. @@ -922,7 +922,10 @@ mark: The articles mark." (defcustom gnus-alter-header-function nil "Function called to allow alteration of article header structures. The function is called with one parameter, the article header vector, -which it may alter in any way.") +which it may alter in any way." + :type '(choice (const :tag "None" nil) + function) + :group 'gnus-summary) (defvar gnus-decode-encoded-word-function 'mail-decode-encoded-word-string "Variable that says which function should be used to decode a string with encoded words.") @@ -1523,444 +1526,442 @@ increase the score of each group you read." (defvar gnus-article-commands-menu) -(when t - ;; Non-orthogonal keys - - (gnus-define-keys gnus-summary-mode-map - " " gnus-summary-next-page - "\177" gnus-summary-prev-page - [delete] gnus-summary-prev-page - [backspace] gnus-summary-prev-page - "\r" gnus-summary-scroll-up - "\M-\r" gnus-summary-scroll-down - "n" gnus-summary-next-unread-article - "p" gnus-summary-prev-unread-article - "N" gnus-summary-next-article - "P" gnus-summary-prev-article - "\M-\C-n" gnus-summary-next-same-subject - "\M-\C-p" gnus-summary-prev-same-subject - "\M-n" gnus-summary-next-unread-subject - "\M-p" gnus-summary-prev-unread-subject - "." gnus-summary-first-unread-article - "," gnus-summary-best-unread-article - "\M-s" gnus-summary-search-article-forward - "\M-r" gnus-summary-search-article-backward - "<" gnus-summary-beginning-of-article - ">" gnus-summary-end-of-article - "j" gnus-summary-goto-article - "^" gnus-summary-refer-parent-article - "\M-^" gnus-summary-refer-article - "u" gnus-summary-tick-article-forward - "!" gnus-summary-tick-article-forward - "U" gnus-summary-tick-article-backward - "d" gnus-summary-mark-as-read-forward - "D" gnus-summary-mark-as-read-backward - "E" gnus-summary-mark-as-expirable - "\M-u" gnus-summary-clear-mark-forward - "\M-U" gnus-summary-clear-mark-backward - "k" gnus-summary-kill-same-subject-and-select - "\C-k" gnus-summary-kill-same-subject - "\M-\C-k" gnus-summary-kill-thread - "\M-\C-l" gnus-summary-lower-thread - "e" gnus-summary-edit-article - "#" gnus-summary-mark-as-processable - "\M-#" gnus-summary-unmark-as-processable - "\M-\C-t" gnus-summary-toggle-threads - "\M-\C-s" gnus-summary-show-thread - "\M-\C-h" gnus-summary-hide-thread - "\M-\C-f" gnus-summary-next-thread - "\M-\C-b" gnus-summary-prev-thread - [(meta down)] gnus-summary-next-thread - [(meta up)] gnus-summary-prev-thread - "\M-\C-u" gnus-summary-up-thread - "\M-\C-d" gnus-summary-down-thread - "&" gnus-summary-execute-command - "c" gnus-summary-catchup-and-exit - "\C-w" gnus-summary-mark-region-as-read - "\C-t" gnus-summary-toggle-truncation - "?" gnus-summary-mark-as-dormant - "\C-c\M-\C-s" gnus-summary-limit-include-expunged - "\C-c\C-s\C-n" gnus-summary-sort-by-number - "\C-c\C-s\C-l" gnus-summary-sort-by-lines - "\C-c\C-s\C-c" gnus-summary-sort-by-chars - "\C-c\C-s\C-a" gnus-summary-sort-by-author - "\C-c\C-s\C-s" gnus-summary-sort-by-subject - "\C-c\C-s\C-d" gnus-summary-sort-by-date - "\C-c\C-s\C-i" gnus-summary-sort-by-score - "\C-c\C-s\C-o" gnus-summary-sort-by-original - "\C-c\C-s\C-r" gnus-summary-sort-by-random - "=" gnus-summary-expand-window - "\C-x\C-s" gnus-summary-reselect-current-group - "\M-g" gnus-summary-rescan-group - "w" gnus-summary-stop-page-breaking - "\C-c\C-r" gnus-summary-caesar-message - "f" gnus-summary-followup - "F" gnus-summary-followup-with-original - "C" gnus-summary-cancel-article - "r" gnus-summary-reply - "R" gnus-summary-reply-with-original - "\C-c\C-f" gnus-summary-mail-forward - "o" gnus-summary-save-article - "\C-o" gnus-summary-save-article-mail - "|" gnus-summary-pipe-output - "\M-k" gnus-summary-edit-local-kill - "\M-K" gnus-summary-edit-global-kill - ;; "V" gnus-version - "\C-c\C-d" gnus-summary-describe-group - "q" gnus-summary-exit - "Q" gnus-summary-exit-no-update - "\C-c\C-i" gnus-info-find-node - gnus-mouse-2 gnus-mouse-pick-article - "m" gnus-summary-mail-other-window - "a" gnus-summary-post-news - "i" gnus-summary-news-other-window - "x" gnus-summary-limit-to-unread - "s" gnus-summary-isearch-article - "t" gnus-summary-toggle-header - "g" gnus-summary-show-article - "l" gnus-summary-goto-last-article - "\C-c\C-v\C-v" gnus-uu-decode-uu-view - "\C-d" gnus-summary-enter-digest-group - "\M-\C-d" gnus-summary-read-document - "\M-\C-e" gnus-summary-edit-parameters - "\M-\C-a" gnus-summary-customize-parameters - "\C-c\C-b" gnus-bug - "*" gnus-cache-enter-article - "\M-*" gnus-cache-remove-article - "\M-&" gnus-summary-universal-argument - "\C-l" gnus-recenter - "I" gnus-summary-increase-score - "L" gnus-summary-lower-score - "\M-i" gnus-symbolic-argument - "h" gnus-summary-select-article-buffer - - "b" gnus-article-view-part - "\M-t" gnus-summary-toggle-display-buttonized - - "V" gnus-summary-score-map - "X" gnus-uu-extract-map - "S" gnus-summary-send-map) - - ;; Sort of orthogonal keymap - (gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map) - "t" gnus-summary-tick-article-forward - "!" gnus-summary-tick-article-forward - "d" gnus-summary-mark-as-read-forward - "r" gnus-summary-mark-as-read-forward - "c" gnus-summary-clear-mark-forward - " " gnus-summary-clear-mark-forward - "e" gnus-summary-mark-as-expirable - "x" gnus-summary-mark-as-expirable - "?" gnus-summary-mark-as-dormant - "b" gnus-summary-set-bookmark - "B" gnus-summary-remove-bookmark - "#" gnus-summary-mark-as-processable - "\M-#" gnus-summary-unmark-as-processable - "S" gnus-summary-limit-include-expunged - "C" gnus-summary-catchup - "H" gnus-summary-catchup-to-here - "h" gnus-summary-catchup-from-here - "\C-c" gnus-summary-catchup-all - "k" gnus-summary-kill-same-subject-and-select - "K" gnus-summary-kill-same-subject - "P" gnus-uu-mark-map) - - (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map) - "c" gnus-summary-clear-above - "u" gnus-summary-tick-above - "m" gnus-summary-mark-above - "k" gnus-summary-kill-below) - - (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map) - "/" gnus-summary-limit-to-subject - "n" gnus-summary-limit-to-articles - "w" gnus-summary-pop-limit - "s" gnus-summary-limit-to-subject - "a" gnus-summary-limit-to-author - "u" gnus-summary-limit-to-unread - "m" gnus-summary-limit-to-marks - "M" gnus-summary-limit-exclude-marks - "v" gnus-summary-limit-to-score - "*" gnus-summary-limit-include-cached - "D" gnus-summary-limit-include-dormant - "T" gnus-summary-limit-include-thread - "d" gnus-summary-limit-exclude-dormant - "t" gnus-summary-limit-to-age - "." gnus-summary-limit-to-unseen - "x" gnus-summary-limit-to-extra - "p" gnus-summary-limit-to-display-predicate - "E" gnus-summary-limit-include-expunged - "c" gnus-summary-limit-exclude-childless-dormant - "C" gnus-summary-limit-mark-excluded-as-read - "o" gnus-summary-insert-old-articles - "N" gnus-summary-insert-new-articles) - - (gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map) - "n" gnus-summary-next-unread-article - "p" gnus-summary-prev-unread-article - "N" gnus-summary-next-article - "P" gnus-summary-prev-article - "\C-n" gnus-summary-next-same-subject - "\C-p" gnus-summary-prev-same-subject - "\M-n" gnus-summary-next-unread-subject - "\M-p" gnus-summary-prev-unread-subject - "f" gnus-summary-first-unread-article - "b" gnus-summary-best-unread-article - "j" gnus-summary-goto-article - "g" gnus-summary-goto-subject - "l" gnus-summary-goto-last-article - "o" gnus-summary-pop-article) - - (gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map) - "k" gnus-summary-kill-thread - "l" gnus-summary-lower-thread - "i" gnus-summary-raise-thread - "T" gnus-summary-toggle-threads - "t" gnus-summary-rethread-current - "^" gnus-summary-reparent-thread - "s" gnus-summary-show-thread - "S" gnus-summary-show-all-threads - "h" gnus-summary-hide-thread - "H" gnus-summary-hide-all-threads - "n" gnus-summary-next-thread - "p" gnus-summary-prev-thread - "u" gnus-summary-up-thread - "o" gnus-summary-top-thread - "d" gnus-summary-down-thread - "#" gnus-uu-mark-thread - "\M-#" gnus-uu-unmark-thread) - - (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map) - "g" gnus-summary-prepare - "c" gnus-summary-insert-cached-articles - "d" gnus-summary-insert-dormant-articles) - - (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map) - "c" gnus-summary-catchup-and-exit - "C" gnus-summary-catchup-all-and-exit - "E" gnus-summary-exit-no-update - "Q" gnus-summary-exit - "Z" gnus-summary-exit - "n" gnus-summary-catchup-and-goto-next-group - "R" gnus-summary-reselect-current-group - "G" gnus-summary-rescan-group - "N" gnus-summary-next-group - "s" gnus-summary-save-newsrc - "P" gnus-summary-prev-group) - - (gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map) - " " gnus-summary-next-page - "n" gnus-summary-next-page - "\177" gnus-summary-prev-page - [delete] gnus-summary-prev-page - "p" gnus-summary-prev-page - "\r" gnus-summary-scroll-up - "\M-\r" gnus-summary-scroll-down - "<" gnus-summary-beginning-of-article - ">" gnus-summary-end-of-article - "b" gnus-summary-beginning-of-article - "e" gnus-summary-end-of-article - "^" gnus-summary-refer-parent-article - "r" gnus-summary-refer-parent-article - "D" gnus-summary-enter-digest-group - "R" gnus-summary-refer-references - "T" gnus-summary-refer-thread - "g" gnus-summary-show-article - "s" gnus-summary-isearch-article - "P" gnus-summary-print-article - "M" gnus-mailing-list-insinuate - "t" gnus-article-babel) - - (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map) - "b" gnus-article-add-buttons - "B" gnus-article-add-buttons-to-head - "o" gnus-article-treat-overstrike - "e" gnus-article-emphasize - "w" gnus-article-fill-cited-article - "Q" gnus-article-fill-long-lines - "C" gnus-article-capitalize-sentences - "c" gnus-article-remove-cr - "q" gnus-article-de-quoted-unreadable - "6" gnus-article-de-base64-unreadable - "Z" gnus-article-decode-HZ - "h" gnus-article-wash-html - "u" gnus-article-unsplit-urls - "s" gnus-summary-force-verify-and-decrypt - "f" gnus-article-display-x-face - "l" gnus-summary-stop-page-breaking - "r" gnus-summary-caesar-message - "m" gnus-summary-morse-message - "t" gnus-summary-toggle-header - "g" gnus-treat-smiley - "v" gnus-summary-verbose-headers - "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive - "p" gnus-article-verify-x-pgp-sig - "d" gnus-article-treat-dumbquotes - "k" gnus-article-outlook-deuglify-article) ;; mnemonic: outloo*k* - - (gnus-define-keys (gnus-summary-wash-deuglify-map "Y" gnus-summary-wash-map) - ;; mnemonic: deuglif*Y* - "u" gnus-outlook-unwrap-lines - "a" gnus-outlook-repair-attribution - "c" gnus-outlook-rearrange-citation - "f" gnus-article-outlook-deuglify-article) ;; mnemonic: full deuglify - - (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map) - "a" gnus-article-hide - "h" gnus-article-hide-headers - "b" gnus-article-hide-boring-headers - "s" gnus-article-hide-signature - "c" gnus-article-hide-citation - "C" gnus-article-hide-citation-in-followups - "l" gnus-article-hide-list-identifiers - "p" gnus-article-hide-pgp - "B" gnus-article-strip-banner - "P" gnus-article-hide-pem - "\C-c" gnus-article-hide-citation-maybe) - - (gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map) - "a" gnus-article-highlight - "h" gnus-article-highlight-headers - "c" gnus-article-highlight-citation - "s" gnus-article-highlight-signature) - - (gnus-define-keys (gnus-summary-wash-header-map "G" gnus-summary-wash-map) - "f" gnus-article-treat-fold-headers - "u" gnus-article-treat-unfold-headers - "n" gnus-article-treat-fold-newsgroups) - - (gnus-define-keys (gnus-summary-wash-display-map "D" gnus-summary-wash-map) - "x" gnus-article-display-x-face - "d" gnus-article-display-face - "s" gnus-treat-smiley - "D" gnus-article-remove-images - "f" gnus-treat-from-picon - "m" gnus-treat-mail-picon - "n" gnus-treat-newsgroups-picon) - - (gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map) - "w" gnus-article-decode-mime-words - "c" gnus-article-decode-charset - "v" gnus-mime-view-all-parts - "b" gnus-article-view-part) - - (gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map) - "z" gnus-article-date-ut - "u" gnus-article-date-ut - "l" gnus-article-date-local - "p" gnus-article-date-english - "e" gnus-article-date-lapsed - "o" gnus-article-date-original - "i" gnus-article-date-iso8601 - "s" gnus-article-date-user) - - (gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map) - "t" gnus-article-remove-trailing-blank-lines - "l" gnus-article-strip-leading-blank-lines - "m" gnus-article-strip-multiple-blank-lines - "a" gnus-article-strip-blank-lines - "A" gnus-article-strip-all-blank-lines - "s" gnus-article-strip-leading-space - "e" gnus-article-strip-trailing-space - "w" gnus-article-remove-leading-whitespace) - - (gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map) - "v" gnus-version - "f" gnus-summary-fetch-faq - "d" gnus-summary-describe-group - "h" gnus-summary-describe-briefly - "i" gnus-info-find-node - "c" gnus-group-fetch-charter - "C" gnus-group-fetch-control) - - (gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map) - "e" gnus-summary-expire-articles - "\M-\C-e" gnus-summary-expire-articles-now - "\177" gnus-summary-delete-article - [delete] gnus-summary-delete-article - [backspace] gnus-summary-delete-article - "m" gnus-summary-move-article - "r" gnus-summary-respool-article - "w" gnus-summary-edit-article - "c" gnus-summary-copy-article - "B" gnus-summary-crosspost-article - "q" gnus-summary-respool-query - "t" gnus-summary-respool-trace - "i" gnus-summary-import-article - "I" gnus-summary-create-article - "p" gnus-summary-article-posted-p) - - (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map) - "o" gnus-summary-save-article - "m" gnus-summary-save-article-mail - "F" gnus-summary-write-article-file - "r" gnus-summary-save-article-rmail - "f" gnus-summary-save-article-file - "b" gnus-summary-save-article-body-file - "h" gnus-summary-save-article-folder - "v" gnus-summary-save-article-vm - "p" gnus-summary-pipe-output - "P" gnus-summary-muttprint - "s" gnus-soup-add-article) - - (gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map) - "b" gnus-summary-display-buttonized - "m" gnus-summary-repair-multipart - "v" gnus-article-view-part - "o" gnus-article-save-part - "c" gnus-article-copy-part - "C" gnus-article-view-part-as-charset - "e" gnus-article-view-part-externally - "E" gnus-article-encrypt-body - "i" gnus-article-inline-part - "|" gnus-article-pipe-part) - - (gnus-define-keys (gnus-uu-mark-map "P" gnus-summary-mark-map) - "p" gnus-summary-mark-as-processable - "u" gnus-summary-unmark-as-processable - "U" gnus-summary-unmark-all-processable - "v" gnus-uu-mark-over - "s" gnus-uu-mark-series - "r" gnus-uu-mark-region - "g" gnus-uu-unmark-region - "R" gnus-uu-mark-by-regexp - "G" gnus-uu-unmark-by-regexp - "t" gnus-uu-mark-thread - "T" gnus-uu-unmark-thread - "a" gnus-uu-mark-all - "b" gnus-uu-mark-buffer - "S" gnus-uu-mark-sparse - "k" gnus-summary-kill-process-mark - "y" gnus-summary-yank-process-mark - "w" gnus-summary-save-process-mark - "i" gnus-uu-invert-processable) - - (gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map) - ;;"x" gnus-uu-extract-any - "m" gnus-summary-save-parts - "u" gnus-uu-decode-uu - "U" gnus-uu-decode-uu-and-save - "s" gnus-uu-decode-unshar - "S" gnus-uu-decode-unshar-and-save - "o" gnus-uu-decode-save - "O" gnus-uu-decode-save - "b" gnus-uu-decode-binhex - "B" gnus-uu-decode-binhex - "p" gnus-uu-decode-postscript - "P" gnus-uu-decode-postscript-and-save) - - (gnus-define-keys - (gnus-uu-extract-view-map "v" gnus-uu-extract-map) - "u" gnus-uu-decode-uu-view - "U" gnus-uu-decode-uu-and-save-view - "s" gnus-uu-decode-unshar-view - "S" gnus-uu-decode-unshar-and-save-view - "o" gnus-uu-decode-save-view - "O" gnus-uu-decode-save-view - "b" gnus-uu-decode-binhex-view - "B" gnus-uu-decode-binhex-view - "p" gnus-uu-decode-postscript-view - "P" gnus-uu-decode-postscript-and-save-view)) +;; Non-orthogonal keys + +(gnus-define-keys gnus-summary-mode-map + " " gnus-summary-next-page + "\177" gnus-summary-prev-page + [delete] gnus-summary-prev-page + [backspace] gnus-summary-prev-page + "\r" gnus-summary-scroll-up + "\M-\r" gnus-summary-scroll-down + "n" gnus-summary-next-unread-article + "p" gnus-summary-prev-unread-article + "N" gnus-summary-next-article + "P" gnus-summary-prev-article + "\M-\C-n" gnus-summary-next-same-subject + "\M-\C-p" gnus-summary-prev-same-subject + "\M-n" gnus-summary-next-unread-subject + "\M-p" gnus-summary-prev-unread-subject + "." gnus-summary-first-unread-article + "," gnus-summary-best-unread-article + "\M-s" gnus-summary-search-article-forward + "\M-r" gnus-summary-search-article-backward + "<" gnus-summary-beginning-of-article + ">" gnus-summary-end-of-article + "j" gnus-summary-goto-article + "^" gnus-summary-refer-parent-article + "\M-^" gnus-summary-refer-article + "u" gnus-summary-tick-article-forward + "!" gnus-summary-tick-article-forward + "U" gnus-summary-tick-article-backward + "d" gnus-summary-mark-as-read-forward + "D" gnus-summary-mark-as-read-backward + "E" gnus-summary-mark-as-expirable + "\M-u" gnus-summary-clear-mark-forward + "\M-U" gnus-summary-clear-mark-backward + "k" gnus-summary-kill-same-subject-and-select + "\C-k" gnus-summary-kill-same-subject + "\M-\C-k" gnus-summary-kill-thread + "\M-\C-l" gnus-summary-lower-thread + "e" gnus-summary-edit-article + "#" gnus-summary-mark-as-processable + "\M-#" gnus-summary-unmark-as-processable + "\M-\C-t" gnus-summary-toggle-threads + "\M-\C-s" gnus-summary-show-thread + "\M-\C-h" gnus-summary-hide-thread + "\M-\C-f" gnus-summary-next-thread + "\M-\C-b" gnus-summary-prev-thread + [(meta down)] gnus-summary-next-thread + [(meta up)] gnus-summary-prev-thread + "\M-\C-u" gnus-summary-up-thread + "\M-\C-d" gnus-summary-down-thread + "&" gnus-summary-execute-command + "c" gnus-summary-catchup-and-exit + "\C-w" gnus-summary-mark-region-as-read + "\C-t" gnus-summary-toggle-truncation + "?" gnus-summary-mark-as-dormant + "\C-c\M-\C-s" gnus-summary-limit-include-expunged + "\C-c\C-s\C-n" gnus-summary-sort-by-number + "\C-c\C-s\C-l" gnus-summary-sort-by-lines + "\C-c\C-s\C-c" gnus-summary-sort-by-chars + "\C-c\C-s\C-a" gnus-summary-sort-by-author + "\C-c\C-s\C-s" gnus-summary-sort-by-subject + "\C-c\C-s\C-d" gnus-summary-sort-by-date + "\C-c\C-s\C-i" gnus-summary-sort-by-score + "\C-c\C-s\C-o" gnus-summary-sort-by-original + "\C-c\C-s\C-r" gnus-summary-sort-by-random + "=" gnus-summary-expand-window + "\C-x\C-s" gnus-summary-reselect-current-group + "\M-g" gnus-summary-rescan-group + "w" gnus-summary-stop-page-breaking + "\C-c\C-r" gnus-summary-caesar-message + "f" gnus-summary-followup + "F" gnus-summary-followup-with-original + "C" gnus-summary-cancel-article + "r" gnus-summary-reply + "R" gnus-summary-reply-with-original + "\C-c\C-f" gnus-summary-mail-forward + "o" gnus-summary-save-article + "\C-o" gnus-summary-save-article-mail + "|" gnus-summary-pipe-output + "\M-k" gnus-summary-edit-local-kill + "\M-K" gnus-summary-edit-global-kill + ;; "V" gnus-version + "\C-c\C-d" gnus-summary-describe-group + "q" gnus-summary-exit + "Q" gnus-summary-exit-no-update + "\C-c\C-i" gnus-info-find-node + gnus-mouse-2 gnus-mouse-pick-article + "m" gnus-summary-mail-other-window + "a" gnus-summary-post-news + "i" gnus-summary-news-other-window + "x" gnus-summary-limit-to-unread + "s" gnus-summary-isearch-article + "t" gnus-summary-toggle-header + "g" gnus-summary-show-article + "l" gnus-summary-goto-last-article + "\C-c\C-v\C-v" gnus-uu-decode-uu-view + "\C-d" gnus-summary-enter-digest-group + "\M-\C-d" gnus-summary-read-document + "\M-\C-e" gnus-summary-edit-parameters + "\M-\C-a" gnus-summary-customize-parameters + "\C-c\C-b" gnus-bug + "*" gnus-cache-enter-article + "\M-*" gnus-cache-remove-article + "\M-&" gnus-summary-universal-argument + "\C-l" gnus-recenter + "I" gnus-summary-increase-score + "L" gnus-summary-lower-score + "\M-i" gnus-symbolic-argument + "h" gnus-summary-select-article-buffer + + "b" gnus-article-view-part + "\M-t" gnus-summary-toggle-display-buttonized + + "V" gnus-summary-score-map + "X" gnus-uu-extract-map + "S" gnus-summary-send-map) + +;; Sort of orthogonal keymap +(gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map) + "t" gnus-summary-tick-article-forward + "!" gnus-summary-tick-article-forward + "d" gnus-summary-mark-as-read-forward + "r" gnus-summary-mark-as-read-forward + "c" gnus-summary-clear-mark-forward + " " gnus-summary-clear-mark-forward + "e" gnus-summary-mark-as-expirable + "x" gnus-summary-mark-as-expirable + "?" gnus-summary-mark-as-dormant + "b" gnus-summary-set-bookmark + "B" gnus-summary-remove-bookmark + "#" gnus-summary-mark-as-processable + "\M-#" gnus-summary-unmark-as-processable + "S" gnus-summary-limit-include-expunged + "C" gnus-summary-catchup + "H" gnus-summary-catchup-to-here + "h" gnus-summary-catchup-from-here + "\C-c" gnus-summary-catchup-all + "k" gnus-summary-kill-same-subject-and-select + "K" gnus-summary-kill-same-subject + "P" gnus-uu-mark-map) + +(gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map) + "c" gnus-summary-clear-above + "u" gnus-summary-tick-above + "m" gnus-summary-mark-above + "k" gnus-summary-kill-below) + +(gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map) + "/" gnus-summary-limit-to-subject + "n" gnus-summary-limit-to-articles + "w" gnus-summary-pop-limit + "s" gnus-summary-limit-to-subject + "a" gnus-summary-limit-to-author + "u" gnus-summary-limit-to-unread + "m" gnus-summary-limit-to-marks + "M" gnus-summary-limit-exclude-marks + "v" gnus-summary-limit-to-score + "*" gnus-summary-limit-include-cached + "D" gnus-summary-limit-include-dormant + "T" gnus-summary-limit-include-thread + "d" gnus-summary-limit-exclude-dormant + "t" gnus-summary-limit-to-age + "." gnus-summary-limit-to-unseen + "x" gnus-summary-limit-to-extra + "p" gnus-summary-limit-to-display-predicate + "E" gnus-summary-limit-include-expunged + "c" gnus-summary-limit-exclude-childless-dormant + "C" gnus-summary-limit-mark-excluded-as-read + "o" gnus-summary-insert-old-articles + "N" gnus-summary-insert-new-articles) + +(gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map) + "n" gnus-summary-next-unread-article + "p" gnus-summary-prev-unread-article + "N" gnus-summary-next-article + "P" gnus-summary-prev-article + "\C-n" gnus-summary-next-same-subject + "\C-p" gnus-summary-prev-same-subject + "\M-n" gnus-summary-next-unread-subject + "\M-p" gnus-summary-prev-unread-subject + "f" gnus-summary-first-unread-article + "b" gnus-summary-best-unread-article + "j" gnus-summary-goto-article + "g" gnus-summary-goto-subject + "l" gnus-summary-goto-last-article + "o" gnus-summary-pop-article) + +(gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map) + "k" gnus-summary-kill-thread + "l" gnus-summary-lower-thread + "i" gnus-summary-raise-thread + "T" gnus-summary-toggle-threads + "t" gnus-summary-rethread-current + "^" gnus-summary-reparent-thread + "s" gnus-summary-show-thread + "S" gnus-summary-show-all-threads + "h" gnus-summary-hide-thread + "H" gnus-summary-hide-all-threads + "n" gnus-summary-next-thread + "p" gnus-summary-prev-thread + "u" gnus-summary-up-thread + "o" gnus-summary-top-thread + "d" gnus-summary-down-thread + "#" gnus-uu-mark-thread + "\M-#" gnus-uu-unmark-thread) + +(gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map) + "g" gnus-summary-prepare + "c" gnus-summary-insert-cached-articles + "d" gnus-summary-insert-dormant-articles) + +(gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map) + "c" gnus-summary-catchup-and-exit + "C" gnus-summary-catchup-all-and-exit + "E" gnus-summary-exit-no-update + "Q" gnus-summary-exit + "Z" gnus-summary-exit + "n" gnus-summary-catchup-and-goto-next-group + "R" gnus-summary-reselect-current-group + "G" gnus-summary-rescan-group + "N" gnus-summary-next-group + "s" gnus-summary-save-newsrc + "P" gnus-summary-prev-group) + +(gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map) + " " gnus-summary-next-page + "n" gnus-summary-next-page + "\177" gnus-summary-prev-page + [delete] gnus-summary-prev-page + "p" gnus-summary-prev-page + "\r" gnus-summary-scroll-up + "\M-\r" gnus-summary-scroll-down + "<" gnus-summary-beginning-of-article + ">" gnus-summary-end-of-article + "b" gnus-summary-beginning-of-article + "e" gnus-summary-end-of-article + "^" gnus-summary-refer-parent-article + "r" gnus-summary-refer-parent-article + "D" gnus-summary-enter-digest-group + "R" gnus-summary-refer-references + "T" gnus-summary-refer-thread + "g" gnus-summary-show-article + "s" gnus-summary-isearch-article + "P" gnus-summary-print-article + "M" gnus-mailing-list-insinuate + "t" gnus-article-babel) + +(gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map) + "b" gnus-article-add-buttons + "B" gnus-article-add-buttons-to-head + "o" gnus-article-treat-overstrike + "e" gnus-article-emphasize + "w" gnus-article-fill-cited-article + "Q" gnus-article-fill-long-lines + "C" gnus-article-capitalize-sentences + "c" gnus-article-remove-cr + "q" gnus-article-de-quoted-unreadable + "6" gnus-article-de-base64-unreadable + "Z" gnus-article-decode-HZ + "h" gnus-article-wash-html + "u" gnus-article-unsplit-urls + "s" gnus-summary-force-verify-and-decrypt + "f" gnus-article-display-x-face + "l" gnus-summary-stop-page-breaking + "r" gnus-summary-caesar-message + "m" gnus-summary-morse-message + "t" gnus-summary-toggle-header + "g" gnus-treat-smiley + "v" gnus-summary-verbose-headers + "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive + "p" gnus-article-verify-x-pgp-sig + "d" gnus-article-treat-dumbquotes) + +(gnus-define-keys (gnus-summary-wash-deuglify-map "Y" gnus-summary-wash-map) + ;; mnemonic: deuglif*Y* + "u" gnus-article-outlook-unwrap-lines + "a" gnus-article-outlook-repair-attribution + "c" gnus-article-outlook-rearrange-citation + "f" gnus-article-outlook-deuglify-article) ;; mnemonic: full deuglify + +(gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map) + "a" gnus-article-hide + "h" gnus-article-hide-headers + "b" gnus-article-hide-boring-headers + "s" gnus-article-hide-signature + "c" gnus-article-hide-citation + "C" gnus-article-hide-citation-in-followups + "l" gnus-article-hide-list-identifiers + "p" gnus-article-hide-pgp + "B" gnus-article-strip-banner + "P" gnus-article-hide-pem + "\C-c" gnus-article-hide-citation-maybe) + +(gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map) + "a" gnus-article-highlight + "h" gnus-article-highlight-headers + "c" gnus-article-highlight-citation + "s" gnus-article-highlight-signature) + +(gnus-define-keys (gnus-summary-wash-header-map "G" gnus-summary-wash-map) + "f" gnus-article-treat-fold-headers + "u" gnus-article-treat-unfold-headers + "n" gnus-article-treat-fold-newsgroups) + +(gnus-define-keys (gnus-summary-wash-display-map "D" gnus-summary-wash-map) + "x" gnus-article-display-x-face + "d" gnus-article-display-face + "s" gnus-treat-smiley + "D" gnus-article-remove-images + "f" gnus-treat-from-picon + "m" gnus-treat-mail-picon + "n" gnus-treat-newsgroups-picon) + +(gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map) + "w" gnus-article-decode-mime-words + "c" gnus-article-decode-charset + "v" gnus-mime-view-all-parts + "b" gnus-article-view-part) + +(gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map) + "z" gnus-article-date-ut + "u" gnus-article-date-ut + "l" gnus-article-date-local + "p" gnus-article-date-english + "e" gnus-article-date-lapsed + "o" gnus-article-date-original + "i" gnus-article-date-iso8601 + "s" gnus-article-date-user) + +(gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map) + "t" gnus-article-remove-trailing-blank-lines + "l" gnus-article-strip-leading-blank-lines + "m" gnus-article-strip-multiple-blank-lines + "a" gnus-article-strip-blank-lines + "A" gnus-article-strip-all-blank-lines + "s" gnus-article-strip-leading-space + "e" gnus-article-strip-trailing-space + "w" gnus-article-remove-leading-whitespace) + +(gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map) + "v" gnus-version + "f" gnus-summary-fetch-faq + "d" gnus-summary-describe-group + "h" gnus-summary-describe-briefly + "i" gnus-info-find-node + "c" gnus-group-fetch-charter + "C" gnus-group-fetch-control) + +(gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map) + "e" gnus-summary-expire-articles + "\M-\C-e" gnus-summary-expire-articles-now + "\177" gnus-summary-delete-article + [delete] gnus-summary-delete-article + [backspace] gnus-summary-delete-article + "m" gnus-summary-move-article + "r" gnus-summary-respool-article + "w" gnus-summary-edit-article + "c" gnus-summary-copy-article + "B" gnus-summary-crosspost-article + "q" gnus-summary-respool-query + "t" gnus-summary-respool-trace + "i" gnus-summary-import-article + "I" gnus-summary-create-article + "p" gnus-summary-article-posted-p) + +(gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map) + "o" gnus-summary-save-article + "m" gnus-summary-save-article-mail + "F" gnus-summary-write-article-file + "r" gnus-summary-save-article-rmail + "f" gnus-summary-save-article-file + "b" gnus-summary-save-article-body-file + "h" gnus-summary-save-article-folder + "v" gnus-summary-save-article-vm + "p" gnus-summary-pipe-output + "P" gnus-summary-muttprint + "s" gnus-soup-add-article) + +(gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map) + "b" gnus-summary-display-buttonized + "m" gnus-summary-repair-multipart + "v" gnus-article-view-part + "o" gnus-article-save-part + "c" gnus-article-copy-part + "C" gnus-article-view-part-as-charset + "e" gnus-article-view-part-externally + "E" gnus-article-encrypt-body + "i" gnus-article-inline-part + "|" gnus-article-pipe-part) + +(gnus-define-keys (gnus-uu-mark-map "P" gnus-summary-mark-map) + "p" gnus-summary-mark-as-processable + "u" gnus-summary-unmark-as-processable + "U" gnus-summary-unmark-all-processable + "v" gnus-uu-mark-over + "s" gnus-uu-mark-series + "r" gnus-uu-mark-region + "g" gnus-uu-unmark-region + "R" gnus-uu-mark-by-regexp + "G" gnus-uu-unmark-by-regexp + "t" gnus-uu-mark-thread + "T" gnus-uu-unmark-thread + "a" gnus-uu-mark-all + "b" gnus-uu-mark-buffer + "S" gnus-uu-mark-sparse + "k" gnus-summary-kill-process-mark + "y" gnus-summary-yank-process-mark + "w" gnus-summary-save-process-mark + "i" gnus-uu-invert-processable) + +(gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map) + ;;"x" gnus-uu-extract-any + "m" gnus-summary-save-parts + "u" gnus-uu-decode-uu + "U" gnus-uu-decode-uu-and-save + "s" gnus-uu-decode-unshar + "S" gnus-uu-decode-unshar-and-save + "o" gnus-uu-decode-save + "O" gnus-uu-decode-save + "b" gnus-uu-decode-binhex + "B" gnus-uu-decode-binhex + "p" gnus-uu-decode-postscript + "P" gnus-uu-decode-postscript-and-save) + +(gnus-define-keys + (gnus-uu-extract-view-map "v" gnus-uu-extract-map) + "u" gnus-uu-decode-uu-view + "U" gnus-uu-decode-uu-and-save-view + "s" gnus-uu-decode-unshar-view + "S" gnus-uu-decode-unshar-and-save-view + "o" gnus-uu-decode-save-view + "O" gnus-uu-decode-save-view + "b" gnus-uu-decode-binhex-view + "B" gnus-uu-decode-binhex-view + "p" gnus-uu-decode-postscript-view + "P" gnus-uu-decode-postscript-and-save-view) (defvar gnus-article-post-menu nil) @@ -2119,9 +2120,9 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs)))) ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t] ["HZ" gnus-article-decode-HZ t] ("(Outlook) Deuglify" - ["Unwrap lines" gnus-outlook-unwrap-lines t] - ["Repair attribution" gnus-outlook-repair-attribution t] - ["Rearrange citation" gnus-outlook-rearrange-citation t] + ["Unwrap lines" gnus-article-outlook-unwrap-lines t] + ["Repair attribution" gnus-article-outlook-repair-attribution t] + ["Rearrange citation" gnus-article-outlook-rearrange-citation t] ["Full (Outlook) deuglify" gnus-article-outlook-deuglify-article t]) ) @@ -2293,7 +2294,8 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs)))) ["Catchup all" gnus-summary-catchup-all t] ["Catchup to here" gnus-summary-catchup-to-here t] ["Catchup from here" gnus-summary-catchup-from-here t] - ["Catchup region" gnus-summary-mark-region-as-read t] + ["Catchup region" gnus-summary-mark-region-as-read + (gnus-mark-active-p)] ["Mark excluded" gnus-summary-limit-mark-excluded-as-read t]) ("Mark Various" ["Tick" gnus-summary-tick-article-forward t] @@ -2327,8 +2329,8 @@ gnus-summary-show-article-from-menu-as-charset-%s" cs)))) ["Remove all marks" gnus-summary-unmark-all-processable t] ["Mark above" gnus-uu-mark-over t] ["Mark series" gnus-uu-mark-series t] - ["Mark region" gnus-uu-mark-region t] - ["Unmark region" gnus-uu-unmark-region t] + ["Mark region" gnus-uu-mark-region (gnus-mark-active-p)] + ["Unmark region" gnus-uu-unmark-region (gnus-mark-active-p)] ["Mark by regexp..." gnus-uu-mark-by-regexp t] ["Unmark by regexp..." gnus-uu-unmark-by-regexp t] ["Mark all" gnus-uu-mark-all t] @@ -4023,40 +4025,41 @@ the id of the parent article (if any)." (gnus-summary-goto-subject article) (let* ((datal (gnus-data-find-list article)) (data (car datal)) - (length (when (cdr datal) - (- (gnus-data-pos data) - (gnus-data-pos (cadr datal))))) (buffer-read-only nil) (level (gnus-summary-thread-level))) (gnus-delete-line) - (gnus-summary-insert-line - header level nil - (memq article gnus-newsgroup-undownloaded) - (gnus-article-mark article) - (memq article gnus-newsgroup-replied) - (memq article gnus-newsgroup-expirable) - ;; Only insert the Subject string when it's different - ;; from the previous Subject string. - (if (and - gnus-show-threads - (gnus-subject-equal - (condition-case () - (mail-header-subject - (gnus-data-header - (cadr - (gnus-data-find-list - article - (gnus-data-list t))))) - ;; Error on the side of excessive subjects. - (error "")) - (mail-header-subject header))) - "" - (mail-header-subject header)) - nil (cdr (assq article gnus-newsgroup-scored)) - (memq article gnus-newsgroup-processable)) - (when length - (gnus-data-update-list - (cdr datal) (- length (- (gnus-data-pos data) (point)))))))) + (let ((inserted (- (point) + (progn + (gnus-summary-insert-line + header level nil + (memq article gnus-newsgroup-undownloaded) + (gnus-article-mark article) + (memq article gnus-newsgroup-replied) + (memq article gnus-newsgroup-expirable) + ;; Only insert the Subject string when it's different + ;; from the previous Subject string. + (if (and + gnus-show-threads + (gnus-subject-equal + (condition-case () + (mail-header-subject + (gnus-data-header + (cadr + (gnus-data-find-list + article + (gnus-data-list t))))) + ;; Error on the side of excessive subjects. + (error "")) + (mail-header-subject header))) + "" + (mail-header-subject header)) + nil (cdr (assq article gnus-newsgroup-scored)) + (memq article gnus-newsgroup-processable)) + (point))))) + (when (cdr datal) + (gnus-data-update-list + (cdr datal) + (- (gnus-data-pos data) (gnus-data-pos (cadr datal)) inserted))))))) (defun gnus-summary-update-article (article &optional iheader) "Update ARTICLE in the summary buffer." @@ -5212,10 +5215,10 @@ If SELECT-ARTICLES, only select those articles from GROUP." (setq gnus-newsgroup-unselected (gnus-sorted-difference gnus-newsgroup-unreads articles)) (when gnus-alter-articles-to-read-function - (setq gnus-newsgroup-unreads + (setq articles (sort (funcall gnus-alter-articles-to-read-function - gnus-newsgroup-name gnus-newsgroup-unreads) + gnus-newsgroup-name articles) '<))) articles))) @@ -6009,7 +6012,8 @@ If EXCLUDE-GROUP, do not go to this group." (progn (while arts (when (or (and undownloaded - (memq (car arts) gnus-newsgroup-undownloaded)) + (memq (car arts) + gnus-newsgroup-undownloaded)) (gnus-data-unread-p (car arts))) (setq result (car arts) arts nil)) @@ -6777,7 +6781,7 @@ If optional argument UNREAD is non-nil, only unread article is selected." (gnus-summary-goto-subject article t))) (gnus-summary-limit (append articles gnus-newsgroup-limit)) (gnus-summary-position-point)) - + (defun gnus-summary-goto-subject (article &optional force silent) "Go the subject line of ARTICLE. If FORCE, also allow jumping to articles not currently shown." @@ -9975,7 +9979,9 @@ The number of articles marked as read is returned." (setq gnus-newsgroup-marked nil gnus-newsgroup-spam-marked nil gnus-newsgroup-dormant nil)) - (setq gnus-newsgroup-unreads gnus-newsgroup-downloadable)) + (setq gnus-newsgroup-unreads + (gnus-intersection gnus-newsgroup-unreads + gnus-newsgroup-downloadable))) ;; We actually mark all articles as canceled, which we ;; have to do when using auto-expiry or adaptive scoring. (gnus-summary-show-all-threads) diff --git a/lisp/gnus-win.el b/lisp/gnus-win.el index 56375db..cd9ef74 100644 --- a/lisp/gnus-win.el +++ b/lisp/gnus-win.el @@ -123,7 +123,7 @@ used to display Gnus windows." (post 1.0 point))) (reply (vertical 1.0 - (article-copy 0.5) + (article 0.5) (message 1.0 point))) (forward (vertical 1.0 diff --git a/lisp/gnus-xmas.el b/lisp/gnus-xmas.el index cb7e0b0..65d003d 100644 --- a/lisp/gnus-xmas.el +++ b/lisp/gnus-xmas.el @@ -1,6 +1,6 @@ ;;; gnus-xmas.el --- Gnus functions for XEmacs -;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 ;; Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen @@ -436,6 +436,7 @@ call it with the value of the `gnus-data' text property." 'gnus-xmas-mode-line-buffer-identification) (defalias 'gnus-key-press-event-p 'key-press-event-p) (defalias 'gnus-region-active-p 'region-active-p) + (defalias 'gnus-mark-active-p 'region-exists-p) (defalias 'gnus-annotation-in-region-p 'gnus-xmas-annotation-in-region-p) (defalias 'gnus-mime-button-menu 'gnus-xmas-mime-button-menu) (defalias 'gnus-image-type-available-p 'gnus-xmas-image-type-available-p) diff --git a/lisp/gnus.el b/lisp/gnus.el index 6d2225c..47c9829 100644 --- a/lisp/gnus.el +++ b/lisp/gnus.el @@ -1,7 +1,7 @@ ;;; gnus.el --- a newsreader for GNU Emacs ;; Copyright (C) 1987, 1988, 1989, 1990, 1993, 1994, 1995, 1996, 1997, -;; 1998, 2000, 2001, 2002 Free Software Foundation, Inc. +;; 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. ;; Author: Masanobu UMEDA ;; Lars Magne Ingebrigtsen @@ -46,8 +46,7 @@ (defgroup gnus-format nil "Dealing with formatting issues." - :group 'news - :group 'mail) + :group 'gnus) (defgroup gnus-charset nil "Group character set issues." @@ -57,6 +56,7 @@ (defgroup gnus-cache nil "Cache interface." + :link '(custom-manual "(gnus)Article Caching") :group 'gnus) (defgroup gnus-start nil @@ -282,7 +282,7 @@ is restarted, and sometimes reloaded." :link '(custom-manual "(gnus)Exiting Gnus") :group 'gnus) -(defconst gnus-version-number "0.12" +(defconst gnus-version-number "0.13" "Version number for this version of Gnus.") (defconst gnus-version (format "Oort Gnus v%s" gnus-version-number) @@ -1038,7 +1038,7 @@ REST is a plist of following: (defcustom gnus-home-directory "~/" "Directory variable that specifies the \"home\" directory. -All other Gnus path variables are initialized from this variable." +All other Gnus file and directory variables are initialized from this variable." :group 'gnus-files :type 'directory) @@ -1304,7 +1304,7 @@ If the default site is too slow, try one of these: ("netins" . (concat "http://www.netins.net/usenet/charter/" (gnus-replace-in-string name "\\." "-") "-charter.html"))) "*An alist of (HIERARCHY . FORM) pairs used to construct the URL of a charter. - When FORM is evaluated `name' is bound to the name of the group." +When FORM is evaluated `name' is bound to the name of the group." :group 'gnus-group-various :type '(repeat (cons (string :tag "Hierarchy") (sexp :tag "Form")))) @@ -1745,181 +1745,194 @@ articles to list when the group is a large newsgroup (see total number of articles in the group.") ;; group parameters for spam processing added by Ted Zlatanov -(defvar gnus-group-spam-classification-spam t - "Spam group classification (requires spam.el). +(defcustom gnus-install-group-spam-parameters t + "*Disable the group parameters for spam detection. +Enable if `G c' in XEmacs is giving you trouble, and make sure to submit a bug report." + :type 'boolean + :group 'gnus-start) + +(when gnus-install-group-spam-parameters + (defvar gnus-group-spam-classification-spam t + "Spam group classification (requires spam.el). This group contains spam messages. On summary entry, unread messages will be marked as spam. On summary exit, the specified spam processors will be invoked on spam-marked messages, then those messages will be expired, so the spam processor will only see a spam-marked message once.") -(defvar gnus-group-spam-classification-ham 'ask - "The ham value for the spam group parameter (requires spam.el). + (defvar gnus-group-spam-classification-ham 'ask + "The ham value for the spam group parameter (requires spam.el). On summary exit, the specified ham processors will be invoked on ham-marked messages. Exercise caution, since the ham processor will see the same message more than once because there is no ham message registry.") -(gnus-define-group-parameter - spam-contents - :type list - :function-document - "The spam type (spam, ham, or neither) of the group." - :variable gnus-spam-newsgroup-contents - :variable-default nil - :variable-document - "*Groups in which to automatically mark new articles as spam on + (gnus-define-group-parameter + spam-contents + :type list + :function-document + "The spam type (spam, ham, or neither) of the group." + :variable gnus-spam-newsgroup-contents + :variable-default nil + :variable-document + "*Groups in which to automatically mark new articles as spam on summary entry. If non-nil, this should be a list of group name regexps that should match all groups in which to do automatic spam tagging, associated with a classification (spam, ham, or neither). This only makes sense for mail groups." - :variable-group spam - :variable-type '(repeat - (list :tag "Group contents spam/ham classification" + :variable-group spam + :variable-type '(repeat + (list :tag "Group contents spam/ham classification" (regexp :tag "Group") (choice (variable-item gnus-group-spam-classification-spam) (variable-item gnus-group-spam-classification-ham) (other :tag "Unclassified" nil)))) - :parameter-type '(list :tag "Group contents spam/ham classification" - (choice :tag "Group contents classification for spam sorting" - (variable-item gnus-group-spam-classification-spam) - (variable-item gnus-group-spam-classification-ham) - (other :tag "Unclassified" nil))) - :parameter-document - "The spam classification (spam, ham, or neither) of this group. + :parameter-type '(list :tag "Group contents spam/ham classification" + (choice :tag "Group contents classification for spam sorting" + (variable-item gnus-group-spam-classification-spam) + (variable-item gnus-group-spam-classification-ham) + (other :tag "Unclassified" nil))) + :parameter-document + "The spam classification (spam, ham, or neither) of this group. When a spam group is entered, all unread articles are marked as spam.") -(defvar gnus-group-spam-exit-processor-ifile "ifile" - "The ifile summary exit spam processor. + (defvar gnus-group-spam-exit-processor-ifile "ifile" + "The ifile summary exit spam processor. Only applicable to spam groups.") -(defvar gnus-group-spam-exit-processor-stat "stat" - "The spam-stat summary exit spam processor. + (defvar gnus-group-spam-exit-processor-stat "stat" + "The spam-stat summary exit spam processor. Only applicable to spam groups.") -(defvar gnus-group-spam-exit-processor-bogofilter "bogofilter" - "The Bogofilter summary exit spam processor. + (defvar gnus-group-spam-exit-processor-bogofilter "bogofilter" + "The Bogofilter summary exit spam processor. Only applicable to spam groups.") -(defvar gnus-group-spam-exit-processor-blacklist "blacklist" - "The Blacklist summary exit spam processor. + (defvar gnus-group-spam-exit-processor-blacklist "blacklist" + "The Blacklist summary exit spam processor. Only applicable to spam groups.") -(defvar gnus-group-ham-exit-processor-ifile "ifile-ham" - "The ifile summary exit ham processor. + (defvar gnus-group-ham-exit-processor-ifile "ifile-ham" + "The ifile summary exit ham processor. Only applicable to non-spam (unclassified and ham) groups.") -(defvar gnus-group-ham-exit-processor-stat "stat-ham" - "The spam-stat summary exit ham processor. + (defvar gnus-group-ham-exit-processor-bogofilter "bogofilter-ham" + "The Bogofilter summary exit ham processor. Only applicable to non-spam (unclassified and ham) groups.") -(defvar gnus-group-ham-exit-processor-whitelist "whitelist" - "The whitelist summary exit ham processor. + (defvar gnus-group-ham-exit-processor-stat "stat-ham" + "The spam-stat summary exit ham processor. Only applicable to non-spam (unclassified and ham) groups.") -(defvar gnus-group-ham-exit-processor-BBDB "bbdb" - "The BBDB summary exit ham processor. + (defvar gnus-group-ham-exit-processor-whitelist "whitelist" + "The whitelist summary exit ham processor. Only applicable to non-spam (unclassified and ham) groups.") -(gnus-define-group-parameter - spam-process - :type list - :parameter-type '(choice :tag "Spam Summary Exit Processor" - :value nil - (list :tag "Spam Summary Exit Processor Choices" - (set - (variable-item gnus-group-spam-exit-processor-ifile) - (variable-item gnus-group-spam-exit-processor-stat) - (variable-item gnus-group-spam-exit-processor-bogofilter) - (variable-item gnus-group-spam-exit-processor-blacklist) - (variable-item gnus-group-ham-exit-processor-ifile) - (variable-item gnus-group-ham-exit-processor-stat) - (variable-item gnus-group-ham-exit-processor-whitelist) - (variable-item gnus-group-ham-exit-processor-BBDB)))) - :function-document - "Which spam or ham processors will be applied to the GROUP articles at summary exit." - :variable gnus-spam-process-newsgroups - :variable-default nil - :variable-document - "*Groups in which to automatically process spam or ham articles with + (defvar gnus-group-ham-exit-processor-BBDB "bbdb" + "The BBDB summary exit ham processor. +Only applicable to non-spam (unclassified and ham) groups.") + + (gnus-define-group-parameter + spam-process + :type list + :parameter-type '(choice :tag "Spam Summary Exit Processor" + :value nil + (list :tag "Spam Summary Exit Processor Choices" + (set + (variable-item gnus-group-spam-exit-processor-ifile) + (variable-item gnus-group-spam-exit-processor-stat) + (variable-item gnus-group-spam-exit-processor-bogofilter) + (variable-item gnus-group-spam-exit-processor-blacklist) + (variable-item gnus-group-ham-exit-processor-bogofilter) + (variable-item gnus-group-ham-exit-processor-ifile) + (variable-item gnus-group-ham-exit-processor-stat) + (variable-item gnus-group-ham-exit-processor-whitelist) + (variable-item gnus-group-ham-exit-processor-BBDB)))) + :function-document + "Which spam or ham processors will be applied to the GROUP articles at summary exit." + :variable gnus-spam-process-newsgroups + :variable-default nil + :variable-document + "*Groups in which to automatically process spam or ham articles with a backend on summary exit. If non-nil, this should be a list of group name regexps that should match all groups in which to do automatic spam processing, associated with the appropriate processor. This only makes sense for mail groups." - :variable-group spam - :variable-type '(repeat :tag "Spam/Ham Processors" - (list :tag "Spam Summary Exit Processor Choices" - (regexp :tag "Group Regexp") - (set :tag "Spam/Ham Summary Exit Processor" - (variable-item gnus-group-spam-exit-processor-ifile) - (variable-item gnus-group-spam-exit-processor-stat) - (variable-item gnus-group-spam-exit-processor-bogofilter) - (variable-item gnus-group-spam-exit-processor-blacklist) - (variable-item gnus-group-ham-exit-processor-ifile) - (variable-item gnus-group-ham-exit-processor-stat) - (variable-item gnus-group-ham-exit-processor-whitelist) - (variable-item gnus-group-ham-exit-processor-BBDB)))) - :parameter-document - "Which spam processors will be applied to the spam or ham GROUP articles at summary exit.") - -(gnus-define-group-parameter - spam-process-destination - :parameter-type '(choice :tag "Destination for spam-processed articles at summary exit" - (string :tag "Move to a group") - (other :tag "Expire" nil)) - :function-document - "Where spam-processed articles will go at summary exit." - :variable gnus-spam-process-destinations - :variable-default nil - :variable-document - "*Groups in which to explicitly send spam-processed articles to + :variable-group spam + :variable-type '(repeat :tag "Spam/Ham Processors" + (list :tag "Spam Summary Exit Processor Choices" + (regexp :tag "Group Regexp") + (set :tag "Spam/Ham Summary Exit Processor" + (variable-item gnus-group-spam-exit-processor-ifile) + (variable-item gnus-group-spam-exit-processor-stat) + (variable-item gnus-group-spam-exit-processor-bogofilter) + (variable-item gnus-group-spam-exit-processor-blacklist) + (variable-item gnus-group-ham-exit-processor-bogofilter) + (variable-item gnus-group-ham-exit-processor-ifile) + (variable-item gnus-group-ham-exit-processor-stat) + (variable-item gnus-group-ham-exit-processor-whitelist) + (variable-item gnus-group-ham-exit-processor-BBDB)))) + :parameter-document + "Which spam processors will be applied to the spam or ham GROUP articles at summary exit.") + + (gnus-define-group-parameter + spam-process-destination + :parameter-type '(choice :tag "Destination for spam-processed articles at summary exit" + (string :tag "Move to a group") + (other :tag "Expire" nil)) + :function-document + "Where spam-processed articles will go at summary exit." + :variable gnus-spam-process-destinations + :variable-default nil + :variable-document + "*Groups in which to explicitly send spam-processed articles to another group, or expire them (the default). If non-nil, this should be a list of group name regexps that should match all groups in which to do spam-processed article moving, associated with the destination group or `nil' for explicit expiration. This only makes sense for mail groups." - :variable-group spam - :variable-type '(repeat - :tag "Spam-processed articles destination" - (list - (regexp :tag "Group Regexp") - (choice - :tag "Destination for spam-processed articles at summary exit" - (string :tag "Move to a group") - (other :tag "Expire" nil)))) - :parameter-document - "Where spam-processed articles will go at summary exit.") - -(gnus-define-group-parameter - ham-process-destination - :parameter-type '(choice - :tag "Destination for ham articles at summary exit from a spam group" - (string :tag "Move to a group") - (other :tag "Do nothing" nil)) - :function-document - "Where ham articles will go at summary exit from a spam group." - :variable gnus-ham-process-destinations - :variable-default nil - :variable-document - "*Groups in which to explicitly send ham articles to + :variable-group spam + :variable-type '(repeat + :tag "Spam-processed articles destination" + (list + (regexp :tag "Group Regexp") + (choice + :tag "Destination for spam-processed articles at summary exit" + (string :tag "Move to a group") + (other :tag "Expire" nil)))) + :parameter-document + "Where spam-processed articles will go at summary exit.") + + (gnus-define-group-parameter + ham-process-destination + :parameter-type '(choice + :tag "Destination for ham articles at summary exit from a spam group" + (string :tag "Move to a group") + (other :tag "Do nothing" nil)) + :function-document + "Where ham articles will go at summary exit from a spam group." + :variable gnus-ham-process-destinations + :variable-default nil + :variable-document + "*Groups in which to explicitly send ham articles to another group, or do nothing (the default). If non-nil, this should be a list of group name regexps that should match all groups in which to do ham article moving, associated with the destination group or `nil' for explicit ignoring. This only makes sense for mail groups, and only works in spam groups." - :variable-group spam - :variable-type '(repeat - :tag "Ham articles destination" - (list - (regexp :tag "Group Regexp") - (choice - :tag "Destination for ham articles at summary exit from spam group" - (string :tag "Move to a group") - (other :tag "Expire" nil)))) - :parameter-document - "Where ham articles will go at summary exit from a spam group.") + :variable-group spam + :variable-type '(repeat + :tag "Ham articles destination" + (list + (regexp :tag "Group Regexp") + (choice + :tag "Destination for ham articles at summary exit from spam group" + (string :tag "Move to a group") + (other :tag "Expire" nil)))) + :parameter-document + "Where ham articles will go at summary exit from a spam group.")) (defcustom gnus-group-uncollapsed-levels 1 "Number of group name elements to leave alone when making a short group name." @@ -2502,7 +2515,7 @@ with some simple extensions. %V Total thread score (number). %P The line number (number). %O Download mark (character). -%C If present, indicates desired cursor position +%* If present, indicates desired cursor position (instead of after first colon). %u User defined specifier. The next character in the format string should be a letter. Gnus will call the function gnus-user-format-function-X, diff --git a/lisp/mailcap.el b/lisp/mailcap.el index 5f77082..ab16136 100644 --- a/lisp/mailcap.el +++ b/lisp/mailcap.el @@ -1,5 +1,6 @@ ;;; mailcap.el --- MIME media types configuration -;; Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 +;; Free Software Foundation, Inc. ;; Author: William M. Perry ;; Lars Magne Ingebrigtsen @@ -48,12 +49,24 @@ table) "A syntax table for parsing sgml attributes.") +(defvar mailcap-print-command + (mapconcat 'identity + (cons (if (boundp 'lpr-command) + lpr-command + "lpr") + (when (boundp 'lpr-switches) + (if (stringp lpr-switches) + (list lpr-switches) + lpr-switches))) + " ") + "Shell command (including switches) used to print Postscript files.") + ;; Postpone using defcustom for this as it's so big and we essentially ;; have to have two copies of the data around then. Perhaps just ;; customize the Lisp viewers and rely on the normal configuration ;; files for the rest? -- fx (defvar mailcap-mime-data - '(("application" + `(("application" ("vnd.ms-excel" (viewer . "gnumeric %s") (test . (getenv "DISPLAY")) @@ -70,20 +83,17 @@ (viewer . mailcap-save-binary-file) (non-viewer . t) (type . "application/octet-stream")) -;;; XEmacs says `ns' device-type not implemented. -;; ("dvi" -;; (viewer . "open %s") -;; (type . "application/dvi") -;; (test . (eq (mm-device-type) 'ns))) ("dvi" (viewer . "xdvi -safer %s") (test . (eq window-system 'x)) ("needsx11") - (type . "application/dvi")) + (type . "application/dvi") + ("print" . "dvips -qRP %s")) ("dvi" (viewer . "dvitty %s") (test . (not (getenv "DISPLAY"))) - (type . "application/dvi")) + (type . "application/dvi") + ("print" . "dvips -qRP %s")) ("emacs-lisp" (viewer . mailcap-maybe-eval) (type . "application/emacs-lisp")) @@ -123,33 +133,41 @@ ("pdf" (viewer . "gv -safer %s") (type . "application/pdf") - (test . window-system)) + (test . window-system) + ("print" . ,(concat "pdf2ps %s - | " mailcap-print-command))) ("pdf" (viewer . "xpdf %s") (type . "application/pdf") + ("print" . ,(concat "pdftops %s - | " mailcap-print-command)) (test . (eq window-system 'x))) ("pdf" (viewer . "acroread %s") - (type . "application/pdf")) -;;; XEmacs says `ns' device-type not implemented. -;; ("postscript" -;; (viewer . "open %s") -;; (type . "application/postscript") -;; (test . (eq (mm-device-type) 'ns))) + (type . "application/pdf") + ("print" . ,(concat "cat %s | acroread -toPostScript | " + mailcap-print-command)) + (test . window-system)) + ("pdf" + (viewer . ,(concat "pdftotext %s - | ")) + (type . "application/pdf") + ("print" . ,(concat "pdftops %s - | " mailcap-print-command)) + ("copiousoutput")) ("postscript" (viewer . "gv -safer %s") (type . "application/postscript") (test . window-system) + ("print" . ,(concat mailcap-print-command " %s")) ("needsx11")) ("postscript" (viewer . "ghostview -dSAFER %s") (type . "application/postscript") (test . (eq window-system 'x)) + ("print" . ,(concat mailcap-print-command " %s")) ("needsx11")) ("postscript" (viewer . "ps2ascii %s") (type . "application/postscript") (test . (not (getenv "DISPLAY"))) + ("print" . ,(concat mailcap-print-command " %s")) ("copiousoutput")) ("sieve" (viewer . sieve-mode) @@ -198,11 +216,6 @@ ("compose" . "xwd -frame > %s") (test . (eq window-system 'x)) ("needsx11")) -;;; XEmacs says `ns' device-type not implemented. -;; (".*" -;; (viewer . "aopen %s") -;; (type . "image/*") -;; (test . (eq (mm-device-type) 'ns))) (".*" (viewer . "display %s") (type . "image/*") diff --git a/lisp/message.el b/lisp/message.el index fd82439..9419ce7 100644 --- a/lisp/message.el +++ b/lisp/message.el @@ -1178,18 +1178,23 @@ candidates: The cdr of each entry is a function for applying the face to a region.") (defcustom message-send-hook nil - "Hook run before sending messages." + "Hook run before sending messages. +This hook is run quite early when sending." :group 'message-various :options '(ispell-message) :type 'hook) (defcustom message-send-mail-hook nil - "Hook run before sending mail messages." + "Hook run before sending mail messages. +This hook is run very late -- just before the message is sent as +mail." :group 'message-various :type 'hook) (defcustom message-send-news-hook nil - "Hook run before sending news messages." + "Hook run before sending news messages. +This hook is run very late -- just before the message is sent as +news." :group 'message-various :type 'hook) @@ -1411,6 +1416,10 @@ no, only reply back to the author." `(delete-region (progn (beginning-of-line) (point)) (progn (forward-line ,(or n 1)) (point)))) +(defun message-mark-active-p () + "Non-nil means the mark and region are currently active in this buffer." + mark-active) + (defun message-unquote-tokens (elems) "Remove double quotes (\") from strings in list ELEMS." (mapcar (lambda (item) @@ -2053,13 +2062,19 @@ Point is left at the beginning of the narrowed-to region." (easy-menu-define message-mode-menu message-mode-map "Message Menu." `("Message" - ["Yank Original" message-yank-original t] + ["Yank Original" message-yank-original message-reply-buffer] ["Fill Yanked Message" message-fill-yanked-message t] ["Insert Signature" message-insert-signature t] ["Caesar (rot13) Message" message-caesar-buffer-body t] - ["Caesar (rot13) Region" message-caesar-region (mark t)] - ["Elide Region" message-elide-region (mark t)] - ["Delete Outside Region" message-delete-not-region (mark t)] + ["Caesar (rot13) Region" message-caesar-region (message-mark-active-p)] + ["Elide Region" message-elide-region + :active (message-mark-active-p) + ,@(if (featurep 'xemacs) nil + '(:help "Replace text in region with an ellipsis"))] + ["Delete Outside Region" message-delete-not-region + :active (message-mark-active-p) + ,@(if (featurep 'xemacs) nil + '(:help "Delete all quoted text outside region"))] ["Kill To Signature" message-kill-to-signature t] ["Newline and Reformat" message-newline-and-reformat t] ["Rename buffer" message-rename-buffer t] @@ -2068,7 +2083,8 @@ Point is left at the beginning of the narrowed-to region." '(:help "Spellcheck this message"))] "----" ["Insert Region Marked" message-mark-inserted-region - ,@(if (featurep 'xemacs) '(t) + :active (message-mark-active-p) + ,@(if (featurep 'xemacs) nil '(:help "Mark region with enclosing tags"))] ["Insert File Marked..." message-mark-insert-file ,@(if (featurep 'xemacs) '(t) @@ -3136,6 +3152,7 @@ It should typically alter the sending method in some way or other." (when (funcall (cadr elem)) (when (and (or (not (memq (car elem) message-sent-message-via)) + (not (message-fetch-field "supersedes")) (if (or (message-gnksa-enable-p 'multiple-copies) (not (eq (car elem) 'news))) (y-or-n-p diff --git a/lisp/messagexmas.el b/lisp/messagexmas.el index bc02b00..694626e 100644 --- a/lisp/messagexmas.el +++ b/lisp/messagexmas.el @@ -1,6 +1,6 @@ ;;; messagexmas.el --- XEmacs extensions to message -;; Copyright (C) 1996, 1997, 1998, 1999, 2000 +;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2003 ;; Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen @@ -120,7 +120,8 @@ If it is non-nil, it must be a toolbar. The five valid values are "Redefine message functions for XEmacs." (defalias 'message-exchange-point-and-mark 'message-xmas-exchange-point-and-mark) - + (defalias 'message-mark-active-p + 'region-exists-p) (when (>= emacs-major-version 20) (defalias 'message-make-caesar-translation-table 'message-xmas-make-caesar-translation-table))) diff --git a/lisp/nnfolder.el b/lisp/nnfolder.el index b50c6bd..e6cd305 100644 --- a/lisp/nnfolder.el +++ b/lisp/nnfolder.el @@ -1046,7 +1046,7 @@ This command does not work if you use short group names." (nnheader-message 5 ""))) (defun nnfolder-group-pathname (group) - "Make pathname for GROUP." + "Make file name for GROUP." (setq group (mm-encode-coding-string group nnmail-pathname-coding-system)) (let ((dir (file-name-as-directory (expand-file-name nnfolder-directory)))) diff --git a/lisp/nnheader.el b/lisp/nnheader.el index adc9c9d..c13b522 100644 --- a/lisp/nnheader.el +++ b/lisp/nnheader.el @@ -658,7 +658,7 @@ the line could be found." "Regexp that matches numerical file names.") (defvar nnheader-numerical-full-files (concat "/" nnheader-numerical-files) - "Regexp that matches numerical full file paths.") + "Regexp that matches numerical full file names.") (defsubst nnheader-file-to-number (file) "Take a FILE name and return the article number." @@ -824,10 +824,10 @@ without formatting." (<= level gnus-verbose-backends))) (defvar nnheader-pathname-coding-system 'iso-8859-1 - "*Coding system for pathname.") + "*Coding system for file name.") (defun nnheader-group-pathname (group dir &optional file) - "Make pathname for GROUP." + "Make file name for GROUP." (concat (let ((dir (file-name-as-directory (expand-file-name dir)))) ;; If this directory exists, we use it directly. diff --git a/lisp/nnimap.el b/lisp/nnimap.el index f4e9c35..f6c3705 100644 --- a/lisp/nnimap.el +++ b/lisp/nnimap.el @@ -195,6 +195,14 @@ RFC2060 section 6.4.4." :group 'nnimap :type 'sexp) +(defcustom nnimap-split-download-body nil + "Whether to download entire articles during splitting. +This is generally not required, and will slow things down considerably. +You may need it if you want to use an advanced splitting function that +analyses the body before splitting the article." + :group 'nnimap + :type 'boolean) + ;; Performance / bug workaround variables (defcustom nnimap-close-asynchronous t @@ -556,7 +564,7 @@ If EXAMINE is non-nil the group is selected read-only." articles)))) (defun nnimap-group-overview-filename (group server) - "Make pathname for GROUP on SERVER." + "Make file name for GROUP on SERVER." (let* ((dir (file-name-as-directory (expand-file-name nnimap-directory))) (uidvalidity (gnus-group-get-parameter (gnus-group-prefixed-name @@ -1246,7 +1254,10 @@ function is generally only called when Gnus is shutting down." (when (setq rule (nnimap-split-find-rule server inbox)) ;; iterate over articles (dolist (article (imap-search nnimap-split-predicate)) - (when (nnimap-request-head article) + (when (if nnimap-split-download-body + (and (nnimap-request-article article) + (mail-narrow-to-head)) + (nnimap-request-head article)) ;; copy article to right group(s) (setq removeorig nil) (dolist (to-group (nnimap-split-to-groups rule)) @@ -1270,6 +1281,8 @@ function is generally only called when Gnus is shutting down." (t (message "IMAP split failed to move %s:%s:%d to %s" server inbox article to-group)))) + (if nnimap-split-download-body + (widen)) ;; remove article if it was successfully copied somewhere (and removeorig (imap-message-flags-add (format "%d" article) diff --git a/lisp/nnmail.el b/lisp/nnmail.el index 032fe93..cb1fb79 100644 --- a/lisp/nnmail.el +++ b/lisp/nnmail.el @@ -538,7 +538,7 @@ parameter. It should return nil, `warn' or `delete'." "Coding system used in reading inbox") (defvar nnmail-pathname-coding-system nil - "*Coding system for pathname.") + "*Coding system for file name.") (defun nnmail-find-file (file) "Insert FILE in server buffer safely." @@ -555,7 +555,7 @@ parameter. It should return nil, `warn' or `delete'." (file-error nil)))) (defun nnmail-group-pathname (group dir &optional file) - "Make pathname for GROUP." + "Make file name for GROUP." (concat (let ((dir (file-name-as-directory (expand-file-name dir)))) (setq group (nnheader-replace-duplicate-chars-in-string @@ -786,7 +786,9 @@ If SOURCE is a directory spec, try to return the group name component." (if (not (and (re-search-forward "^From " nil t) (goto-char (match-beginning 0)))) ;; Possibly wrong format? - (error "Error, unknown mail format! (Possibly corrupted.)") + (error "Error, unknown mail format! (Possibly corrupted %s `%s'.)" + (if (buffer-file-name) "file" "buffer") + (or (buffer-file-name) (buffer-name))) ;; Carry on until the bitter end. (while (not (eobp)) (setq start (point) diff --git a/lisp/nnsoup.el b/lisp/nnsoup.el index e4c8271..4d9d884 100644 --- a/lisp/nnsoup.el +++ b/lisp/nnsoup.el @@ -399,7 +399,7 @@ backend for the messages.") prefix)) (defun nnsoup-file-name (dir file) - "Return the full path of FILE (in any case) in DIR." + "Return the full name of FILE (in any case) in DIR." (let* ((case-fold-search t) (files (directory-files dir t)) (regexp (concat (regexp-quote file) "$"))) diff --git a/lisp/nnspool.el b/lisp/nnspool.el index d8709ec..4efdeae 100644 --- a/lisp/nnspool.el +++ b/lisp/nnspool.el @@ -460,7 +460,7 @@ there.") (nnheader-report 'nnspool "No such newsgroup: %s" group))))) (defun nnspool-article-pathname (group &optional article) - "Find the path for GROUP." + "Find the file name for GROUP." (nnheader-group-pathname group nnspool-spool-directory article)) (provide 'nnspool) diff --git a/lisp/spam.el b/lisp/spam.el index cb171df..86012dc 100644 --- a/lisp/spam.el +++ b/lisp/spam.el @@ -105,8 +105,15 @@ The regular expression is matched against the address." :type 'boolean :group 'spam) +(defcustom spam-use-bogofilter-headers nil + "Whether bogofilter headers should be used by spam-split. +Enable this if you pre-process messages with Bogofilter BEFORE Gnus sees them." + :type 'boolean + :group 'spam) + (defcustom spam-use-bogofilter nil - "Whether bogofilter should be used by spam-split." + "Whether bogofilter should be invoked by spam-split. +Enable this if you want Gnus to invoke Bogofilter on new messages." :type 'boolean :group 'spam) @@ -202,40 +209,23 @@ your main source of newsgroup names." "Spam bogofilter configuration." :group 'spam) -(defcustom spam-bogofilter-output-buffer-name "*Bogofilter Output*" - "Name of buffer when displaying `bogofilter -v' output." - :type 'string - :group 'spam-bogofilter) - -(defcustom spam-bogofilter-initial-timeout 40 - "Timeout in seconds for the initial reply from the `bogofilter' program." - :type 'integer - :group 'spam-bogofilter) - -(defcustom spam-bogofilter-subsequent-timeout 15 - "Timeout in seconds for any subsequent reply from the `bogofilter' program." - :type 'integer - :group 'spam-bogofilter) - (defcustom spam-bogofilter-path (executable-find "bogofilter") "File path of the Bogofilter executable program." :type '(choice (file :tag "Location of bogofilter") (const :tag "Bogofilter is not installed")) :group 'spam-bogofilter) -;; FIXME! In the following regexp, we should explain which tool produces -;; which kind of header. I do not even remember them all by now. X-Junk -;; (and previously X-NoSpam) are produced by the `NoSpam' tool, which has -;; never been published, so it might not be reasonable leaving it in the -;; list. -(defcustom spam-bogofilter-spaminfo-header-regexp - "^X-\\(jf\\|Junk\\|NoSpam\\|Spam\\|SB\\)[^:]*:" - "Regexp for spam markups in headers. -Markup from spam recognisers, as well as `Xref', are to be removed from -articles before they get registered by Bogofilter." - :type 'regexp +(defcustom spam-bogofilter-header "X-Bogosity" + "The header that Bogofilter inserts in messages." + :type 'string :group 'spam-bogofilter) +(defcustom spam-bogofilter-database-directory nil + "Directory path of the Bogofilter databases." + :type '(choice (directory :tag "Location of the Bogofilter database directory") + (const :tag "Use the default")) + :group 'spam-ifile) + ;;; Key bindings for spam control. (gnus-define-keys gnus-summary-mode-map @@ -284,6 +274,9 @@ articles before they get registered by Bogofilter." (defun spam-group-ham-processor-ifile-p (group) (spam-group-processor-p group 'gnus-group-ham-exit-processor-ifile)) +(defun spam-group-ham-processor-bogofilter-p (group) + (spam-group-processor-p group 'gnus-group-ham-exit-processor-ifile)) + (defun spam-group-spam-processor-stat-p (group) (spam-group-processor-p group 'gnus-group-spam-exit-processor-stat)) @@ -307,7 +300,7 @@ articles before they get registered by Bogofilter." ;; The spam processors are invoked for any group, spam or ham or neither (when (and spam-bogofilter-path (spam-group-spam-processor-bogofilter-p gnus-newsgroup-name)) - (spam-bogofilter-register-routine)) + (spam-bogofilter-register-spam-routine)) (when (and spam-ifile-path (spam-group-spam-processor-ifile-p gnus-newsgroup-name)) @@ -316,7 +309,7 @@ articles before they get registered by Bogofilter." (when (spam-group-spam-processor-stat-p gnus-newsgroup-name) (spam-stat-register-spam-routine)) - (when (spam-group-spam-processor-bogofilter-p gnus-newsgroup-name) + (when (spam-group-spam-processor-blacklist-p gnus-newsgroup-name) (spam-blacklist-register-routine)) (if spam-move-spam-nonspam-groups-only @@ -335,6 +328,8 @@ articles before they get registered by Bogofilter." (spam-whitelist-register-routine)) (when (spam-group-ham-processor-ifile-p gnus-newsgroup-name) (spam-ifile-register-ham-routine)) + (when (spam-group-ham-processor-bogofilter-p gnus-newsgroup-name) + (spam-bogofilter-register-ham-routine)) (when (spam-group-ham-processor-stat-p gnus-newsgroup-name) (spam-stat-register-ham-routine)) (when (spam-group-ham-processor-BBDB-p gnus-newsgroup-name) @@ -417,14 +412,31 @@ articles before they get registered by Bogofilter." 'line-end-position))) (defun spam-get-article-as-string (article) - (let ((article-string)) + (let ((article-buffer (spam-get-article-as-buffer article)) + article-string) + (when article-buffer + (save-window-excursion + (set-buffer article-buffer) + (setq article-string (buffer-string)))) + article-string)) + +(defun spam-get-article-as-buffer (article) + (let ((article-buffer)) (when (numberp article) (save-window-excursion (gnus-summary-goto-subject article) (gnus-summary-show-article t) - (set-buffer gnus-article-buffer) - (setq article-string (buffer-string)))) - article-string)) + (setq article-buffer (get-buffer gnus-article-buffer)))) + article-buffer)) + +(defun spam-get-article-as-filename (article) + (let ((article-filename)) + (when (numberp article) + (nnml-possibly-change-directory (gnus-group-real-name gnus-newsgroup-name)) + (setq article-filename (expand-file-name (int-to-string article) nnml-current-directory))) + (if (file-exists-p article-filename) + article-filename + nil))) (defun spam-fetch-field-from-fast (article) "Fetch the `from' field quickly, using the internal gnus-data-list function" @@ -444,13 +456,14 @@ articles before they get registered by Bogofilter." ;;;; Spam determination. (defvar spam-list-of-checks - '((spam-use-blacklist . spam-check-blacklist) - (spam-use-whitelist . spam-check-whitelist) - (spam-use-BBDB . spam-check-BBDB) - (spam-use-ifile . spam-check-ifile) - (spam-use-stat . spam-check-stat) - (spam-use-blackholes . spam-check-blackholes) - (spam-use-bogofilter . spam-check-bogofilter)) + '((spam-use-blacklist . spam-check-blacklist) + (spam-use-whitelist . spam-check-whitelist) + (spam-use-BBDB . spam-check-BBDB) + (spam-use-ifile . spam-check-ifile) + (spam-use-stat . spam-check-stat) + (spam-use-blackholes . spam-check-blackholes) + (spam-use-bogofilter-headers . spam-check-bogofilter-headers) + (spam-use-bogofilter . spam-check-bogofilter)) "The spam-list-of-checks list contains pairs associating a parameter variable with a spam checking function. If the parameter variable is true, then the checking function is called, and its value decides what @@ -770,225 +783,72 @@ Uses `gnus-newsgroup-name' if category is nil (for ham registration)." ;;;; Bogofilter -;;; See Paul Graham article, at `http://www.paulgraham.com/spam.html'. - -;;; This page is for those wanting to control spam with the help of -;;; Eric Raymond's speedy Bogofilter, see -;;; http://www.tuxedo.org/~esr/bogofilter. This has been tested with -;;; a locally patched copy of version 0.4. - -;;; Make sure Bogofilter is installed. Bogofilter internally uses -;;; Judy fast associative arrays, so you need to install Judy first, -;;; and Bogofilter next. Fetch both distributions by visiting the -;;; following links and downloading the latest version of each: -;;; -;;; http://sourceforge.net/projects/judy/ -;;; http://www.tuxedo.org/~esr/bogofilter/ -;;; -;;; Unpack the Judy distribution and enter its main directory. Then do: -;;; -;;; ./configure -;;; make -;;; make install -;;; -;;; You will likely need to become super-user for the last step. -;;; Then, unpack the Bogofilter distribution and enter its main -;;; directory: -;;; -;;; make -;;; make install -;;; -;;; Here as well, you need to become super-user for the last step. -;;; Now, initialize your word lists by doing, under your own identity: -;;; -;;; mkdir ~/.bogofilter -;;; touch ~/.bogofilter/badlist -;;; touch ~/.bogofilter/goodlist -;;; -;;; These two files are text files you may edit, but you normally don't! - -;;; The `M-d' command gets added to Gnus summary mode, marking current -;;; article as spam, showing it with the `H' mark. Whenever you see a -;;; spam article, make sure to mark its summary line with `M-d' before -;;; leaving the group. Some groups, as per variable -;;; `spam-junk-mailgroups' below, receive articles from Gnus splitting -;;; on clues added by spam recognisers, so for these groups, we tack -;;; an `H' mark at group entry for all summary lines which would -;;; otherwise have no other mark. Make sure to _remove_ `H' marks for -;;; any article which is _not_ genuine spam, before leaving such -;;; groups: you may use `M-u' to "unread" the article, or `d' for -;;; declaring it read the non-spam way. When you leave a group, all -;;; `H' marked articles, saved or unsaved, are sent to Bogofilter -;;; which will study them as spam samples. - -;;; Messages may also be deleted in various other ways, and unless -;;; `spam-ham-marks-form' gets overridden below, marks `R' and `r' for -;;; default read or explicit delete, marks `X' and 'K' for automatic -;;; or explicit kills, as well as mark `Y' for low scores, are all -;;; considered to be associated with articles which are not spam. -;;; This assumption might be false, in particular if you use kill -;;; files or score files as means for detecting genuine spam, you -;;; should then adjust `spam-ham-marks-form'. When you leave a group, -;;; all _unsaved_ articles bearing any the above marks are sent to -;;; Bogofilter which will study these as not-spam samples. If you -;;; explicit kill a lot, you might sometimes end up with articles -;;; marked `K' which you never saw, and which might accidentally -;;; contain spam. Best is to make sure that real spam is marked with -;;; `H', and nothing else. - -;;; All other marks do not contribute to Bogofilter pre-conditioning. -;;; In particular, ticked, dormant or souped articles are likely to -;;; contribute later, when they will get deleted for real, so there is -;;; no need to use them prematurely. Explicitly expired articles do -;;; not contribute, command `E' is a way to get rid of an article -;;; without Bogofilter ever seeing it. - -;;; In a word, with a minimum of care for associating the `H' mark for -;;; spam articles only, Bogofilter training all gets fairly automatic. -;;; You should do this until you get a few hundreds of articles in -;;; each category, spam or not. The shell command `head -1 -;;; ~/.bogofilter/*' shows both article counts. The command `S S' in -;;; summary mode, either for debugging or for curiosity, triggers -;;; Bogofilter into displaying in another buffer the "spamicity" score -;;; of the current article (between 0.0 and 1.0), together with the -;;; article words which most significantly contribute to the score. - -;;; The real way for using Bogofilter, however, is to have some use -;;; tool like `procmail' for invoking it on message reception, then -;;; adding some recognisable header in case of detected spam. Gnus -;;; splitting rules might later trip on these added headers and react -;;; by sorting such articles into specific junk folders as per -;;; `spam-junk-mailgroups'. Here is a possible `.procmailrc' contents -;;; (still untested -- please tell me how it goes): -;;; -;;; :0HBf: -;;; * ? bogofilter -;;; | formail -bfI "X-Spam-Status: Yes" - -(defun spam-check-bogofilter () - ;; Dynamic spam check. I do not know how to check the exit status, - ;; so instead, read `bogofilter -v' output. - (when (and spam-use-bogofilter spam-bogofilter-path) - (spam-bogofilter-articles nil "-v" (list (gnus-summary-article-number))) - (when (save-excursion - (set-buffer spam-bogofilter-output-buffer-name) - (goto-char (point-min)) - (re-search-forward "Spamicity: \\(0\\.9\\|1\\.0\\)" nil t)) - spam-split-group))) - +(defun spam-check-bogofilter-headers (&optional score) + (let ((header (message-fetch-field spam-bogofilter-header))) + (when (and header + (string-match "^Yes" header)) + (if score + (when (string-match "spamicity=\\([0-9.]+\\)" header) + (match-string 1 header)) + spam-split-group)))) + + +;; return something sensible if the score can't be determined (defun spam-bogofilter-score () - "Use `bogofilter -v' on the current article. -This yields the 15 most discriminant words for this article and the -spamicity coefficient of each, and the overall article spamicity." + "Get the Bogofilter spamicity score" (interactive) - (when (and spam-use-bogofilter spam-bogofilter-path) - (spam-bogofilter-articles nil "-v" (list (gnus-summary-article-number))) - (with-current-buffer spam-bogofilter-output-buffer-name - (unless (zerop (buffer-size)) - (if (<= (count-lines (point-min) (point-max)) 1) - (progn - (goto-char (point-max)) - (when (bolp) - (backward-char 1)) - (message "%s" (buffer-substring (point-min) (point)))) - (goto-char (point-min)) - (display-buffer (current-buffer))))))) - -(defun spam-bogofilter-register-routine () - (let ((articles gnus-newsgroup-articles) - article mark ham-articles spam-articles spam-mark-values - ham-mark-values) - - ;; marks are stored as symbolic values, so we have to dereference - ;; them for memq to work we wouldn't have to do this if - ;; gnus-summary-article-mark returned a symbol. - (dolist (mark spam-ham-marks) - (push (symbol-value mark) ham-mark-values)) + (save-window-excursion + (gnus-summary-show-article t) + (set-buffer gnus-article-buffer) + (let ((score (spam-check-bogofilter t))) + (message "Spamicity score %s" score) + (or score "0")))) + +(defun spam-check-bogofilter (&optional score) + "Check the Bogofilter backend for the classification of this message" + (let ((article-buffer-name (buffer-name)) + return) + (with-temp-buffer + (let ((temp-buffer-name (buffer-name))) + (save-excursion + (set-buffer article-buffer-name) + (if spam-bogofilter-database-directory + (call-process-region (point-min) (point-max) + spam-bogofilter-path + nil temp-buffer-name nil "-v" + "-d" spam-bogofilter-database-directory) + (call-process-region (point-min) (point-max) spam-bogofilter-path + nil temp-buffer-name nil "-v"))) + (setq return (spam-check-bogofilter-headers score)))) + return)) - (dolist (mark spam-spam-marks) - (push (symbol-value mark) spam-mark-values)) +(defun spam-bogofilter-register-with-bogofilter (article-string spam) + "Register an article, given as a string, as spam or non-spam." + (when (stringp article-string) + (let ((switch (if spam "-s" "-n"))) + (with-temp-buffer + (insert-string article-string) + (if spam-bogofilter-database-directory + (call-process-region (point-min) (point-max) + spam-bogofilter-path + nil nil nil "-v" switch + "-d" spam-bogofilter-database-directory) + (call-process-region (point-min) (point-max) spam-bogofilter-path + nil nil nil "-v" switch)))))) + +(defun spam-bogofilter-register-spam-routine () + (spam-generic-register-routine + (lambda (article) + (spam-bogofilter-register-with-bogofilter + (spam-get-article-as-string article) t)) + nil)) - (while articles - (setq article (pop articles) - mark (gnus-summary-article-mark article)) - (cond ((memq mark spam-mark-values) (push article spam-articles)) - ((memq article gnus-newsgroup-saved)) - ((memq mark ham-mark-values) (push article ham-articles)))) - (when ham-articles - (spam-bogofilter-articles "ham" "-n" ham-articles)) - (when spam-articles - (spam-bogofilter-articles "SPAM" "-s" spam-articles)))) - -(defun spam-bogofilter-articles (type option articles) - (let ((output-buffer (get-buffer-create spam-bogofilter-output-buffer-name)) - (article-copy (get-buffer-create " *Bogofilter Article Copy*")) - (remove-regexp (concat spam-bogofilter-spaminfo-header-regexp - "\\|Xref:")) - (counter 0) - prefix process article) - (when type - (setq prefix (format "Studying %d articles as %s..." (length articles) - type)) - (message "%s" prefix)) - (save-excursion (set-buffer output-buffer) (erase-buffer)) - (setq process (start-process "bogofilter" output-buffer - spam-bogofilter-path "-F" option)) - (process-kill-without-query process t) - (unwind-protect - (save-window-excursion - (while articles - (setq counter (1+ counter)) - (when prefix - (message "%s %d" prefix counter)) - (setq article (pop articles)) - (gnus-summary-goto-subject article) - (gnus-summary-show-article t) - (gnus-eval-in-buffer-window article-copy - (insert-buffer-substring gnus-original-article-buffer) - ;; Remove spam classification redundant headers: they may induce - ;; unwanted biases in later analysis. - (message-remove-header remove-regexp t) - ;; Bogofilter really wants From envelopes for counting articles. - ;; Fake one at the beginning, make sure there will be no other. - (goto-char (point-min)) - (if (looking-at "From ") - (forward-line 1) - (insert "From nobody " (current-time-string) "\n")) - (let (case-fold-search) - (while (re-search-forward "^From " nil t) - (beginning-of-line) - (insert ">"))) - (process-send-region process (point-min) (point-max)) - (erase-buffer)))) - ;; Sending the EOF is unwind-protected. This is to prevent lost copies - ;; of `bogofilter', hung on reading their standard input, in case the - ;; whole registering process gets interrupted by the user. - (process-send-eof process)) - (kill-buffer article-copy) - ;; Receive process output. It sadly seems that we still have to protect - ;; ourselves against hung `bogofilter' processes. - (let ((status (process-status process)) - (timeout (* 1000 spam-bogofilter-initial-timeout)) - (quanta 200)) ; also counted in milliseconds - (while (and (not (eq status 'exit)) (> timeout 0)) - ;; `accept-process-output' timeout is counted in microseconds. - (setq timeout (if (accept-process-output process 0 (* 1000 quanta)) - (* 1000 spam-bogofilter-subsequent-timeout) - (- timeout quanta)) - status (process-status process))) - (if (eq status 'exit) - (when prefix - (message "%s done!" prefix)) - ;; Sigh! The process did time out... Become brutal! - (interrupt-process process) - (message "%s %d INTERRUPTED! (Article %d, status %s)" - (or prefix "Bogofilter process...") - counter article status) - ;; Give some time for user to read. Sitting redisplays but gives up - ;; if input is pending. Sleeping does not give up, but it does not - ;; redisplay either. Mix both: let's redisplay and not give up. - (sit-for 1) - (sleep-for 3))))) +(defun spam-bogofilter-register-ham-routine () + (spam-generic-register-routine + nil + (lambda (article) + (spam-bogofilter-register-with-bogofilter + (spam-get-article-as-string article) nil)))) (provide 'spam) diff --git a/make-x.bat b/make-x.bat index 4f5c4e0..f741794 100644 --- a/make-x.bat +++ b/make-x.bat @@ -10,28 +10,42 @@ set PWD= if "%1" == "" goto usage +rem Directory where the info files are installed +set GNUS_INFO_DIR=%1\..\..\xemacs-packages\info + set emacs=xemacs.exe if "%2" == "" set copy="false" if "%2" == "copy" set copy=true if "%2" == "/copy" set copy=true +set EMACSBATCH=call %1\%emacs% -batch -q -no-site-file + cd lisp -call %1\%emacs% -batch -q -no-site-file -l ./dgnushack.el -f dgnushack-compile +%EMACSBATCH% -l ./dgnushack.el -f dgnushack-compile if not %copy%==true goto info attrib -r %1\..\..\xemacs-packages\lisp\gnus\*.* copy *.el? %1\..\..\xemacs-packages\lisp\gnus :info -set EMACSINFO=call %1\%emacs% -no-site-file -no-init-file -batch -q -l infohack.el -f batch-makeinfo +set EMACSINFO=%EMACSBATCH% -l infohack.el -f batch-makeinfo cd ..\texi %EMACSINFO% message.texi %EMACSINFO% emacs-mime.texi %EMACSINFO% gnus.texi if not %copy%==true goto done -copy gnus %1\..\..\xemacs-packages\info -copy gnus-?? %1\..\..\xemacs-packages\info -copy message %1\..\..\xemacs-packages\info -copy emacs-mime %1\..\..\xemacs-packages\info +copy gnus %GNUS_INFO_DIR% +copy gnus-? %GNUS_INFO_DIR% +copy gnus-?? %GNUS_INFO_DIR% +copy message %GNUS_INFO_DIR% +copy message-? %GNUS_INFO_DIR% +copy emacs-mime %GNUS_INFO_DIR% +copy sieve %GNUS_INFO_DIR% +copy pgg %GNUS_INFO_DIR% +echo Maybe you should add the following line to %GNUS_INFO_DIR%\dir: +echo. +echo * PGG: (pgg). Emacs interface to various PGP implementations. +echo * Sieve: (sieve). Managing Sieve scripts in Emacs. +echo. :etc cd ..\etc @@ -57,4 +71,6 @@ echo set W3DIR=C:\Progra~1\XEmacs\xemacs-packages\lisp\w3 rem Restore PWD so whoever called this batch file doesn't get confused set PWD=%GNUS_PWD_SAVE% set GNUS_PWD_SAVE= +set EMACSBATCH= +set GNUS_INFO_DIR= :end diff --git a/make.bat b/make.bat index c4c8cc4..cbd49df 100755 --- a/make.bat +++ b/make.bat @@ -28,28 +28,41 @@ set PWD= if "%1" == "" goto usage +rem Directory where the info files are installed +set GNUS_INFO_DIR=%1\info + rem Emacs 20.7 no longer includes emacs.bat. Use emacs.exe if the batch file is rem not present -- this also fixes the problem about too many parameters on Win9x. set emacs=emacs.exe if exist %1\bin\emacs.bat set emacs=emacs.bat +set EMACSBATCH=call %1\bin\%emacs% -no-site-file -batch -q cd lisp -call %1\bin\%emacs% -batch -q -no-site-file -l ./dgnushack.el -f dgnushack-compile +%EMACSBATCH% -l ./dgnushack.el -f dgnushack-compile if not "%2" == "/copy" goto info attrib -r %1\lisp\gnus\* copy *.el* %1\lisp\gnus :info -set EMACSINFO=call %1\bin\%emacs% -no-site-file -no-init-file -batch -q -l infohack.el -f batch-makeinfo +set EMACSINFO=%EMACSBATCH% -l infohack.el -f batch-makeinfo cd ..\texi %EMACSINFO% message.texi %EMACSINFO% emacs-mime.texi %EMACSINFO% gnus.texi if not "%2" == "/copy" goto done -copy gnus %1\info -copy gnus-?? %1\info -copy message %1\info -copy emacs-mime %1\info +copy gnus %GNUS_INFO_DIR% +copy gnus-? %GNUS_INFO_DIR% +copy gnus-?? %GNUS_INFO_DIR% +copy message %GNUS_INFO_DIR% +copy message-? %GNUS_INFO_DIR% +copy emacs-mime %GNUS_INFO_DIR% +copy sieve %GNUS_INFO_DIR% +copy pgg %GNUS_INFO_DIR% +echo Maybe you should add the following line to %GNUS_INFO_DIR%\dir: +echo. +echo * PGG: (pgg). Emacs interface to various PGP implementations. +echo * Sieve: (sieve). Managing Sieve scripts in Emacs. +echo. :etc cd ..\etc @@ -74,4 +87,6 @@ echo set W3DIR=d:\lisp\w3-4.0pre46\lisp rem Restore PWD so whoever called this batch file doesn't get confused set PWD=%GNUS_PWD_SAVE% set GNUS_PWD_SAVE= +set EMACSBATCH= +set GNUS_INFO_DIR= :end diff --git a/texi/ChangeLog b/texi/ChangeLog index 4aeb90d..84b9365 100644 --- a/texi/ChangeLog +++ b/texi/ChangeLog @@ -1,3 +1,84 @@ +2003-01-21 Jesper Harder + + * gnus.texi (Various Summary Stuff): Add + gnus-summary-display-while-building. + (Group Parameters): Index gnus-parameters. + (Startup Files): Index gnus-site-init-file + +2003-01-20 Jesper Harder + + * gnus.texi (Summary Buffer Lines): Additions to %B. + + * gnus.texi: Markup fixes: use @code for nil and t, use @file for + files. + + * message.texi: do. + + * emacs-mime.texi: do. + +2003-01-19 Jesper Harder + + * dir (File): Add pgg. + + * gnus.texi (Selecting a Group): Index gnus-auto-select-subject + + * emacs-mime.texi (Display Customization): Add mm-keep-viewer-alive-types + +2003-01-16 Lars Magne Ingebrigtsen + + * gnus.texi (Summary Agent Commands): Addition. + +2003-01-16 Teodor Zlatanov + + * gnus.texi (Filtering Spam Using The Spam ELisp Package): + clarified syntax of gnus-spam-process-destinations and + gnus-ham-process-destinations variables + (Extending the spam elisp package): fixed typo in node name + (Bogofilter): new functionality and variables noted + (Filtering Spam Using The Spam ELisp Package): added mention of + nnimap-split-download-body + +2003-01-15 ShengHuo ZHU + + * gnus.texi: Don't use `path' in some cases. + From the GNU coding standards: + + Please do not use the term ``pathname'' that is used in Unix + documentation; use ``file name'' (two words) instead. We use + the term ``path'' only for search paths, which are lists of + directory names. + + * message.texi: Ditto. + +2003-01-15 Simon Josefsson + + * gnus.texi (X-Face): Revert substantial part of last fix. + (Splitting in IMAP): Add. + +2003-01-13 Reiner Steib + + * gnus.texi (Window Layout): Fixed braces in example. + +2003-01-13 Reiner Steib + + * gnus.texi (Article Washing): Use new function names in + `deuglify.el'. Addition. + +2003-01-13 Simon Josefsson + + * gnus.texi (X-Face): Fix. + + * message.texi (Security): Fix. + + * gnus.texi (Security): Fix. + (Signing and encrypting): Fix. + +2003-01-12 Teodor Zlatanov + + * gnus.texi (Filtering Spam Using The Spam ELisp Package): removed + spam.el and spam-stat.el from the node and section names wherever + possible, since info indexing doesn't like `.' in the name + 2003-01-12 Lars Magne Ingebrigtsen * gnus.texi (Article Display): Addition. diff --git a/texi/dir b/texi/dir index 3877572..57e9dec 100644 --- a/texi/dir +++ b/texi/dir @@ -20,3 +20,4 @@ File: dir Node: Top This is the Gnus Info tree * Message: (message). The Message sending thingamabob. * Emacs MIME: (emacs-mime). Libraries for handling MIME. * Sieve: (sieve). Managing Sieve scripts in Emacs. +* PGG: (pgg). Emacs interface to various PGP implementations. diff --git a/texi/emacs-mime.texi b/texi/emacs-mime.texi index 9fcc914..2261722 100644 --- a/texi/emacs-mime.texi +++ b/texi/emacs-mime.texi @@ -18,7 +18,8 @@ This file documents the Emacs MIME interface functionality. -Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or @@ -47,7 +48,7 @@ license to the document, as described in section 6 of the license. @page @vskip 0pt plus 1filll -Copyright @copyright{} 1998, 1999, 2000, 2001, 2002 Free Software +Copyright @copyright{} 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document @@ -309,6 +310,11 @@ be displayed automatically. This is a list of types that will be displayed automatically in an external viewer. +@item mm-keep-viewer-alive-types +@vindex mm-keep-viewer-alive-types +This is a list of media types for which the external viewer will not +be killed when selecting a different article. + @item mm-attachment-override-types @vindex mm-attachment-override-types Some @sc{mime} agents create parts that have a content-disposition of @@ -718,7 +724,7 @@ by using the @code{encoding} MML tag (@pxref{MML Definition}). @item mm-coding-system-priorities @vindex mm-coding-system-priorities Prioritize coding systems to use for outgoing messages. The default -is nil, which means to use the defaults in Emacs. It is a list of +is @code{nil}, which means to use the defaults in Emacs. It is a list of coding system symbols (aliases of coding systems does not work, use @kbd{M-x describe-coding-system} to make sure you are not specifying an alias in this variable). For example, if you have configured Emacs @@ -739,7 +745,7 @@ the @code{encoding} MML tag (@pxref{MML Definition}). @item mm-use-ultra-safe-encoding @vindex mm-use-ultra-safe-encoding -When this is non-nil, it means that textual parts are encoded as +When this is non-@code{nil}, it means that textual parts are encoded as quoted-printable if they contain lines longer than 76 characters or starting with "From " in the body. Non-7bit encodings (8bit, binary) are generally disallowed. This reduce the probability that a non-8bit @@ -1589,7 +1595,7 @@ Interface functions: @table @code @item mailcap-parse-mailcaps @findex mailcap-parse-mailcaps -Parse the @code{~/.mailcap} file. +Parse the @file{~/.mailcap} file. @item mailcap-mime-info Takes a @sc{mime} type as its argument and returns the matching viewer. diff --git a/texi/gnus.texi b/texi/gnus.texi index 6f5a309..1dcfeda 100644 --- a/texi/gnus.texi +++ b/texi/gnus.texi @@ -33,7 +33,7 @@ \makeindex \begin{document} -\newcommand{\gnusversionname}{Oort Gnus v0.12} +\newcommand{\gnusversionname}{Oort Gnus v0.13} \newcommand{\gnuschaptername}{} \newcommand{\gnussectionname}{} @@ -385,7 +385,7 @@ can be gotten by any nefarious means you can think of---@sc{nntp}, local spool or your mbox file. All at the same time, if you want to push your luck. -This manual corresponds to Oort Gnus v0.12. +This manual corresponds to Oort Gnus v0.13. @end ifinfo @@ -860,8 +860,8 @@ Thwarting Email Spam * Anti-Spam Basics:: Simple steps to reduce the amount of spam. * SpamAssassin:: How to use external anti-spam tools. * Hashcash:: Reduce spam by burning CPU time. -* Filtering Spam Using spam.el:: -* Filtering Spam Using Statistics (spam-stat.el):: +* Filtering Spam Using The Spam ELisp Package:: +* Filtering Spam Using Statistics with spam-stat:: Appendices @@ -1473,6 +1473,7 @@ startup files. If you want to turn backup creation off, say something like: @end lisp @vindex gnus-init-file +@vindex gnus-site-init-file When Gnus starts, it will read the @code{gnus-site-init-file} (@file{.../site-lisp/gnus} by default) and @code{gnus-init-file} (@file{~/.gnus} by default) files. These are normal Emacs Lisp files @@ -1624,7 +1625,7 @@ in a while from the group buffer instead (@pxref{Group Maintenance}). If non-@code{nil}, the startup message won't be displayed. That way, your boss might not notice as easily that you are reading news instead of doing your job. Note that this variable is used before -@file{.gnus.el} is loaded, so it should be set in @code{.emacs} instead. +@file{.gnus.el} is loaded, so it should be set in @file{.emacs} instead. @item gnus-no-groups-message @vindex gnus-no-groups-message @@ -2119,6 +2120,7 @@ be fetched. @vindex gnus-select-group-hook @vindex gnus-auto-select-first +@vindex gnus-auto-select-subject If @code{gnus-auto-select-first} is non-@code{nil}, select an article automatically when entering a group with the @kbd{SPACE} command. Which article this is is controlled by the @@ -2966,6 +2968,7 @@ presents you with a Customize-like interface. The latter helps avoid silly Lisp errors.) You might also be interested in reading about topic parameters (@pxref{Topic Parameters}). +@vindex gnus-parameters Group parameters can be set via the @code{gnus-parameters} variable too. But some variables, such as @code{visible}, have no effect. For example: @@ -4035,7 +4038,8 @@ For example: @vindex gnus-group-name-charset-group-alist An alist of regexp of group name and the charset for group names. It is used to show non-ASCII group names. @code{((".*" utf-8))} is the -default value if UTF-8 is supported, otherwise the default is nil. +default value if UTF-8 is supported, otherwise the default is +@code{nil}. For example: @lisp @@ -4143,10 +4147,10 @@ Fetch the control messages for the group from the archive at @code{ftp.isc.org} (@code{gnus-group-fetch-control}). Query for a group if given a prefix argument. -If @code{gnus-group-fetch-control-use-browse-url} is non-nil, Gnus -will open the control messages in a browser using @code{browse-url}. -Otherwise they are fetched using @code{ange-ftp} and displayed in an -ephemeral group. +If @code{gnus-group-fetch-control-use-browse-url} is non-@code{nil}, +Gnus will open the control messages in a browser using +@code{browse-url}. Otherwise they are fetched using @code{ange-ftp} +and displayed in an ephemeral group. Note that the control messages are compressed. To use this command you need to turn on @code{auto-compression-mode} @@ -4297,14 +4301,14 @@ regenerate the Sieve script. @vindex gnus-sieve-crosspost The variable @code{gnus-sieve-crosspost} controls how the Sieve script -is generated. If it is non-nil (the default) articles is placed in -all groups that have matching rules, otherwise the article is only -placed in the group with the first matching rule. For example, the -group parameter @samp{(sieve address "sender" +is generated. If it is non-@code{nil} (the default) articles is +placed in all groups that have matching rules, otherwise the article +is only placed in the group with the first matching rule. For +example, the group parameter @samp{(sieve address "sender" "owner-ding@@hpc.uh.edu")} will generate the following piece of Sieve -code if @code{gnus-sieve-crosspost} is nil. (When -@code{gnus-sieve-crosspost} is non-nil, it looks the same except that -the line containing the call to @code{stop} is removed.) +code if @code{gnus-sieve-crosspost} is @code{nil}. (When +@code{gnus-sieve-crosspost} is non-@code{nil}, it looks the same +except that the line containing the call to @code{stop} is removed.) @example if address "sender" "owner-ding@@hpc.uh.edu" @{ @@ -4486,7 +4490,52 @@ for example, @samp{1.2k} or @samp{0.4M}. Indentation based on thread level (@pxref{Customizing Threading}). @item B A complex trn-style thread tree, showing response-connecting trace -lines. +lines. A thread could be drawn like this: + +@example +> ++-> +| +-> +| | \-> +| | \-> +| \-> ++-> +\-> +@end example + +You can customize the appearance with the following options. Note +that it is possible to make the thread display look really neat by +replacing the default ASCII characters with graphic line-drawing +glyphs. +@table @code +@item gnus-sum-thread-tree-root +@vindex gnus-sum-thread-tree-root +Used for the root of a thread. If @code{nil}, use subject +instead. The default is @samp{> }. + +@item gnus-sum-thread-tree-single-indent +@vindex gnus-sum-thread-tree-single-indent +Used for a thread with just one message. If @code{nil}, use subject +instead. The default is @samp{}. + +@item gnus-sum-thread-tree-vertical +@vindex gnus-sum-thread-tree-vertical +Used for drawing a vertical line. The default is @samp{| }. + +@item gnus-sum-thread-tree-indent +@vindex gnus-sum-thread-tree-indent +Used for indenting. The default is @samp{ }. + +@item gnus-sum-thread-tree-leaf-with-other +@vindex gnus-sum-thread-tree-leaf-with-other +Used for a leaf with brothers. The default is @samp{+-> }. + +@item gnus-sum-thread-tree-single-leaf +@vindex gnus-sum-thread-tree-single-leaf +Used for a leaf without brothers. The default is @samp{\-> } + +@end table + @item T Nothing if the article is a root and lots of spaces if it isn't (it pushes everything after it off the screen). @@ -5503,7 +5552,7 @@ execute the @code{gnus-delay-send-queue} function. @findex gnus-delay-initialize By default, this function installs @code{gnus-delay-send-queue} in @code{gnus-get-new-news-hook}. But it accepts the optional second -argument @code{no-check}. If it is non-nil, +argument @code{no-check}. If it is non-@code{nil}, @code{gnus-get-new-news-hook} is not changed. The optional first argument is ignored. @@ -6340,7 +6389,7 @@ article. @code{gnus-summary-dummy-line-format} is used to specify the format of the dummy roots. It accepts only one format spec: @samp{S}, which is the subject of the article. @xref{Formatting Variables}. If you want all threads to have a dummy root, even the non-gathered -ones, set @code{gnus-summary-make-false-root-always} to t. +ones, set @code{gnus-summary-make-false-root-always} to @code{t}. @item empty Gnus won't actually make any article the parent, but simply leave the @@ -8296,17 +8345,17 @@ an attempt to provide more quoting characters. If you see something like @code{\222} or @code{\264} where you're expecting some kind of apostrophe or quotation mark, then try this wash. -@item W k -@kindex W k (Summary) +@item W Y f @kindex W Y f (Summary) @findex gnus-article-outlook-deuglify-article @cindex Outlook Express -Deuglify broken Outlook (Express) articles. +Full deuglify of broken Outlook (Express) articles: Treat dumbquotes, +unwrap lines, repair attribution and rearrange citation. (@code{gnus-article-outlook-deuglify-article}). @item W Y u @kindex W Y u (Summary) -@findex gnus-outlook-unwrap-lines +@findex gnus-article-outlook-unwrap-lines Unwrap lines that appear to be wrapped citation lines. You can control what lines will be unwrapped by frobbing @code{gnus-outlook-deuglify-unwrap-min} and @@ -8316,15 +8365,15 @@ maximum length of an unwrapped citation line. @item W Y a @kindex W Y a (Summary) -@findex gnus-outlook-repair-attribution -Repair a broken attribution line -(@code{gnus-outlook-repair-attribution}). +@findex gnus-article-outlook-repair-attribution +Repair a broken attribution line. +(@code{gnus-article-outlook-repair-attribution}). @item W Y c @kindex W Y c (Summary) -@findex gnus-outlook-rearrange-citation +@findex gnus-article-outlook-rearrange-citation Repair broken citations by rearranging the text. -(@code{gnus-outlook-rearrange-citation}). +(@code{gnus-article-outlook-rearrange-citation}). @item W w @kindex W w (Summary) @@ -9772,6 +9821,13 @@ suggestions you find reasonable. (Note that @end menu @table @code +@vindex gnus-summary-display-while-building +@item gnus-summary-display-while-building +If non-@code{nil}, show and update the summary buffer as it's being +built. If @code{t}, update the buffer after every line is inserted. +If the value is an integer, @var{n}, update the display every @var{n} +lines. The default is @code{nil}. + @vindex gnus-summary-mode-hook @item gnus-summary-mode-hook This hook is called when creating a summary mode buffer. @@ -10260,8 +10316,10 @@ however you need some external programs to get things to work: @enumerate @item -To handle PGP messages, you have to install mailcrypt or gpg.el as -well as a OpenPGP implementation (such as GnuPG). +To handle PGP and PGP/MIME messages, you have to install an OpenPGP +implementation such as GnuPG. The lisp interface to GnuPG included +with Gnus is called PGG (@pxref{Top, ,PGG, pgg, PGG Manual}), but +Mailcrypt and gpg.el are also supported. @item To handle @sc{s/mime} message, you need to install OpenSSL. OpenSSL 0.9.6 @@ -10285,6 +10343,18 @@ Option of decrypting encrypted parts. @code{never}, no decryption; @code{always}, always decrypt; @code{known}, only decrypt known protocols. Otherwise, ask user. +@item mml1991-use +@vindex mml1991-use +Symbol indicating elisp interface to OpenPGP implementation for PGP +messages. The default is @code{pgg}, but @code{mailcrypt} and +@code{gpg} are also supported although deprecated. + +@item mml2015-use +@vindex mml2015-use +Symbol indicating elisp interface to OpenPGP implementation for +PGP/MIME messages. The default is @code{pgg}, but @code{mailcrypt} +and @code{gpg} are also supported although deprecated. + @end table @node Mailing List @@ -10549,7 +10619,10 @@ message/external-body @sc{mime} type. @item c (Article) @kindex c (Article) Copy the @sc{mime} object to a fresh buffer and display this buffer -(@code{gnus-mime-copy-part}). +(@code{gnus-mime-copy-part}). Compressed files like @file{.gz} and +@file{.bz2} are automatically decompressed if +@code{auto-compression-mode} is enabled (@pxref{Compressed Files,, +Accessing Compressed Files, emacs, The Emacs Editor}). @findex gnus-mime-print-part @item p (Article) @@ -11507,10 +11580,6 @@ format or @sc{pgp/mime} or @sc{s/mime}. For decoding such messages, see the @code{mm-verify-option} and @code{mm-decrypt-option} options (@pxref{Security}). -For PGP, Gnus supports two external libraries, @sc{gpg.el} and -@sc{Mailcrypt}, you need to install at least one of them. The -@sc{s/mime} support in Gnus requires the external program OpenSSL. - Often, you would like to sign replies to people who send you signed messages. Even more often, you might want to encrypt messages which are in reply to encrypted messages. Gnus offers @@ -11568,7 +11637,7 @@ Remove security related MML tags from message. @end table -Also @xref{Security, ,Security, message, Message Manual}. +@xref{Security, ,Security, message, Message Manual}, for more information. @node Select Methods @chapter Select Methods @@ -12492,19 +12561,19 @@ Where the news lib dir is (@file{/usr/lib/news/} by default). @item nnspool-active-file @vindex nnspool-active-file -The path to the active file. +The name of the active file. @item nnspool-newsgroups-file @vindex nnspool-newsgroups-file -The path to the group descriptions file. +The name of the group descriptions file. @item nnspool-history-file @vindex nnspool-history-file -The path to the news history file. +The name of the news history file. @item nnspool-active-times-file @vindex nnspool-active-times-file -The path to the active date file. +The name of the active date file. @item nnspool-nov-is-evil @vindex nnspool-nov-is-evil @@ -12804,7 +12873,7 @@ Keywords: @table @code @item :path -The path of the file. Defaults to the value of the @code{MAIL} +The file name. Defaults to the value of the @code{MAIL} environment variable or the value of @code{rmail-spool-directory} (usually something like @file{/usr/mail/spool/user-name}). @end table @@ -12815,7 +12884,7 @@ An example file mail source: (file :path "/usr/spool/mail/user-name") @end lisp -Or using the default path: +Or using the default file name: @lisp (file) @@ -12869,7 +12938,7 @@ Keywords: @table @code @item :path -The path of the directory where the files are. There is no default +The name of the directory where the files are. There is no default value. @item :suffix @@ -13003,7 +13072,7 @@ Keywords: @table @code @item :path -The path of the directory where the mails are stored. The default is +The name of the directory where the mails are stored. The default is taken from the @code{MAILDIR} environment variable or @samp{~/Maildir/}. @item :subdirs @@ -13723,18 +13792,18 @@ Here's how: Go to the group buffer. @item -Type `G f' and give the path to the mbox file when prompted to create an +Type @kbd{G f} and give the file name to the mbox file when prompted to create an @code{nndoc} group from the mbox file (@pxref{Foreign Groups}). @item -Type `SPACE' to enter the newly created group. +Type @kbd{SPACE} to enter the newly created group. @item -Type `M P b' to process-mark all articles in this group's buffer +Type @kbd{M P b} to process-mark all articles in this group's buffer (@pxref{Setting Process Marks}). @item -Type `B r' to respool all the process-marked articles, and answer +Type @kbd{B r} to respool all the process-marked articles, and answer @samp{nnml} when prompted (@pxref{Mail Group Commands}). @end enumerate @@ -15508,6 +15577,15 @@ Example: Nnmail equivalent: @code{nnmail-split-fancy}. +@item nnimap-split-download-body +@findex nnimap-split-download-body +@vindex nnimap-split-download-body + +Set to non-nil to download entire articles during splitting. This is +generally not required, and will slow things down considerably. You +may need it if you want to use an advanced splitting function that +analyses the body to split the article. + @end table @node Expiring in IMAP @@ -17096,10 +17174,13 @@ Mark the article for downloading (@code{gnus-agent-mark-article}). Remove the downloading mark from the article (@code{gnus-agent-unmark-article}). +@cindex % @item @@ @kindex @@ (Agent Summary) @findex gnus-agent-toggle-mark -Toggle whether to download the article (@code{gnus-agent-toggle-mark}). +Toggle whether to download the article +(@code{gnus-agent-toggle-mark}). The dowload mark is @samp{%} by +default. @item J c @kindex J c (Agent Summary) @@ -18295,13 +18376,6 @@ The headers you can score on are @code{from}, @code{subject}, on the @code{References} header using the @code{Message-ID} of the current article, thereby matching the following thread. -You can also score on @code{thread}, which will try to score all -articles that appear in a thread. @code{thread} matches uses a -@code{Message-ID} to match on the @code{References} header of the -article. If the match is made, the @code{Message-ID} of the article is -added to the @code{thread} rule. (Think about it. I'd recommend two -aspirins afterwards.) - If you use this scheme, you should set the score file atom @code{mark} to something small---like -300, perhaps, to avoid having small random changes result in articles getting marked as read. @@ -19911,7 +19985,7 @@ might be used: (vertical 0.24 (if (buffer-live-p gnus-summary-buffer) '(summary 0.5)) - (group 1.0))))) + (group 1.0)))) @end lisp One common desire for a multiple frame split is to have a separate frame @@ -20029,7 +20103,7 @@ satisfied. This will result in the new specs being byte-compiled, and you'll get top speed again. Gnus will save these compiled specs in the @file{.newsrc.eld} file. (User-defined functions aren't compiled by this function, though---you should compile them yourself by sticking -them into the @code{.gnus.el} file and byte-compiling that file.) +them into the @file{.gnus.el} file and byte-compiling that file.) @node Mode Lines @@ -20963,17 +21037,24 @@ Gnus provides a few convenience functions and variables to allow easier insertion of X-Face headers in outgoing messages. @findex gnus-random-x-face -@code{gnus-random-x-face} goes through all the @samp{pbm} files -in @code{gnus-x-face-directory} and picks one at random, and then +@code{gnus-random-x-face} goes through all the @samp{pbm} files in +@code{gnus-x-face-directory} and picks one at random, and then converts it to the X-Face format by using the @code{gnus-convert-pbm-to-x-face-command} shell command. The -@samp{pbm} files should be 48x48 pixels big. +@samp{pbm} files should be 48x48 pixels big. It returns the X-Face +header data as a string. + +@findex gnus-insert-random-x-face-header +@code{gnus-insert-random-x-face-header} calls +@code{gnus-random-x-face} and inserts a @samp{X-Face} header with the +randomly generated data. +@findex gnus-x-face-from-file @code{gnus-x-face-from-file} takes a GIF file as the parameter, and then converts the file to X-Face format by using the @code{gnus-convert-image-to-x-face-command} shell command. -Here's how you would typically use the former function. Put something +Here's how you would typically use the first function. Put something like the following in your @file{.gnus.el} file: @lisp @@ -20982,7 +21063,7 @@ like the following in your @file{.gnus.el} file: (list '(X-Face . gnus-random-x-face)))) @end lisp -Using the latter function would be something like this: +Using the last function would be something like this: @lisp (setq message-required-news-headers @@ -21112,8 +21193,8 @@ This is annoying. Here's what you can do about it. * Anti-Spam Basics:: Simple steps to reduce the amount of spam. * SpamAssassin:: How to use external anti-spam tools. * Hashcash:: Reduce spam by burning CPU time. -* Filtering Spam Using spam.el:: -* Filtering Spam Using Statistics (spam-stat.el):: +* Filtering Spam Using The Spam ELisp Package:: +* Filtering Spam Using Statistics with spam-stat:: @end menu @node The problem of spam @@ -21407,10 +21488,10 @@ hashcash cookies, it is expected that this is performed by your hand customized mail filtering scripts. Improvements in this area would be a useful contribution, however. -@node Filtering Spam Using spam.el -@subsection Filtering Spam Using spam.el +@node Filtering Spam Using The Spam ELisp Package +@subsection Filtering Spam Using The Spam ELisp Package @cindex spam filtering -@cindex spam.el +@cindex spam The idea behind @code{spam.el} is to have a control center for spam detection and filtering in Gnus. To that end, @code{spam.el} does two things: it @@ -21444,8 +21525,7 @@ for unread articles in @emph{spam} groups. @findex spam-bogofilter-score @code{spam-bogofilter-score}. -You must have bogofilter processing enabled for that command to work -properly. +You must have Bogofilter installed for that command to work properly. @xref{Bogofilter}. @@ -21521,7 +21601,10 @@ marked as expired after processing with the spam processor. This is not done for @emph{unclassified} or @emph{ham} groups. Also, any @strong{ham} articles in a spam group will be moved to a location determined by either the @code{ham-process-destination} group -parameter or the @code{gnus-ham-process-destinations} variable. The +parameter or a match in the @code{gnus-ham-process-destinations} +variable, which is a list of regular expressions matched with group +names (it's easiest to customize this variable with +@code{customize-variable gnus-ham-process-destinations}). The ultimate location is a group name. If the @code{ham-process-destination} parameter is not set, spam articles are only expired. @@ -21530,10 +21613,13 @@ a ham processor, which will study these as non-spam samples. When you leave a @emph{ham} or @emph{unclassified} group, all @strong{spam} articles are moved to a location determined by either -the @code{spam-process-destination} group parameter or the -@code{gnus-spam-process-destinations} variable. The location is a -group name. If the @code{spam-process-destination} parameter is not -set, the spam articles are only expired. +the @code{spam-process-destination} group parameter or a match in the +@code{gnus-spam-process-destinations} variable, which is a list of +regular expressions matched with group names (it's easiest to +customize this variable with @code{customize-variable +gnus-spam-process-destinations}). The ultimate location is a group +name. If the @code{spam-process-destination} parameter is not set, +the spam articles are only expired. To use the @code{spam.el} facilities for incoming mail filtering, you must add the following to your fancy split list @@ -21552,6 +21638,18 @@ mail considered to be spam into the group name given by the variable @code{spam-split-group}. By default that group name is @samp{spam}, but you can customize it. +@emph{Note for IMAP users} + +The boolean variable @code{nnimap-split-download-body} needs to be +set, if you want to split based on the whole message instead of just +the headers. By default, the nnimap backend will only retrieve the +message headers. If you use spam-check-bogofilter, spam-check-ifile, +or spam-check-stat (the splitters that can benefit from the full +message body), you should set this variable. It is not set by default +because it will slow IMAP down. + +@xref{Splitting in IMAP}. + @emph{TODO: Currently, spam.el only supports insertion of articles into a backend. There is no way to tell spam.el that an article is no longer spam or ham.} @@ -21570,7 +21668,7 @@ The following are the methods you can use to control the behavior of * Bogofilter:: * ifile spam filtering:: * spam-stat spam filtering:: -* Extending spam.el:: +* Extending the spam elisp package:: @end menu @node Blacklists and Whitelists @@ -21578,22 +21676,22 @@ The following are the methods you can use to control the behavior of @cindex spam filtering @cindex whitelists, spam filtering @cindex blacklists, spam filtering -@cindex spam.el +@cindex spam @defvar spam-use-blacklist -Set this variable to t if you want to use blacklists when splitting -incoming mail. Messages whose senders are in the blacklist will be -sent to the @code{spam-split-group}. This is an explicit filter, -meaning that it acts only on mail senders @emph{declared} to be -spammers. +Set this variable to @code{t} if you want to use blacklists when +splitting incoming mail. Messages whose senders are in the blacklist +will be sent to the @code{spam-split-group}. This is an explicit +filter, meaning that it acts only on mail senders @emph{declared} to +be spammers. @end defvar @defvar spam-use-whitelist -Set this variable to t if you want to use whitelists when splitting -incoming mail. Messages whose senders are not in the whitelist will -be sent to the @code{spam-split-group}. This is an implicit filter, -meaning it believes everyone to be a spammer unless told otherwise. -Use with care. +Set this variable to @code{t} if you want to use whitelists when +splitting incoming mail. Messages whose senders are not in the +whitelist will be sent to the @code{spam-split-group}. This is an +implicit filter, meaning it believes everyone to be a spammer unless +told otherwise. Use with care. @end defvar @defvar gnus-group-spam-exit-processor-blacklist @@ -21639,7 +21737,7 @@ directly. The whitelist and blacklist files will by default be in the @cindex spam filtering @cindex BBDB whitelists, spam filtering @cindex BBDB, spam filtering -@cindex spam.el +@cindex spam @defvar spam-use-BBDB @@ -21665,7 +21763,7 @@ or @emph{unclassified} groups. @subsubsection Blackholes @cindex spam filtering @cindex blackholes, spam filtering -@cindex spam.el +@cindex spam @defvar spam-use-blackholes @@ -21694,7 +21792,7 @@ The list of servers to consult for blackhole checks. @defvar spam-use-dig Use the @code{dig.el} package instead of the @code{dns.el} package. -The default setting of t is recommended. +The default setting of @code{t} is recommended. @end defvar @@ -21705,47 +21803,82 @@ ham processor for blackholes. @subsubsection Bogofilter @cindex spam filtering @cindex bogofilter, spam filtering -@cindex spam.el +@cindex spam @defvar spam-use-bogofilter Set this variable if you want @code{spam-split} to use Eric Raymond's -speedy Bogofilter. This has been tested with a locally patched copy -of version 0.4. Make sure to read the installation comments in -@code{spam.el}. +speedy Bogofilter. With a minimum of care for associating the @samp{H} mark for spam articles only, Bogofilter training all gets fairly automatic. You should do this until you get a few hundreds of articles in each -category, spam or not. The shell command @command{head -1 -~/.bogofilter/*} shows both article counts. The command @kbd{S t} in -summary mode, either for debugging or for curiosity, triggers -Bogofilter into displaying in another buffer the @emph{spamicity} -score of the current article (between 0.0 and 1.0), together with the -article words which most significantly contribute to the score. +category, spam or not. The command @kbd{S t} in summary mode, either +for debugging or for curiosity, shows the @emph{spamicity} score of +the current article (between 0.0 and 1.0). + +Bogofilter determines if a message is spam based on an internal +threshold, set at compilation time. That threshold can't be +customized. If the @code{bogofilter} executable is not in your path, Bogofilter processing will be turned off. +You should not enable this if you use @code{spam-use-bogofilter-headers}. + @end defvar +@defvar spam-use-bogofilter-headers + +Set this variable if you want @code{spam-split} to use Eric Raymond's +speedy Bogofilter, looking only at the message headers. It works +similarly to @code{spam-use-bogofilter}, but the @code{X-Bogosity} header +must be in the message already. Normally you would do this with a +procmail recipe or something similar; consult the Bogofilter +installation documents for details. + +You should not enable this if you use @code{spam-use-bogofilter}. + +@end defvar @defvar gnus-group-spam-exit-processor-bogofilter Add this symbol to a group's @code{spam-process} parameter by customizing the group parameters or the @code{gnus-spam-process-newsgroups} variable. When this symbol is added to a group's @code{spam-process} parameter, spam-marked articles -will be added to the bogofilter spam database, and ham-marked articles -will be added to the bogofilter ham database. @strong{Note that the -Bogofilter spam processor is the only spam processor to also do ham -processing.} +will be added to the Bogofilter spam database. @end defvar +@defvar gnus-group-ham-exit-processor-bogofilter +Add this symbol to a group's @code{spam-process} parameter by +customizing the group parameters or the +@code{gnus-spam-process-newsgroups} variable. When this symbol is +added to a group's @code{spam-process} parameter, the ham-marked +articles in @emph{ham} groups will be added to the Bogofilter database +of non-spam messages. Note that this ham processor has no effect in +@emph{spam} or @emph{unclassified} groups. +@end defvar + +@defvar spam-bogofilter-database-directory + +This is the directory where Bogofilter will store its databases. It +is not specified by default, so Bogofilter will use its own default +database directory. + +@end defvar + +The Bogofilter mail classifier is similar to ifile in intent and +purpose. A ham and a spam processor are provided, plus the +@code{spam-use-bogofilter} and @code{spam-use-bogofilter-headers} +variables to indicate to spam-split that Bogofilter should either be +used, or has already been used on the article. The 0.9.2.1 version of +Bogofilter was used to test this functionality. + @node ifile spam filtering @subsubsection ifile spam filtering @cindex spam filtering @cindex ifile, spam filtering -@cindex spam.el +@cindex spam @defvar spam-use-ifile @@ -21786,10 +21919,10 @@ functionality. @subsubsection spam-stat spam filtering @cindex spam filtering @cindex spam-stat, spam filtering -@cindex spam-stat.el -@cindex spam.el +@cindex spam-stat +@cindex spam -@xref{Filtering Spam Using Statistics (spam-stat.el)}. +@xref{Filtering Spam Using Statistics with spam-stat}. @defvar spam-use-stat @@ -21822,11 +21955,11 @@ Bogofilter does not require external programs. A spam and a ham processor, and the @code{spam-use-stat} variable for @code{spam-split} are provided. -@node Extending spam.el -@subsubsection Extending spam.el +@node Extending the spam elisp package +@subsubsection Extending the spam elisp package @cindex spam filtering -@cindex spam.el, extending -@cindex extending spam.el +@cindex spam elisp package, extending +@cindex extending the spam elisp package Say you want to add a new back end called blackbox. For filtering incoming mail, provide the following: @@ -21911,8 +22044,8 @@ senders are kept in memory by Gnus. @end enumerate -@node Filtering Spam Using Statistics (spam-stat.el) -@subsection Filtering Spam Using Statistics (spam-stat.el) +@node Filtering Spam Using Statistics with spam-stat +@subsection Filtering Spam Using Statistics with spam-stat @cindex Paul Graham @cindex Graham, Paul @cindex naive Bayesian spam filtering @@ -22192,14 +22325,14 @@ Save table: (spam-stat-save) @table @code @item gnus-home-directory -All Gnus path variables will be initialized from this variable, which -defaults to @file{~/}. +All Gnus file and directory variables will be initialized from this +variable, which defaults to @file{~/}. @item gnus-directory @vindex gnus-directory -Most Gnus storage path variables will be initialized from this variable, -which defaults to the @samp{SAVEDIR} environment variable, or -@file{~/News/} if that variable isn't set. +Most Gnus storage file and directory variables will be initialized from +this variable, which defaults to the @samp{SAVEDIR} environment +variable, or @file{~/News/} if that variable isn't set. Note that Gnus is mostly loaded when the @file{.gnus.el} file is read. This means that other directory variables that are initialized from this @@ -25827,10 +25960,10 @@ write the following: This function (really ``special form'') @code{setq} is the one that can set a variable to some value. This is really all you need to know. Now -you can go and fill your @code{.emacs} file with lots of these to change +you can go and fill your @file{.emacs} file with lots of these to change how Gnus works. -If you have put that thing in your @code{.emacs} file, it will be read +If you have put that thing in your @file{.emacs} file, it will be read and @code{eval}ed (which is lisp-ese for ``run'') the next time you start Emacs. If you want to change the variable right away, simply say @kbd{C-x C-e} after the closing parenthesis. That will @code{eval} the diff --git a/texi/message.texi b/texi/message.texi index 1e6cd65..c63ad62 100644 --- a/texi/message.texi +++ b/texi/message.texi @@ -1004,14 +1004,14 @@ care in handling it. @subsection Using PGP/MIME @sc{pgp/mime} requires an external OpenPGP implementation, such as GNU -Privacy Guard (@uref{http://www.gnupg.org/}). It also requires an -Emacs interface to it, such as Mailcrypt (available from -@uref{http://www.nb.net/~lbudney/linux/software/mailcrypt.html}) or -Florian Weimer's @code{gpg.el}. +Privacy Guard (@uref{http://www.gnupg.org/}). One Emacs interface to +OpenPGP implementations, PGG (@pxref{Top, ,PGG, pgg, PGG Manual}), is +included, but Mailcrypt and Florian Weimer's @code{gpg.el} are also +supported. @vindex gpg-temp-directory Note, if you are using the @code{gpg.el} you must make sure that the -path specified by @code{gpg-temp-directory} have permissions 0700. +directory specified by @code{gpg-temp-directory} have permissions 0700. Creating your own OpenPGP key is described in detail in the documentation of your OpenPGP implementation, so we refer to it. @@ -1413,9 +1413,9 @@ the problem will actually occur. @item message-send-mail-partially-limit @vindex message-send-mail-partially-limit -The limitation of messages sent as message/partial. -The lower bound of message size in characters, beyond which the message -should be sent in several parts. If it is nil, the size is unlimited. +The limitation of messages sent as message/partial. The lower bound +of message size in characters, beyond which the message should be sent +in several parts. If it is @code{nil}, the size is unlimited. @end table @@ -1834,11 +1834,13 @@ This function won't add the header if the header is already present. @item message-send-mail-hook @vindex message-send-mail-hook -Hook run before sending mail messages. +Hook run before sending mail messages. This hook is run very late -- +just before the message is actually sent as mail. @item message-send-news-hook @vindex message-send-news-hook -Hook run before sending news messages. +Hook run before sending news messages. This hook is run very late -- +just before the message is actually sent as news. @item message-sent-hook @vindex message-sent-hook -- 1.7.10.4