184
206
(defvar rmail-new-summary-line-count)
186
(defun rmail-new-summary (description redo-form function &rest args)
208
(defun rmail-new-summary (desc redo func &rest args)
187
209
"Create a summary of selected messages.
188
DESCRIPTION makes part of the mode line of the summary buffer.
189
For each message, FUNCTION is applied to the message number and ARGS...
210
DESC makes part of the mode line of the summary buffer. REDO is form ...
211
For each message, FUNC is applied to the message number and ARGS...
190
212
and if the result is non-nil, that message is included.
191
213
nil for FUNCTION means all messages."
192
214
(message "Computing summary lines...")
193
(let (sumbuf mesg was-in-summary)
195
;; Go to the Rmail buffer.
196
(if (eq major-mode 'rmail-summary-mode)
197
(setq was-in-summary t))
198
(set-buffer rmail-buffer)
199
;; Find its summary buffer, or make one.
201
(if (and rmail-summary-buffer
202
(buffer-name rmail-summary-buffer))
204
(generate-new-buffer (concat (buffer-name) "-summary"))))
205
(setq mesg rmail-current-message)
206
;; Filter the messages; make or get their summary lines.
207
(let ((summary-msgs ())
208
(rmail-new-summary-line-count 0))
210
(buffer-read-only nil)
211
(old-min (point-min-marker))
212
(old-max (point-max-marker)))
213
;; Can't use save-restriction here; that doesn't work if we
214
;; plan to modify text outside the original restriction.
217
(goto-char (point-min))
218
(while (>= rmail-total-messages msgnum)
219
(if (or (null function)
220
(apply function (cons msgnum args)))
222
(cons (cons msgnum (rmail-make-summary-line msgnum))
224
(setq msgnum (1+ msgnum)))
225
(setq summary-msgs (nreverse summary-msgs)))
226
(narrow-to-region old-min old-max))
227
;; Temporarily, while summary buffer is unfinished,
228
;; we "don't have" a summary.
229
(setq rmail-summary-buffer nil)
230
(if rmail-enable-mime
231
(with-current-buffer rmail-view-buffer
232
(setq rmail-summary-buffer nil)))
234
(let ((rbuf (current-buffer))
235
(vbuf rmail-view-buffer)
236
(total rmail-total-messages))
238
;; Set up the summary buffer's contents.
239
(let ((buffer-read-only nil))
242
(princ (cdr (car summary-msgs)) sumbuf)
243
(setq summary-msgs (cdr summary-msgs)))
244
(goto-char (point-min)))
245
;; Set up the rest of its state and local variables.
246
(setq buffer-read-only t)
248
(make-local-variable 'minor-mode-alist)
249
(setq minor-mode-alist (list (list t (concat ": " description))))
250
(setq rmail-buffer rbuf
251
rmail-view-buffer vbuf
252
rmail-summary-redo redo-form
253
rmail-total-messages total))))
254
(setq rmail-summary-buffer sumbuf))
216
(error "No RMAIL buffer found"))
217
(let (mesg was-in-summary)
218
(if (eq major-mode 'rmail-summary-mode)
219
(setq was-in-summary t))
220
(with-current-buffer rmail-buffer
221
(if (zerop (setq mesg rmail-current-message))
222
(error "No messages to summarize"))
223
(setq rmail-summary-buffer (rmail-new-summary-1 desc redo func args)))
255
224
;; Now display the summary buffer and go to the right place in it.
258
(if (and (one-window-p)
259
pop-up-windows (not pop-up-frames))
260
;; If there is just one window, put the summary on the top.
262
(split-window (selected-window) rmail-summary-window-size)
263
(select-window (next-window (frame-first-window)))
264
(pop-to-buffer sumbuf)
265
;; If pop-to-buffer did not use that window, delete that
266
;; window. (This can happen if it uses another frame.)
267
(if (not (eq sumbuf (window-buffer (frame-first-window))))
268
(delete-other-windows)))
269
(pop-to-buffer sumbuf))
270
(set-buffer rmail-buffer)
271
;; This is how rmail makes the summary buffer reappear.
272
;; We do this here to make the window the proper size.
273
(rmail-select-summary nil)
274
(set-buffer rmail-summary-buffer)))
225
(unless was-in-summary
226
(if (and (one-window-p)
229
;; If there is just one window, put the summary on the top.
231
(split-window (selected-window) rmail-summary-window-size)
232
(select-window (next-window (frame-first-window)))
233
(pop-to-buffer rmail-summary-buffer)
234
;; If pop-to-buffer did not use that window, delete that
235
;; window. (This can happen if it uses another frame.)
236
(if (not (eq rmail-summary-buffer
237
(window-buffer (frame-first-window))))
238
(delete-other-windows)))
239
(pop-to-buffer rmail-summary-buffer))
240
(set-buffer rmail-buffer)
241
;; This is how rmail makes the summary buffer reappear.
242
;; We do this here to make the window the proper size.
243
(rmail-select-summary nil)
244
(set-buffer rmail-summary-buffer))
275
245
(rmail-summary-goto-msg mesg t t)
276
246
(rmail-summary-construct-io-menu)
277
247
(message "Computing summary lines...done")))
249
(defun rmail-new-summary-1 (description form function args)
250
"Filter messages to obtain summary lines.
251
DESCRIPTION is added to the mode line.
253
Return the summary buffer by invoking FUNCTION on each message
254
passing the message number and ARGS...
258
The current buffer must be a Rmail buffer either containing a
259
collection of mbox formatted messages or displaying a single
261
(let ((summary-msgs ())
262
(rmail-new-summary-line-count 0)
263
(sumbuf (rmail-get-create-summary-buffer)))
264
;; Scan the messages, getting their summary strings
265
;; and putting the list of them in SUMMARY-MSGS.
267
(main-buffer (current-buffer))
268
(total rmail-total-messages)
269
(inhibit-read-only t))
271
;; Go where the mbox text is.
272
(if (rmail-buffers-swapped-p)
273
(set-buffer rmail-view-buffer))
274
(let ((old-min (point-min-marker))
275
(old-max (point-max-marker)))
277
;; Can't use save-restriction here; that doesn't work if we
278
;; plan to modify text outside the original restriction.
281
(goto-char (point-min))
282
(while (>= total msgnum)
283
;; Go back to the Rmail buffer so
284
;; so FUNCTION and rmail-get-summary can see its local vars.
285
(with-current-buffer main-buffer
286
;; First test whether to include this message.
287
(if (or (null function)
288
(apply function msgnum args))
290
(cons (cons msgnum (rmail-get-summary msgnum))
292
(setq msgnum (1+ msgnum))
293
;; Provide a periodic User progress message.
294
(if (zerop (% rmail-new-summary-line-count 10))
295
(message "Computing summary lines...%d"
296
rmail-new-summary-line-count)))
297
(setq summary-msgs (nreverse summary-msgs)))
298
(narrow-to-region old-min old-max)))))
299
;; Temporarily, while summary buffer is unfinished,
300
;; we "don't have" a summary.
301
(setq rmail-summary-buffer nil)
304
(error "Nothing to summarize"))
305
;; I have not a clue what this clause is doing. If you read this
306
;; chunk of code and have a clue, then please email that clue to
308
(if rmail-enable-mime
309
(with-current-buffer rmail-buffer
310
(setq rmail-summary-buffer nil)))
312
(let ((rbuf (current-buffer))
313
(total rmail-total-messages))
315
;; Set up the summary buffer's contents.
316
(let ((buffer-read-only nil))
319
(princ (cdr (car summary-msgs)) sumbuf)
320
(setq summary-msgs (cdr summary-msgs)))
321
(goto-char (point-min)))
322
;; Set up the rest of its state and local variables.
323
(setq buffer-read-only t)
325
(make-local-variable 'minor-mode-alist)
326
(setq minor-mode-alist (list (list t (concat ": " description))))
327
(setq rmail-buffer rbuf
328
rmail-summary-redo form
329
rmail-total-messages total)))
332
(defun rmail-get-create-summary-buffer ()
333
"Return the Rmail summary buffer.
334
If necessary, it is created and undo is disabled."
335
(if (and rmail-summary-buffer (buffer-name rmail-summary-buffer))
337
(let ((buff (generate-new-buffer (concat (buffer-name) "-summary"))))
338
(with-current-buffer buff
339
(setq buffer-undo-list t))
279
343
;; Low levels of generating a summary.
281
(defun rmail-make-summary-line (msg)
282
(let ((line (or (aref rmail-summary-vector (1- msg))
284
(setq rmail-new-summary-line-count
285
(1+ rmail-new-summary-line-count))
286
(if (zerop (% rmail-new-summary-line-count 10))
287
(message "Computing summary lines...%d"
288
rmail-new-summary-line-count))
289
(rmail-make-summary-line-1 msg))))
291
;; Fix up the part of the summary that says "deleted" or "unseen".
292
(string-match "[0-9]+" line)
293
(aset line (match-end 0)
294
(if (rmail-message-deleted-p msg) ?D
295
(if (= ?0 (char-after (+ 3 (rmail-msgbeg msg))))
345
(defun rmail-get-summary (msgnum)
346
"Return the summary line for message MSGNUM.
347
The mbox buffer must be current when you call this function
348
even if its text is swapped.
350
If the message has a summary line already, it will be stored in
351
the message as a header and simply returned, otherwise the
352
summary line is created, saved in the message header, cached and
355
The current buffer contains the unrestricted message collection."
356
(let ((line (aref rmail-summary-vector (1- msgnum))))
358
;; Register a summary line for MSGNUM.
359
(setq rmail-new-summary-line-count (1+ rmail-new-summary-line-count)
360
line (rmail-create-summary-line msgnum))
361
;; Cache the summary line for use during this Rmail session.
362
(aset rmail-summary-vector (1- msgnum) line))
300
365
(defcustom rmail-summary-line-decoder (function identity)
301
"*Function to decode summary-line.
366
"Function to decode a Rmail summary line.
367
It receives the summary line for one message as a string
368
and should return the decoded string.
303
By default, `identity' is set."
370
By default, it is `identity', which returns the string unaltered."
305
372
:group 'rmail-summary)
307
(defun rmail-make-summary-line-1 (msg)
308
(goto-char (rmail-msgbeg msg))
309
(let* ((lim (save-excursion (forward-line 2) (point)))
315
; (if (save-excursion (re-search-forward ",answered," lim t))
317
; (if (save-excursion (re-search-forward ",filed," lim t))
319
(if (progn (search-forward ",,") (eolp))
322
(buffer-substring (point)
332
(if (looking-at "Summary-line: ")
334
(goto-char (match-end 0))
335
(buffer-substring (point)
336
(progn (forward-line 1) (point))))))))
337
;; Obsolete status lines lacking a # should be flushed.
339
(not (string-match "#" line))
374
(defun rmail-create-summary-line (msgnum)
375
"Return the summary line for message MSGNUM.
376
Obtain the message summary from the header if it is available
377
otherwise create it and store it in the message header.
379
The mbox buffer must be current when you call this function
380
even if its text is swapped."
381
(let ((beg (rmail-msgbeg msgnum))
382
(end (rmail-msgend msgnum))
383
(deleted (rmail-message-deleted-p msgnum))
384
;; Does not work (swapped?)
385
;;; (unseen (rmail-message-unseen-p msgnum))
388
;; Switch to the buffer that has the whole mbox text.
389
(if (rmail-buffers-swapped-p)
390
(set-buffer rmail-view-buffer))
391
;; Now we can compute the line count.
392
(if rmail-summary-line-count-flag
393
(setq lines (count-lines beg end)))
394
;; Narrow to the message header.
399
(if (search-forward "\n\n" end t)
401
(narrow-to-region beg (point))
402
;; Replace rmail-message-unseen-p from above.
404
(setq unseen (and (search-forward
405
(concat rmail-attribute-header ": ") nil t)
406
(looking-at "......U")))
407
;; Generate a status line from the message.
408
(rmail-create-summary msgnum deleted unseen lines))
409
(rmail-error-bad-format msgnum)))))))
411
;; FIXME this is now unused.
412
;; The intention was to display in the summary something like {E}
413
;; for an edited messaged, similarly for answered, etc.
414
;; But that conflicts with the previous rmail usage, where
415
;; any user-defined { labels } occupied this space.
416
;; So whilst it would be nice to have this information in the summary,
417
;; it would need to go somewhere else.
418
(defun rmail-get-summary-status ()
419
"Return a coded string wrapped in curly braces denoting the status.
421
The current buffer must already be narrowed to the message headers for
422
the message being processed."
423
(let ((status (mail-fetch-field rmail-attribute-header))
427
;; Strip off the read/unread and the deleted attribute which are
428
;; handled separately.
431
(concat (substring status 0 1) (substring status 2 6))
433
(while (< index (length status))
434
(unless (string= "-" (setq char (substring status index (1+ index))))
435
(setq result (concat result char)))
436
(setq index (1+ index)))
437
(when (> (length result) 0)
438
(setq result (concat "{" result "}")))
441
(autoload 'rmail-make-label "rmailkwd")
443
(defun rmail-get-summary-labels ()
444
"Return a string wrapped in curly braces with the current message labels.
445
Returns nil if there are no labels. The current buffer must
446
already be narrowed to the message headers for the message being
448
(let ((labels (mail-fetch-field rmail-keyword-header)))
450
(not (string-equal labels ""))
341
(delete-region (point)
342
(progn (forward-line -1) (point)))
344
;; If we didn't get a valid status line from the message,
345
;; make a new one and put it in the message.
347
(let* ((case-fold-search t)
348
(next (rmail-msgend msg))
349
(beg (if (progn (goto-char (rmail-msgbeg msg))
350
(search-forward "\n*** EOOH ***\n" next t))
354
(end (progn (search-forward "\n\n" nil t) (point))))
356
(narrow-to-region beg end)
358
(setq line (rmail-make-basic-summary-line)))
359
(goto-char (rmail-msgbeg msg))
361
(insert "Summary-line: " line)))
362
(setq pos (string-match "#" line))
363
(aset rmail-summary-vector (1- msg)
364
(funcall rmail-summary-line-decoder
365
(concat (format "%5d " msg)
366
(substring line 0 pos)
368
(substring line (1+ pos)))))
452
;; Intern so that rmail-read-label can offer completion.
453
(mapc 'rmail-make-label (split-string labels ", "))
454
(format "{ %s } " labels)))))
456
(defun rmail-create-summary (msgnum deleted unseen lines)
457
"Return the summary line for message MSGNUM.
458
The current buffer should already be narrowed to the header for that message.
459
It could be either buffer, so don't access Rmail local variables.
460
DELETED is t if this message is marked deleted.
461
UNSEEN is t if it is marked unseen.
462
LINES is the number of lines in the message (if we should display that)
464
(goto-char (point-min))
465
(let ((line (rmail-header-summary))
466
(labels (rmail-get-summary-labels))
467
pos status prefix basic-start basic-end linecount-string)
469
(setq linecount-string
472
((<= lines 9) (format " [%d]" lines))
473
((<= lines 99) (format " [%d]" lines))
474
((<= lines 999) (format " [%d]" lines))
475
((<= lines 9999) (format " [%dk]" (/ lines 1000)))
476
((<= lines 99999) (format " [%dk]" (/ lines 1000)))
477
(t (format "[%dk]" (/ lines 1000)))))
483
prefix (format "%5d%c " msgnum status)
484
basic-start (car line)
485
basic-end (cadr line))
486
(funcall rmail-summary-line-decoder
487
(concat prefix basic-start linecount-string " "
490
;; FIXME move to rmail.el?
372
492
(defcustom rmail-user-mail-address-regexp nil
373
"*Regexp matching user mail addresses.
493
"Regexp matching user mail addresses.
374
494
If non-nil, this variable is used to identify the correspondent
375
495
when receiving new mail. If it matches the address of the sender,
376
496
the recipient is taken as correspondent of a mail.
386
506
:group 'rmail-retrieve
389
(defun rmail-make-basic-summary-line ()
509
(defun rmail-header-summary ()
510
"Return a message summary based on the message headers.
511
The value is a list of two strings, the first and second parts of the summary.
513
The current buffer must already be narrowed to the message headers for
514
the message being processed."
390
515
(goto-char (point-min))
391
(concat (save-excursion
392
(if (not (re-search-forward "^Date:" nil t))
394
(cond ((re-search-forward "\\([^0-9:]\\)\\([0-3]?[0-9]\\)\\([- \t_]+\\)\\([adfjmnos][aceopu][bcglnprtvy]\\)"
395
(save-excursion (end-of-line) (point)) t)
397
(string-to-number (buffer-substring
401
(match-beginning 4) (match-end 4))))
402
((re-search-forward "\\([^a-z]\\)\\([adfjmnos][acepou][bcglnprtvy]\\)\\([-a-z \t_]*\\)\\([0-9][0-9]?\\)"
403
(save-excursion (end-of-line) (point)) t)
405
(string-to-number (buffer-substring
409
(match-beginning 2) (match-end 2))))
410
((re-search-forward "\\(19\\|20\\)\\([0-9][0-9]\\)-\\([01][0-9]\\)-\\([0-3][0-9]\\)"
411
(save-excursion (end-of-line) (point)) t)
414
(match-beginning 2) (match-end 2))
416
(match-beginning 3) (match-end 3))
418
(match-beginning 4) (match-end 4))))
422
(let* ((from (and (re-search-forward "^From:[ \t]*" nil t)
423
(mail-strip-quoted-names
426
;; Get all the lines of the From field
427
;; so that we get a whole comment if there is one,
428
;; so that mail-strip-quoted-names can discard it.
429
(let ((opoint (point)))
430
(while (progn (forward-line 1)
431
(looking-at "[ \t]")))
432
;; Back up over newline, then trailing spaces or tabs
434
(skip-chars-backward " \t")
439
(or rmail-user-mail-address-regexp
441
(regexp-quote (user-login-name))
444
;; Don't lose if run from init file
445
;; where user-mail-address is not
447
(or user-mail-address
448
(concat (user-login-name) "@"
449
(or mail-host-address
453
;; No From field, or it's this user.
455
(goto-char (point-min))
456
(if (not (re-search-forward "^To:[ \t]*" nil t))
460
(mail-strip-quoted-names
464
(skip-chars-backward " \t")
468
(setq len (length from))
469
(setq mch (string-match "[@%]" from))
471
(if (or (not mch) (<= len 25))
472
(substring from (max 0 (- len 25)))
474
(setq lo (cond ((< (- mch 14) 0) 0)
478
(min len (+ lo 25))))))))
479
(if rmail-summary-line-count-flag
483
(let ((beg (rmail-msgbeg msgnum))
484
(end (rmail-msgend msgnum))
488
;; Count only lines in the reformatted header,
489
;; if we have reformatted it.
490
(search-forward "\n*** EOOH ***\n" end t)
491
(setq lines (count-lines (point) end)))
493
((<= lines 9) " [%d]")
494
((<= lines 99) " [%d]")
495
((<= lines 999) " [%3d]")
499
" #" ;The # is part of the format.
500
(if (re-search-forward "^Subject:" nil t)
501
(progn (skip-chars-forward " \t")
502
(buffer-substring (point)
517
(concat (save-excursion
518
(if (not (re-search-forward "^Date:" nil t))
520
(cond ((re-search-forward "\\([^0-9:]\\)\\([0-3]?[0-9]\\)\\([- \t_]+\\)\\([adfjmnos][aceopu][bcglnprtvy]\\)"
521
(line-end-position) t)
523
(string-to-number (buffer-substring
527
(match-beginning 4) (match-end 4))))
528
((re-search-forward "\\([^a-z]\\)\\([adfjmnos][acepou][bcglnprtvy]\\)\\([-a-z \t_]*\\)\\([0-9][0-9]?\\)"
529
(line-end-position) t)
531
(string-to-number (buffer-substring
535
(match-beginning 2) (match-end 2))))
536
((re-search-forward "\\(19\\|20\\)\\([0-9][0-9]\\)-\\([01][0-9]\\)-\\([0-3][0-9]\\)"
537
(line-end-position) t)
540
(match-beginning 2) (match-end 2))
542
(match-beginning 3) (match-end 3))
544
(match-beginning 4) (match-end 4))))
548
(let* ((from (and (re-search-forward "^From:[ \t]*" nil t)
549
(mail-strip-quoted-names
552
;; Get all the lines of the From field
553
;; so that we get a whole comment if there is one,
554
;; so that mail-strip-quoted-names can discard it.
555
(let ((opoint (point)))
556
(while (progn (forward-line 1)
557
(looking-at "[ \t]")))
558
;; Back up over newline, then trailing spaces or tabs
560
(skip-chars-backward " \t")
565
(or rmail-user-mail-address-regexp
567
(regexp-quote (user-login-name))
570
;; Don't lose if run from init file
571
;; where user-mail-address is not
573
(or user-mail-address
574
(concat (user-login-name) "@"
575
(or mail-host-address
579
;; No From field, or it's this user.
581
(goto-char (point-min))
582
(if (not (re-search-forward "^To:[ \t]*" nil t))
586
(mail-strip-quoted-names
503
589
(progn (end-of-line)
505
(re-search-forward "[\n][\n]+" nil t)
506
(buffer-substring (point) (progn (end-of-line) (point))))
590
(skip-chars-backward " \t")
594
(setq len (length from))
595
(setq mch (string-match "[@%]" from))
597
(if (or (not mch) (<= len 25))
598
(substring from (max 0 (- len 25)))
600
(setq lo (cond ((< (- mch 14) 0) 0)
604
(min len (+ lo 25)))))))))
605
(concat (if (re-search-forward "^Subject:" nil t)
606
(progn (skip-chars-forward " \t")
607
(buffer-substring (point)
610
(re-search-forward "[\n][\n]+" nil t)
611
(buffer-substring (point) (progn (end-of-line) (point))))
509
614
;; Simple motion in a summary buffer.
1646
1794
;; Sorting messages in Rmail Summary buffer.
1648
1796
(defun rmail-summary-sort-by-date (reverse)
1649
"Sort messages of current Rmail summary by date.
1650
If prefix argument REVERSE is non-nil, sort them in reverse order."
1797
"Sort messages of current Rmail summary by \"Date\" header.
1798
If prefix argument REVERSE is non-nil, sorts in reverse order."
1651
1799
(interactive "P")
1652
1800
(rmail-sort-from-summary (function rmail-sort-by-date) reverse))
1654
1802
(defun rmail-summary-sort-by-subject (reverse)
1655
"Sort messages of current Rmail summary by subject.
1656
If prefix argument REVERSE is non-nil, sort them in reverse order."
1803
"Sort messages of current Rmail summary by \"Subject\" header.
1804
Ignores any \"Re: \" prefix. If prefix argument REVERSE is
1805
non-nil, sorts in reverse order."
1657
1806
(interactive "P")
1658
1807
(rmail-sort-from-summary (function rmail-sort-by-subject) reverse))
1660
1809
(defun rmail-summary-sort-by-author (reverse)
1661
1810
"Sort messages of current Rmail summary by author.
1662
If prefix argument REVERSE is non-nil, sort them in reverse order."
1811
This uses either the \"From\" or \"Sender\" header, downcased.
1812
If prefix argument REVERSE is non-nil, sorts in reverse order."
1663
1813
(interactive "P")
1664
1814
(rmail-sort-from-summary (function rmail-sort-by-author) reverse))
1666
1816
(defun rmail-summary-sort-by-recipient (reverse)
1667
1817
"Sort messages of current Rmail summary by recipient.
1668
If prefix argument REVERSE is non-nil, sort them in reverse order."
1818
This uses either the \"To\" or \"Apparently-To\" header, downcased.
1819
If prefix argument REVERSE is non-nil, sorts in reverse order."
1669
1820
(interactive "P")
1670
1821
(rmail-sort-from-summary (function rmail-sort-by-recipient) reverse))
1672
1823
(defun rmail-summary-sort-by-correspondent (reverse)
1673
1824
"Sort messages of current Rmail summary by other correspondent.
1674
If prefix argument REVERSE is non-nil, sort them in reverse order."
1825
This uses either the \"From\", \"Sender\", \"To\", or
1826
\"Apparently-To\" header, downcased. Uses the first header not
1827
excluded by `rmail-dont-reply-to-names'. If prefix argument
1828
REVERSE is non-nil, sorts in reverse order."
1675
1829
(interactive "P")
1676
1830
(rmail-sort-from-summary (function rmail-sort-by-correspondent) reverse))
1678
1832
(defun rmail-summary-sort-by-lines (reverse)
1679
"Sort messages of current Rmail summary by lines of the message.
1680
If prefix argument REVERSE is non-nil, sort them in reverse order."
1833
"Sort messages of current Rmail summary by the number of lines.
1834
If prefix argument REVERSE is non-nil, sorts in reverse order."
1681
1835
(interactive "P")
1682
1836
(rmail-sort-from-summary (function rmail-sort-by-lines) reverse))
1684
1838
(defun rmail-summary-sort-by-labels (reverse labels)
1685
1839
"Sort messages of current Rmail summary by labels.
1686
If prefix argument REVERSE is non-nil, sort them in reverse order.
1687
KEYWORDS is a comma-separated list of labels."
1840
LABELS is a comma-separated list of labels.
1841
If prefix argument REVERSE is non-nil, sorts in reverse order."
1688
1842
(interactive "P\nsSort by labels: ")
1689
1843
(rmail-sort-from-summary
1690
(function (lambda (reverse)
1691
(rmail-sort-by-labels reverse labels)))
1844
(lambda (reverse) (rmail-sort-by-labels reverse labels))
1694
1847
(defun rmail-sort-from-summary (sortfun reverse)
1695
"Sort Rmail messages from Summary buffer and update it after sorting."
1848
"Sort the Rmail buffer using sorting function SORTFUN.
1849
Passes REVERSE to SORTFUN as its sole argument. Then regenerates
1850
the summary. Note that the whole Rmail buffer is sorted, even if
1851
the summary is only showing a subset of messages."
1696
1852
(require 'rmailsort)
1697
1853
(let ((selwin (selected-window)))
1698
1854
(unwind-protect