about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--concat.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/concat.c b/concat.c
index 54a49a7..a3b4bac 100644
--- a/concat.c
+++ b/concat.c
@@ -46,12 +46,28 @@ static uint32_t threadRoot(struct List thread) {
 	return dataCheck(thread.ptr[0], Number).number;
 }
 
-void concatFetch(FILE *imap, enum Atom tag, struct List threads) {
-	fprintf(imap, "%s UID FETCH ", Atoms[tag]);
+static void compressRoots(FILE *imap, struct List threads) {
+	uint32_t base = 0;
+	uint32_t prev = 0;
 	for (size_t i = 0; i < threads.len; ++i) {
 		uint32_t root = threadRoot(dataCheck(threads.ptr[i], List).list);
-		fprintf(imap, "%s%" PRIu32, (i ? "," : ""), root);
+		if (!base) {
+			fprintf(imap, "%" PRIu32, root);
+			base = prev = root;
+		} else if (root == prev + 1) {
+			prev = root;
+		} else {
+			if (prev > base) fprintf(imap, ":%" PRIu32, prev);
+			fprintf(imap, ",%" PRIu32, root);
+			base = prev = root;
+		}
 	}
+	if (prev > base) fprintf(imap, ":%" PRIu32, prev);
+}
+
+void concatFetch(FILE *imap, enum Atom tag, struct List threads) {
+	fprintf(imap, "%s UID FETCH ", Atoms[tag]);
+	compressRoots(imap, threads);
 	fprintf(imap, " (UID ENVELOPE)\r\n");
 }
 
@@ -59,10 +75,7 @@ void concatSearch(
 	FILE *imap, enum Atom tag, struct List threads, const char *expr
 ) {
 	fprintf(imap, "%s UID SEARCH CHARSET UTF-8 UID ", Atoms[tag]);
-	for (size_t i = 0; i < threads.len; ++i) {
-		uint32_t root = threadRoot(dataCheck(threads.ptr[i], List).list);
-		fprintf(imap, "%s%" PRIu32, (i ? "," : ""), root);
-	}
+	compressRoots(imap, threads);
 	fprintf(imap, " %s\r\n", expr);
 }