81
76
(defun mew-sort-insert (line msg)
85
(mew-syntax-change-message-number msg)))
81
(mew-syntax-change-message-number msg))))
83
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
88
(defun mew-summary-sort-move-rename (src dst pos &optional lastp)
89
(rename-file (mew-msg-get-filename src) (mew-msg-new-filename dst))
90
(mew-refile-change src dst)
91
(mew-summary-sort-move src dst pos lastp))
93
(defun mew-summary-sort-move-for-selection (src dst pos &optional lastp)
94
(mew-summary-sort-move src nil pos lastp))
87
96
;; If not found, returns nil.
88
(defun mew-summary-sort-rename (src dst pos &optional lastp)
91
(insert (format "move %s to %s\n" src dst)))
97
(defun mew-summary-sort-move (src dst pos &optional lastp)
104
(mew-sort-insert mew-sort-line dst)
107
(when (mew-summary-search-msg src)
111
;; We need to keep properties in Summary mode.
112
;; This must be "buffer-substring".
113
(setq mew-sort-line (buffer-substring beg end))
114
(delete-region beg end)
117
(when (mew-summary-search-msg src)
123
;; We need to keep properties in Summary mode.
124
;; This must be "buffer-substring".
125
(setq line (buffer-substring beg end))
127
(delete-region beg end)
130
(mew-sort-insert line dst))
133
;; We need to keep properties in Summary mode.
134
;; This must be "buffer-substring".
135
(setq line (buffer-substring beg end))
136
(delete-region beg end)
138
(mew-sort-insert line dst)
141
;; We need to keep properties in Summary mode.
142
;; This must be "buffer-substring".
143
(setq line (buffer-substring beg end))
145
(mew-sort-insert line dst)
146
(delete-region beg end)
149
(defun mew-summary-sort-move-for-debug (src dst pos &optional lastp)
151
(insert (format "move %s to %s\n" src dst))))
153
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
158
(defun mew-sort-get-range (arg)
159
(let (region beg end range rbeg rend)
162
(setq region (mew-summary-get-region))
163
(setq beg (car region))
164
(setq end (cdr region))
165
(if (= beg end) (error "No region")))
166
(setq beg (point-min))
167
(setq end (point-max)))
170
(setq rbeg (mew-summary-message-number))
173
(setq rend (mew-summary-message-number))
176
(setq range (concat rbeg "-" rend))
177
(error "No region")))
178
(list range beg end)))
180
(defun mew-sort-ask-key (folder)
181
(let* ((sort-key (or (mew-alist-get-value
182
(assoc folder mew-sort-default-key-alist))
183
mew-sort-default-key))
184
key type funcs newkey)
185
(mew-set '(key type) (mew-input-sort-key sort-key))
186
(setq funcs (assoc type mew-sort-switch))
187
(setq newkey (concat (capitalize key) ":"))
188
(cons newkey (cdr funcs))))
190
(defun mew-sort-get-file-index (folder range key func1 func2)
192
(fld (mew-expand-folder2 folder))
193
num med value ent files idx)
196
mew-prog-mewl nil t nil
197
(append (list "-b" mew-mail-path "-l" "0"
200
(mew-scan-mewl-src fld range)))
201
(goto-char (point-min))
203
(if (not (looking-at "^\\([0-9]+\\)[ \t]*:[ \t]*"))
205
(setq num (mew-match-string 1))
206
(setq med (match-end 0))
208
(mew-header-goto-next)
209
(mew-header-decode-region key med (point))
210
(setq value (mew-buffer-substring med (1- (point))))
211
(setq files (cons num files))
212
(setq ent (cons (cons i (funcall func1 value folder num)) ent))
214
(setq files (vconcat (nreverse files)))
215
(setq ent (sort ent func2))
216
(setq idx (vconcat (mapcar 'mew-sort-index ent)))
219
(defun mew-sort-files (folder files idx func)
222
;; files idx -> files
235
;; *a: initial src is 0
236
;; *b: initial files[dst] is 31 (new tmp file)
237
;; *c: break condition, src is looped!
238
;; files[src] is 31 (new tmp file)
240
(let* ((dir (mew-expand-folder folder))
241
(default-directory dir)
242
(len (length idx)) ;; not (length files)
243
(tmp (mew-folder-new-message folder 'num-only))
246
(setq mew-sort-line nil)
247
(unless (= i (aref idx i))
250
(setq pos (funcall func (aref files src) tmp nil))
254
(setq src (aref idx dst))
255
(if (= src i) (throw 'loop nil))
256
(setq pos (funcall func (aref files src) (aref files dst) pos))
258
(funcall func tmp (aref files dst) pos 'last)
259
(aset idx dst dst)))))
261
(defun mew-sort-push-mark ()
94
(rename-file (mew-msg-get-filename src) (mew-msg-new-filename dst))
95
(mew-refile-change src dst)
100
(mew-sort-insert mew-sort-line dst)
103
(when (mew-summary-search-msg src)
107
;; We need to keep properties in Summary mode.
108
;; This must be "buffer-substring".
109
(setq mew-sort-line (buffer-substring beg end))
110
(delete-region beg end)
113
(when (mew-summary-search-msg src)
119
;; We need to keep properties in Summary mode.
120
;; This must be "buffer-substring".
121
(setq line (buffer-substring beg end))
123
(delete-region beg end)
126
(mew-sort-insert line dst))
129
;; We need to keep properties in Summary mode.
130
;; This must be "buffer-substring".
131
(setq line (buffer-substring beg end))
132
(delete-region beg end)
134
(mew-sort-insert line dst)
137
;; We need to keep properties in Summary mode.
138
;; This must be "buffer-substring".
139
(setq line (buffer-substring beg end))
141
(mew-sort-insert line dst)
142
(delete-region beg end)
265
(put-text-property (point) (1+ (point)) 'mew-sort-orig t))))
267
(defun mew-sort-pop-mark ()
268
(let ((orig (next-single-property-change (point-min) 'mew-sort-orig)))
269
;; 'mew-sort-orig may start with bob.
277
;; 'mew-sort-orig is copied onto the entire message
278
;; number. (window-width) is long enough to remove
280
(remove-text-properties
281
orig (+ orig (window-width)) '(mew-sort-orig nil)))
284
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
289
(defun mew-summary-sort-body (folder arg)
290
(let (key idx files range beg end func1 func2 diag)
291
;; Summary cache updates
293
(mew-summary-retrieve-gap folder)
295
(mew-set '(range beg end) (mew-sort-get-range arg))
296
(mew-set '(key func1 func2) (mew-sort-ask-key folder))
297
(setq diag (if arg folder (format "%s: %s" folder range)))
299
(message "Sorting %s..." diag)
300
(mew-summary-lock t "Sorting")
303
(mew-set '(files idx) (mew-sort-get-file-index folder range key func1 func2))
306
(if arg (narrow-to-region beg end))
308
(mew-sort-files folder files idx 'mew-summary-sort-move-rename)
310
(goto-char (point-min))
314
(run-hooks 'mew-sort-hook)
315
(message "Sorting %s...done. Type '%s' to update ID database" diag (mew-substitute-for-summary "\\[mew-summary-make-id-index-folder]")))
316
(mew-summary-folder-cache-save)
317
(set-buffer-modified-p nil)
318
(mew-summary-unlock))))
320
(defun mew-summary-sort-body-for-debug (folder arg)
321
(let ((win (selected-window))
322
key idx files range func1 func2 diag)
323
(mew-set '(range beg end) (mew-sort-get-range arg))
324
(mew-set '(key func1 func2) (mew-sort-ask-key folder))
325
(setq diag (if arg folder (format "%s: %s" folder range)))
327
(message "Sorting %s..." diag)
328
(mew-summary-lock t "Sorting")
330
(mew-set '(files idx) (mew-sort-get-file-index folder range key func1 func2))
331
(mew-summary-unlock))
332
(when (and files idx)
333
(mew-window-configure 'message)
337
(insert "Sort as follows:\n"))
341
(mew-sort-files folder files idx 'mew-summary-sort-move-for-debug)
342
(message "Sorting %s...done" diag))
343
(mew-message-clear-end-of)
344
(set-buffer-modified-p nil)
345
(goto-char (point-min))
346
(select-window win)))))
348
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
145
353
(defun mew-summary-sort (&optional arg)
146
354
"Sort messages and list them up again.
147
355
If called with '\\[universal-argument]', sort the region.
148
356
After sorting, the cursor moves onto the beginning of the buffer
151
If this command is used in a remote folder, local cache messages are
152
sorted. But if you do so, '\\<mew-summary-mode-map>\\[mew-summary-ls]' + 'sync' would not work well."
153
358
(interactive "P")
154
359
(mew-summary-only
155
360
(mew-summary-local-only
161
366
(if (null folder)
162
367
(message "No message")
163
368
(if (mew-mark-active-p) (setq arg t))
164
(mew-summary-sort-body folder arg))))))))))
166
(defun mew-summary-sort-body (folder arg)
167
(let ((win (selected-window))
168
key type idx files range beg end)
170
;; Summary cache updates
173
(mew-summary-retrieve-gap folder)
177
(let (region rbeg rend)
369
(if (mew-debug 'sort)
370
(mew-summary-sort-body-for-debug folder arg)
371
(mew-summary-sort-body folder arg)))))))))))
373
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
375
;;; Sort for selection
378
(defun mew-summary-selection-by-sort-body (arg)
379
(let* ((buf (current-buffer))
380
(ofolder (mew-summary-folder-name 'ext))
381
(vfolder (mew-folder-to-selection ofolder))
382
(pfolder (mew-summary-physical-folder))
383
key idx files range beg end func1 func2 diag)
384
(mew-set '(range beg end) (mew-sort-get-range arg))
385
(mew-set '(key func1 func2) (mew-sort-ask-key ofolder))
386
(setq diag (if arg ofolder (format "%s: %s" ofolder range)))
388
(message "Sorting %s..." diag)
389
(mew-summary-lock t "Sorting")
391
(mew-set '(files idx) (mew-sort-get-file-index ofolder range key func1 func2))
392
(mew-summary-unlock))
393
(when (and files idx)
394
(mew-summary-switch-to-folder vfolder)
395
(mew-vinfo-set-mode 'selection)
396
(mew-vinfo-set-physical-folder pfolder)
397
(mew-vinfo-set-original-folder ofolder)
180
(setq region (mew-summary-get-region))
181
(setq beg (car region))
182
(setq end (cdr region))
183
(if (= beg end) (error "No region")))
184
(setq beg (point-min))
185
(setq end (point-max)))
187
(setq rbeg (mew-summary-message-number))
190
(setq rend (mew-summary-message-number))
193
(setq range (concat rbeg "-" rend))
194
(error "No region")))
196
;; Asking a sort key after range
198
(let* ((sort-key (or (cdr (assoc folder mew-sort-default-key-alist))
199
mew-sort-default-key))
200
(key-type (mew-input-sort-key sort-key)))
201
(setq type (cdr key-type))
202
(setq key (concat (capitalize (car key-type)) ":")))
205
(message "Sorting %s: %s..." folder range)
206
(message "Sorting %s..." folder))
207
(mew-summary-lock t "Sorting")
213
(let* ((funcs (assoc type mew-sort-switch))
214
(func1 (nth 1 funcs))
215
(func2 (nth 2 funcs))
217
(fld (mew-expand-folder2 folder))
221
mew-prog-mewl nil t nil
222
(append (list "-b" mew-mail-path "-l" "0"
225
(mew-scan-mewl-src fld range)))
226
(goto-char (point-min))
228
(if (not (looking-at "^\\([0-9]+\\)[ \t]*:[ \t]*"))
230
(setq num (mew-match-string 1))
231
(setq med (match-end 0))
233
(mew-header-goto-next)
234
(mew-header-decode-region key med (point))
235
(setq value (mew-buffer-substring med (1- (point))))
236
(setq files (cons num files))
237
(setq ent (cons (cons i (funcall func1 value folder num)) ent))
239
(setq files (vconcat (nreverse files)))
240
(setq ent (sort ent func2))
241
(setq idx (vconcat (mapcar 'mew-sort-index ent))))
243
(when (mew-debug 'sort)
244
(mew-window-configure 'message)
248
(insert "Sort as follows:\n")))
249
(when (and (not (mew-debug 'sort)) (not (eobp)))
252
(put-text-property (point) (1+ (point)) 'mew-sort-orig t)))
254
(if arg (narrow-to-region beg end))
257
;; files idx -> files
270
;; *a: initial src is 0
271
;; *b: initial files[dst] is 31 (new tmp file)
272
;; *c: break condition, src is looped!
273
;; files[src] is 31 (new tmp file)
275
(let* ((dir (mew-expand-folder folder))
276
(default-directory dir)
277
(len (length idx)) ;; not (length files)
278
(tmp (mew-folder-new-message folder 'num-only))
282
(setq mew-sort-line nil)
283
(unless (= i (aref idx i))
286
(setq pos (mew-summary-sort-rename (aref files src) tmp nil))
290
(setq src (aref idx dst))
291
(if (= src i) (throw 'loop nil))
292
(setq pos (mew-summary-sort-rename (aref files src) (aref files dst) pos))
294
(mew-summary-sort-rename tmp (aref files dst) pos 'last)
297
;; The cursor moves onto point-min of the region.
298
(unless (mew-debug 'sort)
299
(goto-char (point-min)))
304
(mew-message-clear-end-of)
305
(set-buffer-modified-p nil)
306
(goto-char (point-min))
309
(let ((orig (next-single-property-change
310
(point-min) 'mew-sort-orig)))
311
;; 'mew-sort-orig may start with bob.
319
;; 'mew-sort-orig is copied onto the entire message
320
;; number. (window-width) is long enough to remove
322
(remove-text-properties
323
orig (+ orig (window-width)) '(mew-sort-orig nil)))
325
(mew-summary-folder-cache-save)
326
(set-buffer-modified-p nil)))
329
(unless (mew-debug 'sort)
330
(run-hooks 'mew-sort-hook))
332
(message "Sorting %s: %s...done" folder range)
333
(message "Sorting %s...done" folder)))
336
(set-buffer-modified-p nil)
337
(mew-summary-unlock)))))
402
(insert (save-excursion (set-buffer buf) (buffer-substring beg end)))
403
(mew-sort-files ofolder files idx 'mew-summary-sort-move-for-selection)
404
(mew-summary-set-count-line)
405
(goto-char (point-min))
406
(message "Sorting %s...done" diag)))
407
(set-buffer-modified-p nil)))))
409
(defun mew-summary-selection-by-sort (&optional arg)
412
(mew-summary-not-in-queue
413
(mew-summary-not-in-draft
414
(mew-summary-with-mewl
415
(when (mew-summary-exclusive-p)
416
(if (mew-mark-active-p) (setq arg t))
417
(mew-summary-selection-by-sort-body arg)))))))
339
419
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;