From: yamaoka Date: Sun, 29 Aug 1999 23:53:08 +0000 (+0000) Subject: Sync up with Pterodactyl Gnus v0.96. X-Git-Tag: t-gnus-6_13_1-00~2 X-Git-Url: http://git.chise.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f4d4864936932e6e425d28a5b8b5e92c41942a2;p=elisp%2Fgnus.git- Sync up with Pterodactyl Gnus v0.96. --- diff --git a/README b/README index f845bbd..e487c43 100644 --- a/README +++ b/README @@ -9,7 +9,7 @@ You should definitely byte-compile the source files. To do that, you can simply say "./configure && make" in this directory. If you are using XEmacs, you *must* say "make EMACS=xemacs". In that case you may also want to pull down the package of nice glyphs from -. It should be installed +. It should be installed into the "gnus-5.6.53/etc" directory. Then you have to tell Emacs where Gnus is. You might put something diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 09a7cf5..b0c1665 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,229 @@ +Fri Aug 27 13:17:48 1999 Lars Magne Ingebrigtsen + + * gnus.el: Pterodactyl Gnus v0.96 is released. + +1999-08-17 Simon Josefsson + + * gnus-start.el (gnus-groups-to-gnus-format): Only use agent + to get active info if method is covered by agent, otherwise + active info is lost. + +1999-08-17 Simon Josefsson + + * gnus-sum.el (gnus-summary-move-article): Report backend errors. + +1999-08-09 Dave Love + + * mm-util.el: Use `defalias', not `fset' for dummy functions. + +1999-08-09 Simon Josefsson + + * gnus-art.el (gnus-ignored-headers): Remove "X-Pgp-*" + (already matched by "^X-Pgp"), removed duplicate + X-Mailing-List, added several new junk headers. + +1999-08-01 Simon Josefsson + + * gnus-art.el (article-decode-charset): Don't assume + gnus-summary-buffer is live. + +1999-08-27 15:07:43 Paul Flinders + + * smiley.el (smiley-deformed-regexp-alist): Fix % smileys. + +1999-08-27 15:02:58 Florian Weimer + + * gnus-score.el (gnus-home-score-file): Work with absolute path + names. + +1999-07-17 Shenghuo ZHU + + * gnus-sum.el (gnus-articles-to-read): Return cached articles if + nothing else in the group. + +1999-07-16 Shenghuo ZHU + + * gnus-bcklg.el (gnus-backlog-enter-article): Check the size of + the article. + +1999-07-15 Shenghuo ZHU + + * mm-uu.el (mm-uu-dissect): Fix for base64 message. + +1999-07-15 Shenghuo ZHU + + * mm-uu.el (mm-uu-forward-end-line): Support forwarded message + from mutt. + +1999-07-14 Shenghuo ZHU + + * mm-bodies.el (mm-decode-content-transfer-encoding): Delete + whitespace. + +1999-07-14 Shenghuo ZHU + + * mm-util.el (mm-text-coding-system-for-write): New variable. + (mm-append-to-file): New function. + (mm-write-region): New function. + + * gnus-art.el (gnus-output-to-file): Use it. + * gnus-util.el (gnus-output-to-rmail): Ditto. + (gnus-output-to-mail): Ditto. + * gnus-uu.el (gnus-uu-binhex-article): Ditto. + +1999-07-14 Shenghuo ZHU + + * nnmail.el (nnmail-find-file): Use mm-auto-mode-alist. + + * nnheader.el (nnheader-insert-file-contents): Revert and use + mm-insert-file-contents. + (nnheader-find-file-noselect): Use mm-auto-mode-alist. + (nnheader-auto-mode-alist): Removed. + + * mm-util.el (mm-inhibit-file-name-handlers): New variable. + (mm-insert-file-contents): Add a new parameter for inserting + compressed file literally. + + * mml.el (mml-generate-mime-1): Insert non-text literally. + + * gnus.el: Change most mm-insert-file-contents back to nnheader. + +1999-07-13 Hrvoje Niksic + + * gnus-art.el (gnus-unbuttonized-mime-types): Fix docstring. + +1999-08-27 14:53:42 Oleg S. Tihonov + + * gnus-sum.el (gnus-group-charset-alist): Default fido7 to + koi8-r. + +1999-07-11 Shenghuo ZHU + + * mml.el (mml-insert-mime): Decode text. + (mml-to-mime): Narrow to headers-or-head. + +1999-07-11 Shenghuo ZHU + + * mm-view.el (mm-inline-text): Check + w3-meta-content-type-charset-regexp. + +1999-07-10 Simon Josefsson + + * gnus-agent.el (gnus-agent-fetch-group-1): Search topics for + predicate. + +1999-07-10 Alexandre Oliva + + * gnus-mlspl.el: Documentation fixes. + +1999-08-27 14:42:14 Rui Zhu + + * gnus-sum.el (gnus-summary-limit-to-age): Prompt better. + +1999-08-27 14:40:52 Michael Cook + + * gnus-art.el (gnus-article-setup-buffer): Kill all local + variables. + +1999-08-27 14:39:34 Hrvoje Niksic + + * nnmail.el (nnmail-get-new-mail): "Done". + +1999-08-27 14:38:14 Lars Magne Ingebrigtsen + + * gnus-group.el (gnus-group-kill-all-zombies): Only prompt when + interactive. + +1999-07-12 Shenghuo ZHU + + * gnus-art.el (article-decode-charset): Fix broken CT. + +1999-07-12 Shenghuo ZHU + + * gnus-agent.el (gnus-agent-fetch-group-1): Recreate agent + overview buffer if it is killed. +1999-08-27 14:26:03 Eric Marsden + + * gnus-art.el (article-babel): New version. + +1999-08-27 14:22:39 Jon Kv + + * nnfolder.el (nnfolder-request-list-newsgroups): Faster expiry. + +1999-07-10 Mike McEwan + + * gnus.texi (More Threading): Document new variable + `gnus-sort-gathered-threads-function'. + +1999-07-10 Mike McEwan + + * gnus.texi (More Threading): Document new variable + `gnus-sort-gathered-threads-function'. + +1999-07-11 Andreas Jaeger + + * gnus-uu.el (gnus-uu-digest-mail-forward): Delete file after + usage. + +1999-07-10 Shenghuo ZHU + + * mm-util.el (mm-running-xemacs): Removed. + (mm-coding-system-p): New function. + (mm-binary-coding-system): Safe guess. + (mm-text-coding-system): Ditto. + (mm-auto-save-coding-system): Ditto. + +1999-07-11 11:02:03 Lars Magne Ingebrigtsen + + * mm-encode.el (mm-qp-or-base64): Also consider control chars. + (mm-qp-or-base64): Reversed logic. + + * mm-decode.el (mm-save-part-to-file): Let coding system be + binary. + +1999-07-15 Mike McEwan + + * gnus-agent.el (gnus-agent-fetch-group-1): Allow 'agent-score' to + be set in topic parameters. + +1999-07-10 Mike McEwan + + * gnus-sum.el (gnus-sort-gathered-threads-function): New variable. + (gnus-sort-gathered-threads): Allow the user to specify the + function to use when sorting gathered threads. + + * gnus-agent.el (gnus-agent-get-undownloaded-list): Don't + mark cached articles as `undownloaded'. + +Tue Jul 20 02:39:56 1999 Peter von der Ahé + + * gnus-sum.el (gnus-summary-exit): Allow gnus-use-adaptive-scoring + to have buffer local values. + +1999-07-25 Matt Pharr + + * gnus-group.el (gnus-group-make-doc-group): Notice when user + types 'g' for 'guess group type. + +1999-07-30 Simon Josefsson + + * nnmail.el (nnmail-remove-list-identifiers): Remove whitespace + after each regexp in nnmail-list-identifiers, not just after last + one. + + * gnus-sum.el (gnus-list-identifiers): New variable. + (gnus-summary-remove-list-identifiers): New function. + (gnus-select-newsgroup): Use it. + (gnus-summary-wash-hide-map): Bind + `gnus-article-hide-list-identifiers' to W W l. + (gnus-summary-make-menu-bar): Add list-identifiers command. + + * gnus-art.el (gnus-treat-strip-list-identifiers): New variable. + (gnus-treatment-function-alist): Add variable. + (article-hide-list-identifiers): New function. + (mapcar): Add function. + (gnus-article-hide): Use it. + Fri Jul 9 22:21:16 1999 Lars Magne Ingebrigtsen * gnus.el: Pterodactyl Gnus v0.95 is released. diff --git a/lisp/gnus-agent.el b/lisp/gnus-agent.el index a3ee284..0edd473 100644 --- a/lisp/gnus-agent.el +++ b/lisp/gnus-agent.el @@ -528,7 +528,8 @@ the actual number of articles toggled is returned." article) (while (setq article (pop articles)) (unless (or (cdr (assq article gnus-agent-article-alist)) - (memq article gnus-newsgroup-downloadable)) + (memq article gnus-newsgroup-downloadable) + (memq article gnus-newsgroup-cached)) (push article gnus-newsgroup-undownloaded)))) ;; Then mark downloaded downloadable as not-downloadable, ;; if you get my drift. @@ -964,20 +965,31 @@ the actual number of articles toggled is returned." category predicate info marks score-param) ;; Fetch headers. (when (and (or (gnus-active group) (gnus-activate-group group)) - (setq articles (gnus-agent-fetch-headers group))) - ;; Parse them and see which articles we want to fetch. - (setq gnus-newsgroup-dependencies - (make-vector (length articles) 0)) - ;; No need to call `gnus-get-newsgroup-headers-xover' with - ;; the entire .overview for group as we still have the just - ;; downloaded headers in `gnus-agent-overview-buffer'. - (let ((nntp-server-buffer gnus-agent-overview-buffer)) - (setq gnus-newsgroup-headers - (gnus-get-newsgroup-headers-xover articles nil nil group))) + (setq articles (gnus-agent-fetch-headers group)) + (progn + ;; Parse them and see which articles we want to fetch. + (setq gnus-newsgroup-dependencies + (make-vector (length articles) 0)) + ;; No need to call `gnus-get-newsgroup-headers-xover' with + ;; the entire .overview for group as we still have the just + ;; downloaded headers in `gnus-agent-overview-buffer'. + (let ((nntp-server-buffer gnus-agent-overview-buffer)) + (setq gnus-newsgroup-headers + (gnus-get-newsgroup-headers-xover articles nil nil + group))) + ;; `gnus-agent-overview-buffer' may be killed for + ;; timeout reason. If so, recreate it. + (if (gnus-buffer-live-p gnus-agent-overview-buffer) + t + (setq gnus-agent-overview-buffer + (gnus-get-buffer-create " *Gnus agent overview*")) + (with-current-buffer gnus-agent-overview-buffer + (set-buffer-multibyte t)) + nil))) (setq category (gnus-group-category group)) (setq predicate (gnus-get-predicate - (or (gnus-group-get-parameter group 'agent-predicate t) + (or (gnus-group-find-parameter group 'agent-predicate t) (cadr category)))) ;; Do we want to download everything, or nothing? (if (or (eq (caaddr predicate) 'gnus-agent-true) @@ -991,7 +1003,7 @@ the actual number of articles toggled is returned." (setq score-param (let ((score-method (or - (gnus-group-get-parameter group 'agent-score t) + (gnus-group-find-parameter group 'agent-score t) (caddr category)))) (when score-method (require 'gnus-score) @@ -1381,161 +1393,165 @@ The following commands are available: (save-excursion (setq overview (gnus-get-buffer-create " *expire overview*")) (while (setq gnus-command-method (pop methods)) - (with-temp-buffer - (insert-file-contents-as-coding-system - gnus-agent-file-coding-system (gnus-agent-lib-file "active")) - (gnus-active-to-gnus-format - gnus-command-method - (setq orig (gnus-make-hashtable - (count-lines (point-min) (point-max)))))) - (let ((expiry-hashtb (gnus-make-hashtable 1023))) - (gnus-agent-open-history) - (set-buffer - (setq gnus-agent-current-history - (setq history (gnus-agent-history-buffer)))) - (goto-char (point-min)) - (when (> (buffer-size) 1) - (goto-char (point-min)) - (while (not (eobp)) - (skip-chars-forward "^\t") - (if (> (read (current-buffer)) day) - ;; New article; we don't expire it. - (forward-line 1) - ;; Old article. Schedule it for possible nuking. - (while (not (eolp)) - (setq sym (let ((obarray expiry-hashtb)) - (read (current-buffer)))) - (if (boundp sym) - (set sym (cons (cons (read (current-buffer)) (point)) - (symbol-value sym))) - (set sym (list (cons (read (current-buffer)) (point))))) - (skip-chars-forward " ")) - (forward-line 1))) - ;; We now have all articles that can possibly be expired. - (mapatoms - (lambda (sym) - (setq group (symbol-name sym) - articles (sort (symbol-value sym) 'car-less-than-car) - low (car (gnus-active group)) - info (gnus-get-info group) - unreads (ignore-errors (gnus-list-of-unread-articles group)) - marked (nconc (gnus-uncompress-range - (cdr (assq 'tick (gnus-info-marks info)))) - (gnus-uncompress-range - (cdr (assq 'dormant (gnus-info-marks info)))) - (gnus-uncompress-range - (cdr (assq 'save (gnus-info-marks info)))) - (gnus-uncompress-range - (cdr (assq 'reply (gnus-info-marks info))))) - nov-file (gnus-agent-article-name ".overview" group) - lowest nil - highest nil) - (gnus-agent-load-alist group) - (gnus-message 5 "Expiring articles in %s" group) - (set-buffer overview) - (erase-buffer) - (when (file-exists-p nov-file) - (nnheader-insert-file-contents nov-file)) - (goto-char (point-min)) - (setq article 0) - (while (setq elem (pop articles)) - (setq article (car elem)) - (when (or (null low) - (< article low) - gnus-agent-expire-all - (and (not (memq article unreads)) - (not (memq article marked)))) - ;; Find and nuke the NOV line. - (while (and (not (eobp)) - (or (not (numberp - (setq art (read (current-buffer))))) - (< art article))) - (if (file-exists-p - (gnus-agent-article-name - (number-to-string art) group)) - (progn - (unless lowest - (setq lowest art)) - (setq highest art) - (forward-line 1)) - ;; Remove old NOV lines that have no articles. - (gnus-delete-line))) - (if (or (eobp) - (/= art article)) - (beginning-of-line) - (gnus-delete-line)) - ;; Nuke the article. - (when (file-exists-p (setq file (gnus-agent-article-name - (number-to-string article) - group))) - (delete-file file)) - ;; Schedule the history line for nuking. - (push (cdr elem) histories))) - (gnus-make-directory (file-name-directory nov-file)) - (write-region-as-coding-system - gnus-agent-file-coding-system - (point-min) (point-max) nov-file nil 'silent) - ;; Delete the unwanted entries in the alist. - (setq gnus-agent-article-alist - (sort gnus-agent-article-alist 'car-less-than-car)) - (let* ((alist gnus-agent-article-alist) - (prev (cons nil alist)) - (first prev) - expired) - (while (and alist - (<= (caar alist) article)) - (if (or (not (cdar alist)) - (not (file-exists-p - (gnus-agent-article-name - (number-to-string - (caar alist)) - group)))) - (progn - (push (caar alist) expired) - (setcdr prev (setq alist (cdr alist)))) - (setq prev alist - alist (cdr alist)))) - (setq gnus-agent-article-alist (cdr first)) - (gnus-agent-save-alist group) - ;; Mark all articles up to the first article - ;; in `gnus-article-alist' as read. - (when (and info (caar gnus-agent-article-alist)) - (setcar (nthcdr 2 info) - (gnus-range-add - (nth 2 info) - (cons 1 (- (caar gnus-agent-article-alist) 1))))) - ;; Maybe everything has been expired from `gnus-article-alist' - ;; and so the above marking as read could not be conducted, - ;; or there are expired article within the range of the alist. - (when (and info - expired - (or (not (caar gnus-agent-article-alist)) - (> (car expired) - (caar gnus-agent-article-alist)))) - (setcar (nthcdr 2 info) - (gnus-add-to-range - (nth 2 info) - (nreverse expired)))) - (gnus-dribble-enter - (concat "(gnus-group-set-info '" - (gnus-prin1-to-string info) - ")"))) - (when lowest - (if (gnus-gethash group orig) - (setcar (gnus-gethash group orig) lowest) - (gnus-sethash group (cons lowest highest) orig)))) - expiry-hashtb) - (set-buffer history) - (setq histories (nreverse (sort histories '<))) - (while histories - (goto-char (pop histories)) - (gnus-delete-line)) - (gnus-agent-save-history) - (gnus-agent-close-history) - (gnus-write-active-file-as-coding-system - gnus-agent-file-coding-system - (gnus-agent-lib-file "active") orig)) - (gnus-message 4 "Expiry...done")))))) + (when (file-exists-p (gnus-agent-lib-file "active")) + (with-temp-buffer + (insert-file-contents-as-coding-system + gnus-agent-file-coding-system (gnus-agent-lib-file "active")) + (gnus-active-to-gnus-format + gnus-command-method + (setq orig (gnus-make-hashtable + (count-lines (point-min) (point-max)))))) + (let ((expiry-hashtb (gnus-make-hashtable 1023))) + (gnus-agent-open-history) + (set-buffer + (setq gnus-agent-current-history + (setq history (gnus-agent-history-buffer)))) + (goto-char (point-min)) + (when (> (buffer-size) 1) + (goto-char (point-min)) + (while (not (eobp)) + (skip-chars-forward "^\t") + (if (> (read (current-buffer)) day) + ;; New article; we don't expire it. + (forward-line 1) + ;; Old article. Schedule it for possible nuking. + (while (not (eolp)) + (setq sym (let ((obarray expiry-hashtb)) + (read (current-buffer)))) + (if (boundp sym) + (set sym (cons (cons (read (current-buffer)) (point)) + (symbol-value sym))) + (set sym (list (cons (read (current-buffer)) (point))))) + (skip-chars-forward " ")) + (forward-line 1))) + ;; We now have all articles that can possibly be expired. + (mapatoms + (lambda (sym) + (setq group (symbol-name sym) + articles (sort (symbol-value sym) 'car-less-than-car) + low (car (gnus-active group)) + info (gnus-get-info group) + unreads (ignore-errors + (gnus-list-of-unread-articles group)) + marked (nconc + (gnus-uncompress-range + (cdr (assq 'tick (gnus-info-marks info)))) + (gnus-uncompress-range + (cdr (assq 'dormant (gnus-info-marks info)))) + (gnus-uncompress-range + (cdr (assq 'save (gnus-info-marks info)))) + (gnus-uncompress-range + (cdr (assq 'reply (gnus-info-marks info))))) + nov-file (gnus-agent-article-name ".overview" group) + lowest nil + highest nil) + (gnus-agent-load-alist group) + (gnus-message 5 "Expiring articles in %s" group) + (set-buffer overview) + (erase-buffer) + (when (file-exists-p nov-file) + (nnheader-insert-file-contents nov-file)) + (goto-char (point-min)) + (setq article 0) + (while (setq elem (pop articles)) + (setq article (car elem)) + (when (or (null low) + (< article low) + gnus-agent-expire-all + (and (not (memq article unreads)) + (not (memq article marked)))) + ;; Find and nuke the NOV line. + (while (and (not (eobp)) + (or (not (numberp + (setq art (read (current-buffer))))) + (< art article))) + (if (file-exists-p + (gnus-agent-article-name + (number-to-string art) group)) + (progn + (unless lowest + (setq lowest art)) + (setq highest art) + (forward-line 1)) + ;; Remove old NOV lines that have no articles. + (gnus-delete-line))) + (if (or (eobp) + (/= art article)) + (beginning-of-line) + (gnus-delete-line)) + ;; Nuke the article. + (when (file-exists-p + (setq file (gnus-agent-article-name + (number-to-string article) + group))) + (delete-file file)) + ;; Schedule the history line for nuking. + (push (cdr elem) histories))) + (gnus-make-directory (file-name-directory nov-file)) + (write-region-as-coding-system + gnus-agent-file-coding-system + (point-min) (point-max) nov-file nil 'silent) + ;; Delete the unwanted entries in the alist. + (setq gnus-agent-article-alist + (sort gnus-agent-article-alist 'car-less-than-car)) + (let* ((alist gnus-agent-article-alist) + (prev (cons nil alist)) + (first prev) + expired) + (while (and alist + (<= (caar alist) article)) + (if (or (not (cdar alist)) + (not (file-exists-p + (gnus-agent-article-name + (number-to-string + (caar alist)) + group)))) + (progn + (push (caar alist) expired) + (setcdr prev (setq alist (cdr alist)))) + (setq prev alist + alist (cdr alist)))) + (setq gnus-agent-article-alist (cdr first)) + (gnus-agent-save-alist group) + ;; Mark all articles up to the first article + ;; in `gnus-article-alist' as read. + (when (and info (caar gnus-agent-article-alist)) + (setcar (nthcdr 2 info) + (gnus-range-add + (nth 2 info) + (cons 1 (- (caar gnus-agent-article-alist) 1))))) + ;; Maybe everything has been expired from `gnus-article-alist' + ;; and so the above marking as read could not be conducted, + ;; or there are expired article within the range of the alist. + (when (and info + expired + (or (not (caar gnus-agent-article-alist)) + (> (car expired) + (caar gnus-agent-article-alist)))) + (setcar (nthcdr 2 info) + (gnus-add-to-range + (nth 2 info) + (nreverse expired)))) + (gnus-dribble-enter + (concat "(gnus-group-set-info '" + (gnus-prin1-to-string info) + ")"))) + (when lowest + (if (gnus-gethash group orig) + (setcar (gnus-gethash group orig) lowest) + (gnus-sethash group (cons lowest highest) orig)))) + expiry-hashtb) + (set-buffer history) + (setq histories (nreverse (sort histories '<))) + (while histories + (goto-char (pop histories)) + (gnus-delete-line)) + (gnus-agent-save-history) + (gnus-agent-close-history) + (gnus-write-active-file-as-coding-system + gnus-agent-file-coding-system + (gnus-agent-lib-file "active") orig)) + (gnus-message 4 "Expiry...done"))))))) ;;;###autoload (defun gnus-agent-batch () diff --git a/lisp/gnus-art.el b/lisp/gnus-art.el index 29e27b0..caa14c1 100644 --- a/lisp/gnus-art.el +++ b/lisp/gnus-art.el @@ -127,11 +127,18 @@ "^Originator:" "^X-Problems-To:" "^X-Auth-User:" "^X-Post-Time:" "^X-Admin:" "^X-UID:" "^Resent-[-A-Za-z]+:" "^X-Mailing-List:" "^Precedence:" "^Original-[-A-Za-z]+:" "^X-filename:" "^X-Orcpt:" - "^Old-Received:" "^X-Pgp-Fingerprint:" "^X-Pgp-Key-Id:" - "^X-Pgp-Public-Key-Url:" "^X-Auth:" "^X-From-Line:" + "^Old-Received:" "^X-Pgp" "^X-Auth:" "^X-From-Line:" "^X-Gnus-Article-Number:" "^X-Majordomo:" "^X-Url:" "^X-Sender:" - "^X-Mailing-List:" "^MBOX-Line" "^Priority:" "^X-Pgp" "^X400-[-A-Za-z]+:" - "^Status:" "^X-Gnus-Mail-Source:" "^Cancel-Lock:") + "^MBOX-Line" "^Priority:" "^X-Pgp" "^X400-[-A-Za-z]+:" + "^Status:" "^X-Gnus-Mail-Source:" "^Cancel-Lock:" + "^X-FTN" "^X-EXP32-SerialNo:" "^Encoding:" "^Importance:" + "^Autoforwarded:" "^Original-Encoded-Information-Types:" "^X-Ya-Pop3:" + "^X-Face-Version:" "^X-Vms-To:" "^X-ML-NAME:" "^X-ML-COUNT:" + "^Mailing-List:" "^X-finfo:" "^X-md5sum:" "^X-md5sum-Origin:" + "^X-Sun-Charset:" "^X-Accept-Language:" "^X-Envelope-Sender:" + "^List-[A-Za-z]+:" "^X-Listprocessor-Version:" + "^X-Received:" "^X-Distribute:" "^X-Sequence:" "^X-Juno-Line-Breaks:" + "^X-Notes-Item:" "^X-MS-TNEF-Correlator:" "^x-uunet-gateway:") "*All headers that start with this regexp will be hidden. This variable can also be a list of regexps of headers to be ignored. If `gnus-visible-headers' is non-nil, this variable will be ignored." @@ -611,7 +618,7 @@ displayed by the first non-nil matching CONTENT face." :type '(repeat regexp)) (defcustom gnus-unbuttonized-mime-types '(".*/.*") - "List of MIME types that should not be given buttons when rendered." + "List of MIME types that should not be given buttons when rendered inline." :group 'gnus-article-mime :type '(repeat regexp)) @@ -734,6 +741,13 @@ See the manual for details." :group 'gnus-article-treat :type gnus-article-treat-custom) +(defcustom gnus-treat-strip-list-identifiers 'head + "Strip list identifiers from `gnus-list-identifiers`. +Valid values are nil, t, `head', `last', an integer or a predicate. +See the manual for details." + :group 'gnus-article-treat + :type gnus-article-treat-custom) + (defcustom gnus-treat-strip-pgp t "Strip PGP signatures. Valid values are nil, t, `head', `last', an integer or a predicate. @@ -936,6 +950,7 @@ See the manual for details." (gnus-treat-hide-boring-headers gnus-article-hide-boring-headers) (gnus-treat-hide-signature gnus-article-hide-signature) (gnus-treat-hide-citation gnus-article-hide-citation) + (gnus-treat-strip-list-identifiers gnus-article-hide-list-identifiers) (gnus-treat-strip-pgp gnus-article-hide-pgp) (gnus-treat-strip-pem gnus-article-hide-pem) (gnus-treat-highlight-headers gnus-article-highlight-headers) @@ -1533,9 +1548,13 @@ If PROMPT (the prefix), prompt for a coding system to use." (mail-content-type-get ctl 'charset)))) (mail-parse-charset gnus-newsgroup-charset) (mail-parse-ignored-charsets - (save-excursion (set-buffer gnus-summary-buffer) + (save-excursion (condition-case nil + (set-buffer gnus-summary-buffer) + (error)) gnus-newsgroup-ignored-charsets)) buffer-read-only) + (if (and ctl (not (string-match "/" (car ctl)))) + (setq ctl nil)) (goto-char (point-max)) (widen) (forward-line 1) @@ -1575,6 +1594,24 @@ or not." (when charset (mm-decode-body charset))))))) +(defun article-hide-list-identifiers () + "Remove any list identifiers in `gnus-list-identifiers' from Subject +header in the current article." + (interactive) + (save-excursion + (save-restriction + (let ((inhibit-point-motion-hooks t) + buffer-read-only) + (article-narrow-to-head) + (let ((regexp (if (stringp gnus-list-identifiers) gnus-list-identifiers + (mapconcat 'identity gnus-list-identifiers " *\\|")))) + (when regexp + (goto-char (point-min)) + (when (re-search-forward + (concat "^Subject: +\\(Re: +\\)?\\(" regexp " *\\)") + nil t) + (delete-region (match-beginning 2) (match-end 0))))))))) + (defun article-hide-pgp () "Remove any PGP headers and signatures in the current article." (interactive) @@ -1659,17 +1696,9 @@ always hide." (while (re-search-forward banner nil t) (delete-region (match-beginning 0) (match-end 0)))))))))) -(defun article-babel-prompt () - "Prompt for a babel translation." - (require 'babel) - (completing-read "Translate from: " - babel-translations nil t - (car (car babel-translations)) - babel-history)) - -(defun article-babel (translation) - "Translate article according to TRANSLATION using babelfish." - (interactive (list (article-babel-prompt))) +(defun article-babel () + "Translate article using an online translation service." + (interactive) (require 'babel) (save-excursion (set-buffer gnus-article-buffer) @@ -1677,14 +1706,12 @@ always hide." (let* ((buffer-read-only nil) (start (point)) (end (point-max)) - (msg (buffer-substring start end))) + (orig (buffer-substring start end)) + (trans (babel-as-string orig))) (save-restriction (narrow-to-region start end) (delete-region start end) - (babel-fetch msg (cdr (assoc translation babel-translations))) - (save-restriction - (narrow-to-region start (point-max)) - (babel-wash))))))) + (insert trans)))))) (defun article-hide-signature (&optional arg) "Hide the signature in the current article. @@ -2501,6 +2528,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is article-remove-cr article-display-x-face article-de-quoted-unreadable + article-hide-list-identifiers article-hide-pgp article-strip-banner article-babel @@ -2680,6 +2708,7 @@ commands: (if (get-buffer name) (save-excursion (set-buffer name) + (kill-all-local-variables) (buffer-disable-undo) (setq buffer-read-only t) (unless (eq major-mode 'gnus-article-mode) @@ -3613,7 +3642,7 @@ Provided for backwards compatibility." ;; save it to file. (goto-char (point-max)) (insert "\n") - (append-to-file (point-min) (point-max) file-name) + (write-region-as-binary (point-min) (point-max) file-name 'append) t))) (defun gnus-narrow-to-page (&optional arg) @@ -3849,6 +3878,7 @@ headers will be hidden. If given a prefix, show the hidden text instead." (interactive (append (gnus-article-hidden-arg) (list 'force))) (gnus-article-hide-headers arg) + (gnus-article-hide-list-identifiers arg) (gnus-article-hide-pgp arg) (gnus-article-hide-citation-maybe arg force) (gnus-article-hide-signature arg)) diff --git a/lisp/gnus-bcklg.el b/lisp/gnus-bcklg.el index 9badf94..a47a199 100644 --- a/lisp/gnus-bcklg.el +++ b/lisp/gnus-bcklg.el @@ -82,7 +82,9 @@ (setq b (point)) (insert-buffer-substring buffer) ;; Tag the beginning of the article with the ident. - (gnus-put-text-property b (1+ b) 'gnus-backlog ident)))))) + (if (> (point-max) b) + (gnus-put-text-property b (1+ b) 'gnus-backlog ident) + (gnus-error 3 "Article %d is blank" number))))))) (defun gnus-backlog-remove-oldest-article () (save-excursion diff --git a/lisp/gnus-group.el b/lisp/gnus-group.el index 4593af0..3428f3b 100644 --- a/lisp/gnus-group.el +++ b/lisp/gnus-group.el @@ -2054,6 +2054,7 @@ and NEW-NAME will be prompted for." ((= char ?d) 'digest) ((= char ?f) 'forward) ((= char ?a) 'mmfd) + ((= char ?g) 'guess) (t (setq err (format "%c unknown. " char)) nil)))) (setq type found))) @@ -2687,10 +2688,11 @@ N and the number of steps taken is returned." (gnus-group-yank-group) (gnus-group-position-point))) -(defun gnus-group-kill-all-zombies () - "Kill all zombie newsgroups." - (interactive) - (when (gnus-yes-or-no-p "Really kill all zombies? ") +(defun gnus-group-kill-all-zombies (&optional dummy) + "Kill all zombie newsgroups. +The optional DUMMY should always be nil." + (interactive (list (not (gnus-yes-or-no-p "Really kill all zombies? ")))) + (unless dummy (setq gnus-killed-list (nconc gnus-zombie-list gnus-killed-list)) (setq gnus-zombie-list nil) (gnus-dribble-touch) diff --git a/lisp/gnus-mlspl.el b/lisp/gnus-mlspl.el index 8936bc5..716426e 100644 --- a/lisp/gnus-mlspl.el +++ b/lisp/gnus-mlspl.el @@ -38,8 +38,8 @@ default catch-all group") splitting, and defines the variable nnmail-split-fancy according with group parameters. -if AUTO-UPDATE is non-nil (prefix argument accepted, if called -interactive), makes sure nnmail-split-fancy is re-computed before +If AUTO-UPDATE is non-nil (prefix argument accepted, if called +interactively), it makes sure nnmail-split-fancy is re-computed before getting new mail, by adding gnus-group-split-update to nnmail-pre-get-new-mail-hook." (interactive "P") @@ -92,7 +92,7 @@ otherwise, a | split, that does not allow crossposting, will be returned. if CATCH-ALL is not nil, and there is no selected group whose -split-regexp matches the empty string, nor is there a selected group +SPLIT-REGEXP matches the empty string, nor is there a selected group whose SPLIT-SPEC is 'catch-all, this group name will be appended to the returned SPLIT list, as the last element in a '| SPLIT. @@ -121,10 +121,10 @@ nnml:mail.others: Calling (gnus-group-split-fancy nil nil \"mail.misc\") returns: \(| (& (any \"\\\\(bar@femail\\\\.com\\\\|.*@femail\\\\.com\\\\)\" - \"nnml:mail.bar\") + \"mail.bar\") (any \"\\\\(foo@nowhere\\\\.gov\\\\|foo@localhost\\\\|foo-redist@home\\\\)\" - - \"bugs-foo\" - \"rambling-foo\" \"nnml:mail.foo\")) - \"nnml:mail.others\")" + - \"bugs-foo\" - \"rambling-foo\" \"mail.foo\")) + \"mail.others\")" (let* ((newsrc (cdr gnus-newsrc-alist)) split) (dolist (info newsrc) diff --git a/lisp/gnus-score.el b/lisp/gnus-score.el index 8a39075..aac8a97 100644 --- a/lisp/gnus-score.el +++ b/lisp/gnus-score.el @@ -2887,7 +2887,9 @@ If ADAPT, return the home adaptive file instead." (when (string-match (gnus-globalify-regexp (car elem)) group) (replace-match (cadr elem) t nil group )))))) (when found - (nnheader-concat gnus-kill-files-directory found)))) + (if (file-name-absolute-p found) + found + (nnheader-concat gnus-kill-files-directory found))))) (defun gnus-hierarchial-home-score-file (group) "Return the score file of the top-level hierarchy of GROUP." diff --git a/lisp/gnus-start.el b/lisp/gnus-start.el index eca5c70..ec37c36 100644 --- a/lisp/gnus-start.el +++ b/lisp/gnus-start.el @@ -1832,7 +1832,7 @@ newsgroup." (gnus-group-prefixed-name "" method)))) ;; Let the Gnus agent save the active file. - (if (and gnus-agent real-active gnus-plugged) + (if (and gnus-agent real-active gnus-plugged (gnus-agent-method-p method)) (progn (gnus-agent-save-groups method) (gnus-active-to-gnus-format method hashtb nil real-active)) diff --git a/lisp/gnus-sum.el b/lisp/gnus-sum.el index 89f612f..347111f 100644 --- a/lisp/gnus-sum.el +++ b/lisp/gnus-sum.el @@ -568,6 +568,15 @@ with some simple extensions: :group 'gnus-summary-format :type 'string) +(defcustom gnus-list-identifiers nil + "Regexp that matches list identifiers to be removed from subject. +This can also be a list of regexps." + :group 'gnus-summary-format + :group 'gnus-article-hiding + :type '(choice (const :tag "none" nil) + (regexp :value ".*") + (repeat :value (".*") regexp))) + (defcustom gnus-summary-mark-below 0 "*Mark all articles with a score below this variable as read. This variable is local to each summary buffer and usually set by the @@ -832,6 +841,7 @@ which it may alter in any way.") ("^cn\\>\\|\\" cn-gb-2312) ("^fj\\>\\|^japan\\>" iso-2022-jp-2) ("^relcom\\>" koi8-r) + ("^fido7\\>" koi8-r) ("^\\(cz\\|hun\\|pl\\|sk\\|hr\\)\\>" iso-8859-2) ("^israel\\>" iso-8859-1) ("^han\\>" euc-kr) @@ -900,6 +910,9 @@ by moving the mouse over the edge of the article window." (defvar gnus-thread-indent-array nil) (defvar gnus-thread-indent-array-level gnus-thread-indent-level) +(defvar gnus-sort-gathered-threads-function 'gnus-thread-sort-by-number + "Function called to sort the articles within a thread after it has +been gathered together.") ;; Avoid highlighting in kill files. (defvar gnus-summary-inhibit-highlight nil) @@ -1515,6 +1528,7 @@ increase the score of each group you read." "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 @@ -1631,6 +1645,7 @@ increase the score of each group you read." ["Headers" gnus-article-toggle-headers t] ["Signature" gnus-article-hide-signature t] ["Citation" gnus-article-hide-citation t] + ["List identifiers" gnus-article-hide-list-identifiers t] ["PGP" gnus-article-hide-pgp t] ["Banner" gnus-article-strip-banner t] ["Boring headers" gnus-article-hide-boring-headers t]) @@ -3031,7 +3046,7 @@ If SHOW-ALL is non-nil, already read articles are also listed." (while threads (when (stringp (caar threads)) (setcdr (car threads) - (sort (cdar threads) 'gnus-thread-sort-by-number))) + (sort (cdar threads) gnus-sort-gathered-threads-function))) (setq threads (cdr threads))) result)) @@ -4028,6 +4043,22 @@ or a straight list of headers." (cdr (assq number gnus-newsgroup-scored)) (memq number gnus-newsgroup-processable)))))) +(defun gnus-summary-remove-list-identifiers () + "Remove list identifiers in `gnus-list-identifiers' from articles in +the current group." + (let ((regexp (if (stringp gnus-list-identifiers) + gnus-list-identifiers + (mapconcat 'identity gnus-list-identifiers " *\\|")))) + (when regexp + (dolist (header gnus-newsgroup-headers) + (when (string-match (concat "\\(Re: +\\)?\\(" regexp " *\\)") + (mail-header-subject header)) + (mail-header-set-subject + header (concat (substring (mail-header-subject header) + 0 (match-beginning 2)) + (substring (mail-header-subject header) + (match-end 2))))))))) + (defun gnus-select-newsgroup (group &optional read-all select-articles) "Select newsgroup GROUP. If READ-ALL is non-nil, all articles in the group are selected. @@ -4144,6 +4175,9 @@ If SELECT-ARTICLES, only select those articles from GROUP." ;; Let the Gnus agent mark articles as read. (when gnus-agent (gnus-agent-get-undownloaded-list)) + ;; Remove list identifiers from subject + (when gnus-list-identifiers + (gnus-summary-remove-list-identifiers)) ;; Check whether auto-expire is to be done in this group. (setq gnus-newsgroup-auto-expire (gnus-group-auto-expirable-p group)) @@ -4170,7 +4204,9 @@ If SELECT-ARTICLES, only select those articles from GROUP." (zerop (length gnus-newsgroup-unreads))) (eq (gnus-group-find-parameter group 'display) 'all)) - (gnus-uncompress-range (gnus-active group)) + (or + (gnus-uncompress-range (gnus-active group)) + (gnus-cache-articles-in-group group)) (sort (append gnus-newsgroup-dormant gnus-newsgroup-marked (copy-sequence gnus-newsgroup-unreads)) '<))) @@ -5307,7 +5343,8 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil." (unless quit-config ;; Do adaptive scoring, and possibly save score files. (when gnus-newsgroup-adaptive - (gnus-score-adaptive)) + (let ((gnus-newsgroup-adaptive gnus-use-adaptive-scoring)) + (gnus-score-adaptive))) (when gnus-use-scoring (gnus-score-save))) (gnus-run-hooks 'gnus-summary-prepare-exit-hook) @@ -6208,7 +6245,21 @@ If given a prefix, remove all limits." "Limit the summary buffer to articles that are older than (or equal) AGE days. If YOUNGER-P (the prefix) is non-nil, limit the summary buffer to articles that are younger than AGE days." - (interactive "nLimit to articles older than (in days): \nP") + (interactive + (let ((younger current-prefix-arg) + (days-got nil) + days) + (while (not days-got) + (setq days (if younger + (read-string "Limit to articles within (in days): ") + (read-string "Limit to articles old than (in days): "))) + (when (> (length days) 0) + (setq days (read days))) + (if (numberp days) + (setq days-got t) + (message "Please enter a number.") + (sleep-for 1))) + (list days younger))) (prog1 (let ((data gnus-newsgroup-data) (cutoff (days-to-time age)) @@ -7406,8 +7457,9 @@ and `request-accept' functions." art-group)))))) (cond ((not art-group) - (gnus-message 1 "Couldn't %s article %s" - (cadr (assq action names)) article)) + (gnus-message 1 "Couldn't %s article %s: %s" + (cadr (assq action names)) article + (nnheader-get-report (car to-method)))) ((and (eq art-group 'junk) (eq action 'move)) (gnus-summary-mark-article article gnus-canceled-mark) diff --git a/lisp/gnus-util.el b/lisp/gnus-util.el index ee18c66..d8c7cf1 100644 --- a/lisp/gnus-util.el +++ b/lisp/gnus-util.el @@ -733,7 +733,7 @@ with potentially long computations." ;; Decide whether to append to a file or to an Emacs buffer. (let ((outbuf (get-file-buffer filename))) (if (not outbuf) - (append-to-file (point-min) (point-max) filename) + (write-region-as-binary (point-min) (point-max) filename 'append) ;; File has been visited, in buffer OUTBUF. (set-buffer outbuf) (let ((buffer-read-only nil) diff --git a/lisp/gnus-uu.el b/lisp/gnus-uu.el index 38d7edb..39b1e08 100644 --- a/lisp/gnus-uu.el +++ b/lisp/gnus-uu.el @@ -526,6 +526,7 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (gnus-get-buffer-create " *gnus-uu-forward*"))) (erase-buffer) (insert-file file) + (delete-file file) (let ((fs gnus-uu-digest-from-subject)) (when fs (setq from (caar fs) @@ -954,7 +955,8 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (beginning-of-line) (forward-line 1) (when (file-exists-p gnus-uu-binhex-article-name) - (append-to-file start-char (point) gnus-uu-binhex-article-name)))) + (write-region-as-binary start-char (point) + gnus-uu-binhex-article-name 'append)))) (if (memq 'begin state) (cons gnus-uu-binhex-article-name state) state))) diff --git a/lisp/mm-bodies.el b/lisp/mm-bodies.el index 1107947..3ced083 100644 --- a/lisp/mm-bodies.el +++ b/lisp/mm-bodies.el @@ -168,6 +168,7 @@ If no encoding was done, nil is returned." (save-excursion (goto-char (point-max)) (skip-chars-backward "\n\t ") + (delete-region (point) (point-max)) (point)))) ((memq encoding '(7bit 8bit binary)) ) diff --git a/lisp/mm-decode.el b/lisp/mm-decode.el index c43b1b6..a6f9a3f 100644 --- a/lisp/mm-decode.el +++ b/lisp/mm-decode.el @@ -566,15 +566,10 @@ external if displayed external." (defun mm-save-part-to-file (handle file) (mm-with-unibyte-buffer (mm-insert-part handle) - ;; Now every coding system is 100% binary within mm-with-unibyte-buffer - ;; Is text still special? - (let ((coding-system-for-write - (if (equal "text" (mm-handle-media-supertype handle)) - buffer-file-coding-system - 'binary)) + (let ((coding-system-for-write 'binary) ;; Don't re-compress .gz & al. Arguably we should make ;; `file-name-handler-alist' nil, but that would chop - ;; ange-ftp which it's reasonable to use here. + ;; ange-ftp, which is reasonable to use here. (inhibit-file-name-operation 'write-region) (inhibit-file-name-handlers (if (equal (mm-handle-media-type handle) diff --git a/lisp/mm-encode.el b/lisp/mm-encode.el index ddb5b0b..7bf65ff 100644 --- a/lisp/mm-encode.el +++ b/lisp/mm-encode.el @@ -132,18 +132,18 @@ The encoding used is returned." (let ((8bit 0)) (cond ((not (featurep 'mule)) - (while (re-search-forward "[^\x00-\x7f]" nil t) + (while (re-search-forward "[^\x20-\x7f\r\n\t]" nil t) (incf 8bit))) (t ;; Mule version (while (not (eobp)) - (skip-chars-forward "\0-\177") + (skip-chars-forward "\x20-\x7f\r\n\t") (unless (eobp) (forward-char 1) (incf 8bit))))) (if (> (/ (* 8bit 1.0) (buffer-size)) 0.166) - 'quoted-printable - 'base64))))) + 'base64 + 'quoted-printable))))) (provide 'mm-encode) diff --git a/lisp/mm-util.el b/lisp/mm-util.el index a8e8f8b..58131ac 100644 --- a/lisp/mm-util.el +++ b/lisp/mm-util.el @@ -24,19 +24,6 @@ ;;; Code: -(defconst mm-running-xemacs (string-match "XEmacs" emacs-version)) - -(defconst mm-binary-coding-system - (if mm-running-xemacs - 'binary 'no-conversion) - "100% binary coding system.") - -(defconst mm-text-coding-system - (and (fboundp 'coding-system-list) - (if (memq system-type '(windows-nt ms-dos ms-windows)) - 'raw-text-dos 'raw-text)) - "Text-safe coding system (For removing ^M).") - (defvar mm-mime-mule-charset-alist '((us-ascii ascii) (iso-8859-1 latin-iso8859-1) @@ -84,8 +71,8 @@ (lambda (elem) (let ((nfunc (intern (format "mm-%s" (car elem))))) (if (fboundp (car elem)) - (fset nfunc (car elem)) - (fset nfunc (cdr elem))))) + (defalias nfunc (car elem)) + (defalias nfunc (cdr elem))))) '((decode-coding-string . (lambda (s a) s)) (encode-coding-string . (lambda (s a) s)) (encode-coding-region . ignore) @@ -118,16 +105,37 @@ (x-ctext . ctext)) "A mapping from invalid charset names to the real charset names.") -(defconst mm-auto-save-coding-system +(defun mm-coding-system-p (sym) + "Return non-nil if SYM is a coding system." + (or (and (fboundp 'coding-system-p) (coding-system-p sym)) + (memq sym (mm-get-coding-system-list)))) + +(defvar mm-binary-coding-system (cond - ((memq 'emacs-mule (mm-get-coding-system-list)) - (if (memq system-type '(windows-nt ms-dos ms-windows)) - 'emacs-mule-dos 'emacs-mule)) - ((memq 'escape-quoted (mm-get-coding-system-list)) - 'escape-quoted) - ((memq 'no-conversion (mm-get-coding-system-list)) - 'no-conversion) + ((mm-coding-system-p 'no-conversion) 'no-conversion) + ((mm-coding-system-p 'binary) 'binary) (t nil)) + "100% binary coding system.") + +(defvar mm-text-coding-system + (or (if (memq system-type '(windows-nt ms-dos ms-windows)) + (and (mm-coding-system-p 'raw-text-dos) 'raw-text-dos) + (and (mm-coding-system-p 'raw-text) 'raw-text)) + mm-binary-coding-system) + "Text-safe coding system (For removing ^M).") + +(defvar mm-text-coding-system-for-write nil + "Text coding system for write.") + +(defvar mm-auto-save-coding-system + (cond + ((mm-coding-system-p 'emacs-mule) + (if (memq system-type '(windows-nt ms-dos ms-windows)) + (if (mm-coding-system-p 'emacs-mule-dos) + 'emacs-mule-dos mm-binary-coding-system) + 'emacs-mule)) + ((mm-coding-system-p 'escape-quoted) 'escape-quoted) + (t mm-binary-coding-system)) "Coding system of auto save file.") ;;; Internal variables: @@ -317,21 +325,74 @@ See also `with-temp-file' and `with-output-to-string'." (pop alist)) (nreverse out))) -(defun mm-insert-file-contents (filename &optional visit beg end replace) +(defvar mm-inhibit-file-name-handlers + '(jka-compr-handler) + "A list of handlers doing (un)compression (etc) thingies.") + +(defun mm-insert-file-contents (filename &optional visit beg end replace + inhibit) "Like `insert-file-contents', q.v., but only reads in the file. A buffer may be modified in several ways after reading into the buffer due to advanced Emacs features, such as file-name-handlers, format decoding, find-file-hooks, etc. +If INHIBIT is non-nil, inhibit mm-inhibit-file-name-handlers. This function ensures that none of these modifications will take place." (let ((format-alist nil) - (auto-mode-alist (mm-auto-mode-alist)) + (auto-mode-alist (if inhibit nil (mm-auto-mode-alist))) (default-major-mode 'fundamental-mode) (enable-local-variables nil) (after-insert-file-functions nil) (enable-local-eval nil) - (find-file-hooks nil)) + (find-file-hooks nil) + (inhibit-file-name-operation (if inhibit + 'insert-file-contents + inhibit-file-name-operation)) + (inhibit-file-name-handlers + (if inhibit + (append mm-inhibit-file-name-handlers + inhibit-file-name-handlers) + inhibit-file-name-handlers))) (insert-file-contents filename visit beg end replace))) +(defun mm-append-to-file (start end filename &optional codesys inhibit) + "Append the contents of the region to the end of file FILENAME. +When called from a function, expects three arguments, +START, END and FILENAME. START and END are buffer positions +saying what text to write. +Optional fourth argument specifies the coding system to use when +encoding the file. +If INHIBIT is non-nil, inhibit mm-inhibit-file-name-handlers." + (let ((coding-system-for-write + (or codesys mm-text-coding-system-for-write + mm-text-coding-system)) + (inhibit-file-name-operation (if inhibit + 'append-to-file + inhibit-file-name-operation)) + (inhibit-file-name-handlers + (if inhibit + (append mm-inhibit-file-name-handlers + inhibit-file-name-handlers) + inhibit-file-name-handlers))) + (append-to-file start end filename))) + +(defun mm-write-region (start end filename &optional append visit lockname + coding-system inhibit) + + "Like `write-region'. +If INHIBIT is non-nil, inhibit mm-inhibit-file-name-handlers." + (let ((coding-system-for-write + (or coding-system mm-text-coding-system-for-write + mm-text-coding-system)) + (inhibit-file-name-operation (if inhibit + 'write-region + inhibit-file-name-operation)) + (inhibit-file-name-handlers + (if inhibit + (append mm-inhibit-file-name-handlers + inhibit-file-name-handlers) + inhibit-file-name-handlers))) + (write-region start end filename append visit lockname))) + (provide 'mm-util) ;;; mm-util.el ends here diff --git a/lisp/mm-uu.el b/lisp/mm-uu.el index c3991c3..ba23c74 100644 --- a/lisp/mm-uu.el +++ b/lisp/mm-uu.el @@ -82,7 +82,7 @@ decoder, such as hexbin." ;;; Thanks to Edward J. Sabol and ;;; Peter von der Ah\'e (defconst mm-uu-forward-begin-line "^-+ \\(?:Start of \\)?Forwarded message") -(defconst mm-uu-forward-end-line "^-+ End of forwarded message") +(defconst mm-uu-forward-end-line "^-+ End\\(?: of\\)? forwarded message") (defvar mm-uu-begin-line nil) @@ -146,7 +146,10 @@ To disable dissecting shar codes, for instance, add (if (stringp cte) (setq cte (intern (downcase (mail-header-remove-whitespace (mail-header-remove-comments - cte))))))) + cte)))))) + (if (eq cte 'base64) + (setq charset 'gnus-encoded ;; a fake charset + cte nil))) (goto-char (point-max))) (forward-line) (setq text-start (point) @@ -170,7 +173,9 @@ To disable dissecting shar codes, for instance, add (intern (concat "mm-uu-" (symbol-name type) "-end-line")))) (when (and (re-search-forward end-line nil t) - (not (eq (match-beginning 0) (match-end 0)))) + (not (eq (match-beginning 0) (match-end 0))) + ;; Do not dissect base64 forward. + (not (and (eq charset 'gnus-encoded) (eq type 'forward)))) (setq end-char-1 (match-beginning 0)) (forward-line) (setq end-char (point)) diff --git a/lisp/mm-view.el b/lisp/mm-view.el index c2131a7..caee4f0 100644 --- a/lisp/mm-view.el +++ b/lisp/mm-view.el @@ -84,10 +84,12 @@ (save-restriction (narrow-to-region b (point)) (goto-char (point-min)) - (if (or (re-search-forward - w3-meta-content-type-charset-regexp nil t) - (re-search-forward - w3-meta-charset-content-type-regexp nil t)) + (if (or (and (boundp 'w3-meta-content-type-charset-regexp) + (re-search-forward + w3-meta-content-type-charset-regexp nil t)) + (and (boundp 'w3-meta-charset-content-type-regexp) + (re-search-forward + w3-meta-charset-content-type-regexp nil t))) (setq charset (w3-coding-system-for-mime-charset (buffer-substring-no-properties (match-beginning 2) diff --git a/lisp/mml.el b/lisp/mml.el index 286c8e4..9f4ed01 100644 --- a/lisp/mml.el +++ b/lisp/mml.el @@ -229,7 +229,7 @@ (insert-buffer-substring (cdr (assq 'buffer cont)))) ((and (setq filename (cdr (assq 'filename cont))) (not (equal (cdr (assq 'nofile cont)) "yes"))) - (mm-insert-file-contents filename)) + (mm-insert-file-contents filename nil nil nil nil t)) (t (insert (cdr (assq 'contents cont))))) (setq encoding (mm-encode-buffer type) @@ -430,7 +430,7 @@ "Translate the current buffer from MML to MIME." (message-encode-message-body) (save-restriction - (message-narrow-to-headers) + (message-narrow-to-headers-or-head) (mail-encode-encoded-word-buffer))) (defun mml-insert-mime (handle &optional no-markup) @@ -449,7 +449,10 @@ (mapcar 'mml-insert-mime (cdr handle)) (insert "<#/multipart>\n")) (textp - (mm-insert-part handle) + (let ((text (mm-get-part handle)) + (charset (mail-content-type-get + (mm-handle-type handle) 'charset))) + (insert (mm-decode-string text charset))) (goto-char (point-max))) (t (insert "<#/part>\n"))))) diff --git a/lisp/nnfolder.el b/lisp/nnfolder.el index 1937780..59a6e9a 100644 --- a/lisp/nnfolder.el +++ b/lisp/nnfolder.el @@ -297,39 +297,64 @@ If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.") (let ((nnmail-file-coding-system nnfolder-file-coding-system)) (nnmail-find-file nnfolder-newsgroups-file)))) +;; Return a list consisting of all article numbers existing in the +;; current folder. + +(defun nnfolder-existing-articles () + (save-excursion + (when nnfolder-current-buffer + (set-buffer nnfolder-current-buffer) + (goto-char (point-min)) + (let ((marker (concat "\n" nnfolder-article-marker)) + (number "[0-9]+") + numbers) + + (while (and (search-forward marker nil t) + (re-search-forward number nil t)) + (let ((newnum (string-to-number (match-string 0)))) + (if (nnmail-within-headers-p) + (push newnum numbers)))) + numbers)))) + (deffoo nnfolder-request-expire-articles (articles newsgroup &optional server force) (nnfolder-possibly-change-group newsgroup server) (let* ((is-old t) - rest) + ;; The articles we have deleted so far. + (deleted-articles nil) + ;; The articles that really exist and will be expired if they are old enough. + (maybe-expirable (gnus-intersection articles (nnfolder-existing-articles)))) (nnmail-activate 'nnfolder) (save-excursion (set-buffer nnfolder-current-buffer) - (while (and articles is-old) + ;; Since messages are sorted in arrival order and expired in the + ;; same order, we can stop as soon as we find a message that is + ;; too old. + (while (and maybe-expirable is-old) (goto-char (point-min)) - (when (and (nnfolder-goto-article (car articles)) + (when (and (nnfolder-goto-article (car maybe-expirable)) (search-forward (concat "\n" nnfolder-article-marker) nil t)) (forward-sexp) - (if (setq is-old + (when (setq is-old (nnmail-expired-article-p newsgroup (buffer-substring (point) (progn (end-of-line) (point))) force nnfolder-inhibit-expiry)) - (progn (nnheader-message 5 "Deleting article %d..." - (car articles) newsgroup) - (nnfolder-delete-mail)) - (push (car articles) rest))) - (setq articles (cdr articles))) + (car maybe-expirable) newsgroup) + (nnfolder-delete-mail) + ;; Must remember which articles were actually deleted + (push (car maybe-expirable) deleted-articles))) + (setq maybe-expirable (cdr maybe-expirable))) (unless nnfolder-inhibit-expiry (nnheader-message 5 "Deleting articles...done")) (nnfolder-save-buffer) (nnfolder-adjust-min-active newsgroup) (nnfolder-save-active nnfolder-group-alist nnfolder-active-file) - (nconc rest articles)))) + (gnus-sorted-complement articles (nreverse deleted-articles))))) (deffoo nnfolder-request-move-article (article group server accept-form &optional last) @@ -840,9 +865,10 @@ This command does not work if you use short group names." (when (buffer-modified-p) (run-hooks 'nnfolder-save-buffer-hook) (gnus-make-directory (file-name-directory (buffer-file-name))) - (let ((coding-system-for-write - (or nnfolder-file-coding-system-for-write - nnfolder-file-coding-system))) + (let* ((coding-system-for-write + (or nnfolder-file-coding-system-for-write + nnfolder-file-coding-system)) + (output-coding-system coding-system-for-write)) (save-buffer)))) (defun nnfolder-save-active (group-alist active-file) diff --git a/lisp/nnmail.el b/lisp/nnmail.el index 1fd24cf..33d120a 100644 --- a/lisp/nnmail.el +++ b/lisp/nnmail.el @@ -1039,11 +1039,11 @@ Return the number of characters in the body." (defun nnmail-remove-list-identifiers () "Remove list identifiers from Subject headers." (let ((regexp (if (stringp nnmail-list-identifiers) nnmail-list-identifiers - (mapconcat 'identity nnmail-list-identifiers "\\|")))) + (mapconcat 'identity nnmail-list-identifiers " *\\|")))) (when regexp (goto-char (point-min)) (when (re-search-forward - (concat "^Subject: +\\(Re: +\\)?\\(" regexp "\\) *") + (concat "^Subject: +\\(Re: +\\)?\\(" regexp " *\\)") nil t) (delete-region (match-beginning 2) (match-end 0)))))) @@ -1447,7 +1447,9 @@ See the documentation for the variable `nnmail-split-fancy' for documentation." (incf total new) (incf i)))) ;; If we did indeed read any incoming spools, we save all info. - (unless (zerop total) + (if (zerop total) + (nnheader-message 4 "%s: Reading incoming mail (no new mail)...done" + method (car source)) (nnmail-save-active (nnmail-get-value "%s-group-alist" method) (nnmail-get-value "%s-active-file" method)) diff --git a/lisp/nntp.el b/lisp/nntp.el index f2bc3d9..8b63b8e 100644 --- a/lisp/nntp.el +++ b/lisp/nntp.el @@ -296,6 +296,11 @@ noticing asynchronous data.") (unless discard (erase-buffer))))) +(defun nntp-kill-buffer (buffer) + (when (buffer-name buffer) + (kill-buffer buffer) + (nnheader-init-server-buffer))) + (defsubst nntp-find-connection (buffer) "Find the connection delivering to BUFFER." (let ((alist nntp-connection-alist) @@ -308,8 +313,7 @@ noticing asynchronous data.") (when process (if (memq (process-status process) '(open run)) process - (when (buffer-name (process-buffer process)) - (kill-buffer (process-buffer process))) + (nntp-kill-buffer (process-buffer process)) (setq nntp-connection-alist (delq entry nntp-connection-alist)) nil)))) @@ -700,8 +704,7 @@ noticing asynchronous data.") ;; QUIT command actually is sent out before we kill ;; the process. (sleep-for 1)))) - (when (buffer-name (process-buffer process)) - (kill-buffer (process-buffer process))) + (nntp-kill-buffer (process-buffer process)) (setq process (car (pop nntp-connection-alist)))) (nnoo-close-server 'nntp))) @@ -717,8 +720,7 @@ noticing asynchronous data.") ;; QUIT command actually is sent out before we kill ;; the process. (sleep-for 1)))) - (when (buffer-name (process-buffer process)) - (kill-buffer (process-buffer process)))))) + (nntp-kill-buffer (process-buffer process))))) (deffoo nntp-request-list (&optional server) (nntp-possibly-change-group nil server) @@ -866,8 +868,7 @@ password contained in '~/.nntp-authinfo'." (nnheader-run-at-time nntp-connection-timeout nil `(lambda () - (when (buffer-name ,pbuffer) - (kill-buffer ,pbuffer)))))) + (nntp-kill-buffer ,pbuffer))))) (process (condition-case () (funcall nntp-open-connection-function pbuffer) @@ -891,8 +892,7 @@ password contained in '~/.nntp-authinfo'." (let ((nnheader-callback-function nil)) (run-hooks 'nntp-server-opened-hook) (nntp-send-authinfo t)))) - (when (buffer-name (process-buffer process)) - (kill-buffer (process-buffer process))) + (nntp-kill-buffer (process-buffer process)) nil)))) (defun nntp-open-network-stream (buffer) diff --git a/lisp/smiley.el b/lisp/smiley.el index 34b416e..6e0237c 100644 --- a/lisp/smiley.el +++ b/lisp/smiley.el @@ -65,7 +65,7 @@ ("\\(:-*[)>}(I;(B]+\\)\\W" 1 "FaceHappy.xpm") ("\\(=[)>(I;(B]+\\)\\W" 1 "FaceHappy.xpm") ("\\(:-*[/\\\"]\\)[^/]\\W" 1 "FaceIronic.xpm") - ("\\([8|]-*[|Oo%]\\)\\W" 1 "FaceKOed.xpm") + ("[^.0-9]\\([8|]-*[|Oo%]\\)\\W" 1 "FaceKOed.xpm") ("\\([:|]-*#+\\)\\W" 1 "FaceNyah.xpm") ("\\(:-*[({]+\\)\\W" 1 "FaceSad.xpm") ("\\(=[({]+\\)\\W" 1 "FaceSad.xpm") diff --git a/texi/ChangeLog b/texi/ChangeLog index 42c9e20..152302f 100644 --- a/texi/ChangeLog +++ b/texi/ChangeLog @@ -1,3 +1,24 @@ +1999-08-27 15:09:01 Jim Meyering + + * gnus.texi (The Active File): Typo fix. + +1999-08-27 15:00:23 Yoshiki Hayashi + + * gnus.texi (Generic Marking Commands): Typo fixes. + +1999-08-27 14:46:21 Lee Willis + + * gnus.texi (Customizing Articles): More explanation. + +1999-07-10 Mike McEwan + + * gnus.texi (More Threading): Document new variable + `gnus-sort-gathered-threads-function'. + +1999-07-30 Simon Josefsson + + * gnus.texi: Added `gnus-list-identifiers' stuff. + 1999-07-09 19:41:34 Lars Magne Ingebrigtsen * gnus.texi (Using MIME): Addition. diff --git a/texi/gnus-ja.texi b/texi/gnus-ja.texi index 020a8dc..c97aded 100644 --- a/texi/gnus-ja.texi +++ b/texi/gnus-ja.texi @@ -8195,37 +8195,39 @@ GNUS $B$d(B Gnus $B$G$O!"$3$N$?$A$N0-$$LdBj$G6C$+$5$l$J$$$h$&$K$9$k$K$O!"35N, $B0J2<$N07$$$N%*%W%7%g%s$,;HMQ2DG=$G$9!#$3$l$r%+%9%?%^%$%:$9$k$?$a$N:G$b4J(B $BC1$JJ}K!$O(B @code{gnus-article-treat} $B%+%9%?%^%$%:%0%k!<%W$rD4::$9$k$3$H(B -$B$G$9!#(B +$B$G$9!#(BValues in brackets are suggested sensible values. Others are possible +but those listed are probably sufficient for most people. @table @code -@item gnus-treat-buttonize -@item gnus-treat-buttonize-head -@item gnus-treat-emphasize -@item gnus-treat-fill-article -@item gnus-treat-strip-cr -@item gnus-treat-hide-headers -@item gnus-treat-hide-boring-headers -@item gnus-treat-hide-signature -@item gnus-treat-hide-citation -@item gnus-treat-strip-pgp -@item gnus-treat-strip-pem -@item gnus-treat-highlight-headers -@item gnus-treat-highlight-citation -@item gnus-treat-highlight-signature -@item gnus-treat-date-ut -@item gnus-treat-date-local -@item gnus-treat-date-lapsed -@item gnus-treat-date-original -@item gnus-treat-strip-headers-in-body -@item gnus-treat-strip-trailing-blank-lines -@item gnus-treat-strip-leading-blank-lines -@item gnus-treat-strip-multiple-blank-lines -@item gnus-treat-overstrike -@item gnus-treat-display-xface -@item gnus-treat-display-smileys -@item gnus-treat-display-picons -@item gnus-treat-capitalize-sentences -@item gnus-treat-fill-long-lines +@item gnus-treat-highlight-signature (t, last) +@item gnus-treat-buttonize (t, integer) +@item gnus-treat-buttonize-head (head) +@item gnus-treat-emphasize (t, head, integer) +@item gnus-treat-fill-article (t, integer) +@item gnus-treat-strip-cr (t, integer) +@item gnus-treat-hide-headers (head) +@item gnus-treat-hide-boring-headers (head) +@item gnus-treat-hide-signature (t, last) +@item gnus-treat-hide-citation (t, integer) +@item gnus-treat-strip-pgp (t, last, integer) +@item gnus-treat-strip-pem (t, last, integer) +@item gnus-treat-highlight-headers (head) +@item gnus-treat-highlight-citation (t, integer) +@item gnus-treat-highlight-signature (t, last, integer) +@item gnus-treat-date-ut (head) +@item gnus-treat-date-local (head) +@item gnus-treat-date-lapsed (head) +@item gnus-treat-date-original (head) +@item gnus-treat-strip-headers-in-body (t, integer) +@item gnus-treat-strip-trailing-blank-lines (t, last, integer) +@item gnus-treat-strip-leading-blank-lines (t, integer) +@item gnus-treat-strip-multiple-blank-lines (t, integer) +@item gnus-treat-overstrike (t, integer) +@item gnus-treat-display-xface (head) +@item gnus-treat-display-smileys (t, integer) +@item gnus-treat-display-picons (head) +@item gnus-treat-capitalize-sentences (t, integer) +@item gnus-treat-fill-long-lines (t, integer) @item gnus-treat-play-sounds @item gnus-treat-translate @item gnus-treat-decode-article-as-default-mime-charset diff --git a/texi/gnus.texi b/texi/gnus.texi index 19800d6..1561ced 100644 --- a/texi/gnus.texi +++ b/texi/gnus.texi @@ -1002,7 +1002,7 @@ is certainly faster than @code{t} over slow lines. Some news servers (Leafnode and old versions of INN, for instance) do not support the @code{LIST ACTIVE group}. For these servers, @code{nil} -is probably the most effficient value for this variable. +is probably the most efficient value for this variable. If this variable is @code{nil}, gnus will ask for group info in total lock-step, which isn't very fast. If it is @code{some} and you use an @@ -2403,7 +2403,7 @@ Sort the group buffer alphabetically by backend name @end table -All the commands below obeys the process/prefix convention +All the commands below obey the process/prefix convention (@pxref{Process/Prefix}). When given a symbolic prefix (@pxref{Symbolic Prefixes}), all these @@ -3353,7 +3353,7 @@ The following format specification characters are understood: @item N Article number. @item S -Subject string. +Subject string. List identifiers stripped, @code{gnus-list-identifies}. @xref{Article Hiding}. @item s Subject if the article is the root of the thread or the previous article had a different subject, @code{gnus-summary-same-subject} otherwise. @@ -4541,7 +4541,7 @@ The default is @code{t}. Some people would like the command that ticks an article (@kbd{!}) go to the next article. Others would like it to go to the next unread article. Yet others would like it to stay on the current article. And -even though I haven't heard of anybody wanting it to go the the +even though I haven't heard of anybody wanting it to go to the previous (unread) article, I'm sure there are people that want that as well. @@ -4556,7 +4556,7 @@ to list in this manual. While you can use these commands directly, most users would prefer altering the summary mode keymap. For instance, if you would like the -@kbd{!} command to go the the next article instead of the next unread +@kbd{!} command to go to the next article instead of the next unread article, you could say something like: @lisp @@ -5135,6 +5135,18 @@ in a new thread. This is a number that says how much each sub-thread should be indented. The default is 4. +@item gnus-sort-gathered-threads-function +@vindex gnus-sort-gathered-threads-function +Sometimes, particularly with mailing lists, the order in which mails +arrive locally is not necessarily the same as the order in which they +arrived on the mailing list. Consequently, when sorting sub-threads +using the default @code{gnus-thread-sort-by-number}, responses can end +up appearing before the article to which they are responding to. Setting +this variable to an alternate value +(e.g. @code{gnus-thread-sort-by-date}), in a group's parameters or in an +appropriate hook (e.g. @code{gnus-summary-generate-hook}) can produce a +more logical sub-thread ordering in such instances. + @end table @@ -6521,6 +6533,23 @@ Hide headers that aren't particularly interesting Hide signature (@code{gnus-article-hide-signature}). @xref{Article Signature}. +@item W W l +@kindex W W l (Summary) +@findex gnus-article-hide-list-identifiers +@vindex gnus-list-identifiers +Hide list identifiers specified in @code{gnus-list-identifiers}. Theese +are strings some list servers add to the beginning of all @code{Subject} +headers---for example, @samp{[zebra 4711]}. + +@table @code + +@item gnus-list-identifiers +@vindex gnus-list-identifiers +A regular expression that matches list identifiers to be removed from +subject. This can also be a list of regular expressions. + +@end table + @item W W p @kindex W W p (Summary) @findex gnus-article-hide-pgp @@ -6723,7 +6752,7 @@ Fill long lines (@code{gnus-article-fill-long-lines}). @item W C @kindex W C (Summary) -@findex gnus-article-capitalize-sentencse +@findex gnus-article-capitalize-sentences Capitalize the first word in each sentence (@code{gnus-article-capitalize-sentences}). @@ -8378,6 +8407,9 @@ To have them called automatically, you should set the corresponding @code{gnus-treat-hide-headers}. Below is a list of variables that can be set, but first we discuss the values these variables can have. +Note: Some values, while valid, make little sense. Check the list below +for sensible values. + @enumerate @item @code{nil}: Don't do this treatment. @@ -8433,37 +8465,39 @@ controlling variable is a predicate list, as described above. The following treatment options are available. The easiest way to customize this is to examine the @code{gnus-article-treat} customization -group. +group. Values in brackets are suggested sensible values. Others are possible +but those listed are probably sufficient for most people. @table @code -@item gnus-treat-buttonize -@item gnus-treat-buttonize-head -@item gnus-treat-emphasize -@item gnus-treat-fill-article -@item gnus-treat-strip-cr -@item gnus-treat-hide-headers -@item gnus-treat-hide-boring-headers -@item gnus-treat-hide-signature -@item gnus-treat-hide-citation -@item gnus-treat-strip-pgp -@item gnus-treat-strip-pem -@item gnus-treat-highlight-headers -@item gnus-treat-highlight-citation -@item gnus-treat-highlight-signature -@item gnus-treat-date-ut -@item gnus-treat-date-local -@item gnus-treat-date-lapsed -@item gnus-treat-date-original -@item gnus-treat-strip-headers-in-body -@item gnus-treat-strip-trailing-blank-lines -@item gnus-treat-strip-leading-blank-lines -@item gnus-treat-strip-multiple-blank-lines -@item gnus-treat-overstrike -@item gnus-treat-display-xface -@item gnus-treat-display-smileys -@item gnus-treat-display-picons -@item gnus-treat-capitalize-sentences -@item gnus-treat-fill-long-lines +@item gnus-treat-highlight-signature (t, last) +@item gnus-treat-buttonize (t, integer) +@item gnus-treat-buttonize-head (head) +@item gnus-treat-emphasize (t, head, integer) +@item gnus-treat-fill-article (t, integer) +@item gnus-treat-strip-cr (t, integer) +@item gnus-treat-hide-headers (head) +@item gnus-treat-hide-boring-headers (head) +@item gnus-treat-hide-signature (t, last) +@item gnus-treat-hide-citation (t, integer) +@item gnus-treat-strip-pgp (t, last, integer) +@item gnus-treat-strip-pem (t, last, integer) +@item gnus-treat-highlight-headers (head) +@item gnus-treat-highlight-citation (t, integer) +@item gnus-treat-highlight-signature (t, last, integer) +@item gnus-treat-date-ut (head) +@item gnus-treat-date-local (head) +@item gnus-treat-date-lapsed (head) +@item gnus-treat-date-original (head) +@item gnus-treat-strip-headers-in-body (t, integer) +@item gnus-treat-strip-trailing-blank-lines (t, last, integer) +@item gnus-treat-strip-leading-blank-lines (t, integer) +@item gnus-treat-strip-multiple-blank-lines (t, integer) +@item gnus-treat-overstrike (t, integer) +@item gnus-treat-display-xface (head) +@item gnus-treat-display-smileys (t, integer) +@item gnus-treat-display-picons (head) +@item gnus-treat-capitalize-sentences (t, integer) +@item gnus-treat-fill-long-lines (t, integer) @item gnus-treat-play-sounds @item gnus-treat-translate @item gnus-treat-decode-article-as-default-mime-charset @@ -9911,6 +9945,7 @@ course. * Mail Sources:: How to tell Gnus where to get mail from. * Mail Backend Variables:: Variables for customizing mail handling. * Fancy Mail Splitting:: Gnus can do hairy splitting of incoming mail. +* Group Mail Splitting:: Use group customize to drive mail splitting. * Incorporating Old Mail:: What about the old mail you have? * Expiring Mail:: Getting rid of unwanted mail. * Washing Mail:: Removing gruft from the mail you get. @@ -10588,6 +10623,131 @@ up to @samp{\\9} will be substituted with the text matched by the groupings 1 through 9. +@node Group Mail Splitting +@subsection Group Mail Splitting +@cindex mail splitting +@cindex group mail splitting + +@findex gnus-group-split +If you subscribe to dozens of mailing lists but you don't want to +maintain mail splitting rules manually, group mail splitting is for you. +You just have to set @var{to-list} and/or @var{to-address} in group +parameters or group customization and set @code{nnmail-split-methods} to +@code{gnus-group-split}. This splitting function will scan all groups +for those parameters and split mail accordingly, i.e., messages posted +from or to the addresses specified in the parameters @var{to-list} or +@var{to-address} of a mail group will be stored in that group. + +Sometimes, mailing lists have multiple addresses, and you may want mail +splitting to recognize them all: just set the @var{extra-aliases} group +parameter to the list of additional addresses and it's done. If you'd +rather use a regular expression, set @var{split-regexp}. + +All these parameters in a group will be used to create an +@code{nnmail-split-fancy} split, in which the @var{FIELD} is @samp{any}, +the @var{VALUE} is a single regular expression that matches +@var{to-list}, @var{to-address}, all of @var{extra-aliases} and all +matches of @var{split-regexp}, and the @var{SPLIT} is the name of the +group. @var{RESTRICT}s are also supported: just set the +@var{split-exclude} parameter to a list of regular expressions. + +If you can't get the right split to be generated using all these +parameters, or you just need something fancier, you can set the +parameter @var{split-spec} to an @code{nnmail-split-fancy} split. In +this case, all other aforementioned parameters will be ignored by +@code{gnus-group-split}. In particular, @var{split-spec} may be set to +@code{nil}, in which case the group will be ignored by +@code{gnus-group-split}. + +@vindex gnus-group-split-default-catch-all-group +@code{gnus-group-split} will do cross-posting on all groups that match, +by defining a single @code{&} fancy split containing one split for each +group. If a message doesn't match any split, it will be stored in the +group named in @code{gnus-group-split-default-catch-all-group}, unless +some group has @var{split-spec} set to @code{catch-all}, in which case +that group is used as the catch-all group. Note that, in this case, +there's no cross-posting, as a @code{|} fancy split encloses the +@code{&} split and the catch-all group. + +It's time for an example. Assume the following group parameters have +been defined: + +@example +nnml:mail.bar: +((to-address . "bar@@femail.com") + (split-regexp . ".*@@femail\\.com")) +nnml:mail.foo: +((to-list . "foo@@nowhere.gov") + (extra-aliases "foo@@localhost" "foo-redist@@home") + (split-exclude "bugs-foo" "rambling-foo") + (admin-address . "foo-request@@nowhere.gov")) +nnml:mail.others: +((split-spec . catch-all)) +@end example + +Setting @code{nnmail-split-methods} to @code{gnus-group-split} will +behave as if @code{nnmail-split-fancy} had been selected and variable +@code{nnmail-split-fancy} had been set as follows: + +@lisp +(| (& (any "\\(bar@@femail\\.com\\|.*@@femail\\.com\\)" "mail.bar") + (any "\\(foo@@nowhere\\.gov\\|foo@@localhost\\|foo-redist@@home\\)" + - "bugs-foo" - "rambling-foo" "mail.foo")) + "mail.others") +@end lisp + +@findex gnus-group-split-fancy +If you'd rather not use group splitting for all your mail groups, you +may use it for only some of them, by using @code{nnmail-split-fancy} +splits like this: + +@lisp +(: gnus-mlsplt-fancy GROUPS NO-CROSSPOST CATCH-ALL) +@end lisp + +@var{GROUPS} may be a regular expression or a list of group names whose +parameters will be scanned to generate the output split. +@var{NO-CROSSPOST} can be used to disable cross-posting; in this case, a +single @code{|} split will be output. @var{CATCH-ALL} may be the name +of a group to be used as the default catch-all group. If +@var{CATCH-ALL} is @code{nil}, or if @var{SPLIT-REGEXP} matches the +empty string in any selected group, no catch-all split will be issued. +Otherwise, if some group has @var{SPLIT-SPEC} set to @code{catch-all}, +this group will override the value of the @var{CATCH-ALL} argument. + +@findex gnus-group-split-setup +Unfortunately, scanning all groups and their parameters can be quite +slow, especially considering that it has to be done for every message. +But don't despair! The function @code{gnus-group-split-setup} can be +used to select @code{gnus-group-split} in a much more efficient way. It +sets @code{nnmail-split-methods} to @code{nnmail-split-fancy} and sets +@code{nnmail-split-fancy} to the split produced by +@code{gnus-group-split-fancy}. Thus, the group parameters are only +scanned once, no matter how many messages are split. + +@findex gnus-group-split-update +However, if you change group parameters, you have to update +@code{nnmail-split-fancy} manually. You can do it by running +@code{gnus-group-split-update}. If you'd rather have it updated +automatically, just tell @code{gnus-group-split-setup} to do it for +you. For example, add to your @file{.gnus}: + +@lisp +(gnus-group-split-setup AUTO-UPDATE CATCH-ALL) +@end lisp + +If @var{AUTO-UPDATE} is non-@code{nil}, @code{gnus-group-split-update} +will be added to @code{nnmail-pre-get-new-mail-hook}, so you won't ever +have to worry about updating @code{nnmail-split-fancy} again. If you +don't omit @var{CATCH-ALL} (it's optional), +@code{gnus-group-split-default-catch-all-group} will be set to its +value. + +@vindex gnus-group-split-updated-hook +Because you may want to change @code{nnmail-split-fancy} after it is set +by @code{gnus-group-split-update}, this function will run +@code{gnus-group-split-updated-hook} just before finishing. + @node Incorporating Old Mail @subsection Incorporating Old Mail @@ -10833,6 +10993,9 @@ For instance, if you want to remove the @samp{(idm)} and the '("(idm)" "nagnagnag")) @end lisp +This can also be done non-destructively with +@code{gnus-list-identifiers}, @xref{Article Hiding}. + @item nnmail-remove-tabs @findex nnmail-remove-tabs Translate all @samp{TAB} characters into @samp{SPACE} characters. @@ -11297,7 +11460,7 @@ slowness of access parsing when learning what's new in one's groups. @item nnfolder -Basically the effetc of @code{nnfolder} is @code{nnmbox} (the first +Basically the effect of @code{nnfolder} is @code{nnmbox} (the first method described above) on a per-group basis. That is, @code{nnmbox} itself puts *all* one's mail in one file; @code{nnfolder} provides a little bit of optimization to this so that each of one's mail groups has @@ -12804,7 +12967,7 @@ Fetch all eligible articles in all groups @kindex J S (Agent Group) @findex gnus-group-send-drafts Send all sendable messages in the draft group -(@code{gnus-agent-fetch-session}). @xref{Drafts}. +(@code{gnus-group-send-drafts}). @xref{Drafts}. @item J a @kindex J a (Agent Group)