aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Ingebrigtsen2022-01-17 12:40:43 +0100
committerLars Ingebrigtsen2022-01-17 15:47:50 +0100
commit39d4e1ca21f3270d4835d5efa8862efc618c4cd9 (patch)
treec7449bb32cc89e37d3ce8266ad4f135bda70d3a1
parentab17e353253a88d92f68b3909b27ded9e536fb28 (diff)
downloademacs-39d4e1ca21f3270d4835d5efa8862efc618c4cd9.tar.gz
emacs-39d4e1ca21f3270d4835d5efa8862efc618c4cd9.zip
Move the Gnus range functions to a new range.el file
* lisp/emacs-lisp/range.el: New file. * lisp/gnus/gnus-agent.el (range): (gnus-agent-synchronize-group-flags): (gnus-agent-possibly-alter-active): (gnus-agent-fetch-headers): (gnus-agent-read-agentview): (gnus-agent-fetch-group-1): (gnus-agent-read-p): (gnus-agent-expire-group-1): (gnus-agent-retrieve-headers): Adjust callers. * lisp/gnus/gnus-art.el (range): (gnus-article-describe-bindings): * lisp/gnus/gnus-cloud.el (range): (gnus-cloud-available-chunks): * lisp/gnus/gnus-draft.el (gnus-group-send-queue): * lisp/gnus/gnus-group.el (range): (gnus-group-line-format-alist): (gnus-number-of-unseen-articles-in-group): (gnus-group-update-eval-form): (gnus-group-read-group): (gnus-group-delete-articles): (gnus-group-catchup): (gnus-group-expire-articles-1): (gnus-add-marked-articles): * lisp/gnus/gnus-int.el (gnus-request-marks): * lisp/gnus/gnus-kill.el (gnus-apply-kill-file-internal): * lisp/gnus/gnus-range.el (gnus-range-difference) (gnus-sorted-range-intersection, gnus-uncompress-range) (gnus-add-to-range, gnus-remove-from-range) (gnus-member-of-range, gnus-list-range-intersection) (gnus-list-range-difference, gnus-range-length, gnus-range-add) (gnus-range-map): Make into obsolete aliases. * lisp/gnus/gnus-start.el (gnus-make-articles-unread): (gnus-convert-old-ticks): (gnus-read-old-newsrc-el-file): * lisp/gnus/gnus-sum.el (gnus-select-newsgroup): (gnus-articles-to-read): (gnus-articles-to-read): (gnus-killed-articles): (gnus-adjust-marked-articles): (gnus-update-marks): (gnus-update-marks): (gnus-compute-read-articles): (gnus-list-of-read-articles): (gnus-summary-update-info): (gnus-summary-move-article): (gnus-summary-expire-articles): (gnus-update-read-articles): (gnus-summary-insert-old-articles): (gnus-summary-insert-old-articles): (gnus-summary-insert-old-articles): * lisp/gnus/mail-source.el (gnus-range): (gnus-compress-sequence): * lisp/gnus/nnheader.el (range): (gnus-range-add): (nnheader-update-marks-actions): * lisp/gnus/nnimap.el (nnimap-update-info): (nnimap-update-info): (nnimap-update-info): (nnimap-update-qresync-info): (nnimap-update-qresync-info): (nnimap-update-qresync-info): (nnimap-parse-copied-articles): * lisp/gnus/nnmaildir.el (nnmaildir-request-update-info): (nnmaildir-request-update-info): (nnmaildir-request-expire-articles): (nnmaildir-request-expire-articles): (nnmaildir-request-set-mark): * lisp/gnus/nnmairix.el (nnmairix-request-set-mark): * lisp/gnus/nnmbox.el (nnmbox-record-active-article): (nnmbox-record-deleted-article): * lisp/gnus/nnml.el (nnml-request-compact-group): * lisp/gnus/nnvirtual.el (nnvirtual-request-expire-articles): * lisp/gnus/nnselect.el (numbers-by-group): (nnselect-request-update-info): (nnselect-push-info):
-rw-r--r--lisp/emacs-lisp/range.el467
-rw-r--r--lisp/gnus/gnus-agent.el45
-rw-r--r--lisp/gnus/gnus-art.el3
-rw-r--r--lisp/gnus/gnus-cloud.el3
-rw-r--r--lisp/gnus/gnus-draft.el2
-rw-r--r--lisp/gnus/gnus-group.el52
-rw-r--r--lisp/gnus/gnus-int.el2
-rw-r--r--lisp/gnus/gnus-kill.el2
-rw-r--r--lisp/gnus/gnus-range.el443
-rw-r--r--lisp/gnus/gnus-start.el14
-rw-r--r--lisp/gnus/gnus-sum.el64
-rw-r--r--lisp/gnus/mail-source.el3
-rw-r--r--lisp/gnus/nnheader.el8
-rw-r--r--lisp/gnus/nnimap.el29
-rw-r--r--lisp/gnus/nnmaildir.el16
-rw-r--r--lisp/gnus/nnmairix.el2
-rw-r--r--lisp/gnus/nnmbox.el6
-rw-r--r--lisp/gnus/nnml.el19
-rw-r--r--lisp/gnus/nnselect.el30
-rw-r--r--lisp/gnus/nnvirtual.el2
-rw-r--r--test/lisp/emacs-lisp/range-tests.el65
21 files changed, 710 insertions, 567 deletions
diff --git a/lisp/emacs-lisp/range.el b/lisp/emacs-lisp/range.el
new file mode 100644
index 00000000000..38c2866cd4c
--- /dev/null
+++ b/lisp/emacs-lisp/range.el
@@ -0,0 +1,467 @@
1;;; ranges.el --- range functions -*- lexical-binding: t; -*-
2
3;; Copyright (C) 1996-2022 Free Software Foundation, Inc.
4
5;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;; A "range" is a list that represents a list of integers. A range is
25;; a list containing cons cells of start/end pairs, as well as integers.
26;;
27;; ((2 . 5) 9 (11 . 13))
28;;
29;; represents the list (2 3 4 5 9 11 12 13).
30
31;;; Code:
32
33(defun range-normalize (range)
34 "Normalize RANGE.
35If RANGE is a single range, return (RANGE). Otherwise, return RANGE."
36 (if (listp (cdr-safe range))
37 range
38 (list range)))
39
40(defun range-denormalize (range)
41 "If RANGE contains a single range, then return that.
42If not, return RANGE as is."
43 (if (and (consp (car range))
44 (length= range 1))
45 (car range)
46 range))
47
48(defun range-difference (range1 range2)
49 "Return the range of elements in RANGE1 that do not appear in RANGE2.
50Both ranges must be in ascending order."
51 (setq range1 (range-normalize range1))
52 (setq range2 (range-normalize range2))
53 (let* ((new-range (cons nil (copy-sequence range1)))
54 (r new-range))
55 (while (cdr r)
56 (let* ((r1 (cadr r))
57 (r2 (car range2))
58 (min1 (if (numberp r1) r1 (car r1)))
59 (max1 (if (numberp r1) r1 (cdr r1)))
60 (min2 (if (numberp r2) r2 (car r2)))
61 (max2 (if (numberp r2) r2 (cdr r2))))
62
63 (cond ((> min1 max1)
64 ;; Invalid range: may result from overlap condition (below)
65 ;; remove Invalid range
66 (setcdr r (cddr r)))
67 ((and (= min1 max1)
68 (listp r1))
69 ;; Inefficient representation: may result from overlap
70 ;; condition (below)
71 (setcar (cdr r) min1))
72 ((not min2)
73 ;; All done with range2
74 (setq r nil))
75 ((< max1 min2)
76 ;; No overlap: range1 precedes range2
77 (pop r))
78 ((< max2 min1)
79 ;; No overlap: range2 precedes range1
80 (pop range2))
81 ((and (<= min2 min1) (<= max1 max2))
82 ;; Complete overlap: range1 removed
83 (setcdr r (cddr r)))
84 (t
85 (setcdr r (nconc (list (cons min1 (1- min2))
86 (cons (1+ max2) max1))
87 (cddr r)))))))
88 (cdr new-range)))
89
90(defun range-intersection (range1 range2)
91 "Return intersection of RANGE1 and RANGE2."
92 (let* (out
93 (min1 (car range1))
94 (max1 (if (numberp min1)
95 (if (numberp (cdr range1))
96 (prog1 (cdr range1)
97 (setq range1 nil)) min1)
98 (prog1 (cdr min1)
99 (setq min1 (car min1)))))
100 (min2 (car range2))
101 (max2 (if (numberp min2)
102 (if (numberp (cdr range2))
103 (prog1 (cdr range2)
104 (setq range2 nil)) min2)
105 (prog1 (cdr min2)
106 (setq min2 (car min2))))))
107 (setq range1 (cdr range1)
108 range2 (cdr range2))
109 (while (and min1 min2)
110 (cond ((< max1 min2) ; range1 precedes range2
111 (setq range1 (cdr range1)
112 min1 nil))
113 ((< max2 min1) ; range2 precedes range1
114 (setq range2 (cdr range2)
115 min2 nil))
116 (t ; some sort of overlap is occurring
117 (let ((min (max min1 min2))
118 (max (min max1 max2)))
119 (setq out (if (= min max)
120 (cons min out)
121 (cons (cons min max) out))))
122 (if (< max1 max2) ; range1 ends before range2
123 (setq min1 nil) ; incr range1
124 (setq min2 nil)))) ; incr range2
125 (unless min1
126 (setq min1 (car range1)
127 max1 (if (numberp min1) min1
128 (prog1 (cdr min1) (setq min1 (car min1))))
129 range1 (cdr range1)))
130 (unless min2
131 (setq min2 (car range2)
132 max2 (if (numberp min2) min2
133 (prog1 (cdr min2) (setq min2 (car min2))))
134 range2 (cdr range2))))
135 (cond ((cdr out)
136 (nreverse out))
137 ((numberp (car out))
138 out)
139 (t
140 (car out)))))
141
142(defun range-compress-list (numbers)
143 "Convert a sorted list of numbers to a range list."
144 (let ((first (car numbers))
145 (last (car numbers))
146 result)
147 (cond
148 ((null numbers)
149 nil)
150 ((not (listp (cdr numbers)))
151 numbers)
152 (t
153 (while numbers
154 (cond ((= last (car numbers)) nil) ;Omit duplicated number
155 ((= (1+ last) (car numbers)) ;Still in sequence
156 (setq last (car numbers)))
157 (t ;End of one sequence
158 (setq result
159 (cons (if (= first last) first
160 (cons first last))
161 result))
162 (setq first (car numbers))
163 (setq last (car numbers))))
164 (setq numbers (cdr numbers)))
165 (nreverse (cons (if (= first last) first (cons first last))
166 result))))))
167
168(defun range-uncompress (ranges)
169 "Expand a list of ranges into a list of numbers.
170RANGES is either a single range on the form `(num . num)' or a list of
171these ranges."
172 (let (first last result)
173 (cond
174 ((null ranges)
175 nil)
176 ((not (listp (cdr ranges)))
177 (setq first (car ranges))
178 (setq last (cdr ranges))
179 (while (<= first last)
180 (setq result (cons first result))
181 (setq first (1+ first)))
182 (nreverse result))
183 (t
184 (while ranges
185 (if (atom (car ranges))
186 (when (numberp (car ranges))
187 (setq result (cons (car ranges) result)))
188 (setq first (caar ranges))
189 (setq last (cdar ranges))
190 (while (<= first last)
191 (setq result (cons first result))
192 (setq first (1+ first))))
193 (setq ranges (cdr ranges)))
194 (nreverse result)))))
195
196(defun range-add-list (ranges list)
197 "Return a list of ranges that has all articles from both RANGES and LIST.
198Note: LIST has to be sorted over `<'."
199 (if (not ranges)
200 (range-compress-list list)
201 (setq list (copy-sequence list))
202 (unless (listp (cdr ranges))
203 (setq ranges (list ranges)))
204 (let ((out ranges)
205 ilist lowest highest temp)
206 (while (and ranges list)
207 (setq ilist list)
208 (setq lowest (or (and (atom (car ranges)) (car ranges))
209 (caar ranges)))
210 (while (and list (cdr list) (< (cadr list) lowest))
211 (setq list (cdr list)))
212 (when (< (car ilist) lowest)
213 (setq temp list)
214 (setq list (cdr list))
215 (setcdr temp nil)
216 (setq out (nconc (range-compress-list ilist) out)))
217 (setq highest (or (and (atom (car ranges)) (car ranges))
218 (cdar ranges)))
219 (while (and list (<= (car list) highest))
220 (setq list (cdr list)))
221 (setq ranges (cdr ranges)))
222 (when list
223 (setq out (nconc (range-compress-list list) out)))
224 (setq out (sort out (lambda (r1 r2)
225 (< (or (and (atom r1) r1) (car r1))
226 (or (and (atom r2) r2) (car r2))))))
227 (setq ranges out)
228 (while ranges
229 (if (atom (car ranges))
230 (when (cdr ranges)
231 (if (atom (cadr ranges))
232 (when (= (1+ (car ranges)) (cadr ranges))
233 (setcar ranges (cons (car ranges)
234 (cadr ranges)))
235 (setcdr ranges (cddr ranges)))
236 (when (= (1+ (car ranges)) (caadr ranges))
237 (setcar (cadr ranges) (car ranges))
238 (setcar ranges (cadr ranges))
239 (setcdr ranges (cddr ranges)))))
240 (when (cdr ranges)
241 (if (atom (cadr ranges))
242 (when (= (1+ (cdar ranges)) (cadr ranges))
243 (setcdr (car ranges) (cadr ranges))
244 (setcdr ranges (cddr ranges)))
245 (when (= (1+ (cdar ranges)) (caadr ranges))
246 (setcdr (car ranges) (cdadr ranges))
247 (setcdr ranges (cddr ranges))))))
248 (setq ranges (cdr ranges)))
249 out)))
250
251(defun range-remove (range1 range2)
252 "Return a range that has all articles from RANGE2 removed from RANGE1.
253The returned range is always a list. RANGE2 can also be a unsorted
254list of articles. RANGE1 is modified by side effects, RANGE2 is not
255modified."
256 (if (or (null range1) (null range2))
257 range1
258 (let (out r1 r2 r1-min r1-max r2-min r2-max
259 (range2 (copy-tree range2)))
260 (setq range1 (if (listp (cdr range1)) range1 (list range1))
261 range2 (sort (if (listp (cdr range2)) range2 (list range2))
262 (lambda (e1 e2)
263 (< (if (consp e1) (car e1) e1)
264 (if (consp e2) (car e2) e2))))
265 r1 (car range1)
266 r2 (car range2)
267 r1-min (if (consp r1) (car r1) r1)
268 r1-max (if (consp r1) (cdr r1) r1)
269 r2-min (if (consp r2) (car r2) r2)
270 r2-max (if (consp r2) (cdr r2) r2))
271 (while (and range1 range2)
272 (cond ((< r2-max r1-min) ; r2 < r1
273 (pop range2)
274 (setq r2 (car range2)
275 r2-min (if (consp r2) (car r2) r2)
276 r2-max (if (consp r2) (cdr r2) r2)))
277 ((and (<= r2-min r1-min) (<= r1-max r2-max)) ; r2 overlap r1
278 (pop range1)
279 (setq r1 (car range1)
280 r1-min (if (consp r1) (car r1) r1)
281 r1-max (if (consp r1) (cdr r1) r1)))
282 ((and (<= r2-min r1-min) (<= r2-max r1-max)) ; r2 overlap min r1
283 (pop range2)
284 (setq r1-min (1+ r2-max)
285 r2 (car range2)
286 r2-min (if (consp r2) (car r2) r2)
287 r2-max (if (consp r2) (cdr r2) r2)))
288 ((and (<= r1-min r2-min) (<= r2-max r1-max)) ; r2 contained in r1
289 (if (eq r1-min (1- r2-min))
290 (push r1-min out)
291 (push (cons r1-min (1- r2-min)) out))
292 (pop range2)
293 (if (< r2-max r1-max) ; finished with r1?
294 (setq r1-min (1+ r2-max))
295 (pop range1)
296 (setq r1 (car range1)
297 r1-min (if (consp r1) (car r1) r1)
298 r1-max (if (consp r1) (cdr r1) r1)))
299 (setq r2 (car range2)
300 r2-min (if (consp r2) (car r2) r2)
301 r2-max (if (consp r2) (cdr r2) r2)))
302 ((and (<= r2-min r1-max) (<= r1-max r2-max)) ; r2 overlap max r1
303 (if (eq r1-min (1- r2-min))
304 (push r1-min out)
305 (push (cons r1-min (1- r2-min)) out))
306 (pop range1)
307 (setq r1 (car range1)
308 r1-min (if (consp r1) (car r1) r1)
309 r1-max (if (consp r1) (cdr r1) r1)))
310 ((< r1-max r2-min) ; r2 > r1
311 (pop range1)
312 (if (eq r1-min r1-max)
313 (push r1-min out)
314 (push (cons r1-min r1-max) out))
315 (setq r1 (car range1)
316 r1-min (if (consp r1) (car r1) r1)
317 r1-max (if (consp r1) (cdr r1) r1)))))
318 (when r1
319 (if (eq r1-min r1-max)
320 (push r1-min out)
321 (push (cons r1-min r1-max) out))
322 (pop range1))
323 (while range1
324 (push (pop range1) out))
325 (nreverse out))))
326
327(defun range-member-p (number ranges)
328 "Say whether NUMBER is in RANGES."
329 (if (not (listp (cdr ranges)))
330 (and (>= number (car ranges))
331 (<= number (cdr ranges)))
332 (let ((not-stop t))
333 (while (and ranges
334 (if (numberp (car ranges))
335 (>= number (car ranges))
336 (>= number (caar ranges)))
337 not-stop)
338 (when (if (numberp (car ranges))
339 (= number (car ranges))
340 (and (>= number (caar ranges))
341 (<= number (cdar ranges))))
342 (setq not-stop nil))
343 (setq ranges (cdr ranges)))
344 (not not-stop))))
345
346(defun range-list-intersection (list ranges)
347 "Return a list of numbers in LIST that are members of RANGES.
348oLIST is a sorted list."
349 (setq ranges (range-normalize ranges))
350 (let (number result)
351 (while (setq number (pop list))
352 (while (and ranges
353 (if (numberp (car ranges))
354 (< (car ranges) number)
355 (< (cdar ranges) number)))
356 (setq ranges (cdr ranges)))
357 (when (and ranges
358 (if (numberp (car ranges))
359 (= (car ranges) number)
360 ;; (caar ranges) <= number <= (cdar ranges)
361 (>= number (caar ranges))))
362 (push number result)))
363 (nreverse result)))
364
365(defun range-list-difference (list ranges)
366 "Return a list of numbers in LIST that are not members of RANGES.
367LIST is a sorted list."
368 (setq ranges (range-normalize ranges))
369 (let (number result)
370 (while (setq number (pop list))
371 (while (and ranges
372 (if (numberp (car ranges))
373 (< (car ranges) number)
374 (< (cdar ranges) number)))
375 (setq ranges (cdr ranges)))
376 (when (or (not ranges)
377 (if (numberp (car ranges))
378 (not (= (car ranges) number))
379 ;; not ((caar ranges) <= number <= (cdar ranges))
380 (< number (caar ranges))))
381 (push number result)))
382 (nreverse result)))
383
384(defun range-length (range)
385 "Return the length RANGE would have if uncompressed."
386 (cond
387 ((null range)
388 0)
389 ((not (listp (cdr range)))
390 (- (cdr range) (car range) -1))
391 (t
392 (let ((sum 0))
393 (dolist (x range sum)
394 (setq sum
395 (+ sum (if (consp x) (- (cdr x) (car x) -1) 1))))))))
396
397(defun range-concat (range1 range2)
398 "Add RANGE2 to RANGE1 (nondestructively)."
399 (unless (listp (cdr range1))
400 (setq range1 (list range1)))
401 (unless (listp (cdr range2))
402 (setq range2 (list range2)))
403 (let ((item1 (pop range1))
404 (item2 (pop range2))
405 range item selector)
406 (while (or item1 item2)
407 (setq selector
408 (cond
409 ((null item1) nil)
410 ((null item2) t)
411 ((and (numberp item1) (numberp item2)) (< item1 item2))
412 ((numberp item1) (< item1 (car item2)))
413 ((numberp item2) (< (car item1) item2))
414 (t (< (car item1) (car item2)))))
415 (setq item
416 (or
417 (let ((tmp1 item) (tmp2 (if selector item1 item2)))
418 (cond
419 ((null tmp1) tmp2)
420 ((null tmp2) tmp1)
421 ((and (numberp tmp1) (numberp tmp2))
422 (cond
423 ((eq tmp1 tmp2) tmp1)
424 ((eq (1+ tmp1) tmp2) (cons tmp1 tmp2))
425 ((eq (1+ tmp2) tmp1) (cons tmp2 tmp1))
426 (t nil)))
427 ((numberp tmp1)
428 (cond
429 ((and (>= tmp1 (car tmp2)) (<= tmp1 (cdr tmp2))) tmp2)
430 ((eq (1+ tmp1) (car tmp2)) (cons tmp1 (cdr tmp2)))
431 ((eq (1- tmp1) (cdr tmp2)) (cons (car tmp2) tmp1))
432 (t nil)))
433 ((numberp tmp2)
434 (cond
435 ((and (>= tmp2 (car tmp1)) (<= tmp2 (cdr tmp1))) tmp1)
436 ((eq (1+ tmp2) (car tmp1)) (cons tmp2 (cdr tmp1)))
437 ((eq (1- tmp2) (cdr tmp1)) (cons (car tmp1) tmp2))
438 (t nil)))
439 ((< (1+ (cdr tmp1)) (car tmp2)) nil)
440 ((< (1+ (cdr tmp2)) (car tmp1)) nil)
441 (t (cons (min (car tmp1) (car tmp2))
442 (max (cdr tmp1) (cdr tmp2))))))
443 (progn
444 (if item (push item range))
445 (if selector item1 item2))))
446 (if selector
447 (setq item1 (pop range1))
448 (setq item2 (pop range2))))
449 (if item (push item range))
450 (reverse range)))
451
452(defun range-map (func range)
453 "Apply FUNC to each value contained by RANGE."
454 (setq range (range-normalize range))
455 (while range
456 (let ((span (pop range)))
457 (if (numberp span)
458 (funcall func span)
459 (let ((first (car span))
460 (last (cdr span)))
461 (while (<= first last)
462 (funcall func first)
463 (setq first (1+ first))))))))
464
465(provide 'range)
466
467;;; range.el ends here
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index fd66135b5c6..e4704b35c8d 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -31,6 +31,7 @@
31(require 'gnus-srvr) 31(require 'gnus-srvr)
32(require 'gnus-util) 32(require 'gnus-util)
33(require 'timer) 33(require 'timer)
34(require 'range)
34(eval-when-compile (require 'cl-lib)) 35(eval-when-compile (require 'cl-lib))
35 36
36(autoload 'gnus-server-update-server "gnus-srvr") 37(autoload 'gnus-server-update-server "gnus-srvr")
@@ -1219,8 +1220,8 @@ This can be added to `gnus-select-article-hook' or
1219 (cond ((eq mark 'read) 1220 (cond ((eq mark 'read)
1220 (setf (gnus-info-read info) 1221 (setf (gnus-info-read info)
1221 (funcall (if (eq what 'add) 1222 (funcall (if (eq what 'add)
1222 #'gnus-range-add 1223 #'range-concat
1223 #'gnus-remove-from-range) 1224 #'range-remove)
1224 (gnus-info-read info) 1225 (gnus-info-read info)
1225 range)) 1226 range))
1226 (gnus-get-unread-articles-in-group 1227 (gnus-get-unread-articles-in-group
@@ -1233,8 +1234,8 @@ This can be added to `gnus-select-article-hook' or
1233 (gnus-info-marks info))) 1234 (gnus-info-marks info)))
1234 (setcdr info-marks 1235 (setcdr info-marks
1235 (funcall (if (eq what 'add) 1236 (funcall (if (eq what 'add)
1236 #'gnus-range-add 1237 #'range-concat
1237 #'gnus-remove-from-range) 1238 #'range-remove)
1238 (cdr info-marks) 1239 (cdr info-marks)
1239 range)))))))) 1240 range))))))))
1240 1241
@@ -1307,7 +1308,7 @@ downloaded into the agent."
1307 1308
1308 (let ((read (gnus-info-read info))) 1309 (let ((read (gnus-info-read info)))
1309 (setf (gnus-info-read info) 1310 (setf (gnus-info-read info)
1310 (gnus-range-add 1311 (range-concat
1311 read 1312 read
1312 (list (cons (1+ agent-max) 1313 (list (cons (1+ agent-max)
1313 (1- active-min)))))) 1314 (1- active-min))))))
@@ -1796,13 +1797,13 @@ article numbers will be returned."
1796 (articles (if fetch-all 1797 (articles (if fetch-all
1797 (if gnus-newsgroup-maximum-articles 1798 (if gnus-newsgroup-maximum-articles
1798 (let ((active (gnus-active group))) 1799 (let ((active (gnus-active group)))
1799 (gnus-uncompress-range 1800 (range-uncompress
1800 (cons (max (car active) 1801 (cons (max (car active)
1801 (- (cdr active) 1802 (- (cdr active)
1802 gnus-newsgroup-maximum-articles 1803 gnus-newsgroup-maximum-articles
1803 -1)) 1804 -1))
1804 (cdr active)))) 1805 (cdr active))))
1805 (gnus-uncompress-range (gnus-active group))) 1806 (range-uncompress (gnus-active group)))
1806 (gnus-list-of-unread-articles group))) 1807 (gnus-list-of-unread-articles group)))
1807 (gnus-decode-encoded-word-function 'identity) 1808 (gnus-decode-encoded-word-function 'identity)
1808 (gnus-decode-encoded-address-function 'identity) 1809 (gnus-decode-encoded-address-function 'identity)
@@ -1817,7 +1818,7 @@ article numbers will be returned."
1817 ;; because otherwise the agent will remove their marks.) 1818 ;; because otherwise the agent will remove their marks.)
1818 (dolist (arts (gnus-info-marks (gnus-get-info group))) 1819 (dolist (arts (gnus-info-marks (gnus-get-info group)))
1819 (unless (memq (car arts) '(seen recent killed cache)) 1820 (unless (memq (car arts) '(seen recent killed cache))
1820 (setq articles (gnus-range-add articles (cdr arts))))) 1821 (setq articles (range-concat articles (cdr arts)))))
1821 (setq articles (sort (gnus-uncompress-sequence articles) #'<))) 1822 (setq articles (sort (gnus-uncompress-sequence articles) #'<)))
1822 1823
1823 ;; At this point, I have the list of articles to consider for 1824 ;; At this point, I have the list of articles to consider for
@@ -1851,15 +1852,15 @@ article numbers will be returned."
1851 ;; gnus-agent-article-alist) equals (cdr (gnus-active 1852 ;; gnus-agent-article-alist) equals (cdr (gnus-active
1852 ;; group))}. The addition of one(the 1+ above) then 1853 ;; group))}. The addition of one(the 1+ above) then
1853 ;; forces Low to be greater than High. When this happens, 1854 ;; forces Low to be greater than High. When this happens,
1854 ;; gnus-list-range-intersection returns nil which 1855 ;; range-list-intersection returns nil which
1855 ;; indicates that no headers need to be fetched. -- Kevin 1856 ;; indicates that no headers need to be fetched. -- Kevin
1856 (setq articles (gnus-list-range-intersection 1857 (setq articles (range-list-intersection
1857 articles (list (cons low high))))))) 1858 articles (list (cons low high)))))))
1858 1859
1859 (when articles 1860 (when articles
1860 (gnus-message 1861 (gnus-message
1861 10 "gnus-agent-fetch-headers: undownloaded articles are `%s'" 1862 10 "gnus-agent-fetch-headers: undownloaded articles are `%s'"
1862 (gnus-compress-sequence articles t))) 1863 (range-compress-list articles)))
1863 1864
1864 (with-current-buffer nntp-server-buffer 1865 (with-current-buffer nntp-server-buffer
1865 (if articles 1866 (if articles
@@ -2060,7 +2061,7 @@ doesn't exist, to valid the overview buffer."
2060 (let (state sequence uncomp) 2061 (let (state sequence uncomp)
2061 (while alist 2062 (while alist
2062 (setq state (caar alist) 2063 (setq state (caar alist)
2063 sequence (inline (gnus-uncompress-range (cdar alist))) 2064 sequence (inline (range-uncompress (cdar alist)))
2064 alist (cdr alist)) 2065 alist (cdr alist))
2065 (while sequence 2066 (while sequence
2066 (push (cons (pop sequence) state) uncomp))) 2067 (push (cons (pop sequence) state) uncomp)))
@@ -2404,7 +2405,7 @@ contents, they are first saved to their own file."
2404 (let ((arts (cdr (assq mark (gnus-info-marks 2405 (let ((arts (cdr (assq mark (gnus-info-marks
2405 (setq info (gnus-get-info group))))))) 2406 (setq info (gnus-get-info group)))))))
2406 (when arts 2407 (when arts
2407 (setq marked-articles (nconc (gnus-uncompress-range arts) 2408 (setq marked-articles (nconc (range-uncompress arts)
2408 marked-articles)) 2409 marked-articles))
2409 )))) 2410 ))))
2410 (setq marked-articles (sort marked-articles #'<)) 2411 (setq marked-articles (sort marked-articles #'<))
@@ -2544,7 +2545,7 @@ contents, they are first saved to their own file."
2544 (let ((read (gnus-info-read 2545 (let ((read (gnus-info-read
2545 (or info (setq info (gnus-get-info group)))))) 2546 (or info (setq info (gnus-get-info group))))))
2546 (setf (gnus-info-read info) 2547 (setf (gnus-info-read info)
2547 (gnus-add-to-range read unfetched-articles))) 2548 (range-add-list read unfetched-articles)))
2548 2549
2549 (gnus-group-update-group group t) 2550 (gnus-group-update-group group t)
2550 (sit-for 0) 2551 (sit-for 0)
@@ -2898,8 +2899,8 @@ The following commands are available:
2898 2899
2899(defun gnus-agent-read-p () 2900(defun gnus-agent-read-p ()
2900 "Say whether an article is read or not." 2901 "Say whether an article is read or not."
2901 (gnus-member-of-range (mail-header-number gnus-headers) 2902 (range-member-p (mail-header-number gnus-headers)
2902 (gnus-info-read (gnus-get-info gnus-newsgroup-name)))) 2903 (gnus-info-read (gnus-get-info gnus-newsgroup-name))))
2903 2904
2904(defun gnus-category-make-function (predicate) 2905(defun gnus-category-make-function (predicate)
2905 "Make a function from PREDICATE." 2906 "Make a function from PREDICATE."
@@ -3115,7 +3116,7 @@ FORCE is equivalent to setting the expiration predicates to true."
3115 ;; All articles EXCEPT those named by the caller 3116 ;; All articles EXCEPT those named by the caller
3116 ;; are protected from expiration 3117 ;; are protected from expiration
3117 (gnus-sorted-difference 3118 (gnus-sorted-difference
3118 (gnus-uncompress-range 3119 (range-uncompress
3119 (cons (caar alist) 3120 (cons (caar alist)
3120 (caar (last alist)))) 3121 (caar (last alist))))
3121 (sort articles #'<))))) 3122 (sort articles #'<)))))
@@ -3137,9 +3138,9 @@ FORCE is equivalent to setting the expiration predicates to true."
3137 ;; Ticked and/or dormant articles are excluded 3138 ;; Ticked and/or dormant articles are excluded
3138 ;; from expiration 3139 ;; from expiration
3139 (nconc 3140 (nconc
3140 (gnus-uncompress-range 3141 (range-uncompress
3141 (cdr (assq 'tick (gnus-info-marks info)))) 3142 (cdr (assq 'tick (gnus-info-marks info))))
3142 (gnus-uncompress-range 3143 (range-uncompress
3143 (cdr (assq 'dormant 3144 (cdr (assq 'dormant
3144 (gnus-info-marks info)))))))) 3145 (gnus-info-marks info))))))))
3145 (nov-file (concat dir ".overview")) 3146 (nov-file (concat dir ".overview"))
@@ -3638,7 +3639,7 @@ has been fetched."
3638 (file-name-directory file) t)) 3639 (file-name-directory file) t))
3639 3640
3640 (when fetch-old 3641 (when fetch-old
3641 (setq articles (gnus-uncompress-range 3642 (setq articles (range-uncompress
3642 (cons (if (numberp fetch-old) 3643 (cons (if (numberp fetch-old)
3643 (max 1 (- (car articles) fetch-old)) 3644 (max 1 (- (car articles) fetch-old))
3644 1) 3645 1)
@@ -3694,7 +3695,7 @@ has been fetched."
3694 3695
3695 ;; Clip this list to the headers that will 3696 ;; Clip this list to the headers that will
3696 ;; actually be returned 3697 ;; actually be returned
3697 (setq fetched-articles (gnus-list-range-intersection 3698 (setq fetched-articles (range-list-intersection
3698 (cdr fetched-articles) 3699 (cdr fetched-articles)
3699 (cons min max))) 3700 (cons min max)))
3700 3701
@@ -3703,7 +3704,7 @@ has been fetched."
3703 ;; excluded IDs may be fetchable using HEAD. 3704 ;; excluded IDs may be fetchable using HEAD.
3704 (if (car tail-fetched-articles) 3705 (if (car tail-fetched-articles)
3705 (setq uncached-articles 3706 (setq uncached-articles
3706 (gnus-list-range-intersection 3707 (range-list-intersection
3707 uncached-articles 3708 uncached-articles
3708 (cons (car uncached-articles) 3709 (cons (car uncached-articles)
3709 (car tail-fetched-articles))))) 3710 (car tail-fetched-articles)))))
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index a286c446724..d35d3bdd3a3 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -42,6 +42,7 @@
42(require 'message) 42(require 'message)
43(require 'mouse) 43(require 'mouse)
44(require 'seq) 44(require 'seq)
45(require 'range)
45 46
46(autoload 'gnus-msg-mail "gnus-msg" nil t) 47(autoload 'gnus-msg-mail "gnus-msg" nil t)
47(autoload 'gnus-button-mailto "gnus-msg") 48(autoload 'gnus-button-mailto "gnus-msg")
@@ -7019,7 +7020,7 @@ then we display only bindings that start with that prefix."
7019 (setq sumkeys 7020 (setq sumkeys
7020 (append (mapcar 7021 (append (mapcar
7021 #'vector 7022 #'vector
7022 (nreverse (gnus-uncompress-range def))) 7023 (nreverse (range-uncompress def)))
7023 sumkeys)))) 7024 sumkeys))))
7024 ((setq def (key-binding key)) 7025 ((setq def (key-binding key))
7025 (unless (eq def 'undefined) 7026 (unless (eq def 'undefined)
diff --git a/lisp/gnus/gnus-cloud.el b/lisp/gnus/gnus-cloud.el
index 6ed9e32c919..9bd9f2155f7 100644
--- a/lisp/gnus/gnus-cloud.el
+++ b/lisp/gnus/gnus-cloud.el
@@ -30,6 +30,7 @@
30 30
31(require 'parse-time) 31(require 'parse-time)
32(require 'nnimap) 32(require 'nnimap)
33(require 'range)
33 34
34(eval-when-compile (require 'epg)) ;; setf-method for `epg-context-armor' 35(eval-when-compile (require 'epg)) ;; setf-method for `epg-context-armor'
35(autoload 'epg-make-context "epg") 36(autoload 'epg-make-context "epg")
@@ -404,7 +405,7 @@ When FULL is t, upload everything, not just a difference from the last full."
404 (let* ((group (gnus-group-full-name gnus-cloud-group-name gnus-cloud-method)) 405 (let* ((group (gnus-group-full-name gnus-cloud-group-name gnus-cloud-method))
405 (active (gnus-active group)) 406 (active (gnus-active group))
406 headers head) 407 headers head)
407 (when (gnus-retrieve-headers (gnus-uncompress-range active) group) 408 (when (gnus-retrieve-headers (range-uncompress active) group)
408 (with-current-buffer nntp-server-buffer 409 (with-current-buffer nntp-server-buffer
409 (goto-char (point-min)) 410 (goto-char (point-min))
410 (while (setq head (nnheader-parse-head)) 411 (while (setq head (nnheader-parse-head))
diff --git a/lisp/gnus/gnus-draft.el b/lisp/gnus/gnus-draft.el
index cd9b025ff0e..56d498cc4d3 100644
--- a/lisp/gnus/gnus-draft.el
+++ b/lisp/gnus/gnus-draft.el
@@ -200,7 +200,7 @@ Obeys the standard process/prefix convention."
200 (gnus-activate-group "nndraft:queue") 200 (gnus-activate-group "nndraft:queue")
201 (save-excursion 201 (save-excursion
202 (let* ((articles (nndraft-articles)) 202 (let* ((articles (nndraft-articles))
203 (unsendable (gnus-uncompress-range 203 (unsendable (range-uncompress
204 (cdr (assq 'unsend 204 (cdr (assq 'unsend
205 (gnus-info-marks 205 (gnus-info-marks
206 (gnus-get-info "nndraft:queue")))))) 206 (gnus-get-info "nndraft:queue"))))))
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index ab874dd0608..d3a94e9f4e0 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -35,6 +35,7 @@
35(require 'gnus-undo) 35(require 'gnus-undo)
36(require 'gmm-utils) 36(require 'gmm-utils)
37(require 'time-date) 37(require 'time-date)
38(require 'range)
38 39
39(eval-when-compile 40(eval-when-compile
40 (require 'mm-url) 41 (require 'mm-url)
@@ -512,8 +513,8 @@ simple manner."
512 ((numberp number) 513 ((numberp number)
513 (int-to-string 514 (int-to-string
514 (+ number 515 (+ number
515 (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) 516 (range-length (cdr (assq 'dormant gnus-tmp-marked)))
516 (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))))) 517 (range-length (cdr (assq 'tick gnus-tmp-marked))))))
517 (t number)) 518 (t number))
518 ?s) 519 ?s)
519 (?R gnus-tmp-number-of-read ?s) 520 (?R gnus-tmp-number-of-read ?s)
@@ -523,10 +524,10 @@ simple manner."
523 ?s) 524 ?s)
524 (?t gnus-tmp-number-total ?d) 525 (?t gnus-tmp-number-total ?d)
525 (?y gnus-tmp-number-of-unread ?s) 526 (?y gnus-tmp-number-of-unread ?s)
526 (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d) 527 (?I (range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d)
527 (?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d) 528 (?T (range-length (cdr (assq 'tick gnus-tmp-marked))) ?d)
528 (?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) 529 (?i (+ (range-length (cdr (assq 'dormant gnus-tmp-marked)))
529 (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) 530 (range-length (cdr (assq 'tick gnus-tmp-marked))))
530 ?d) 531 ?d)
531 (?g gnus-tmp-group ?s) 532 (?g gnus-tmp-group ?s)
532 (?G gnus-tmp-qualified-group ?s) 533 (?G gnus-tmp-qualified-group ?s)
@@ -1482,9 +1483,9 @@ if it is a string, only list groups matching REGEXP."
1482 (active (gnus-active group))) 1483 (active (gnus-active group)))
1483 (if (not active) 1484 (if (not active)
1484 0 1485 0
1485 (length (gnus-uncompress-range 1486 (length (range-uncompress
1486 (gnus-range-difference 1487 (range-difference
1487 (gnus-range-difference (list active) (gnus-info-read info)) 1488 (range-difference (list active) (gnus-info-read info))
1488 seen)))))) 1489 seen))))))
1489 1490
1490;; Moving through the Group buffer (in topic mode) e.g. with C-n doesn't 1491;; Moving through the Group buffer (in topic mode) e.g. with C-n doesn't
@@ -1642,7 +1643,7 @@ Some value are bound so the form can use them."
1642 '(mail post-mail)))) 1643 '(mail post-mail))))
1643 (cons 'level (or (gnus-info-level info) gnus-level-killed)) 1644 (cons 'level (or (gnus-info-level info) gnus-level-killed))
1644 (cons 'score (or (gnus-info-score info) 0)) 1645 (cons 'score (or (gnus-info-score info) 0))
1645 (cons 'ticked (gnus-range-length (cdr (assq 'tick marked)))) 1646 (cons 'ticked (range-length (cdr (assq 'tick marked))))
1646 (cons 'group-age (gnus-group-timestamp-delta group))))) 1647 (cons 'group-age (gnus-group-timestamp-delta group)))))
1647 (while (and list 1648 (while (and list
1648 (not (eval (caar list) env))) 1649 (not (eval (caar list) env)))
@@ -2065,9 +2066,9 @@ that group."
2065 (- (1+ (cdr active)) (car active))))) 2066 (- (1+ (cdr active)) (car active)))))
2066 (gnus-summary-read-group 2067 (gnus-summary-read-group
2067 group (or all (and (numberp number) 2068 group (or all (and (numberp number)
2068 (zerop (+ number (gnus-range-length 2069 (zerop (+ number (range-length
2069 (cdr (assq 'tick marked))) 2070 (cdr (assq 'tick marked)))
2070 (gnus-range-length 2071 (range-length
2071 (cdr (assq 'dormant marked))))))) 2072 (cdr (assq 'dormant marked)))))))
2072 no-article nil no-display nil select-articles))) 2073 no-article nil no-display nil select-articles)))
2073 2074
@@ -2832,7 +2833,7 @@ according to the expiry settings. Note that this will delete old
2832not-expirable articles, too." 2833not-expirable articles, too."
2833 (interactive (list (gnus-group-group-name) current-prefix-arg) 2834 (interactive (list (gnus-group-group-name) current-prefix-arg)
2834 gnus-group-mode) 2835 gnus-group-mode)
2835 (let ((articles (gnus-uncompress-range (gnus-active group)))) 2836 (let ((articles (range-uncompress (gnus-active group))))
2836 (when (gnus-yes-or-no-p 2837 (when (gnus-yes-or-no-p
2837 (format "Do you really want to delete these %d articles forever? " 2838 (format "Do you really want to delete these %d articles forever? "
2838 (length articles))) 2839 (length articles)))
@@ -3755,15 +3756,15 @@ or nil if no action could be taken."
3755 'del '(tick)) 3756 'del '(tick))
3756 (list (cdr (assq 'dormant marks)) 3757 (list (cdr (assq 'dormant marks))
3757 'del '(dormant)))) 3758 'del '(dormant))))
3758 (setq unread (gnus-range-add (gnus-range-add 3759 (setq unread (range-concat (range-concat
3759 unread (cdr (assq 'dormant marks))) 3760 unread (cdr (assq 'dormant marks)))
3760 (cdr (assq 'tick marks)))) 3761 (cdr (assq 'tick marks))))
3761 (gnus-add-marked-articles group 'tick nil nil 'force) 3762 (gnus-add-marked-articles group 'tick nil nil 'force)
3762 (gnus-add-marked-articles group 'dormant nil nil 'force)) 3763 (gnus-add-marked-articles group 'dormant nil nil 'force))
3763 ;; Do auto-expirable marks if that's required. 3764 ;; Do auto-expirable marks if that's required.
3764 (when (and (gnus-group-auto-expirable-p group) 3765 (when (and (gnus-group-auto-expirable-p group)
3765 (not (gnus-group-read-only-p group))) 3766 (not (gnus-group-read-only-p group)))
3766 (gnus-range-map 3767 (range-map
3767 (lambda (article) 3768 (lambda (article)
3768 (gnus-add-marked-articles group 'expire (list article)) 3769 (gnus-add-marked-articles group 'expire (list article))
3769 (gnus-request-set-mark group (list (list (list article) 3770 (gnus-request-set-mark group (list (list (list article)
@@ -3795,7 +3796,7 @@ Uses the process/prefix convention."
3795 (cons nil (gnus-list-of-read-articles group)) 3796 (cons nil (gnus-list-of-read-articles group))
3796 (assq 'expire (gnus-info-marks info)))) 3797 (assq 'expire (gnus-info-marks info))))
3797 (articles-to-expire 3798 (articles-to-expire
3798 (gnus-list-range-difference 3799 (range-list-difference
3799 (gnus-uncompress-sequence (cdr expirable)) 3800 (gnus-uncompress-sequence (cdr expirable))
3800 (cdr (assq 'unexist (gnus-info-marks info))))) 3801 (cdr (assq 'unexist (gnus-info-marks info)))))
3801 (expiry-wait (gnus-group-find-parameter group 'expiry-wait)) 3802 (expiry-wait (gnus-group-find-parameter group 'expiry-wait))
@@ -4671,23 +4672,22 @@ and the second element is the address."
4671 (and (not (setq marked (nthcdr 3 info))) 4672 (and (not (setq marked (nthcdr 3 info)))
4672 (or (null articles) 4673 (or (null articles)
4673 (setcdr (nthcdr 2 info) 4674 (setcdr (nthcdr 2 info)
4674 (list (list (cons type (gnus-compress-sequence 4675 (list (list (cons type (range-compress-list
4675 articles t))))))) 4676 articles)))))))
4676 (and (not (setq m (assq type (car marked)))) 4677 (and (not (setq m (assq type (car marked))))
4677 (or (null articles) 4678 (or (null articles)
4678 (setcar marked 4679 (setcar marked
4679 (cons (cons type (gnus-compress-sequence articles t) ) 4680 (cons (cons type (range-compress-list articles))
4680 (car marked))))) 4681 (car marked)))))
4681 (if force 4682 (if force
4682 (if (null articles) 4683 (if (null articles)
4683 (setcar (nthcdr 3 info) 4684 (setcar (nthcdr 3 info)
4684 (assq-delete-all type (car marked))) 4685 (assq-delete-all type (car marked)))
4685 (setcdr m (gnus-compress-sequence articles t))) 4686 (setcdr m (range-compress-list articles)))
4686 (setcdr m (gnus-compress-sequence 4687 (setcdr m (range-compress-list
4687 (sort (nconc (gnus-uncompress-range (cdr m)) 4688 (sort (nconc (range-uncompress (cdr m))
4688 (copy-sequence articles)) 4689 (copy-sequence articles))
4689 #'<) 4690 #'<)))))))
4690 t))))))
4691 4691
4692(declare-function gnus-summary-add-mark "gnus-sum" (article type)) 4692(declare-function gnus-summary-add-mark "gnus-sum" (article type))
4693 4693
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index 5a619e8f07b..f00f2a0d04e 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -802,7 +802,7 @@ If GROUP is nil, all groups on COMMAND-METHOD are scanned."
802 (when (> min 1) 802 (when (> min 1)
803 (let* ((range (if (= min 2) 1 (cons 1 (1- min)))) 803 (let* ((range (if (= min 2) 1 (cons 1 (1- min))))
804 (read (gnus-info-read info)) 804 (read (gnus-info-read info))
805 (new-read (gnus-range-add read (list range)))) 805 (new-read (range-concat read (list range))))
806 (setf (gnus-info-read info) new-read))) 806 (setf (gnus-info-read info) new-read)))
807 info)))))) 807 info))))))
808 808
diff --git a/lisp/gnus/gnus-kill.el b/lisp/gnus/gnus-kill.el
index bee7860efdb..bc49f8385ea 100644
--- a/lisp/gnus/gnus-kill.el
+++ b/lisp/gnus/gnus-kill.el
@@ -349,7 +349,7 @@ Returns the number of articles marked as read."
349 (setq gnus-newsgroup-kill-headers 349 (setq gnus-newsgroup-kill-headers
350 (mapcar #'mail-header-number headers)) 350 (mapcar #'mail-header-number headers))
351 (while headers 351 (while headers
352 (unless (gnus-member-of-range 352 (unless (range-member-p
353 (mail-header-number (car headers)) 353 (mail-header-number (car headers))
354 gnus-newsgroup-killed) 354 gnus-newsgroup-killed)
355 (push (mail-header-number (car headers)) 355 (push (mail-header-number (car headers))
diff --git a/lisp/gnus/gnus-range.el b/lisp/gnus/gnus-range.el
index da3ff473725..23a71bda209 100644
--- a/lisp/gnus/gnus-range.el
+++ b/lisp/gnus/gnus-range.el
@@ -26,10 +26,8 @@
26 26
27;;; List and range functions 27;;; List and range functions
28 28
29(defsubst gnus-range-normalize (range) 29(require 'range)
30 "Normalize RANGE. 30(define-obsolete-function-alias 'gnus-range-normalize #'range-normalize "29.1")
31If RANGE is a single range, return (RANGE). Otherwise, return RANGE."
32 (if (listp (cdr-safe range)) range (list range)))
33 31
34(defun gnus-last-element (list) 32(defun gnus-last-element (list)
35 "Return last element of LIST." 33 "Return last element of LIST."
@@ -56,10 +54,10 @@ If RANGE is a single range, return (RANGE). Otherwise, return RANGE."
56 "Return a range comprising all the RANGES, which are pre-sorted. 54 "Return a range comprising all the RANGES, which are pre-sorted.
57RANGES will be destructively altered." 55RANGES will be destructively altered."
58 (setq ranges (delete nil ranges)) 56 (setq ranges (delete nil ranges))
59 (let* ((result (gnus-range-normalize (pop ranges))) 57 (let* ((result (range-normalize (pop ranges)))
60 (last (last result))) 58 (last (last result)))
61 (dolist (range ranges) 59 (dolist (range ranges)
62 (setq range (gnus-range-normalize range)) 60 (setq range (range-normalize range))
63 ;; Normalize the single-number case, so that we don't need to 61 ;; Normalize the single-number case, so that we don't need to
64 ;; special-case that so much. 62 ;; special-case that so much.
65 (when (numberp (car last)) 63 (when (numberp (car last))
@@ -82,47 +80,8 @@ RANGES will be destructively altered."
82 (car result) 80 (car result)
83 result))) 81 result)))
84 82
85(defun gnus-range-difference (range1 range2) 83(define-obsolete-function-alias 'gnus-range-difference
86 "Return the range of elements in RANGE1 that do not appear in RANGE2. 84 #'range-difference "29.1")
87Both ranges must be in ascending order."
88 (setq range1 (gnus-range-normalize range1))
89 (setq range2 (gnus-range-normalize range2))
90 (let* ((new-range (cons nil (copy-sequence range1)))
91 (r new-range)
92 ) ;; (safe t)
93 (while (cdr r)
94 (let* ((r1 (cadr r))
95 (r2 (car range2))
96 (min1 (if (numberp r1) r1 (car r1)))
97 (max1 (if (numberp r1) r1 (cdr r1)))
98 (min2 (if (numberp r2) r2 (car r2)))
99 (max2 (if (numberp r2) r2 (cdr r2))))
100
101 (cond ((> min1 max1)
102 ;; Invalid range: may result from overlap condition (below)
103 ;; remove Invalid range
104 (setcdr r (cddr r)))
105 ((and (= min1 max1)
106 (listp r1))
107 ;; Inefficient representation: may result from overlap condition (below)
108 (setcar (cdr r) min1))
109 ((not min2)
110 ;; All done with range2
111 (setq r nil))
112 ((< max1 min2)
113 ;; No overlap: range1 precedes range2
114 (pop r))
115 ((< max2 min1)
116 ;; No overlap: range2 precedes range1
117 (pop range2))
118 ((and (<= min2 min1) (<= max1 max2))
119 ;; Complete overlap: range1 removed
120 (setcdr r (cddr r)))
121 (t
122 (setcdr r (nconc (list (cons min1 (1- min2)) (cons (1+ max2) max1)) (cddr r)))))))
123 (cdr new-range)))
124
125
126 85
127;;;###autoload 86;;;###autoload
128(defun gnus-sorted-difference (list1 list2) 87(defun gnus-sorted-difference (list1 list2)
@@ -200,57 +159,8 @@ LIST1 and LIST2 have to be sorted over <."
200 (setq list2 (cdr list2))))) 159 (setq list2 (cdr list2)))))
201 (nreverse out))) 160 (nreverse out)))
202 161
203;;;###autoload 162(define-obsolete-function-alias 'gnus-sorted-range-intersection
204(defun gnus-sorted-range-intersection (range1 range2) 163 #'range-intersection "29.1")
205 "Return intersection of RANGE1 and RANGE2.
206RANGE1 and RANGE2 have to be sorted over <."
207 (let* (out
208 (min1 (car range1))
209 (max1 (if (numberp min1)
210 (if (numberp (cdr range1))
211 (prog1 (cdr range1)
212 (setq range1 nil)) min1)
213 (prog1 (cdr min1)
214 (setq min1 (car min1)))))
215 (min2 (car range2))
216 (max2 (if (numberp min2)
217 (if (numberp (cdr range2))
218 (prog1 (cdr range2)
219 (setq range2 nil)) min2)
220 (prog1 (cdr min2)
221 (setq min2 (car min2))))))
222 (setq range1 (cdr range1)
223 range2 (cdr range2))
224 (while (and min1 min2)
225 (cond ((< max1 min2) ; range1 precedes range2
226 (setq range1 (cdr range1)
227 min1 nil))
228 ((< max2 min1) ; range2 precedes range1
229 (setq range2 (cdr range2)
230 min2 nil))
231 (t ; some sort of overlap is occurring
232 (let ((min (max min1 min2))
233 (max (min max1 max2)))
234 (setq out (if (= min max)
235 (cons min out)
236 (cons (cons min max) out))))
237 (if (< max1 max2) ; range1 ends before range2
238 (setq min1 nil) ; incr range1
239 (setq min2 nil)))) ; incr range2
240 (unless min1
241 (setq min1 (car range1)
242 max1 (if (numberp min1) min1 (prog1 (cdr min1) (setq min1 (car min1))))
243 range1 (cdr range1)))
244 (unless min2
245 (setq min2 (car range2)
246 max2 (if (numberp min2) min2 (prog1 (cdr min2) (setq min2 (car min2))))
247 range2 (cdr range2))))
248 (cond ((cdr out)
249 (nreverse out))
250 ((numberp (car out))
251 out)
252 (t
253 (car out)))))
254 164
255;;;###autoload 165;;;###autoload
256(defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection) 166(defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection)
@@ -327,315 +237,33 @@ LIST1 and LIST2 have to be sorted over <."
327 "Convert sorted list of numbers to a list of ranges or a single range. 237 "Convert sorted list of numbers to a list of ranges or a single range.
328If ALWAYS-LIST is non-nil, this function will always release a list of 238If ALWAYS-LIST is non-nil, this function will always release a list of
329ranges." 239ranges."
330 (let* ((first (car numbers)) 240 (if always-list
331 (last (car numbers)) 241 (range-compress-list numbers)
332 result) 242 (range-denormalize (range-compress-list numbers))))
333 (if (null numbers)
334 nil
335 (if (not (listp (cdr numbers)))
336 numbers
337 (while numbers
338 (cond ((= last (car numbers)) nil) ;Omit duplicated number
339 ((= (1+ last) (car numbers)) ;Still in sequence
340 (setq last (car numbers)))
341 (t ;End of one sequence
342 (setq result
343 (cons (if (= first last) first
344 (cons first last))
345 result))
346 (setq first (car numbers))
347 (setq last (car numbers))))
348 (setq numbers (cdr numbers)))
349 (if (and (not always-list) (null result))
350 (if (= first last) (list first) (cons first last))
351 (nreverse (cons (if (= first last) first (cons first last))
352 result)))))))
353 243
354(defalias 'gnus-uncompress-sequence 'gnus-uncompress-range) 244(defalias 'gnus-uncompress-sequence 'gnus-uncompress-range)
355(defun gnus-uncompress-range (ranges) 245(define-obsolete-function-alias 'gnus-uncompress-range
356 "Expand a list of ranges into a list of numbers. 246 #'range-uncompress "29.1")
357RANGES is either a single range on the form `(num . num)' or a list of 247
358these ranges." 248(define-obsolete-function-alias 'gnus-add-to-range
359 (let (first last result) 249 #'range-add-list "29.1")
360 (cond 250
361 ((null ranges) 251(define-obsolete-function-alias 'gnus-remove-from-range
362 nil) 252 #'range-remove "29.1")
363 ((not (listp (cdr ranges))) 253
364 (setq first (car ranges)) 254(define-obsolete-function-alias 'gnus-member-of-range #'range-member-p "29.1")
365 (setq last (cdr ranges)) 255
366 (while (<= first last) 256(define-obsolete-function-alias 'gnus-list-range-intersection
367 (setq result (cons first result)) 257 #'range-list-intersection "29.1")
368 (setq first (1+ first)))
369 (nreverse result))
370 (t
371 (while ranges
372 (if (atom (car ranges))
373 (when (numberp (car ranges))
374 (setq result (cons (car ranges) result)))
375 (setq first (caar ranges))
376 (setq last (cdar ranges))
377 (while (<= first last)
378 (setq result (cons first result))
379 (setq first (1+ first))))
380 (setq ranges (cdr ranges)))
381 (nreverse result)))))
382
383(defun gnus-add-to-range (ranges list)
384 "Return a list of ranges that has all articles from both RANGES and LIST.
385Note: LIST has to be sorted over `<'."
386 (if (not ranges)
387 (gnus-compress-sequence list t)
388 (setq list (copy-sequence list))
389 (unless (listp (cdr ranges))
390 (setq ranges (list ranges)))
391 (let ((out ranges)
392 ilist lowest highest temp)
393 (while (and ranges list)
394 (setq ilist list)
395 (setq lowest (or (and (atom (car ranges)) (car ranges))
396 (caar ranges)))
397 (while (and list (cdr list) (< (cadr list) lowest))
398 (setq list (cdr list)))
399 (when (< (car ilist) lowest)
400 (setq temp list)
401 (setq list (cdr list))
402 (setcdr temp nil)
403 (setq out (nconc (gnus-compress-sequence ilist t) out)))
404 (setq highest (or (and (atom (car ranges)) (car ranges))
405 (cdar ranges)))
406 (while (and list (<= (car list) highest))
407 (setq list (cdr list)))
408 (setq ranges (cdr ranges)))
409 (when list
410 (setq out (nconc (gnus-compress-sequence list t) out)))
411 (setq out (sort out (lambda (r1 r2)
412 (< (or (and (atom r1) r1) (car r1))
413 (or (and (atom r2) r2) (car r2))))))
414 (setq ranges out)
415 (while ranges
416 (if (atom (car ranges))
417 (when (cdr ranges)
418 (if (atom (cadr ranges))
419 (when (= (1+ (car ranges)) (cadr ranges))
420 (setcar ranges (cons (car ranges)
421 (cadr ranges)))
422 (setcdr ranges (cddr ranges)))
423 (when (= (1+ (car ranges)) (caadr ranges))
424 (setcar (cadr ranges) (car ranges))
425 (setcar ranges (cadr ranges))
426 (setcdr ranges (cddr ranges)))))
427 (when (cdr ranges)
428 (if (atom (cadr ranges))
429 (when (= (1+ (cdar ranges)) (cadr ranges))
430 (setcdr (car ranges) (cadr ranges))
431 (setcdr ranges (cddr ranges)))
432 (when (= (1+ (cdar ranges)) (caadr ranges))
433 (setcdr (car ranges) (cdadr ranges))
434 (setcdr ranges (cddr ranges))))))
435 (setq ranges (cdr ranges)))
436 out)))
437
438(defun gnus-remove-from-range (range1 range2)
439 "Return a range that has all articles from RANGE2 removed from RANGE1.
440The returned range is always a list. RANGE2 can also be a unsorted
441list of articles. RANGE1 is modified by side effects, RANGE2 is not
442modified."
443 (if (or (null range1) (null range2))
444 range1
445 (let (out r1 r2 r1_min r1_max r2_min r2_max
446 (range2 (copy-tree range2)))
447 (setq range1 (if (listp (cdr range1)) range1 (list range1))
448 range2 (sort (if (listp (cdr range2)) range2 (list range2))
449 (lambda (e1 e2)
450 (< (if (consp e1) (car e1) e1)
451 (if (consp e2) (car e2) e2))))
452 r1 (car range1)
453 r2 (car range2)
454 r1_min (if (consp r1) (car r1) r1)
455 r1_max (if (consp r1) (cdr r1) r1)
456 r2_min (if (consp r2) (car r2) r2)
457 r2_max (if (consp r2) (cdr r2) r2))
458 (while (and range1 range2)
459 (cond ((< r2_max r1_min) ; r2 < r1
460 (pop range2)
461 (setq r2 (car range2)
462 r2_min (if (consp r2) (car r2) r2)
463 r2_max (if (consp r2) (cdr r2) r2)))
464 ((and (<= r2_min r1_min) (<= r1_max r2_max)) ; r2 overlap r1
465 (pop range1)
466 (setq r1 (car range1)
467 r1_min (if (consp r1) (car r1) r1)
468 r1_max (if (consp r1) (cdr r1) r1)))
469 ((and (<= r2_min r1_min) (<= r2_max r1_max)) ; r2 overlap min r1
470 (pop range2)
471 (setq r1_min (1+ r2_max)
472 r2 (car range2)
473 r2_min (if (consp r2) (car r2) r2)
474 r2_max (if (consp r2) (cdr r2) r2)))
475 ((and (<= r1_min r2_min) (<= r2_max r1_max)) ; r2 contained in r1
476 (if (eq r1_min (1- r2_min))
477 (push r1_min out)
478 (push (cons r1_min (1- r2_min)) out))
479 (pop range2)
480 (if (< r2_max r1_max) ; finished with r1?
481 (setq r1_min (1+ r2_max))
482 (pop range1)
483 (setq r1 (car range1)
484 r1_min (if (consp r1) (car r1) r1)
485 r1_max (if (consp r1) (cdr r1) r1)))
486 (setq r2 (car range2)
487 r2_min (if (consp r2) (car r2) r2)
488 r2_max (if (consp r2) (cdr r2) r2)))
489 ((and (<= r2_min r1_max) (<= r1_max r2_max)) ; r2 overlap max r1
490 (if (eq r1_min (1- r2_min))
491 (push r1_min out)
492 (push (cons r1_min (1- r2_min)) out))
493 (pop range1)
494 (setq r1 (car range1)
495 r1_min (if (consp r1) (car r1) r1)
496 r1_max (if (consp r1) (cdr r1) r1)))
497 ((< r1_max r2_min) ; r2 > r1
498 (pop range1)
499 (if (eq r1_min r1_max)
500 (push r1_min out)
501 (push (cons r1_min r1_max) out))
502 (setq r1 (car range1)
503 r1_min (if (consp r1) (car r1) r1)
504 r1_max (if (consp r1) (cdr r1) r1)))))
505 (when r1
506 (if (eq r1_min r1_max)
507 (push r1_min out)
508 (push (cons r1_min r1_max) out))
509 (pop range1))
510 (while range1
511 (push (pop range1) out))
512 (nreverse out))))
513
514(defun gnus-member-of-range (number ranges)
515 (if (not (listp (cdr ranges)))
516 (and (>= number (car ranges))
517 (<= number (cdr ranges)))
518 (let ((not-stop t))
519 (while (and ranges
520 (if (numberp (car ranges))
521 (>= number (car ranges))
522 (>= number (caar ranges)))
523 not-stop)
524 (when (if (numberp (car ranges))
525 (= number (car ranges))
526 (and (>= number (caar ranges))
527 (<= number (cdar ranges))))
528 (setq not-stop nil))
529 (setq ranges (cdr ranges)))
530 (not not-stop))))
531
532(defun gnus-list-range-intersection (list ranges)
533 "Return a list of numbers in LIST that are members of RANGES.
534LIST is a sorted list."
535 (setq ranges (gnus-range-normalize ranges))
536 (let (number result)
537 (while (setq number (pop list))
538 (while (and ranges
539 (if (numberp (car ranges))
540 (< (car ranges) number)
541 (< (cdar ranges) number)))
542 (setq ranges (cdr ranges)))
543 (when (and ranges
544 (if (numberp (car ranges))
545 (= (car ranges) number)
546 ;; (caar ranges) <= number <= (cdar ranges)
547 (>= number (caar ranges))))
548 (push number result)))
549 (nreverse result)))
550 258
551(defalias 'gnus-inverse-list-range-intersection 'gnus-list-range-difference) 259(defalias 'gnus-inverse-list-range-intersection 'gnus-list-range-difference)
552 260
553(defun gnus-list-range-difference (list ranges) 261(define-obsolete-function-alias 'gnus-list-range-difference
554 "Return a list of numbers in LIST that are not members of RANGES. 262 #'range-list-difference "29.1")
555LIST is a sorted list." 263
556 (setq ranges (gnus-range-normalize ranges)) 264(define-obsolete-function-alias 'gnus-range-length #'range-length "29.1")
557 (let (number result)
558 (while (setq number (pop list))
559 (while (and ranges
560 (if (numberp (car ranges))
561 (< (car ranges) number)
562 (< (cdar ranges) number)))
563 (setq ranges (cdr ranges)))
564 (when (or (not ranges)
565 (if (numberp (car ranges))
566 (not (= (car ranges) number))
567 ;; not ((caar ranges) <= number <= (cdar ranges))
568 (< number (caar ranges))))
569 (push number result)))
570 (nreverse result)))
571 265
572(defun gnus-range-length (range) 266(define-obsolete-function-alias 'gnus-range-add #'range-concat "29.1")
573 "Return the length RANGE would have if uncompressed."
574 (cond
575 ((null range)
576 0)
577 ((not (listp (cdr range)))
578 (- (cdr range) (car range) -1))
579 (t
580 (let ((sum 0))
581 (dolist (x range sum)
582 (setq sum
583 (+ sum (if (consp x) (- (cdr x) (car x) -1) 1))))))))
584
585(defun gnus-range-add (range1 range2)
586 "Add RANGE2 to RANGE1 (nondestructively)."
587 (unless (listp (cdr range1))
588 (setq range1 (list range1)))
589 (unless (listp (cdr range2))
590 (setq range2 (list range2)))
591 (let ((item1 (pop range1))
592 (item2 (pop range2))
593 range item selector)
594 (while (or item1 item2)
595 (setq selector
596 (cond
597 ((null item1) nil)
598 ((null item2) t)
599 ((and (numberp item1) (numberp item2)) (< item1 item2))
600 ((numberp item1) (< item1 (car item2)))
601 ((numberp item2) (< (car item1) item2))
602 (t (< (car item1) (car item2)))))
603 (setq item
604 (or
605 (let ((tmp1 item) (tmp2 (if selector item1 item2)))
606 (cond
607 ((null tmp1) tmp2)
608 ((null tmp2) tmp1)
609 ((and (numberp tmp1) (numberp tmp2))
610 (cond
611 ((eq tmp1 tmp2) tmp1)
612 ((eq (1+ tmp1) tmp2) (cons tmp1 tmp2))
613 ((eq (1+ tmp2) tmp1) (cons tmp2 tmp1))
614 (t nil)))
615 ((numberp tmp1)
616 (cond
617 ((and (>= tmp1 (car tmp2)) (<= tmp1 (cdr tmp2))) tmp2)
618 ((eq (1+ tmp1) (car tmp2)) (cons tmp1 (cdr tmp2)))
619 ((eq (1- tmp1) (cdr tmp2)) (cons (car tmp2) tmp1))
620 (t nil)))
621 ((numberp tmp2)
622 (cond
623 ((and (>= tmp2 (car tmp1)) (<= tmp2 (cdr tmp1))) tmp1)
624 ((eq (1+ tmp2) (car tmp1)) (cons tmp2 (cdr tmp1)))
625 ((eq (1- tmp2) (cdr tmp1)) (cons (car tmp1) tmp2))
626 (t nil)))
627 ((< (1+ (cdr tmp1)) (car tmp2)) nil)
628 ((< (1+ (cdr tmp2)) (car tmp1)) nil)
629 (t (cons (min (car tmp1) (car tmp2))
630 (max (cdr tmp1) (cdr tmp2))))))
631 (progn
632 (if item (push item range))
633 (if selector item1 item2))))
634 (if selector
635 (setq item1 (pop range1))
636 (setq item2 (pop range2))))
637 (if item (push item range))
638 (reverse range)))
639 267
640;;;###autoload 268;;;###autoload
641(defun gnus-add-to-sorted-list (list num) 269(defun gnus-add-to-sorted-list (list num)
@@ -649,18 +277,7 @@ LIST is a sorted list."
649 (setcdr prev (cons num list))) 277 (setcdr prev (cons num list)))
650 (cdr top))) 278 (cdr top)))
651 279
652(defun gnus-range-map (func range) 280(define-obsolete-function-alias 'gnus-range-map #'range-map "29.1")
653 "Apply FUNC to each value contained by RANGE."
654 (setq range (gnus-range-normalize range))
655 (while range
656 (let ((span (pop range)))
657 (if (numberp span)
658 (funcall func span)
659 (let ((first (car span))
660 (last (cdr span)))
661 (while (<= first last)
662 (funcall func first)
663 (setq first (1+ first))))))))
664 281
665(provide 'gnus-range) 282(provide 'gnus-range)
666 283
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 252e6e22299..2cf11fb12f9 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -1884,13 +1884,12 @@ The info element is shared with the same element of
1884 (ranges (gnus-info-read info)) 1884 (ranges (gnus-info-read info))
1885 news article) 1885 news article)
1886 (while articles 1886 (while articles
1887 (when (gnus-member-of-range 1887 (when (range-member-p (setq article (pop articles)) ranges)
1888 (setq article (pop articles)) ranges)
1889 (push article news))) 1888 (push article news)))
1890 (when news 1889 (when news
1891 ;; Enter this list into the group info. 1890 ;; Enter this list into the group info.
1892 (setf (gnus-info-read info) 1891 (setf (gnus-info-read info)
1893 (gnus-remove-from-range (gnus-info-read info) (nreverse news))) 1892 (range-remove (gnus-info-read info) (nreverse news)))
1894 1893
1895 ;; Set the number of unread articles in gnus-newsrc-hashtb. 1894 ;; Set the number of unread articles in gnus-newsrc-hashtb.
1896 (gnus-get-unread-articles-in-group info (gnus-active group)) 1895 (gnus-get-unread-articles-in-group info (gnus-active group))
@@ -2362,10 +2361,10 @@ The form should return either t or nil."
2362 ticked (cdr (assq 'tick marks))) 2361 ticked (cdr (assq 'tick marks)))
2363 (when (or dormant ticked) 2362 (when (or dormant ticked)
2364 (setf (gnus-info-read info) 2363 (setf (gnus-info-read info)
2365 (gnus-add-to-range 2364 (range-add-list
2366 (gnus-info-read info) 2365 (gnus-info-read info)
2367 (nconc (gnus-uncompress-range dormant) 2366 (nconc (range-uncompress dormant)
2368 (gnus-uncompress-range ticked))))))))) 2367 (range-uncompress ticked)))))))))
2369 2368
2370(defun gnus-load (file) 2369(defun gnus-load (file)
2371 "Load FILE, but in such a way that read errors can be reported." 2370 "Load FILE, but in such a way that read errors can be reported."
@@ -2457,8 +2456,7 @@ The form should return either t or nil."
2457 (unless (nthcdr 3 info) 2456 (unless (nthcdr 3 info)
2458 (nconc info (list nil))) 2457 (nconc info (list nil)))
2459 (setf (gnus-info-marks info) 2458 (setf (gnus-info-marks info)
2460 (list (cons 'tick (gnus-compress-sequence 2459 (list (cons 'tick (range-compress-list (sort (cdr m) #'<)))))))
2461 (sort (cdr m) #'<) t))))))
2462 (setq newsrc killed) 2460 (setq newsrc killed)
2463 (while newsrc 2461 (while newsrc
2464 (setcar newsrc (caar newsrc)) 2462 (setcar newsrc (caar newsrc))
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index 6dfdcaf55c7..8fb07d5905c 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -5755,7 +5755,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
5755 ;; (let ((n (cdr (gnus-active group)))) 5755 ;; (let ((n (cdr (gnus-active group))))
5756 ;; (lambda () (> number (- n display)))) 5756 ;; (lambda () (> number (- n display))))
5757 (setq select-articles 5757 (setq select-articles
5758 (gnus-uncompress-range 5758 (range-uncompress
5759 (cons (let ((tmp (- (cdr (gnus-active group)) display))) 5759 (cons (let ((tmp (- (cdr (gnus-active group)) display)))
5760 (if (> tmp 0) 5760 (if (> tmp 0)
5761 tmp 5761 tmp
@@ -5928,7 +5928,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
5928 "Find out what articles the user wants to read." 5928 "Find out what articles the user wants to read."
5929 (let* ((only-read-p t) 5929 (let* ((only-read-p t)
5930 (articles 5930 (articles
5931 (gnus-list-range-difference 5931 (range-list-difference
5932 ;; Select all articles if `read-all' is non-nil, or if there 5932 ;; Select all articles if `read-all' is non-nil, or if there
5933 ;; are no unread articles. 5933 ;; are no unread articles.
5934 (if (or read-all 5934 (if (or read-all
@@ -5943,13 +5943,13 @@ If SELECT-ARTICLES, only select those articles from GROUP."
5943 (or 5943 (or
5944 (if gnus-newsgroup-maximum-articles 5944 (if gnus-newsgroup-maximum-articles
5945 (let ((active (gnus-active group))) 5945 (let ((active (gnus-active group)))
5946 (gnus-uncompress-range 5946 (range-uncompress
5947 (cons (max (car active) 5947 (cons (max (car active)
5948 (- (cdr active) 5948 (- (cdr active)
5949 gnus-newsgroup-maximum-articles 5949 gnus-newsgroup-maximum-articles
5950 -1)) 5950 -1))
5951 (cdr active)))) 5951 (cdr active))))
5952 (gnus-uncompress-range (gnus-active group))) 5952 (range-uncompress (gnus-active group)))
5953 (gnus-cache-articles-in-group group)) 5953 (gnus-cache-articles-in-group group))
5954 ;; Select only the "normal" subset of articles. 5954 ;; Select only the "normal" subset of articles.
5955 (setq only-read-p nil) 5955 (setq only-read-p nil)
@@ -6040,7 +6040,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
6040(defun gnus-killed-articles (killed articles) 6040(defun gnus-killed-articles (killed articles)
6041 (let (out) 6041 (let (out)
6042 (while articles 6042 (while articles
6043 (when (inline (gnus-member-of-range (car articles) killed)) 6043 (when (inline (range-member-p (car articles) killed))
6044 (push (car articles) out)) 6044 (push (car articles) out))
6045 (setq articles (cdr articles))) 6045 (setq articles (cdr articles)))
6046 out)) 6046 out))
@@ -6078,7 +6078,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
6078 ;; Adjust "simple" lists - compressed yet unsorted 6078 ;; Adjust "simple" lists - compressed yet unsorted
6079 ((eq mark-type 'list) 6079 ((eq mark-type 'list)
6080 ;; Simultaneously uncompress and clip to active range 6080 ;; Simultaneously uncompress and clip to active range
6081 ;; See gnus-uncompress-range for a description of possible marks 6081 ;; See range-uncompress for a description of possible marks
6082 (let (l lh) 6082 (let (l lh)
6083 (if (not (cadr marks)) 6083 (if (not (cadr marks))
6084 (set var nil) 6084 (set var nil)
@@ -6177,10 +6177,10 @@ If SELECT-ARTICLES, only select those articles from GROUP."
6177 ;; When exiting the group, everything that's previously been 6177 ;; When exiting the group, everything that's previously been
6178 ;; unseen is now seen. 6178 ;; unseen is now seen.
6179 (when (eq (cdr type) 'seen) 6179 (when (eq (cdr type) 'seen)
6180 (setq list (gnus-range-add list gnus-newsgroup-unseen))) 6180 (setq list (range-concat list gnus-newsgroup-unseen)))
6181 6181
6182 (when (eq (gnus-article-mark-to-type (cdr type)) 'list) 6182 (when (eq (gnus-article-mark-to-type (cdr type)) 'list)
6183 (setq list (gnus-compress-sequence (set symbol (sort list #'<)) t))) 6183 (setq list (range-compress-list (set symbol (sort list #'<)))))
6184 6184
6185 (when (and (gnus-check-backend-function 6185 (when (and (gnus-check-backend-function
6186 'request-set-mark gnus-newsgroup-name) 6186 'request-set-mark gnus-newsgroup-name)
@@ -6189,20 +6189,19 @@ If SELECT-ARTICLES, only select those articles from GROUP."
6189 ;; Don't do anything about marks for articles we 6189 ;; Don't do anything about marks for articles we
6190 ;; didn't actually get any headers for. 6190 ;; didn't actually get any headers for.
6191 (del 6191 (del
6192 (gnus-list-range-intersection 6192 (range-list-intersection
6193 gnus-newsgroup-articles 6193 gnus-newsgroup-articles
6194 (gnus-remove-from-range (copy-tree old) list))) 6194 (range-remove (copy-tree old) list)))
6195 (add 6195 (add
6196 (gnus-list-range-intersection 6196 (range-list-intersection
6197 gnus-newsgroup-articles 6197 gnus-newsgroup-articles
6198 (gnus-remove-from-range 6198 (range-remove (copy-tree list) old))))
6199 (copy-tree list) old))))
6200 (when add 6199 (when add
6201 (push (list add 'add (list (cdr type))) delta-marks)) 6200 (push (list add 'add (list (cdr type))) delta-marks))
6202 (when del 6201 (when del
6203 ;; Don't delete marks from outside the active range. 6202 ;; Don't delete marks from outside the active range.
6204 ;; This shouldn't happen, but is a sanity check. 6203 ;; This shouldn't happen, but is a sanity check.
6205 (setq del (gnus-sorted-range-intersection 6204 (setq del (range-intersection
6206 (gnus-active gnus-newsgroup-name) del)) 6205 (gnus-active gnus-newsgroup-name) del))
6207 (push (list del 'del (list (cdr type))) delta-marks)))) 6206 (push (list del 'del (list (cdr type))) delta-marks))))
6208 6207
@@ -6386,7 +6385,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
6386 (setq ninfo (cons 1 (1- (car active)))) 6385 (setq ninfo (cons 1 (1- (car active))))
6387 (setq ninfo (gnus-info-read info))) 6386 (setq ninfo (gnus-info-read info)))
6388 ;; Then we add the read articles to the range. 6387 ;; Then we add the read articles to the range.
6389 (gnus-add-to-range 6388 (range-add-list
6390 ninfo (setq articles (sort articles #'<)))))) 6389 ninfo (setq articles (sort articles #'<))))))
6391 6390
6392(defun gnus-group-make-articles-read (group articles) 6391(defun gnus-group-make-articles-read (group articles)
@@ -6967,10 +6966,10 @@ displayed, no centering will be performed."
6967 (marked (gnus-info-marks info)) 6966 (marked (gnus-info-marks info))
6968 (active (gnus-active group))) 6967 (active (gnus-active group)))
6969 (and info active 6968 (and info active
6970 (gnus-list-range-difference 6969 (range-list-difference
6971 (gnus-list-range-difference 6970 (range-list-difference
6972 (gnus-sorted-complement 6971 (gnus-sorted-complement
6973 (gnus-uncompress-range 6972 (range-uncompress
6974 (if gnus-newsgroup-maximum-articles 6973 (if gnus-newsgroup-maximum-articles
6975 (cons (max (car active) 6974 (cons (max (car active)
6976 (- (cdr active) 6975 (- (cdr active)
@@ -7129,12 +7128,11 @@ The prefix argument ALL means to select all articles."
7129 (when group 7128 (when group
7130 (when gnus-newsgroup-kill-headers 7129 (when gnus-newsgroup-kill-headers
7131 (setq gnus-newsgroup-killed 7130 (setq gnus-newsgroup-killed
7132 (gnus-compress-sequence 7131 (range-compress-list
7133 (gnus-sorted-union 7132 (gnus-sorted-union
7134 (gnus-list-range-intersection 7133 (range-list-intersection
7135 gnus-newsgroup-unselected gnus-newsgroup-killed) 7134 gnus-newsgroup-unselected gnus-newsgroup-killed)
7136 gnus-newsgroup-unreads) 7135 gnus-newsgroup-unreads))))
7137 t)))
7138 (unless (listp (cdr gnus-newsgroup-killed)) 7136 (unless (listp (cdr gnus-newsgroup-killed))
7139 (setq gnus-newsgroup-killed (list gnus-newsgroup-killed))) 7137 (setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
7140 (let ((headers gnus-newsgroup-headers) 7138 (let ((headers gnus-newsgroup-headers)
@@ -10241,8 +10239,8 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
10241 (cdr art-group)) 10239 (cdr art-group))
10242 (push 'read to-marks) 10240 (push 'read to-marks)
10243 (setf (gnus-info-read info) 10241 (setf (gnus-info-read info)
10244 (gnus-add-to-range (gnus-info-read info) 10242 (range-add-list (gnus-info-read info)
10245 (list (cdr art-group))))) 10243 (list (cdr art-group)))))
10246 10244
10247 ;; See whether the article is to be put in the cache. 10245 ;; See whether the article is to be put in the cache.
10248 (let* ((expirable (gnus-group-auto-expirable-p to-group)) 10246 (let* ((expirable (gnus-group-auto-expirable-p to-group))
@@ -10525,7 +10523,7 @@ This will be the case if the article has both been mailed and posted."
10525 ;; This backend supports expiry. 10523 ;; This backend supports expiry.
10526 (let* ((total (gnus-group-total-expirable-p gnus-newsgroup-name)) 10524 (let* ((total (gnus-group-total-expirable-p gnus-newsgroup-name))
10527 (expirable 10525 (expirable
10528 (gnus-list-range-difference 10526 (range-list-difference
10529 (if total 10527 (if total
10530 (progn 10528 (progn
10531 ;; We need to update the info for 10529 ;; We need to update the info for
@@ -12874,8 +12872,8 @@ UNREAD is a sorted list."
12874 (gnus-find-method-for-group group) 12872 (gnus-find-method-for-group group)
12875 'server-marks) 12873 'server-marks)
12876 (gnus-check-backend-function 'request-set-mark group)) 12874 (gnus-check-backend-function 'request-set-mark group))
12877 (let ((del (gnus-remove-from-range (gnus-info-read info) read)) 12875 (let ((del (range-remove (gnus-info-read info) read))
12878 (add (gnus-remove-from-range read (gnus-info-read info)))) 12876 (add (range-remove read (gnus-info-read info))))
12879 (when (or add del) 12877 (when (or add del)
12880 (unless (gnus-check-group group) 12878 (unless (gnus-check-group group)
12881 (error "Can't open server for %s" group)) 12879 (error "Can't open server for %s" group))
@@ -13133,10 +13131,10 @@ If ALL is a number, fetch this number of articles."
13133 ;; Some nntp servers lie about their active range. When 13131 ;; Some nntp servers lie about their active range. When
13134 ;; this happens, the active range can be in the millions. 13132 ;; this happens, the active range can be in the millions.
13135 ;; Use a compressed range to avoid creating a huge list. 13133 ;; Use a compressed range to avoid creating a huge list.
13136 (gnus-range-difference 13134 (range-difference
13137 (gnus-range-difference (list gnus-newsgroup-active) old) 13135 (range-difference (list gnus-newsgroup-active) old)
13138 gnus-newsgroup-unexist)) 13136 gnus-newsgroup-unexist))
13139 (setq len (gnus-range-length older)) 13137 (setq len (range-length older))
13140 (cond 13138 (cond
13141 ((null older) nil) 13139 ((null older) nil)
13142 ((numberp all) 13140 ((numberp all)
@@ -13153,9 +13151,9 @@ If ALL is a number, fetch this number of articles."
13153 (push max older) 13151 (push max older)
13154 (setq all (1- all) 13152 (setq all (1- all)
13155 max (1- max)))))) 13153 max (1- max))))))
13156 (setq older (gnus-uncompress-range older)))) 13154 (setq older (range-uncompress older))))
13157 (all 13155 (all
13158 (setq older (gnus-uncompress-range older))) 13156 (setq older (range-uncompress older)))
13159 (t 13157 (t
13160 (when (and (numberp gnus-large-newsgroup) 13158 (when (and (numberp gnus-large-newsgroup)
13161 (> len gnus-large-newsgroup)) 13159 (> len gnus-large-newsgroup))
@@ -13190,7 +13188,7 @@ If ALL is a number, fetch this number of articles."
13190 (push max older) 13188 (push max older)
13191 (setq all (1- all) 13189 (setq all (1- all)
13192 max (1- max)))))))))) 13190 max (1- max))))))))))
13193 (setq older (gnus-uncompress-range older)))) 13191 (setq older (range-uncompress older))))
13194 (if (not older) 13192 (if (not older)
13195 (message "No old news.") 13193 (message "No old news.")
13196 (gnus-summary-insert-articles older) 13194 (gnus-summary-insert-articles older)
diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el
index 9a48f710e55..5d0c0e2654b 100644
--- a/lisp/gnus/mail-source.el
+++ b/lisp/gnus/mail-source.el
@@ -31,6 +31,7 @@
31(autoload 'pop3-movemail "pop3") 31(autoload 'pop3-movemail "pop3")
32(autoload 'pop3-get-message-count "pop3") 32(autoload 'pop3-get-message-count "pop3")
33(require 'mm-util) 33(require 'mm-util)
34(require 'gnus-range)
34(require 'message) ;; for `message-directory' 35(require 'message) ;; for `message-directory'
35 36
36(defvar display-time-mail-function) 37(defvar display-time-mail-function)
@@ -1048,8 +1049,6 @@ This only works when `display-time' is enabled."
1048(autoload 'imap-range-to-message-set "imap") 1049(autoload 'imap-range-to-message-set "imap")
1049(autoload 'nnheader-ms-strip-cr "nnheader") 1050(autoload 'nnheader-ms-strip-cr "nnheader")
1050 1051
1051(autoload 'gnus-compress-sequence "gnus-range")
1052
1053(defvar mail-source-imap-file-coding-system 'binary 1052(defvar mail-source-imap-file-coding-system 'binary
1054 "Coding system for the crashbox made by `mail-source-fetch-imap'.") 1053 "Coding system for the crashbox made by `mail-source-fetch-imap'.")
1055 1054
diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el
index 8b3718ed7e8..c1c5f00ff7f 100644
--- a/lisp/gnus/nnheader.el
+++ b/lisp/gnus/nnheader.el
@@ -27,6 +27,7 @@
27;;; Code: 27;;; Code:
28 28
29(eval-when-compile (require 'cl-lib)) 29(eval-when-compile (require 'cl-lib))
30(require 'range)
30 31
31(defvar gnus-decode-encoded-word-function) 32(defvar gnus-decode-encoded-word-function)
32(defvar gnus-decode-encoded-address-function) 33(defvar gnus-decode-encoded-address-function)
@@ -44,8 +45,6 @@
44(require 'mm-util) 45(require 'mm-util)
45(require 'gnus-util) 46(require 'gnus-util)
46(autoload 'gnus-remove-odd-characters "gnus-sum") 47(autoload 'gnus-remove-odd-characters "gnus-sum")
47(autoload 'gnus-range-add "gnus-range")
48(autoload 'gnus-remove-from-range "gnus-range")
49;; FIXME none of these are used explicitly in this file. 48;; FIXME none of these are used explicitly in this file.
50(autoload 'gnus-sorted-intersection "gnus-range") 49(autoload 'gnus-sorted-intersection "gnus-range")
51(autoload 'gnus-intersection "gnus-range") 50(autoload 'gnus-intersection "gnus-range")
@@ -1044,10 +1043,9 @@ See `find-file-noselect' for the arguments."
1044 mark 1043 mark
1045 (cond 1044 (cond
1046 ((eq what 'add) 1045 ((eq what 'add)
1047 (gnus-range-add (cdr (assoc mark backend-marks)) range)) 1046 (range-concat (cdr (assoc mark backend-marks)) range))
1048 ((eq what 'del) 1047 ((eq what 'del)
1049 (gnus-remove-from-range 1048 (range-remove (cdr (assoc mark backend-marks)) range))
1050 (cdr (assoc mark backend-marks)) range))
1051 ((eq what 'set) 1049 ((eq what 'set)
1052 range)) 1050 range))
1053 backend-marks))))) 1051 backend-marks)))))
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index cff628061e9..afd5418912f 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -1660,13 +1660,13 @@ If LIMIT, first try to limit the search to the N last articles."
1660 (cdr (assoc '%Seen flags)) 1660 (cdr (assoc '%Seen flags))
1661 (cdr (assoc '%Deleted flags)))) 1661 (cdr (assoc '%Deleted flags))))
1662 (cdr (assoc '%Flagged flags))))) 1662 (cdr (assoc '%Flagged flags)))))
1663 (read (gnus-range-difference 1663 (read (range-difference
1664 (cons start-article high) unread))) 1664 (cons start-article high) unread)))
1665 (when (> start-article 1) 1665 (when (> start-article 1)
1666 (setq read 1666 (setq read
1667 (gnus-range-nconcat 1667 (gnus-range-nconcat
1668 (if (> start-article 1) 1668 (if (> start-article 1)
1669 (gnus-sorted-range-intersection 1669 (range-intersection
1670 (cons 1 (1- start-article)) 1670 (cons 1 (1- start-article))
1671 (gnus-info-read info)) 1671 (gnus-info-read info))
1672 (gnus-info-read info)) 1672 (gnus-info-read info))
@@ -1691,7 +1691,7 @@ If LIMIT, first try to limit the search to the N last articles."
1691 (pop old-marks) 1691 (pop old-marks)
1692 (when (and old-marks 1692 (when (and old-marks
1693 (> start-article 1)) 1693 (> start-article 1))
1694 (setq old-marks (gnus-range-difference 1694 (setq old-marks (range-difference
1695 old-marks 1695 old-marks
1696 (cons start-article high))) 1696 (cons start-article high)))
1697 (setq new-marks (gnus-range-nconcat old-marks new-marks))) 1697 (setq new-marks (gnus-range-nconcat old-marks new-marks)))
@@ -1702,15 +1702,15 @@ If LIMIT, first try to limit the search to the N last articles."
1702 (active (gnus-active group)) 1702 (active (gnus-active group))
1703 (unexists 1703 (unexists
1704 (if completep 1704 (if completep
1705 (gnus-range-difference 1705 (range-difference
1706 active 1706 active
1707 (gnus-compress-sequence existing)) 1707 (gnus-compress-sequence existing))
1708 (gnus-add-to-range 1708 (range-add-list
1709 (cdr old-unexists) 1709 (cdr old-unexists)
1710 (gnus-list-range-difference 1710 (range-list-difference
1711 existing (gnus-active group)))))) 1711 existing (gnus-active group))))))
1712 (when (> (car active) 1) 1712 (when (> (car active) 1)
1713 (setq unexists (gnus-range-add 1713 (setq unexists (range-concat
1714 (cons 1 (1- (car active))) 1714 (cons 1 (1- (car active)))
1715 unexists))) 1715 unexists)))
1716 (if old-unexists 1716 (if old-unexists
@@ -1733,10 +1733,9 @@ If LIMIT, first try to limit the search to the N last articles."
1733(defun nnimap-update-qresync-info (info existing vanished flags) 1733(defun nnimap-update-qresync-info (info existing vanished flags)
1734 ;; Add all the vanished articles to the list of read articles. 1734 ;; Add all the vanished articles to the list of read articles.
1735 (setf (gnus-info-read info) 1735 (setf (gnus-info-read info)
1736 (gnus-add-to-range 1736 (range-add-list
1737 (gnus-add-to-range 1737 (range-add-list
1738 (gnus-range-add (gnus-info-read info) 1738 (range-concat (gnus-info-read info) vanished)
1739 vanished)
1740 (cdr (assq '%Flagged flags))) 1739 (cdr (assq '%Flagged flags)))
1741 (cdr (assq '%Seen flags)))) 1740 (cdr (assq '%Seen flags))))
1742 (let ((marks (gnus-info-marks info))) 1741 (let ((marks (gnus-info-marks info)))
@@ -1750,9 +1749,9 @@ If LIMIT, first try to limit the search to the N last articles."
1750 (setq marks (delq ticks marks)) 1749 (setq marks (delq ticks marks))
1751 (pop ticks) 1750 (pop ticks)
1752 ;; Add the new marks we got. 1751 ;; Add the new marks we got.
1753 (setq ticks (gnus-add-to-range ticks new-marks)) 1752 (setq ticks (range-add-list ticks new-marks))
1754 ;; Remove the marks from messages that don't have them. 1753 ;; Remove the marks from messages that don't have them.
1755 (setq ticks (gnus-remove-from-range 1754 (setq ticks (range-remove
1756 ticks 1755 ticks
1757 (gnus-compress-sequence 1756 (gnus-compress-sequence
1758 (gnus-sorted-complement existing new-marks)))) 1757 (gnus-sorted-complement existing new-marks))))
@@ -1762,7 +1761,7 @@ If LIMIT, first try to limit the search to the N last articles."
1762 ;; Add vanished to the list of unexisting articles. 1761 ;; Add vanished to the list of unexisting articles.
1763 (when vanished 1762 (when vanished
1764 (let* ((old-unexists (assq 'unexist marks)) 1763 (let* ((old-unexists (assq 'unexist marks))
1765 (unexists (gnus-range-add (cdr old-unexists) vanished))) 1764 (unexists (range-concat (cdr old-unexists) vanished)))
1766 (if old-unexists 1765 (if old-unexists
1767 (setcdr old-unexists unexists) 1766 (setcdr old-unexists unexists)
1768 (push (cons 'unexist unexists) marks))) 1767 (push (cons 'unexist unexists) marks)))
@@ -2242,7 +2241,7 @@ Return the server's response to the SELECT or EXAMINE command."
2242 (while (re-search-forward "^\\([0-9]+\\) OK\\b" nil t) 2241 (while (re-search-forward "^\\([0-9]+\\) OK\\b" nil t)
2243 (setq sequence (string-to-number (match-string 1))) 2242 (setq sequence (string-to-number (match-string 1)))
2244 (when (setq range (cadr (assq sequence sequences))) 2243 (when (setq range (cadr (assq sequence sequences)))
2245 (push (gnus-uncompress-range range) copied))) 2244 (push (range-uncompress range) copied)))
2246 (gnus-compress-sequence (sort (apply #'nconc copied) #'<)))) 2245 (gnus-compress-sequence (sort (apply #'nconc copied) #'<))))
2247 2246
2248(defun nnimap-new-articles (flags) 2247(defun nnimap-new-articles (flags)
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index 690761a2d6c..30f473b1291 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -1006,10 +1006,10 @@ This variable is set by `nnmaildir-request-article'.")
1006 existing (nnmaildir--grp-nlist group) 1006 existing (nnmaildir--grp-nlist group)
1007 existing (mapcar #'car existing) 1007 existing (mapcar #'car existing)
1008 existing (nreverse existing) 1008 existing (nreverse existing)
1009 existing (gnus-compress-sequence existing 'always-list) 1009 existing (range-compress-list existing)
1010 missing (list (cons 1 (nnmaildir--group-maxnum 1010 missing (list (cons 1 (nnmaildir--group-maxnum
1011 nnmaildir--cur-server group))) 1011 nnmaildir--cur-server group)))
1012 missing (gnus-range-difference missing existing) 1012 missing (range-difference missing existing)
1013 dir (nnmaildir--srv-dir nnmaildir--cur-server) 1013 dir (nnmaildir--srv-dir nnmaildir--cur-server)
1014 dir (nnmaildir--srvgrp-dir dir gname) 1014 dir (nnmaildir--srvgrp-dir dir gname)
1015 dir (nnmaildir--nndir dir) 1015 dir (nnmaildir--nndir dir)
@@ -1076,10 +1076,10 @@ This variable is set by `nnmaildir-request-article'.")
1076 (let ((article (nnmaildir--flist-art flist prefix))) 1076 (let ((article (nnmaildir--flist-art flist prefix)))
1077 (when article 1077 (when article
1078 (push (nnmaildir--art-num article) article-list)))))) 1078 (push (nnmaildir--art-num article) article-list))))))
1079 (setq ranges (gnus-add-to-range ranges (sort article-list #'<))))) 1079 (setq ranges (range-add-list ranges (sort article-list #'<)))))
1080 (if (eq mark 'read) (setq read ranges) 1080 (if (eq mark 'read) (setq read ranges)
1081 (if ranges (setq marks (cons (cons mark ranges) marks))))) 1081 (if ranges (setq marks (cons (cons mark ranges) marks)))))
1082 (setf (gnus-info-read info) (gnus-range-add read missing)) 1082 (setf (gnus-info-read info) (range-concat read missing))
1083 (gnus-info-set-marks info marks 'extend) 1083 (gnus-info-set-marks info marks 'extend)
1084 (setf (nnmaildir--grp-mmth group) new-mmth) 1084 (setf (nnmaildir--grp-mmth group) new-mmth)
1085 info))) 1085 info)))
@@ -1548,11 +1548,11 @@ This variable is set by `nnmaildir-request-article'.")
1548 (unless group 1548 (unless group
1549 (setf (nnmaildir--srv-error nnmaildir--cur-server) 1549 (setf (nnmaildir--srv-error nnmaildir--cur-server)
1550 (if gname (concat "No such group: " gname) "No current group")) 1550 (if gname (concat "No such group: " gname) "No current group"))
1551 (throw 'return (gnus-uncompress-range ranges))) 1551 (throw 'return (range-uncompress ranges)))
1552 (setq gname (nnmaildir--grp-name group) 1552 (setq gname (nnmaildir--grp-name group)
1553 pgname (nnmaildir--pgname nnmaildir--cur-server gname)) 1553 pgname (nnmaildir--pgname nnmaildir--cur-server gname))
1554 (if (nnmaildir--param pgname 'read-only) 1554 (if (nnmaildir--param pgname 'read-only)
1555 (throw 'return (gnus-uncompress-range ranges))) 1555 (throw 'return (range-uncompress ranges)))
1556 (setq time (nnmaildir--param pgname 'expire-age)) 1556 (setq time (nnmaildir--param pgname 'expire-age))
1557 (unless time 1557 (unless time
1558 (setq time (or (and nnmail-expiry-wait-function 1558 (setq time (or (and nnmail-expiry-wait-function
@@ -1564,7 +1564,7 @@ This variable is set by `nnmaildir-request-article'.")
1564 (setq time (round (* time 86400)))))) 1564 (setq time (round (* time 86400))))))
1565 (when no-force 1565 (when no-force
1566 (unless (integerp time) ;; handle 'never 1566 (unless (integerp time) ;; handle 'never
1567 (throw 'return (gnus-uncompress-range ranges))) 1567 (throw 'return (range-uncompress ranges)))
1568 (setq boundary (time-since time))) 1568 (setq boundary (time-since time)))
1569 (setq dir (nnmaildir--srv-dir nnmaildir--cur-server) 1569 (setq dir (nnmaildir--srv-dir nnmaildir--cur-server)
1570 dir (nnmaildir--srvgrp-dir dir gname) 1570 dir (nnmaildir--srvgrp-dir dir gname)
@@ -1686,7 +1686,7 @@ This variable is set by `nnmaildir-request-article'.")
1686 (setf (nnmaildir--srv-error nnmaildir--cur-server) 1686 (setf (nnmaildir--srv-error nnmaildir--cur-server)
1687 (concat "No such group: " gname)) 1687 (concat "No such group: " gname))
1688 (dolist (action actions) 1688 (dolist (action actions)
1689 (setq ranges (gnus-range-add ranges (car action)))) 1689 (setq ranges (range-concat ranges (car action))))
1690 (throw 'return ranges)) 1690 (throw 'return ranges))
1691 (setq nlist (nnmaildir--grp-nlist group) 1691 (setq nlist (nnmaildir--grp-nlist group)
1692 marksdir (nnmaildir--srv-dir nnmaildir--cur-server) 1692 marksdir (nnmaildir--srv-dir nnmaildir--cur-server)
diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el
index 8ca1cf0fe8b..4e8e329f983 100644
--- a/lisp/gnus/nnmairix.el
+++ b/lisp/gnus/nnmairix.el
@@ -597,7 +597,7 @@ Other back ends might or might not work.")
597 (dolist (cur actions) 597 (dolist (cur actions)
598 (let ((type (nth 1 cur)) 598 (let ((type (nth 1 cur))
599 (cmdmarks (nth 2 cur)) 599 (cmdmarks (nth 2 cur))
600 (range (gnus-uncompress-range (nth 0 cur))) 600 (range (range-uncompress (nth 0 cur)))
601 mid ogroup temp) ;; number method 601 mid ogroup temp) ;; number method
602 (when (and corr 602 (when (and corr
603 (not (zerop (cadr corr)))) 603 (not (zerop (cadr corr))))
diff --git a/lisp/gnus/nnmbox.el b/lisp/gnus/nnmbox.el
index 5a350aac746..96ecc34e156 100644
--- a/lisp/gnus/nnmbox.el
+++ b/lisp/gnus/nnmbox.el
@@ -529,7 +529,7 @@
529 ;; add article to index, either by building complete list 529 ;; add article to index, either by building complete list
530 ;; in reverse order, or as a list of ranges. 530 ;; in reverse order, or as a list of ranges.
531 (if (not nnmbox-group-building-active-articles) 531 (if (not nnmbox-group-building-active-articles)
532 (setcdr entry (gnus-add-to-range (cdr entry) (list article))) 532 (setcdr entry (range-add-list (cdr entry) (list article)))
533 (when (memq article (cdr entry)) 533 (when (memq article (cdr entry))
534 (switch-to-buffer nnmbox-mbox-buffer) 534 (switch-to-buffer nnmbox-mbox-buffer)
535 (error "Article %s:%d already exists!" group article)) 535 (error "Article %s:%d already exists!" group article))
@@ -548,10 +548,10 @@
548 nnmbox-group-active-articles) 548 nnmbox-group-active-articles)
549 (car nnmbox-group-active-articles))))) 549 (car nnmbox-group-active-articles)))))
550 ;; remove article from index 550 ;; remove article from index
551 (setcdr entry (gnus-remove-from-range (cdr entry) (list article))))) 551 (setcdr entry (range-remove (cdr entry) (list article)))))
552 552
553(defun nnmbox-is-article-active-p (article) 553(defun nnmbox-is-article-active-p (article)
554 (gnus-member-of-range 554 (range-member-p
555 article 555 article
556 (cdr (assoc nnmbox-current-group 556 (cdr (assoc nnmbox-current-group
557 nnmbox-group-active-articles)))) 557 nnmbox-group-active-articles))))
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index afdb0c780a5..7fe2b516cce 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -1078,21 +1078,20 @@ Use the nov database for the current group if available."
1078 ;; #### doing anything on them. 1078 ;; #### doing anything on them.
1079 ;; 2 a/ read articles: 1079 ;; 2 a/ read articles:
1080 (let ((read (gnus-info-read info))) 1080 (let ((read (gnus-info-read info)))
1081 (setq read (gnus-remove-from-range read (list new-number))) 1081 (setq read (range-remove read (list new-number)))
1082 (when (gnus-member-of-range old-number read) 1082 (when (range-member-p old-number read)
1083 (setq read (gnus-remove-from-range read (list old-number))) 1083 (setq read (range-remove read (list old-number)))
1084 (setq read (gnus-add-to-range read (list new-number)))) 1084 (setq read (range-add-list read (list new-number))))
1085 (setf (gnus-info-read info) read)) 1085 (setf (gnus-info-read info) read))
1086 ;; 2 b/ marked articles: 1086 ;; 2 b/ marked articles:
1087 (let ((oldmarks (gnus-info-marks info)) 1087 (let ((oldmarks (gnus-info-marks info))
1088 mark newmarks) 1088 mark newmarks)
1089 (while (setq mark (pop oldmarks)) 1089 (while (setq mark (pop oldmarks))
1090 (setcdr mark (gnus-remove-from-range (cdr mark) 1090 (setcdr mark (range-remove (cdr mark) (list new-number)))
1091 (list new-number))) 1091 (when (range-member-p old-number (cdr mark))
1092 (when (gnus-member-of-range old-number (cdr mark)) 1092 (setcdr mark (range-remove (cdr mark)
1093 (setcdr mark (gnus-remove-from-range (cdr mark) 1093 (list old-number)))
1094 (list old-number))) 1094 (setcdr mark (range-add-list (cdr mark)
1095 (setcdr mark (gnus-add-to-range (cdr mark)
1096 (list new-number)))) 1095 (list new-number))))
1097 (push mark newmarks)) 1096 (push mark newmarks))
1098 (setf (gnus-info-marks info) newmarks)) 1097 (setf (gnus-info-marks info) newmarks))
diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el
index 9d744ea411e..205456a57df 100644
--- a/lisp/gnus/nnselect.el
+++ b/lisp/gnus/nnselect.el
@@ -207,7 +207,7 @@ as `(keyfunc member)' and the corresponding element is just
207 (inline-quote 207 (inline-quote
208 (cond 208 (cond
209 ((eq ,type 'range) 209 ((eq ,type 'range)
210 (nnselect-categorize (gnus-uncompress-range ,articles) 210 (nnselect-categorize (range-uncompress ,articles)
211 #'nnselect-article-group #'nnselect-article-number)) 211 #'nnselect-article-group #'nnselect-article-number))
212 ((eq ,type 'tuple) 212 ((eq ,type 'tuple)
213 (nnselect-categorize ,articles 213 (nnselect-categorize ,articles
@@ -542,10 +542,10 @@ If this variable is nil, or if the provided function returns nil,
542 (group-info (gnus-get-info artgroup)) 542 (group-info (gnus-get-info artgroup))
543 (marks (gnus-info-marks group-info)) 543 (marks (gnus-info-marks group-info))
544 (unread (gnus-uncompress-sequence 544 (unread (gnus-uncompress-sequence
545 (gnus-range-difference (gnus-active artgroup) 545 (range-difference (gnus-active artgroup)
546 (gnus-info-read group-info))))) 546 (gnus-info-read group-info)))))
547 (setf (gnus-info-read info) 547 (setf (gnus-info-read info)
548 (gnus-add-to-range 548 (range-add-list
549 (gnus-info-read info) 549 (gnus-info-read info)
550 (delq nil (mapcar 550 (delq nil (mapcar
551 (lambda (art) 551 (lambda (art)
@@ -567,7 +567,7 @@ If this variable is nil, or if the provided function returns nil,
567 artids)) 567 artids))
568 (t 568 (t
569 (setq mark-list 569 (setq mark-list
570 (gnus-uncompress-range mark-list)) 570 (range-uncompress mark-list))
571 (mapcar 571 (mapcar
572 (lambda (id) 572 (lambda (id)
573 (when (memq (cdr id) mark-list) 573 (when (memq (cdr id) mark-list)
@@ -866,16 +866,16 @@ article came from is also searched."
866 (when (and (gnus-check-backend-function 866 (when (and (gnus-check-backend-function
867 'request-set-mark artgroup) 867 'request-set-mark artgroup)
868 (not (gnus-article-unpropagatable-p type))) 868 (not (gnus-article-unpropagatable-p type)))
869 (let* ((old (gnus-list-range-intersection 869 (let* ((old (range-list-intersection
870 artlist 870 artlist
871 (alist-get type (gnus-info-marks group-info)))) 871 (alist-get type (gnus-info-marks group-info))))
872 (del (gnus-remove-from-range (copy-tree old) list)) 872 (del (range-remove (copy-tree old) list))
873 (add (gnus-remove-from-range (copy-tree list) old))) 873 (add (range-remove (copy-tree list) old)))
874 (when add (push (list add 'add (list type)) delta-marks)) 874 (when add (push (list add 'add (list type)) delta-marks))
875 (when del 875 (when del
876 ;; Don't delete marks from outside the active range. 876 ;; Don't delete marks from outside the active range.
877 ;; This shouldn't happen, but is a sanity check. 877 ;; This shouldn't happen, but is a sanity check.
878 (setq del (gnus-sorted-range-intersection 878 (setq del (range-intersection
879 (gnus-active artgroup) del)) 879 (gnus-active artgroup) del))
880 (push (list del 'del (list type)) delta-marks)))) 880 (push (list del 'del (list type)) delta-marks))))
881 881
@@ -910,18 +910,18 @@ article came from is also searched."
910 (< (car elt1) (car elt2)))))) 910 (< (car elt1) (car elt2))))))
911 (t 911 (t
912 (setq list 912 (setq list
913 (gnus-compress-sequence 913 (range-compress-list
914 (gnus-sorted-union 914 (gnus-sorted-union
915 (gnus-sorted-difference 915 (gnus-sorted-difference
916 (gnus-uncompress-sequence 916 (gnus-uncompress-sequence
917 (alist-get type (gnus-info-marks group-info))) 917 (alist-get type (gnus-info-marks group-info)))
918 artlist) 918 artlist)
919 (sort list #'<)) t))) 919 (sort list #'<)))))
920 920
921 ;; When exiting the group, everything that's previously been 921 ;; When exiting the group, everything that's previously been
922 ;; unseen is now seen. 922 ;; unseen is now seen.
923 (when (eq type 'seen) 923 (when (eq type 'seen)
924 (setq list (gnus-range-add 924 (setq list (range-concat
925 list (cdr (assoc artgroup select-unseen)))))) 925 list (cdr (assoc artgroup select-unseen))))))
926 926
927 (when (or list (eq type 'unexist)) 927 (when (or list (eq type 'unexist))
@@ -944,9 +944,9 @@ article came from is also searched."
944 ;; update read and unread 944 ;; update read and unread
945 (gnus-update-read-articles 945 (gnus-update-read-articles
946 artgroup 946 artgroup
947 (gnus-uncompress-range 947 (range-uncompress
948 (gnus-add-to-range 948 (range-add-list
949 (gnus-remove-from-range 949 (range-remove
950 old-unread 950 old-unread
951 (cdr (assoc artgroup select-reads))) 951 (cdr (assoc artgroup select-reads)))
952 (sort (cdr (assoc artgroup select-unreads)) #'<)))) 952 (sort (cdr (assoc artgroup select-unreads)) #'<))))
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index 7478a2dd0af..cc87a707ce6 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -365,7 +365,7 @@ It is computed from the marks of individual component groups.")
365 (lambda (article) 365 (lambda (article)
366 (nnvirtual-reverse-map-article 366 (nnvirtual-reverse-map-article
367 group article)) 367 group article))
368 (gnus-uncompress-range 368 (range-uncompress
369 (gnus-group-expire-articles-1 group)))))) 369 (gnus-group-expire-articles-1 group))))))
370 (sort (delq nil unexpired) #'<))) 370 (sort (delq nil unexpired) #'<)))
371 371
diff --git a/test/lisp/emacs-lisp/range-tests.el b/test/lisp/emacs-lisp/range-tests.el
new file mode 100644
index 00000000000..d3abbf9da31
--- /dev/null
+++ b/test/lisp/emacs-lisp/range-tests.el
@@ -0,0 +1,65 @@
1;;; range-tests.el --- Tests for range.el -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2021 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;;
23
24;;; Code:
25
26(require 'range)
27(require 'ert)
28(require 'ert-x)
29
30(ert-deftest ranges ()
31 (should (equal (range-compress-list '(2 3 4 5 9 11 12 13))
32 '((2 . 5) 9 (11 . 13))))
33 (should (equal (range-uncompress '((2 . 5) 9 (11 . 13)))
34 '(2 3 4 5 9 11 12 13)))
35 (should (equal (range-normalize '(1 . 2))
36 '((1 . 2))))
37 (should (equal (range-difference '((1 . 10))
38 '((2 . 7)))
39 '(1 (8 . 10))))
40 (should (equal (range-intersection '((2 . 5) 9 (11 . 13))
41 '((5 . 12)))
42 '(5 9 (11 . 12))))
43 (should (equal (range-add-list '((2 . 5) 9 (11 . 13))
44 '(10 11 12 15 16 17))
45 '((2 . 5) (9 . 10) (11 . 13) (15 . 17))))
46 (should (equal (range-remove (copy-tree '((2 . 5) 9 (11 . 13)))
47 '((5 . 9)))
48 '((2 . 4) (11 . 13))))
49 (should (range-member-p 9 '((2 . 5) 9 (11 . 13))))
50 (should (range-member-p 12 '((2 . 5) 9 (11 . 13))))
51 (should (equal (range-list-intersection
52 '(4 5 6 7 8 9)
53 '((2 . 5) 9 (11 . 13)))
54 '(4 5 9)))
55 (should (equal (range-list-difference
56 '(4 5 6 7 8 9)
57 '((2 . 5) 9 (11 . 13)))
58 '(6 7 8)))
59 (should (equal (range-length '((2 . 5) 9 (11 . 13)))
60 8))
61 (should (equal (range-concat '((2 . 5) 9 (11 . 13))
62 '(6 (12 . 15)))
63 '((2 . 6) 9 (11 . 15)))))
64
65;;; range-tests.el ends here