;;; gnus-sum.el --- summary mode commands for Gnus
-;; Copyright (C) 1996-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2013 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
:group 'gnus-summary-maneuvering
:type 'boolean)
-(defcustom gnus-auto-center-summary
+(defcustom gnus-auto-center-summary
(max (or (bound-and-true-p scroll-margin) 0) 2)
"*If non-nil, always center the current summary buffer.
In particular, if `vertical' do only vertical recentering. If non-nil
(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'."
+ :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.
(defcustom gnus-summary-newsgroup-prefix "=> "
"*String prefixed to the Newsgroup field in the summary
-line when using `gnus-ignored-from-addresses'."
+line when using the option `gnus-ignored-from-addresses'."
:version "22.1"
:group 'gnus-summary
:type 'string)
(defvar gnus-newsgroup-seen nil
"Range of seen articles in the current newsgroup.")
+(defvar gnus-newsgroup-unexist nil
+ "Range of unexisting articles in the current newsgroup.")
+
(defvar gnus-newsgroup-articles nil
"List of articles in the current newsgroup.")
gnus-newsgroup-killed
gnus-newsgroup-unseen
gnus-newsgroup-seen
+ gnus-newsgroup-unexist
gnus-newsgroup-cached
gnus-newsgroup-downloadable
gnus-newsgroup-undownloaded
(gnus-define-keys gnus-summary-mode-map
" " gnus-summary-next-page
+ [?\S-\ ] gnus-summary-prev-page
"\177" gnus-summary-prev-page
[delete] gnus-summary-prev-page
[backspace] gnus-summary-prev-page
"a" gnus-summary-post-news
"x" gnus-summary-limit-to-unread
"s" gnus-summary-isearch-article
- [tab] gnus-summary-widget-forward
+ "\t" gnus-summary-widget-forward
[backtab] gnus-summary-widget-backward
"t" gnus-summary-toggle-header
"g" gnus-summary-show-article
(gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
" " gnus-summary-next-page
"n" gnus-summary-next-page
+ [?\S-\ ] gnus-summary-prev-page
"\177" gnus-summary-prev-page
[delete] gnus-summary-prev-page
"p" gnus-summary-prev-page
"W" gnus-warp-to-article
"g" gnus-summary-show-article
"s" gnus-summary-isearch-article
- [tab] gnus-summary-widget-forward
+ "\t" gnus-summary-widget-forward
[backtab] gnus-summary-widget-backward
"P" gnus-summary-print-article
"S" gnus-sticky-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]
(set-buffer buffer)
(setq gnus-summary-buffer (current-buffer))
(not gnus-newsgroup-prepared))
- ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>
- (setq gnus-summary-buffer (set-buffer (gnus-get-buffer-create buffer)))
+ (set-buffer (gnus-get-buffer-create buffer))
+ (setq gnus-summary-buffer (current-buffer))
(gnus-summary-mode group)
(when (gnus-group-quit-config group)
(set (make-local-variable 'gnus-single-article-buffer) nil))
(if (consp (car locals))
(set (caar locals) (pop vlist))
(set (car locals) (pop vlist)))
- (setq locals (cdr locals))))
- ;; The article buffer also has local variables.
- (when (gnus-buffer-live-p gnus-article-buffer)
- (set-buffer gnus-article-buffer)
- (setq gnus-summary-buffer summary))))))
+ (setq locals (cdr locals))))))))
(defun gnus-summary-article-unread-p (article)
"Say whether ARTICLE is unread or not."
(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.
+ ;; 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)))
(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
(inline
- (gnus-summary-extract-address-component gnus-tmp-from))))))
+ (gnus-summary-extract-address-component gnus-tmp-from))))))
(defun gnus-summary-insert-line (gnus-tmp-header
gnus-tmp-level gnus-tmp-current
gnus-auto-select-first)
(progn
(let ((art (gnus-summary-article-number)))
- (unless (and (not gnus-plugged)
- (or (memq art gnus-newsgroup-undownloaded)
- (memq art gnus-newsgroup-downloadable)))
+ (when (and art
+ gnus-plugged
+ (not (memq art gnus-newsgroup-undownloaded))
+ (not (memq art gnus-newsgroup-downloadable)))
(gnus-summary-goto-article art))))
;; Don't select any articles.
(gnus-summary-position-point)
(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.
(cdr (assq number gnus-newsgroup-scored))
(memq number gnus-newsgroup-processable))))))
+(declare-function gnus-parameter-list-identifier "gnus-art" (name) t)
+
(defun gnus-group-get-list-identifiers (group)
"Get list identifier regexp for GROUP."
(or (gnus-parameter-list-identifier group)
"Find out what articles the user wants to read."
(let* ((only-read-p t)
(articles
+ (gnus-list-range-difference
;; Select all articles if `read-all' is non-nil, or if there
;; are no unread articles.
(if (or read-all
(setq only-read-p nil)
(gnus-sorted-nunion
(gnus-sorted-union gnus-newsgroup-dormant gnus-newsgroup-marked)
- gnus-newsgroup-unreads)))
+ gnus-newsgroup-unreads))
+ (cdr (assq 'unexist (gnus-info-marks (gnus-get-info group))))))
(scored-list (gnus-killed-articles gnus-newsgroup-killed articles))
(scored (length scored-list))
(number (length articles))
(and (numberp (car articles))
(> min (car articles)))))
(pop articles))
- (set var articles))))))))
+ (set var articles))
+ ((eq mark 'unexist)
+ (set var (cdr marks)))))))))
(defun gnus-update-missing-marks (missing)
"Go through the list of MISSING articles and remove them from the mark lists."
(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
(unless quit-config
(setq gnus-newsgroup-name nil)))))
+(declare-function gnus-article-stop-animations "gnus-art" ())
+(declare-function gnus-stop-downloads "gnus-art" ())
+
(defalias 'gnus-summary-quit 'gnus-summary-exit-no-update)
(defun gnus-summary-exit-no-update (&optional no-questions)
"Quit reading current newsgroup without updating read article info."
(and gnus-auto-select-same
(gnus-summary-article-subject))))
+(declare-function gnus-article-only-boring-p "gnus-art" ())
+
(defun gnus-summary-next-page (&optional lines circular stop)
"Show next page of the selected article.
If at the end of the current article, select the next article.
Also see the variable `gnus-article-skip-boring'."
(interactive "P")
- (setq gnus-summary-buffer (current-buffer))
(gnus-set-global-variables)
(let ((article (gnus-summary-article-number))
(article-window (get-buffer-window gnus-article-buffer t))
(interactive "sMatch headers (regexp): \nP")
(gnus-summary-limit-to-bodies match reverse t))
+(declare-function article-goto-body "gnus-art" ())
+
(defun gnus-summary-limit-to-bodies (match &optional reverse headersp)
"Limit the summary buffer to articles that have bodies that match MATCH.
If REVERSE (the prefix), limit to articles that don't match."
(ps-spool-buffer-with-faces)
(ps-spool-buffer)))))
+(declare-function gnus-flush-original-article-buffer "gnus-art" ())
+
(defun gnus-summary-show-complete-article ()
"Show a complete version of the current article.
This is only useful if you're looking at a partial version of the
t)))
(gnus-summary-show-article))
+(declare-function article-narrow-to-head "gnus-art" ())
+(declare-function gnus-article-hidden-text-p "gnus-art" (type))
+(declare-function gnus-delete-wash-type "gnus-art" (type))
+
(defun gnus-summary-toggle-header (&optional arg)
"Show the headers if they are hidden, or hide them if they are shown.
If ARG is a positive number, show the entire header.
(when (message-goto-body)
(gnus-narrow-to-body))
(goto-char (point-min))
- (while (search-forward "·" (point-max) t)
+ (while (search-forward "·" (point-max) t)
(replace-match "."))
(unmorse-region (point-min) (point-max))
(widen)
(defun gnus-summary-push-marks-to-backend (article)
(let ((set nil)
+ (del nil)
(marks gnus-article-mark-lists))
(unless (memq article gnus-newsgroup-unreads)
(push 'read set))
(while marks
- (when (and (eq (gnus-article-mark-to-type (cdar marks)) 'list)
- (memq article (symbol-value
- (intern (format "gnus-newsgroup-%s"
- (caar marks))))))
- (push (cdar marks) set))
+ (if (and (eq (gnus-article-mark-to-type (cdar marks)) 'list)
+ (memq article (symbol-value
+ (intern (format "gnus-newsgroup-%s"
+ (caar marks))))))
+ (push (cdar marks) set)
+ (push (cdar marks) del))
(pop marks))
- (gnus-request-set-mark gnus-newsgroup-name `(((,article) set ,set)))))
+ (gnus-request-set-mark gnus-newsgroup-name `(((,article) set ,set)
+ ((,article) del ,del)))))
(defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
"Copy the current article to some other group.
'request-expire-articles gnus-newsgroup-name))
;; This backend supports expiry.
(let* ((total (gnus-group-total-expirable-p gnus-newsgroup-name))
- (expirable (if total
- (progn
- ;; We need to update the info for
- ;; this group for `gnus-list-of-read-articles'
- ;; to give us the right answer.
- (gnus-run-hooks 'gnus-exit-group-hook)
- (gnus-summary-update-info)
- (gnus-list-of-read-articles gnus-newsgroup-name))
- (setq gnus-newsgroup-expirable
- (sort gnus-newsgroup-expirable '<))))
+ (expirable
+ (gnus-list-range-difference
+ (if total
+ (progn
+ ;; We need to update the info for
+ ;; this group for `gnus-list-of-read-articles'
+ ;; to give us the right answer.
+ (gnus-run-hooks 'gnus-exit-group-hook)
+ (gnus-summary-update-info)
+ (gnus-list-of-read-articles gnus-newsgroup-name))
+ (setq gnus-newsgroup-expirable
+ (sort gnus-newsgroup-expirable '<)))
+ gnus-newsgroup-unexist))
(expiry-wait (if now 'immediate
(gnus-group-find-parameter
gnus-newsgroup-name 'expiry-wait)))
will not be hidden.
Returns nil if no threads were there to be hidden."
(interactive)
+ (beginning-of-line)
(let ((start (point))
(starteol (line-end-position))
(article (gnus-summary-article-number)))
- (goto-char start)
;; Go forward until either the buffer ends or the subthread ends.
(when (and (not (eobp))
(or (zerop (gnus-summary-next-thread 1 t))
(gnus-set-mode-line 'summary)
n))
+(declare-function gnus-summary-save-in-pipe "gnus-art" (&optional command raw))
+
(defun gnus-summary-pipe-output (&optional n sym)
"Pipe the current article to a subprocess.
If N is a positive number, pipe the N next articles.
(not (gnus-ephemeral-group-p (car where))))
(gnus-registry-handle-action
(mail-header-id header) nil
- (gnus-group-prefixed-name (car where) gnus-override-method)
+ (gnus-group-prefixed-name
+ (car where)
+ (or gnus-override-method (gnus-find-method-for-group group)))
(mail-header-subject header)
(mail-header-from header)))
(when (and (stringp id)
(memq article gnus-newsgroup-undownloaded)
(not (memq article gnus-newsgroup-cached)))))
(let ((face (funcall (gnus-summary-highlight-line-0))))
- (unless (eq face (get-text-property beg 'face))
+ (unless (eq face (gnus-get-text-property-excluding-characters-with-faces beg 'face))
(gnus-put-text-property-excluding-characters-with-faces
beg (point-at-eol) 'face
(setq face (if (boundp face) (symbol-value face) face)))
(setq gnus-newsgroup-headers
(gnus-merge 'list
gnus-newsgroup-headers
- (gnus-fetch-headers articles)
+ (gnus-fetch-headers articles nil t)
'gnus-article-sort-by-number))
(setq gnus-newsgroup-articles
(gnus-sorted-nunion gnus-newsgroup-articles articles))
;; Some nntp servers lie about their active range. When
;; this happens, the active range can be in the millions.
;; Use a compressed range to avoid creating a huge list.
- (gnus-range-difference (list gnus-newsgroup-active) old))
+ (gnus-range-difference
+ (gnus-range-difference (list gnus-newsgroup-active) old)
+ gnus-newsgroup-unexist))
(setq len (gnus-range-length older))
(cond
((null older) nil)
(gnus-summary-position-point))
;;; Bookmark support for Gnus.
+(declare-function gnus-article-show-summary "gnus-art" ())
(declare-function bookmark-make-record-default
"bookmark" (&optional no-file no-context posn))
(declare-function bookmark-prop-get "bookmark" (bookmark prop))
(run-hooks 'gnus-sum-load-hook)
;; Local Variables:
-;; coding: iso-8859-1
+;; coding: utf-8
;; End:
;;; gnus-sum.el ends here