;;; gnus-sum.el --- summary mode commands for Gnus
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-;; Free Software Foundation, Inc.
+
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;; 2005 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
(defcustom gnus-summary-make-false-root-always nil
"Always make a false dummy root."
- :version "21.4"
+ :version "22.1"
:group 'gnus-thread
:type 'boolean)
"*Default threshold for a high scored article.
An article will be highlighted as high scored if its score is greater
than this score."
- :version "21.4"
+ :version "22.1"
:group 'gnus-score-default
:type 'integer)
"*Default threshold for a low scored article.
An article will be highlighted as low scored if its score is smaller
than this score."
- :version "21.4"
+ :version "22.1"
:group 'gnus-score-default
:type 'integer)
"*If non-nil, hide all threads initially.
This can be a predicate specifier which says which threads to hide.
If threads are hidden, you have to run the command
-`gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
-to expose hidden threads."
+`gnus-summary-show-thread' by hand or select an article."
:group 'gnus-thread
:type '(radio (sexp :format "Non-nil\n"
:match (lambda (widget value)
first subject), `unread' (place point on the subject line of the first
unread article), `best' (place point on the subject line of the
higest-scored article), `unseen' (place point on the subject line of
-the first unseen article), 'unseen-or-unread' (place point on the subject
+the first unseen article), `unseen-or-unread' (place point on the subject
line of the first unseen article or, if all article have been seen, on the
subject line of the first unread article), or a function to be called to
place point on some subject line."
- :version "21.4"
+ :version "22.1"
:group 'gnus-group-select
:type '(choice (const best)
(const unread)
NOTE: The list of unfetched articles will always be nil when plugged
and, when unplugged, a subset of the undownloaded article list."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary-maneuvering
:type '(choice (const :tag "None" nil)
(const :tag "Undownloaded when unplugged" undownloaded)
(defcustom gnus-spam-mark ?$
"*Mark used for spam articles."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary-marks
:type 'character)
(defcustom gnus-forwarded-mark ?F
"*Mark used for articles that have been forwarded."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary-marks
:type 'character)
(defcustom gnus-recent-mark ?N
"*Mark used for articles that are recent."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary-marks
:type 'character)
(defcustom gnus-unseen-mark ?.
"*Mark used for articles that haven't been seen."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary-marks
:type 'character)
(defcustom gnus-no-mark ? ;Whitespace
"*Mark used for articles that have no other secondary mark."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary-marks
:type 'character)
(defcustom gnus-undownloaded-mark ?-
"*Mark used for articles that weren't downloaded."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary-marks
:type 'character)
function; this specifies reversed sort order.
Ready-made functions include `gnus-thread-sort-by-number',
-`gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
-`gnus-thread-sort-by-date', `gnus-thread-sort-by-score',
-`gnus-thread-sort-by-most-recent-number',
-`gnus-thread-sort-by-most-recent-date',
-`gnus-thread-sort-by-random', and
-`gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').
+`gnus-thread-sort-by-author', `gnus-thread-sort-by-recipient'
+`gnus-thread-sort-by-subject', `gnus-thread-sort-by-date',
+`gnus-thread-sort-by-score', `gnus-thread-sort-by-most-recent-number',
+`gnus-thread-sort-by-most-recent-date', `gnus-thread-sort-by-random',
+and `gnus-thread-sort-by-total-score' (see
+`gnus-thread-score-function').
When threading is turned off, the variable
`gnus-article-sort-functions' controls how articles are sorted."
:group 'gnus-summary-sort
- :type '(repeat
+ :type '(repeat
(gnus-widget-reversible
(choice (function-item gnus-thread-sort-by-number)
(function-item gnus-thread-sort-by-author)
+ (function-item gnus-thread-sort-by-recipient)
(function-item gnus-thread-sort-by-subject)
(function-item gnus-thread-sort-by-date)
(function-item gnus-thread-sort-by-score)
(defcustom gnus-summary-article-move-hook nil
"*A hook called after an article is moved, copied, respooled, or crossposted."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary
:type 'hook)
(defcustom gnus-summary-article-delete-hook nil
"*A hook called after an article is deleted."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary
:type 'hook)
(defcustom gnus-summary-article-expire-hook nil
"*A hook called after an article is expired."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary
:type 'hook)
(and (fboundp 'display-graphic-p)
(display-graphic-p))
"*If non-nil, display an arrow highlighting the current article."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary
:type 'boolean)
-(defcustom gnus-summary-selected-face 'gnus-summary-selected-face
+(defcustom gnus-summary-selected-face 'gnus-summary-selected
"Face used for highlighting the current article in the summary buffer."
:group 'gnus-summary-visual
:type 'face)
(defcustom gnus-summary-highlight
'(((eq mark gnus-canceled-mark)
- . gnus-summary-cancelled-face)
+ . gnus-summary-cancelled)
((and uncached (> score default-high))
- . gnus-summary-high-undownloaded-face)
+ . gnus-summary-high-undownloaded)
((and uncached (< score default-low))
- . gnus-summary-low-undownloaded-face)
+ . gnus-summary-low-undownloaded)
(uncached
- . gnus-summary-normal-undownloaded-face)
+ . gnus-summary-normal-undownloaded)
((and (> score default-high)
(or (eq mark gnus-dormant-mark)
(eq mark gnus-ticked-mark)))
- . gnus-summary-high-ticked-face)
+ . gnus-summary-high-ticked)
((and (< score default-low)
(or (eq mark gnus-dormant-mark)
(eq mark gnus-ticked-mark)))
- . gnus-summary-low-ticked-face)
+ . gnus-summary-low-ticked)
((or (eq mark gnus-dormant-mark)
(eq mark gnus-ticked-mark))
- . gnus-summary-normal-ticked-face)
+ . gnus-summary-normal-ticked)
((and (> score default-high) (eq mark gnus-ancient-mark))
- . gnus-summary-high-ancient-face)
+ . gnus-summary-high-ancient)
((and (< score default-low) (eq mark gnus-ancient-mark))
- . gnus-summary-low-ancient-face)
+ . gnus-summary-low-ancient)
((eq mark gnus-ancient-mark)
- . gnus-summary-normal-ancient-face)
+ . gnus-summary-normal-ancient)
((and (> score default-high) (eq mark gnus-unread-mark))
- . gnus-summary-high-unread-face)
+ . gnus-summary-high-unread)
((and (< score default-low) (eq mark gnus-unread-mark))
- . gnus-summary-low-unread-face)
+ . gnus-summary-low-unread)
((eq mark gnus-unread-mark)
- . gnus-summary-normal-unread-face)
+ . gnus-summary-normal-unread)
((> score default-high)
- . gnus-summary-high-read-face)
+ . gnus-summary-high-read)
((< score default-low)
- . gnus-summary-low-read-face)
+ . gnus-summary-low-read)
(t
- . gnus-summary-normal-read-face))
+ . gnus-summary-normal-read))
"*Controls the highlighting of summary buffer lines.
A list of (FORM . FACE) pairs. When deciding how a a particular
:group 'gnus-summary
:type 'regexp)
+(defcustom gnus-summary-to-prefix "-> "
+ "*String prefixed to the To field in the summary line when
+using `gnus-ignored-from-addresses'."
+ :version "22.1"
+ :group 'gnus-summary
+ :type 'string)
+
+(defcustom gnus-summary-newsgroup-prefix "=> "
+ "*String prefixed to the Newsgroup field in the summary
+line when using `gnus-ignored-from-addresses'."
+ :version "22.1"
+ :group 'gnus-summary
+ :type 'string)
+
(defcustom gnus-newsgroup-ignored-charsets '(unknown-8bit x-unknown)
"List of charsets that should be ignored.
When these charsets are used in the \"charset\" parameter, the
This is mostly relevant for slow back ends where the user may
wish to widen the summary buffer to include all headers
that were fetched. Say, for nnultimate groups."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary
:type '(choice boolean regexp))
(defcustom gnus-summary-muttprint-program "muttprint"
"Command (and optional arguments) used to run Muttprint."
- :version "21.4"
+ :version "22.1"
:group 'gnus-summary
:type 'string)
supply the MIME-Version header or deliberately strip it from the mail.
If non-nil (the default), Gnus will treat some articles as MIME
even if the MIME-Version header is missing."
- :version "21.4"
+ :version "22.1"
:type 'boolean
:group 'gnus-article-mime)
This means that Gnus will search message bodies for text that look
like uuencoded bits, yEncoded bits, and so on, and present that using
the normal Gnus MIME machinery."
- :version "21.4"
+ :version "22.1"
:type 'boolean
:group 'gnus-article-mime)
"m" gnus-summary-repair-multipart
"v" gnus-article-view-part
"o" gnus-article-save-part
+ "O" gnus-article-save-part-and-strip
+ "r" gnus-article-replace-part
+ "d" gnus-article-delete-part
+ "j" gnus-article-jump-to-part
"c" gnus-article-copy-part
"C" gnus-article-view-part-as-charset
"e" gnus-article-view-part-externally
(make-local-variable 'gnus-summary-mark-positions)
(gnus-make-local-hook 'pre-command-hook)
(add-hook 'pre-command-hook 'gnus-set-global-variables nil t)
- (gnus-run-hooks 'gnus-summary-mode-hook)
+ (gnus-run-mode-hooks 'gnus-summary-mode-hook)
(turn-on-gnus-mailing-list-mode)
(mm-enable-multibyte)
(gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
newsgroups)
(cond
((setq to (cdr (assq 'To extra-headers)))
- (concat "-> "
+ (concat gnus-summary-to-prefix
(inline
(gnus-summary-extract-address-component
(funcall gnus-decode-encoded-word-function to)))))
((setq newsgroups (cdr (assq 'Newsgroups extra-headers)))
- (concat "=> " newsgroups)))))
+ (concat gnus-summary-newsgroup-prefix newsgroups)))))
(inline (gnus-summary-extract-address-component gnus-tmp-from)))))
(defun gnus-summary-insert-line (gnus-tmp-header
(or (cdr (assq 'To (mail-header-extra h2))) ""))))
(or (car extract) (cadr extract)))))
+(defun gnus-thread-sort-by-recipient (h1 h2)
+ "Sort threads by root recipient."
+ (gnus-article-sort-by-recipient
+ (gnus-thread-header h1) (gnus-thread-header h2)))
+
(defsubst gnus-article-sort-by-subject (h1 h2)
"Sort articles by root subject."
(string-lessp
(defcustom gnus-sum-thread-tree-root "> "
"With %B spec, used for the root of a thread.
If nil, use subject instead."
- :version "21.4"
+ :version "22.1"
:type '(radio (const :format "%v " nil) string)
:group 'gnus-thread)
+
(defcustom gnus-sum-thread-tree-false-root "> "
"With %B spec, used for a false root of a thread.
If nil, use subject instead."
- :version "21.4"
+ :version "22.1"
:type '(radio (const :format "%v " nil) string)
:group 'gnus-thread)
+
(defcustom gnus-sum-thread-tree-single-indent ""
"With %B spec, used for a thread with just one message.
If nil, use subject instead."
- :version "21.4"
+ :version "22.1"
:type '(radio (const :format "%v " nil) string)
:group 'gnus-thread)
+
(defcustom gnus-sum-thread-tree-vertical "| "
"With %B spec, used for drawing a vertical line."
- :version "21.4"
+ :version "22.1"
:type 'string
:group 'gnus-thread)
+
(defcustom gnus-sum-thread-tree-indent " "
"With %B spec, used for indenting."
- :version "21.4"
+ :version "22.1"
:type 'string
:group 'gnus-thread)
+
(defcustom gnus-sum-thread-tree-leaf-with-other "+-> "
"With %B spec, used for a leaf with brothers."
- :version "21.4"
+ :version "22.1"
:type 'string
:group 'gnus-thread)
+
(defcustom gnus-sum-thread-tree-single-leaf "\\-> "
"With %B spec, used for a leaf without brothers."
- :version "21.4"
+ :version "22.1"
:type 'string
:group 'gnus-thread)
(match-end 1)))
(substring xrefs (match-beginning 1) (match-end 1))))
(setq number
- (string-to-int (substring xrefs (match-beginning 2)
+ (string-to-number (substring xrefs (match-beginning 2)
(match-end 2))))
(if (setq entry (gnus-gethash group xref-hashtb))
(setcdr entry (cons number (cdr entry)))
(defun gnus-list-of-unread-articles (group)
(let* ((read (gnus-info-read (gnus-get-info group)))
(active (or (gnus-active group) (gnus-activate-group group)))
- (last (cdr active))
+ (last (or (cdr active)
+ (error "Group %s couldn't be activated " group)))
first nlast unread)
;; If none are read, then all are unread.
(if (not read)
(if quit-config
(gnus-handle-ephemeral-exit quit-config)
(goto-char group-point)
+ ;; If gnus-group-buffer is already displayed, make sure we also move
+ ;; the cursor in the window that displays it.
+ (let ((win (get-buffer-window (current-buffer) 0)))
+ (if win (set-window-point win (point))))
(unless leave-hidden
(gnus-configure-windows 'group 'force)))
;; Clear the current group name.
(gnus-completing-read-with-default
(symbol-name (car gnus-extra-headers))
(if current-prefix-arg
- "Exclude extra header:"
- "Limit extra header:")
+ "Exclude extra header"
+ "Limit extra header")
(mapcar (lambda (x)
(cons (symbol-name x) x))
gnus-extra-headers)
(let ((start (window-start))
buffer-read-only)
(message-caesar-buffer-body arg)
- (set-window-start (get-buffer-window (current-buffer)) start))))))
+ (set-window-start (get-buffer-window (current-buffer)) start)))))
+ ;; Create buttons and stuff...
+ (gnus-treat-article nil))
(defun gnus-summary-idna-message (&optional arg)
"Decode IDNA encoded domain names in the current articles.
(crosspost "Crosspost" "Crossposting")))
(copy-buf (save-excursion
(nnheader-set-temp-buffer " *copy article*")))
- art-group to-method new-xref article to-groups)
+ art-group to-method new-xref article to-groups articles-to-update-marks)
(unless (assq action names)
(error "Unknown action %s" action))
;; Read the newsgroup name.
((eq action 'move)
;; Remove this article from future suppression.
(gnus-dup-unsuppress-article article)
+ (let* ((from-method (gnus-find-method-for-group
+ gnus-newsgroup-name))
+ (to-method (gnus-find-method-for-group
+ to-newsgroup))
+ (move-is-internal (gnus-method-equal from-method to-method)))
(gnus-request-move-article
article ; Article to move
gnus-newsgroup-name ; From newsgroup
(list 'gnus-request-accept-article
to-newsgroup (list 'quote select-method)
(not articles) t) ; Accept form
- (not articles))) ; Only save nov last time
+ (not articles) ; Only save nov last time
+ move-is-internal))) ; is this move internal?
;; Copy the article.
((eq action 'copy)
(save-excursion
;;;!!!Why is this necessary?
(set-buffer gnus-summary-buffer)
-
+
(gnus-summary-goto-subject article)
(when (eq action 'move)
(gnus-summary-mark-article article gnus-canceled-mark))))
- (gnus-summary-remove-process-mark article))
+ (push article articles-to-update-marks))
+
+ (apply 'gnus-summary-remove-process-mark articles-to-update-marks)
;; Re-activate all groups that have been moved to.
(save-excursion
(set-buffer gnus-group-buffer)
(let ((gnus-group-marked to-groups))
(gnus-group-get-new-news-this-group nil t)))
-
+
(gnus-kill-buffer copy-buf)
(gnus-summary-position-point)
(gnus-set-mode-line 'summary)))
"If non-nil, show and update the summary buffer as it's being built.
If the value is t, update the buffer after every line is inserted. If
the value is an integer (N), update the display every N lines."
- :version "21.4"
+ :version "22.1"
:group 'gnus-thread
:type '(choice (const :tag "off" nil)
number
gnus-newsgroup-name)))))
(method
(gnus-completing-read-with-default
- methname "What backend do you want to use when respooling?"
+ methname "Backend to use when respooling"
methods nil t nil 'gnus-mail-method-history))
ms)
(cond
`(lambda ()
(let ((mbl mml-buffer-list))
(setq mml-buffer-list nil)
- (mime-to-mml ,'current-handles)
+ (let ((rfc2047-quote-decoded-words-containing-tspecials t))
+ (mime-to-mml ,'current-handles))
(let ((mbl1 mml-buffer-list))
(setq mml-buffer-list mbl)
(set (make-local-variable 'mml-buffer-list) mbl1))
(save-excursion
(save-restriction
(message-narrow-to-head)
- (let ((head (buffer-string))
+ (let ((head (buffer-substring-no-properties
+ (point-min) (point-max)))
header)
(with-temp-buffer
(insert (format "211 %d Article retrieved.\n"
(gnus-summary-goto-subject article)
(gnus-summary-update-secondary-mark article)))
-(defun gnus-summary-remove-process-mark (article)
- "Remove the process mark from ARTICLE and update the summary line."
- (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable))
- (when (gnus-summary-goto-subject article)
- (gnus-summary-show-thread)
- (gnus-summary-goto-subject article)
- (gnus-summary-update-secondary-mark article)))
+(defun gnus-summary-remove-process-mark (&rest articles)
+ "Remove the process mark from ARTICLES and update the summary line."
+ (dolist (article articles)
+ (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable))
+ (when (gnus-summary-goto-subject article)
+ (gnus-summary-show-thread)
+ (gnus-summary-goto-subject article)
+ (gnus-summary-update-secondary-mark article))))
(defun gnus-summary-set-saved-mark (article)
"Set the process mark on ARTICLE and update the summary line."
(let* ((split-name (gnus-get-split-value gnus-move-split-methods))
(minibuffer-confirm-incomplete nil) ; XEmacs
(prom
- (format "%s %s to:"
+ (format "%s %s to"
prompt
(if (> (length articles) 1)
(format "these %d articles" (length articles))