Mercurial > emacs
comparison lisp/mail/rmailsort.el @ 3133:2c1553d7aad1
New version from Umeda. Needs detailed entry.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Wed, 26 May 1993 20:28:11 +0000 |
parents | 3b0a06fc7c4b |
children | fab096be7274 |
comparison
equal
deleted
inserted
replaced
3132:e32cef1a19b7 | 3133:2c1553d7aad1 |
---|---|
1 ;;; rmailsort.el --- Rmail: sort messages. | 1 ;;; rmailsort.el --- Rmail: sort messages. |
2 | 2 |
3 ;; Copyright (C) 1990 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1990, 1993 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp> | |
6 ;; Version: $Header: rmailsort.el,v 1.6 93/05/26 22:24:42 umerin Exp $ | |
5 ;; Keywords: mail | 7 ;; Keywords: mail |
6 | 8 |
7 ;; This file is part of GNU Emacs. | 9 ;; This file is part of GNU Emacs. |
8 | 10 |
9 ;; GNU Emacs is free software; you can redistribute it and/or modify | 11 ;; GNU Emacs is free software; you can redistribute it and/or modify |
18 | 20 |
19 ;; You should have received a copy of the GNU General Public License | 21 ;; You should have received a copy of the GNU General Public License |
20 ;; along with GNU Emacs; see the file COPYING. If not, write to | 22 ;; along with GNU Emacs; see the file COPYING. If not, write to |
21 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 23 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
22 | 24 |
25 ;;; Commentary: | |
26 | |
27 ;; LCD Archive Entry: | |
28 ;; rmailsort|Masanobu UMEDA|umerin@mse.kyutech.ac.jp| | |
29 ;; Rmail: sort messages.| | |
30 ;; $Date: 93/05/26 22:24:42 $|$Revision: 1.6 $|~/misc/rmailsort.el.Z| | |
31 | |
23 ;;; Code: | 32 ;;; Code: |
24 | 33 |
25 (require 'rmail) | 34 (require 'rmail) |
26 (require 'sort) | 35 (require 'sort) |
27 | 36 |
37 (autoload 'timezone-make-date-sortable "timezone") | |
38 | |
28 ;; GNUS compatible key bindings. | 39 ;; GNUS compatible key bindings. |
40 | |
29 (define-key rmail-mode-map "\C-c\C-s\C-d" 'rmail-sort-by-date) | 41 (define-key rmail-mode-map "\C-c\C-s\C-d" 'rmail-sort-by-date) |
30 (define-key rmail-mode-map "\C-c\C-s\C-s" 'rmail-sort-by-subject) | 42 (define-key rmail-mode-map "\C-c\C-s\C-s" 'rmail-sort-by-subject) |
31 (define-key rmail-mode-map "\C-c\C-s\C-a" 'rmail-sort-by-author) | 43 (define-key rmail-mode-map "\C-c\C-s\C-a" 'rmail-sort-by-author) |
32 (define-key rmail-mode-map "\C-c\C-s\C-r" 'rmail-sort-by-recipient) | 44 (define-key rmail-mode-map "\C-c\C-s\C-r" 'rmail-sort-by-recipient) |
33 (define-key rmail-mode-map "\C-c\C-s\C-c" 'rmail-sort-by-correspondent) | 45 (define-key rmail-mode-map "\C-c\C-s\C-c" 'rmail-sort-by-correspondent) |
34 (define-key rmail-mode-map "\C-c\C-s\C-l" 'rmail-sort-by-size-lines) | 46 (define-key rmail-mode-map "\C-c\C-s\C-l" 'rmail-sort-by-lines) |
47 | |
48 ;; Key binding may not be installed unless Rmail Summary mode is loaded. | |
49 (if (boundp 'rmail-summary-mode-map) | |
50 (progn | |
51 (define-key rmail-summary-mode-map | |
52 "\C-c\C-s\C-d" 'rmail-summary-sort-by-date) | |
53 (define-key rmail-summary-mode-map | |
54 "\C-c\C-s\C-s" 'rmail-summary-sort-by-subject) | |
55 (define-key rmail-summary-mode-map | |
56 "\C-c\C-s\C-a" 'rmail-summary-sort-by-author) | |
57 (define-key rmail-summary-mode-map | |
58 "\C-c\C-s\C-r" 'rmail-summary-sort-by-recipient) | |
59 (define-key rmail-summary-mode-map | |
60 "\C-c\C-s\C-c" 'rmail-summary-sort-by-correspondent) | |
61 (define-key rmail-summary-mode-map | |
62 "\C-c\C-s\C-l" 'rmail-summary-sort-by-lines) | |
63 )) | |
64 | |
65 | |
66 ;; Sorting messages in Rmail buffer | |
35 | 67 |
36 (defun rmail-sort-by-date (reverse) | 68 (defun rmail-sort-by-date (reverse) |
37 "Sort messages of current Rmail file by date. | 69 "Sort messages of current Rmail file by date. |
38 If prefix argument REVERSE is non-nil, sort them in reverse order." | 70 If prefix argument REVERSE is non-nil, sort them in reverse order." |
39 (interactive "P") | 71 (interactive "P") |
40 (rmail-sort-messages reverse | 72 (rmail-sort-messages reverse |
41 (function | 73 (function |
42 (lambda (msg) | 74 (lambda (msg) |
43 (rmail-sortable-date-string | 75 (rmail-make-date-sortable |
44 (rmail-fetch-field msg "Date")))))) | 76 (rmail-fetch-field msg "Date")))))) |
45 | 77 |
46 (defun rmail-sort-by-subject (reverse) | 78 (defun rmail-sort-by-subject (reverse) |
47 "Sort messages of current Rmail file by subject. | 79 "Sort messages of current Rmail file by subject. |
48 If prefix argument REVERSE is non-nil, sort them in reverse order." | 80 If prefix argument REVERSE is non-nil, sort them in reverse order." |
61 If prefix argument REVERSE is non-nil, sort them in reverse order." | 93 If prefix argument REVERSE is non-nil, sort them in reverse order." |
62 (interactive "P") | 94 (interactive "P") |
63 (rmail-sort-messages reverse | 95 (rmail-sort-messages reverse |
64 (function | 96 (function |
65 (lambda (msg) | 97 (lambda (msg) |
66 (mail-strip-quoted-names | 98 (downcase ;Canonical name |
67 (or (rmail-fetch-field msg "From") | 99 (mail-strip-quoted-names |
68 (rmail-fetch-field msg "Sender") "")))))) | 100 (or (rmail-fetch-field msg "From") |
101 (rmail-fetch-field msg "Sender") ""))))))) | |
69 | 102 |
70 (defun rmail-sort-by-recipient (reverse) | 103 (defun rmail-sort-by-recipient (reverse) |
71 "Sort messages of current Rmail file by recipient. | 104 "Sort messages of current Rmail file by recipient. |
72 If prefix argument REVERSE is non-nil, sort them in reverse order." | 105 If prefix argument REVERSE is non-nil, sort them in reverse order." |
73 (interactive "P") | 106 (interactive "P") |
74 (rmail-sort-messages reverse | 107 (rmail-sort-messages reverse |
75 (function | 108 (function |
76 (lambda (msg) | 109 (lambda (msg) |
77 (mail-strip-quoted-names | 110 (downcase ;Canonical name |
78 (or (rmail-fetch-field msg "To") | 111 (mail-strip-quoted-names |
79 (rmail-fetch-field msg "Apparently-To") "") | 112 (or (rmail-fetch-field msg "To") |
80 ))))) | 113 (rmail-fetch-field msg "Apparently-To") "") |
114 )))))) | |
81 | 115 |
82 (defun rmail-sort-by-correspondent (reverse) | 116 (defun rmail-sort-by-correspondent (reverse) |
83 "Sort messages of current Rmail file by other correspondent. | 117 "Sort messages of current Rmail file by other correspondent. |
84 If prefix argument REVERSE is non-nil, sort them in reverse order." | 118 If prefix argument REVERSE is non-nil, sort them in reverse order." |
85 (interactive "P") | 119 (interactive "P") |
90 msg | 124 msg |
91 '("From" "Sender" "To" "Apparently-To")))))) | 125 '("From" "Sender" "To" "Apparently-To")))))) |
92 | 126 |
93 (defun rmail-select-correspondent (msg fields) | 127 (defun rmail-select-correspondent (msg fields) |
94 (let ((ans "")) | 128 (let ((ans "")) |
95 (while (and fields (string= ans "")) | 129 (while (and fields (string= ans "")) |
96 (setq ans | 130 (setq ans |
97 (rmail-dont-reply-to | 131 (rmail-dont-reply-to |
98 (mail-strip-quoted-names | 132 (mail-strip-quoted-names |
99 (or (rmail-fetch-field msg (car fields)) "")))) | 133 (or (rmail-fetch-field msg (car fields)) "")))) |
100 (setq fields (cdr fields))) | 134 (setq fields (cdr fields))) |
101 ans)) | 135 ans)) |
102 | 136 |
103 (defun rmail-sort-by-size-lines (reverse) | 137 (defun rmail-sort-by-lines (reverse) |
104 "Sort messages of current Rmail file by message size. | 138 "Sort messages of current Rmail file by lines of the message. |
105 If prefix argument REVERSE is non-nil, sort them in reverse order." | 139 If prefix argument REVERSE is non-nil, sort them in reverse order." |
106 (interactive "P") | 140 (interactive "P") |
107 (rmail-sort-messages reverse | 141 (rmail-sort-messages reverse |
108 (function | 142 (function |
109 (lambda (msg) | 143 (lambda (msg) |
110 (format "%9d" | 144 (count-lines (rmail-msgbeg msgnum) |
111 (count-lines (rmail-msgbeg msgnum) | 145 (rmail-msgend msgnum)))))) |
112 (rmail-msgend msgnum))))))) | |
113 | 146 |
114 | 147 ;; Sorting messages in Rmail Summary buffer. |
115 (defun rmail-sort-messages (reverse keyfunc) | 148 |
149 (defun rmail-summary-sort-by-date (reverse) | |
150 "Sort messages of current Rmail summary by date. | |
151 If prefix argument REVERSE is non-nil, sort them in reverse order." | |
152 (interactive "P") | |
153 (rmail-sort-from-summary (function rmail-sort-by-date) reverse)) | |
154 | |
155 (defun rmail-summary-sort-by-subject (reverse) | |
156 "Sort messages of current Rmail summary by subject. | |
157 If prefix argument REVERSE is non-nil, sort them in reverse order." | |
158 (interactive "P") | |
159 (rmail-sort-from-summary (function rmail-sort-by-subject) reverse)) | |
160 | |
161 (defun rmail-summary-sort-by-author (reverse) | |
162 "Sort messages of current Rmail summary by author. | |
163 If prefix argument REVERSE is non-nil, sort them in reverse order." | |
164 (interactive "P") | |
165 (rmail-sort-from-summary (function rmail-sort-by-author) reverse)) | |
166 | |
167 (defun rmail-summary-sort-by-recipient (reverse) | |
168 "Sort messages of current Rmail summary by recipient. | |
169 If prefix argument REVERSE is non-nil, sort them in reverse order." | |
170 (interactive "P") | |
171 (rmail-sort-from-summary (function rmail-sort-by-recipient) reverse)) | |
172 | |
173 (defun rmail-summary-sort-by-correspondent (reverse) | |
174 "Sort messages of current Rmail summary by other correspondent. | |
175 If prefix argument REVERSE is non-nil, sort them in reverse order." | |
176 (interactive "P") | |
177 (rmail-sort-from-summary (function rmail-sort-by-correspondent) reverse)) | |
178 | |
179 (defun rmail-summary-sort-by-lines (reverse) | |
180 "Sort messages of current Rmail summary by lines of the message. | |
181 If prefix argument REVERSE is non-nil, sort them in reverse order." | |
182 (interactive "P") | |
183 (rmail-sort-from-summary (function rmail-sort-by-lines) reverse)) | |
184 | |
185 | |
186 ;; Basic functions | |
187 | |
188 (defun rmail-sort-messages (reverse keyfun) | |
116 "Sort messages of current Rmail file. | 189 "Sort messages of current Rmail file. |
117 1st argument REVERSE is non-nil, sort them in reverse order. | 190 If 1st argument REVERSE is non-nil, sort them in reverse order. |
118 2nd argument KEYFUNC is called with message number, and should return a key." | 191 2nd argument KEYFUN is called with a message number, and should return a key." |
119 (or (eq major-mode 'rmail-mode) | |
120 (error "Current buffer not in Rmail mode")) | |
121 (let ((buffer-read-only nil) | 192 (let ((buffer-read-only nil) |
193 (predicate nil) ;< or string-lessp | |
122 (sort-lists nil)) | 194 (sort-lists nil)) |
123 (message "Finding sort keys...") | 195 (message "Finding sort keys...") |
124 (widen) | 196 (widen) |
125 (let ((msgnum 1)) | 197 (let ((msgnum 1)) |
126 (while (>= rmail-total-messages msgnum) | 198 (while (>= rmail-total-messages msgnum) |
127 (setq sort-lists | 199 (setq sort-lists |
128 (cons (cons (funcall keyfunc msgnum) ;A sort key. | 200 (cons (list (funcall keyfun msgnum) ;Make sorting key |
129 (buffer-substring | 201 (eq rmail-current-message msgnum) ;True if current |
130 (rmail-msgbeg msgnum) (rmail-msgend msgnum))) | 202 (aref rmail-message-vector msgnum) |
203 (aref rmail-message-vector (1+ msgnum))) | |
131 sort-lists)) | 204 sort-lists)) |
132 (if (zerop (% msgnum 10)) | 205 (if (zerop (% msgnum 10)) |
133 (message "Finding sort keys...%d" msgnum)) | 206 (message "Finding sort keys...%d" msgnum)) |
134 (setq msgnum (1+ msgnum)))) | 207 (setq msgnum (1+ msgnum)))) |
135 (or reverse (setq sort-lists (nreverse sort-lists))) | 208 (or reverse (setq sort-lists (nreverse sort-lists))) |
209 ;; Decide predicate: < or string-lessp | |
210 (if (numberp (car (car sort-lists))) ;Is a key numeric? | |
211 (setq predicate (function <)) | |
212 (setq predicate (function string-lessp))) | |
136 (setq sort-lists | 213 (setq sort-lists |
137 (sort sort-lists | 214 (sort sort-lists |
138 (function | 215 (function |
139 (lambda (a b) | 216 (lambda (a b) |
140 (string-lessp (car a) (car b)))))) | 217 (funcall predicate (car a) (car b)))))) |
141 (if reverse (setq sort-lists (nreverse sort-lists))) | 218 (if reverse (setq sort-lists (nreverse sort-lists))) |
142 (message "Reordering buffer...") | 219 ;; Now we enter critical region. So, keyboard quit is disabled. |
143 (delete-region (rmail-msgbeg 1) (rmail-msgend rmail-total-messages)) | 220 (message "Reordering messages...") |
144 (let ((msgnum 1)) | 221 (let ((inhibit-quit t) ;Inhibit quit |
222 (current-message nil) | |
223 (msgnum 1) | |
224 (msginfo nil)) | |
225 ;; There's little hope that we can easily undo after that. | |
226 (buffer-flush-undo (current-buffer)) | |
227 (goto-char (rmail-msgbeg 1)) | |
228 ;; To force update of all markers. | |
229 (insert-before-markers ?Z) | |
230 (backward-char 1) | |
231 ;; Now reorder messages. | |
145 (while sort-lists | 232 (while sort-lists |
146 (insert (cdr (car sort-lists))) | 233 (setq msginfo (car sort-lists)) |
234 ;; Swap two messages. | |
235 (insert-buffer-substring | |
236 (current-buffer) (nth 2 msginfo) (nth 3 msginfo)) | |
237 (delete-region (nth 2 msginfo) (nth 3 msginfo)) | |
238 ;; Is current message? | |
239 (if (nth 1 msginfo) | |
240 (setq current-message msgnum)) | |
241 (setq sort-lists (cdr sort-lists)) | |
147 (if (zerop (% msgnum 10)) | 242 (if (zerop (% msgnum 10)) |
148 (message "Reordering buffer...%d" msgnum)) | 243 (message "Reordering messages...%d" msgnum)) |
149 (setq sort-lists (cdr sort-lists)) | 244 (setq msgnum (1+ msgnum))) |
150 (setq msgnum (1+ msgnum)))) | 245 ;; Delete the garbage inserted before. |
151 (rmail-set-message-counters) | 246 (delete-char 1) |
152 (rmail-show-message 1))) | 247 (setq quit-flag nil) |
248 (buffer-enable-undo) | |
249 (rmail-set-message-counters) | |
250 (rmail-show-message current-message)) | |
251 )) | |
252 | |
253 (defun rmail-sort-from-summary (sortfun reverse) | |
254 "Sort Rmail messages from Summary buffer and update it after sorting." | |
255 (pop-to-buffer rmail-buffer) | |
256 (funcall sortfun reverse) | |
257 (rmail-summary)) | |
153 | 258 |
154 (defun rmail-fetch-field (msg field) | 259 (defun rmail-fetch-field (msg field) |
155 "Return the value of the header field FIELD of MSG. | 260 "Return the value of the header FIELD of MSG. |
156 Arguments are MSG and FIELD." | 261 Arguments are MSG and FIELD." |
157 (let ((next (rmail-msgend msg))) | 262 (save-restriction |
158 (save-restriction | 263 (widen) |
264 (let ((next (rmail-msgend msg))) | |
159 (goto-char (rmail-msgbeg msg)) | 265 (goto-char (rmail-msgbeg msg)) |
160 (narrow-to-region (if (search-forward "\n*** EOOH ***\n" next t) | 266 (narrow-to-region (if (search-forward "\n*** EOOH ***\n" next t) |
161 (point) | 267 (point) |
162 (forward-line 1) | 268 (forward-line 1) |
163 (point)) | 269 (point)) |
164 (progn (search-forward "\n\n" nil t) (point))) | 270 (progn (search-forward "\n\n" nil t) (point))) |
165 (mail-fetch-field field)))) | 271 (mail-fetch-field field)))) |
166 | 272 |
167 ;; Copy of the function gnus-comparable-date in gnus.el | 273 (defun rmail-make-date-sortable (date) |
168 | 274 "Make DATE sortable using the function string-lessp." |
169 (defun rmail-sortable-date-string (date) | 275 ;; Assume the default time zone is GMT. |
170 "Make sortable string by string-lessp from DATE." | 276 (timezone-make-date-sortable date "GMT" "GMT")) |
171 (let ((month '(("JAN" . " 1")("FEB" . " 2")("MAR" . " 3") | 277 |
172 ("APR" . " 4")("MAY" . " 5")("JUN" . " 6") | 278 ;; Copy of the function gnus-comparable-date in gnus.el version 3.13 |
173 ("JUL" . " 7")("AUG" . " 8")("SEP" . " 9") | 279 ; |
174 ("OCT" . "10")("NOV" . "11")("DEC" . "12") | 280 ;(defun rmail-make-date-sortable (date) |
175 ("JANUARY" . " 1") ("FEBRUARY" . " 2") | 281 ; "Make sortable string by string-lessp from DATE." |
176 ("MARCH" . " 3") ("APRIL" . " 4") | 282 ; (let ((month '(("JAN" . " 1")("FEB" . " 2")("MAR" . " 3") |
177 ("MAY" . " 5") ("JUNE" . " 6") | 283 ; ("APR" . " 4")("MAY" . " 5")("JUN" . " 6") |
178 ("JULY" . " 7") ("AUGUST" . " 8") | 284 ; ("JUL" . " 7")("AUG" . " 8")("SEP" . " 9") |
179 ("SEPTEMBER" " 9") ("OCTOBER" . "10") | 285 ; ("OCT" . "10")("NOV" . "11")("DEC" . "12"))) |
180 ("NOVEMBER" "11") ("DECEMBER" . "12"))) | 286 ; (date (or date ""))) |
181 (date (or date ""))) | 287 ; ;; Can understand the following styles: |
182 ;; Can understand the following styles: | 288 ; ;; (1) 14 Apr 89 03:20:12 GMT |
183 ;; (1) 14 Apr 89 03:20:12 GMT | 289 ; ;; (2) Fri, 17 Mar 89 4:01:33 GMT |
184 ;; (2) Fri, 17 Mar 89 4:01:33 GMT | 290 ; (if (string-match |
185 (if (string-match | 291 ; "\\([0-9]+\\) \\([^ ,]+\\) \\([0-9]+\\) \\([0-9:]+\\)" date) |
186 "\\([0-9]+\\) +\\([^ ,]+\\) +\\([0-9]+\\) +\\([0-9:]+\\)" date) | 292 ; (concat |
187 (concat | 293 ; ;; Year |
188 ;; Year | 294 ; (substring date (match-beginning 3) (match-end 3)) |
189 (rmail-date-full-year | 295 ; ;; Month |
190 (substring date (match-beginning 3) (match-end 3))) | 296 ; (cdr |
191 ;; Month | 297 ; (assoc |
192 (cdr | 298 ; (upcase (substring date (match-beginning 2) (match-end 2))) month)) |
193 (assoc | 299 ; ;; Day |
194 (upcase (substring date (match-beginning 2) (match-end 2))) month)) | 300 ; (format "%2d" (string-to-int |
195 ;; Day | 301 ; (substring date |
196 (format "%2d" (string-to-int | 302 ; (match-beginning 1) (match-end 1)))) |
197 (substring date | 303 ; ;; Time |
198 (match-beginning 1) (match-end 1)))) | 304 ; (substring date (match-beginning 4) (match-end 4))) |
199 ;; Time | 305 ; ;; Cannot understand DATE string. |
200 (substring date (match-beginning 4) (match-end 4))) | 306 ; date |
201 | 307 ; ) |
202 ;; Handles this format Fri May 10 21:51:55 1991 | 308 ; )) |
203 (if (string-match | |
204 " \\([a-z][a-z][a-z]\\) +\\([0-9]+\\) \\([0-9:]+\\) \\([0-9]+\\)" date) | |
205 (concat | |
206 ;; Year | |
207 (rmail-date-full-year | |
208 (substring date (match-beginning 4) (match-end 4))) | |
209 ;; Month | |
210 (cdr | |
211 (assoc | |
212 (upcase (substring date (match-beginning 1) (match-end 1))) month)) | |
213 ;; Day | |
214 (format "%2d" (string-to-int | |
215 (substring date | |
216 (match-beginning 2) (match-end 2)))) | |
217 ;; Time | |
218 (substring date (match-beginning 3) (match-end 3))) | |
219 | |
220 ;; Cannot understand DATE string. | |
221 date)))) | |
222 | |
223 (defun rmail-date-full-year (year-string) | |
224 (if (<= (length year-string) 2) | |
225 (concat "19" year-string) | |
226 year-string)) | |
227 | 309 |
228 (provide 'rmailsort) | 310 (provide 'rmailsort) |
229 | 311 |
230 ;;; rmailsort.el ends here | 312 ;;; rmailsort.el ends here |