:group 'gnus-agent)
(defcustom gnus-agent-consider-all-articles nil
- "If non-nil, consider also the read articles for downloading."
+ "When non-`nil', the agent will let the agent predicate decide
+whether articles need to be downloaded or not, for all articles. When
+`nil', the default, the agent will only let the predicate decide
+whether unread articles are downloaded or not. If you enable this,
+groups with large active ranges may open slower and you may also want
+to look into the agent expiry settings to block the expiration of
+read articles as they would just be downloaded again."
:version "21.4"
:type 'boolean
:group 'gnus-agent)
(defun gnus-predicate-implies-unread (predicate)
"Say whether PREDICATE implies unread articles only.
It is okay to miss some cases, but there must be no false positives.
-That is, if this function returns true, then indeed the predicate must
+That is, if this predicate returns true, then indeed the predicate must
return only unread articles."
- (gnus-function-implies-unread-1 (gnus-category-make-function predicate)))
+ (eq t (gnus-function-implies-unread-1
+ (gnus-category-make-function-1 predicate))))
(defun gnus-function-implies-unread-1 (function)
- (cond ((eq function (symbol-function 'gnus-agent-read-p))
- nil)
- ((not function)
- nil)
- ((functionp function)
- 'ignore)
- ((memq (car function) '(or and not))
- (apply (car function)
- (mapcar 'gnus-function-implies-unread-1 (cdr function))))
- (t
- (error "Unknown function: %s" function))))
+ "Recursively evaluate a predicate function to determine whether it can select
+any read articles. Returns t if the function is known to never
+return read articles, nil when it is known to always return read
+articles, and t_nil when the function may return both read and unread
+articles."
+ (let ((func (car function))
+ (args (mapcar 'gnus-function-implies-unread-1 (cdr function))))
+ (cond ((eq func 'and)
+ (cond ((memq t args) ; if any argument returns only unread articles
+ ;; then that argument constrains the result to only unread articles.
+ t)
+ ((memq 't_nil args) ; if any argument is indeterminate
+ ;; then the result is indeterminate
+ 't_nil)))
+ ((eq func 'or)
+ (cond ((memq nil args) ; if any argument returns read articles
+ ;; then that argument ensures that the results includes read articles.
+ nil)
+ ((memq 't_nil args) ; if any argument is indeterminate
+ ;; then that argument ensures that the results are indeterminate
+ 't_nil)
+ (t ; if all arguments return only unread articles
+ ;; then the result returns only unread articles
+ t)))
+ ((eq func 'not)
+ (cond ((eq (car args) 't_nil) ; if the argument is indeterminate
+ ; then the result is indeterminate
+ (car args))
+ (t ; otherwise
+ ; toggle the result to be the opposite of the argument
+ (not (car args)))))
+ ((eq func 'gnus-agent-read-p)
+ nil) ; The read predicate NEVER returns unread articles
+ ((eq func 'gnus-agent-false)
+ t) ; The false predicate returns t as the empty set excludes all read articles
+ ((eq func 'gnus-agent-true)
+ nil) ; The true predicate ALWAYS returns read articles
+ ((catch 'found-match
+ (let ((alist gnus-category-predicate-alist))
+ (while alist
+ (if (eq func (cdar alist))
+ (throw 'found-match t)
+ (setq alist (cdr alist))))))
+ 't_nil) ; All other predicates return read and unread articles
+ (t
+ (error "Unknown predicate function: %s" function)))))
(defun gnus-group-category (group)
"Return the category GROUP belongs to."
@item gnus-agent-consider-all-articles
@vindex gnus-agent-consider-all-articles
-@code{gnus-agent-consider-all-articles} \e$B$,\e(B \e$BHs\e(B-@code{nil} \e$B$@$C$?$i!"%(!<\e(B
-\e$B%8%'%s%H$O$9$Y$F$N8+Ev$?$i$J$$%X%C%@!<$r<hF@$7$^$9!#\e(B@code{nil} \e$B$@$C$?$i\e(B
-\e$B?7$7$$%X%C%@!<$@$1$r<hF@$7$^$9!#%G%#%U%)%k%H$O\e(B @code{nil} \e$B$G$9!#\e(B
+@code{gnus-agent-consider-all-articles} \e$B$,Hs\e(B-@code{nil} \e$B$@$C$?$i!"%(!<%8%'\e(B
+\e$B%s%H$O$9$Y$F$N5-;v$K$D$$$F!"$=$l$i$r%@%&%s%m!<%I$9$kI,MW$,$"$k$+$I$&$+$r\e(B
+\e$B%(!<%8%'%s%H$N=R8l$K7hDj$5$;$^$9!#\e(B@code{nil} \e$B$@$C$?>l9g!"$=$l$,%G%#%U%)\e(B
+\e$B%k%H$G$9$,!"%(!<%8%'%s%H$OL$FI$N5-;v$r%@%&%s%m!<%I$9$k$+$I$&$+$@$1$r=R8l\e(B
+\e$B$K7hDj$5$;$^$9!#$3$l$rM-8z$K$9$k$K$O!"8e$G%(!<%8%'%s%H$,4|8B@Z$l>C5n$9$k\e(B
+\e$B5-;v$r2?EY$b7+$jJV$7%@%&%s%m!<%I$7$J$$$h$&$K!"%(!<%8%'%s%H$N4|8B@Z$l>C5n\e(B
+\e$B$N@_Dj\e(B (@pxref{Category Variables})\e$B$r8+D>$9I,MW$b$"$k$+$b$7$l$^$;$s!#\e(B
@item gnus-agent-max-fetch-size
@vindex gnus-agent-max-fetch-size
@item gnus-agent-consider-all-articles
@vindex gnus-agent-consider-all-articles
If @code{gnus-agent-consider-all-articles} is non-@code{nil}, the
-agent will fetch all missing headers. When @code{nil}, the agent will
-fetch only new headers. The default is @code{nil}.
+agent will let the agent predicate decide whether articles need to be
+downloaded or not, for all articles. When @code{nil}, the default,
+the agent will only let the predicate decide whether unread articles
+are downloaded or not. If you enable this, you may also want to look
+into the agent expiry settings (@pxref{Category Variables}), so that
+the agent doesn't download articles which the agent will later expire,
+over and over again.
@item gnus-agent-max-fetch-size
@vindex gnus-agent-max-fetch-size