;;; gnus-sum.el --- summary mode commands for Gnus
-;; Copyright (C) 1996-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2014 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
(function :tag "other"))
(boolean :tag "Reverse order"))))
-
(defcustom gnus-thread-sort-functions '(gnus-thread-sort-by-number)
"*List of functions used for sorting threads in the summary buffer.
By default, threads are sorted by article number.
`gnus-thread-score-function').
When threading is turned off, the variable
-`gnus-article-sort-functions' controls how articles are sorted."
+`gnus-article-sort-functions' controls how articles are sorted.
+
+By default, threads and their subthreads are sorted according to
+the value of this variable. To use a different sorting order for
+subthreads, customize `gnus-subthread-sort-functions'."
:group 'gnus-summary-sort
:type '(repeat
(gnus-widget-reversible
(function :tag "other"))
(boolean :tag "Reverse order"))))
+(defcustom gnus-subthread-sort-functions 'gnus-thread-sort-functions
+ "*List of functions used for sorting subthreads in the summary buffer.
+By default, subthreads are sorted the same as threads, i.e.,
+according to the value of `gnus-thread-sort-functions'."
+ :version "24.4"
+ :group 'gnus-summary-sort
+ :type '(choice
+ (const :tag "Sort subthreads like threads" gnus-thread-sort-functions)
+ (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)
+ (function-item gnus-thread-sort-by-most-recent-number)
+ (function-item gnus-thread-sort-by-most-recent-date)
+ (function-item gnus-thread-sort-by-random)
+ (function-item gnus-thread-sort-by-total-score)
+ (function :tag "other"))
+ (boolean :tag "Reverse order")))))
+
(defcustom gnus-thread-score-function '+
"*Function used for calculating the total score of a thread.
default: The default article score.
default-high: The default score for high scored articles.
default-low: The default score for low scored articles.
-below: The score below which articles are automatically marked as read.
mark: The article's mark.
uncached: Non-nil if the article is uncached."
:group 'gnus-summary-visual
"Range of seen articles in the current newsgroup.")
(defvar gnus-newsgroup-unexist nil
- "Range of unexistent articles in the current newsgroup.")
+ "Range of unexisting articles in the current newsgroup.")
(defvar gnus-newsgroup-articles nil
"List of articles in the current newsgroup.")
[?\S-\ ] gnus-summary-prev-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
"\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
["Mark above" gnus-summary-mark-above t]
["Tick above" gnus-summary-tick-above t]
["Clear above" gnus-summary-clear-above t])
- ["Current score" gnus-summary-current-score t]
+ ["Current article score" gnus-summary-current-score t]
+ ["Current thread score" (gnus-summary-current-score 'total) t]
["Set score" gnus-summary-set-score t]
["Switch current score file..." gnus-score-change-score-file t]
["Set mark below..." gnus-score-set-mark-below t]
The following commands are available:
\\{gnus-summary-mode-map}"
+ ;; FIXME: Use define-derived-mode.
(interactive)
(kill-all-local-variables)
(let ((gnus-summary-local-variables gnus-newsgroup-variables))
"Set the global equivalents of the buffer-local variables.
They are set to the latest values they had. These reflect the summary
buffer that was in action when the last article was fetched."
- (when (eq major-mode 'gnus-summary-mode)
+ (when (derived-mode-p 'gnus-summary-mode)
(setq gnus-summary-buffer (current-buffer))
(let ((name gnus-newsgroup-name)
(marked gnus-newsgroup-marked)
(or (car (funcall gnus-extract-address-components from))
from))
-(defun gnus-summary-from-or-to-or-newsgroups (header from)
+(defun gnus-summary-from-or-to-or-newsgroups (header gnus-tmp-from)
(let ((mail-parse-charset gnus-newsgroup-charset)
- (ignored-from-addresses (gnus-ignored-from-addresses))
- ;; Is it really necessary to do this next part for each summary line?
- ;; Luckily, doesn't seem to slow things down much.
- (mail-parse-ignored-charsets
- (with-current-buffer gnus-summary-buffer
- gnus-newsgroup-ignored-charsets))
- (address (cadr (gnus-extract-address-components from))))
+ (ignored-from-addresses (gnus-ignored-from-addresses))
+ ;; Is it really necessary to do this next part for each summary line?
+ ;; Luckily, doesn't seem to slow things down much.
+ (mail-parse-ignored-charsets
+ (with-current-buffer gnus-summary-buffer
+ gnus-newsgroup-ignored-charsets)))
(or
(and ignored-from-addresses
- (string-match ignored-from-addresses address)
+ (string-match ignored-from-addresses gnus-tmp-from)
(let ((extra-headers (mail-header-extra header))
to
newsgroups)
(cdr (assq 'Newsgroups extra-headers))
(and
(memq 'Newsgroups gnus-extra-headers)
- (eq (car (gnus-find-method-for-group
- gnus-newsgroup-name)) 'nntp)
+ (eq (car (gnus-find-method-for-group
+ gnus-newsgroup-name)) 'nntp)
(gnus-group-real-name gnus-newsgroup-name))))
(concat gnus-summary-newsgroup-prefix newsgroups)))))
- (gnus-string-mark-left-to-right (gnus-summary-extract-address-component from)))))
+ (gnus-string-mark-left-to-right
+ (inline
+ (gnus-summary-extract-address-component gnus-tmp-from))))))
(defun gnus-summary-insert-line (gnus-tmp-header
gnus-tmp-level gnus-tmp-current
t)
;; We couldn't select this group.
((null did-select)
- (when (and (eq major-mode 'gnus-summary-mode)
+ (when (and (derived-mode-p 'gnus-summary-mode)
(not (equal (current-buffer) kill-buffer)))
(kill-buffer (current-buffer))
(if (not quit-config)
;; The user did a `C-g' while prompting for number of articles,
;; so we exit this group.
((eq did-select 'quit)
- (and (eq major-mode 'gnus-summary-mode)
+ (and (derived-mode-p 'gnus-summary-mode)
(not (equal (current-buffer) kill-buffer))
(kill-buffer (current-buffer)))
(when kill-buffer
(unless no-display
(gnus-summary-prepare))
(when gnus-use-trees
- (gnus-tree-open group)
+ (gnus-tree-open)
(setq gnus-summary-highlight-line-function
'gnus-tree-highlight-article))
;; If the summary buffer is empty, but there are some low-scored
(gnus-delete-line)))))))
(defun gnus-sort-threads-recursive (threads func)
+ ;; Responsible for sorting the root articles of threads.
+ (let ((subthread-sort-func (if (eq gnus-subthread-sort-functions
+ 'gnus-thread-sort-functions)
+ func
+ (gnus-make-sort-function
+ gnus-subthread-sort-functions))))
+ (sort (mapcar (lambda (thread)
+ (cons (car thread)
+ (and (cdr thread)
+ (gnus-sort-subthreads-recursive
+ (cdr thread) subthread-sort-func))))
+ threads) func)))
+
+(defun gnus-sort-subthreads-recursive (threads func)
+ ;; Responsible for sorting subthreads.
(sort (mapcar (lambda (thread)
(cons (car thread)
(and (cdr thread)
- (gnus-sort-threads-recursive (cdr thread) func))))
+ (gnus-sort-subthreads-recursive (cdr thread) func))))
threads) func))
(defun gnus-sort-threads-loop (threads func)
(gnus-message 8 "Sorting threads...")
(prog1
(condition-case nil
- (let ((max-lisp-eval-depth (max max-lisp-eval-depth 5000)))
- (gnus-sort-threads-recursive
- threads (gnus-make-sort-function gnus-thread-sort-functions)))
+ (let ((max-lisp-eval-depth (max max-lisp-eval-depth 5000))
+ (sort-func (gnus-make-sort-function gnus-thread-sort-functions)))
+ (gnus-sort-threads-recursive threads sort-func))
;; Even after binding max-lisp-eval-depth, the recursive
;; sorter might fail for very long threads. In that case,
;; try using a (less well-tested) non-recursive sorter.
(or (and entry (not (eq (car entry) t))) ; Either it's active...
(gnus-activate-group group) ; Or we can activate it...
(progn ; Or we bug out.
- (when (equal major-mode 'gnus-summary-mode)
+ (when (derived-mode-p 'gnus-summary-mode)
(gnus-kill-buffer (current-buffer)))
(error
"Couldn't activate group %s: %s"
(mm-decode-coding-string (gnus-status-message group) charset))))
(unless (gnus-request-group group t)
- (when (equal major-mode 'gnus-summary-mode)
+ (when (derived-mode-p 'gnus-summary-mode)
(gnus-kill-buffer (current-buffer)))
(error "Couldn't request group %s: %s"
(mm-decode-coding-string group charset)
(gnus-active gnus-newsgroup-name) del))
(push (list del 'del (list (cdr type))) delta-marks))))
- (when list
+ (when (or list
+ (eq (cdr type) 'unexist))
(push (cons (cdr type) list) newmarked)))
(when delta-marks
(when gnus-suppress-duplicates
(gnus-dup-enter-articles))
(when gnus-use-trees
- (gnus-tree-close group))
+ (gnus-tree-close))
(when gnus-use-cache
(gnus-cache-write-active))
;; Remove entries for this group.
(not (string= group (gnus-group-group-name))))
(gnus-group-next-unread-group 1))
(setq group-point (point))
+ (gnus-article-stop-animations)
(if temporary
nil ;Nothing to do.
(set-buffer buf)
(unless gnus-single-article-buffer
(setq gnus-article-current nil))
(when gnus-use-trees
- (gnus-tree-close group))
+ (gnus-tree-close))
(gnus-async-prefetch-remove-group group)
(when (get-buffer gnus-article-buffer)
(bury-buffer gnus-article-buffer))
(gnus-group-update-group group nil t))
(when (equal (gnus-group-group-name) group)
(gnus-group-next-unread-group 1))
+ (gnus-article-stop-animations)
(when quit-config
(gnus-handle-ephemeral-exit quit-config)))))
(unless (eq (cdr quit-config) 'group)
(setq gnus-current-select-method
(gnus-find-method-for-group gnus-newsgroup-name)))
- (cond ((eq major-mode 'gnus-summary-mode)
+ (cond ((derived-mode-p 'gnus-summary-mode)
(gnus-set-global-variables))
- ((eq major-mode 'gnus-article-mode)
+ ((derived-mode-p 'gnus-article-mode)
(save-current-buffer
;; The `gnus-summary-buffer' variable may point
;; to the old summary buffer when using a single
(gnus-configure-windows 'pick 'force)
(gnus-configure-windows (cdr quit-config) 'force))
(gnus-configure-windows (cdr quit-config) 'force))
- (when (eq major-mode 'gnus-summary-mode)
+ (when (derived-mode-p 'gnus-summary-mode)
(if (memq gnus-auto-select-on-ephemeral-exit '(next-noselect
next-unread-noselect))
(when (zerop (cond ((eq gnus-auto-select-on-ephemeral-exit
(when (and gnus-use-trees
(gnus-buffer-exists-p buffer))
(with-current-buffer buffer
- (gnus-tree-close gnus-newsgroup-name)))
+ (gnus-tree-close)))
(gnus-kill-buffer buffer))
;; Deaden the buffer.
((gnus-buffer-exists-p buffer)
"Display ARTICLE in article buffer."
(unless (and (gnus-buffer-live-p gnus-article-buffer)
(with-current-buffer gnus-article-buffer
- (eq major-mode 'gnus-article-mode)))
+ (derived-mode-p 'gnus-article-mode)))
(gnus-article-setup-buffer))
(gnus-set-global-variables)
(with-current-buffer gnus-article-buffer
the article buffer. If PSEUDO is non-nil, pseudo-articles will also
be displayed."
;; Make sure we are in the summary buffer to work around bbdb bug.
- (unless (eq major-mode 'gnus-summary-mode)
+ (unless (derived-mode-p 'gnus-summary-mode)
(set-buffer gnus-summary-buffer))
(let ((article (or article (gnus-summary-article-number)))
(all-headers (not (not all-headers))) ;Must be t or nil.
If BACKWARD, the previous article is selected instead of the next."
(interactive "P")
;; Make sure we are in the summary buffer.
- (unless (eq major-mode 'gnus-summary-mode)
+ (unless (derived-mode-p 'gnus-summary-mode)
(set-buffer gnus-summary-buffer))
(cond
;; Is there such an article?
(gnus-fetch-field "from")))
(setq params
(append
+ params
(list (cons 'to-address
(funcall gnus-decode-encoded-address-function
to-address))))))
(let (gnus-mark-article-hook)
(gnus-summary-select-article)
(with-current-buffer gnus-original-article-buffer
- (let ((groups (nnmail-article-group 'identity trace)))
+ (let ((groups
+ (if (eq (car (gnus-find-method-for-group gnus-newsgroup-name))
+ 'nnimap)
+ ;; nnimap has its own splitting variables.
+ (let ((nnmail-split-methods
+ (cond
+ ((eq nnimap-split-methods 'default)
+ nnmail-split-methods)
+ (nnimap-split-methods
+ nnimap-split-methods)
+ (nnimap-split-fancy
+ 'nnmail-split-fancy)))
+ (nnmail-split-fancy (or nnimap-split-fancy
+ nnmail-split-fancy)))
+ (nnmail-article-group 'identity trace))
+ (nnmail-article-group 'identity trace))))
(unless silent
(if groups
(message "This message would go to %s"
(string-match "Summary" buffer)
(with-current-buffer buffer
;; We check that this is, indeed, a summary buffer.
- (and (eq major-mode 'gnus-summary-mode)
+ (and (derived-mode-p 'gnus-summary-mode)
;; Also make sure this isn't bogus.
gnus-newsgroup-prepared
;; Also make sure that this isn't a
(defun gnus-summary-generic-mark (n mark move unread)
"Mark N articles with MARK."
- (unless (eq major-mode 'gnus-summary-mode)
+ (unless (derived-mode-p 'gnus-summary-mode)
(error "This command can only be used in the summary buffer"))
(gnus-summary-show-thread)
(let ((nummove