[Mew-dist 11958] mew-sort.el w/o imsort

Masaki KONUMA masak at example.com
1999年 12月 30日 (木) 23:31:09 JST


Subject: [Mew-dist 11724] Re: mls
A> メッセージのヘッダをなめる imsort、imgrep は C で書きたい。

には反しますが、imsort 相当を elisp で書いてみました。

注意:
o 変数 mew-use-imsort が nil でなければ imsort を使用します。
o 速くなるとは限りません。perl が軽いマシンでは遅くなるはず。
o 正規表現は怪しいです。

-- 小沼雅樹
-------------- next part --------------
diff -u -r ../mew-1.95b16/mew-sort.el ./mew-sort.el
--- ../mew-1.95b16/mew-sort.el	Mon Aug 30 12:43:15 1999
+++ ./mew-sort.el	Thu Dec 30 22:44:23 1999
@@ -10,8 +10,98 @@
 
 (require 'mew)
 
+(defun mew-summary-sort-encode-time (s)
+  (and
+   (stringp s)
+   (string-match
+    "\\([0-9]+\\)\\s-+\\(\\w+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\s-*\\([-+]?[0-9]*\\)\\s-*\(?\\(\\w*\\)?"
+    s)				; "Thu, 9 Dec 1999 22:19:32 +0900 (JST)"
+   (let ((year (string-to-number (match-string 3 s)))
+	 (tz-num (match-string 8 s)))
+     (encode-time
+      (string-to-number (or (match-string 7 s) ""))	; SECOND
+      (string-to-number (match-string 5 s))		; MINUTE
+      (string-to-number (match-string 4 s))		; HOUR
+      (string-to-number (match-string 1 s))		; DAY
+      (or (cdr (assoc (match-string 2 s)
+		      '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4)
+			("May" . 5) ("Jun" . 6) ("Jul" . 7) ("Aug" . 8)
+			("Sep" . 9) ("Oct" . 10) ("Nov" . 11) ("Dec" . 12))))
+	  0)						; MONTH
+      (if (< year 100)
+	  (+ year (if (< year 50) 2000 1900))
+	year)						; YEAR
+      (if (string= tz-num "")
+	  (or (cdr (assoc (match-string 9 s)
+			  '(("PST" . -28800) ("PDT" . -25200) ("MST" . -25200)
+			    ("MDT" . -21600) ("CST" . -21600) ("CDT" . -18000)
+			    ("EST" . -18000) ("EDT" . -14400) ("AST" . -14400)
+			    ("NST" . -10800) ("BST" . 3600) ("MET" . 3600)
+			    ("EET" . 7200) ("JST" . 32400))))
+	      0)
+	(setq tz-num (string-to-number tz-num))
+	(* (+ (* (/ tz-num 100) 60) (% tz-num 100)) 60)))))) ; ZONE
+
+(defun mew-summary-sort-index (msgs field mode len)
+  (let ((param (make-vector len nil))
+	(case-fold-search t)
+	(field (concat field ":"))
+	(i 0) v)
+    ;; get field values
+    (while msgs
+      (aset
+       param i
+       (condition-case nil
+	   (save-excursion
+	     (mew-set-buffer-tmp default-directory)
+	     (mew-frwlet mew-cs-autoconv mew-cs-dummy
+	      (insert-file-contents
+	       (car msgs) nil 0 mew-header-reasonable-size))
+	     (setq v (mew-header-get-value field))
+	     (cond
+	      ((string= field "subject:")
+	       (if (and (string= mode "ml")
+			(string-match
+			 "^[\[\(]\\([^\]\)]*\\)[\]\)]\\(.*\\)$" v))
+		   (let ((ml (match-string 1 v)) (s (match-string 2 v)) n)
+		     (if (string-match "^\\(.*\\)[ :,\t]\\(.*\\)$" ml)
+			 (setq n (match-string 2 ml) ml (match-string 1 ml)))
+		     (string-match "^\\s-*\\(\\(re:\\s-*\\)*\\)\\(.*\\)$" s)
+		     (concat ml (match-string 3 s) (match-string 1 s)
+			     (and n (format "%08d" (string-to-number n)))))
+		 (string-match "^\\s-*\\(\\(re:\\s-*\\)*\\)\\(.*\\)$" v)
+		 (concat (match-string 3 v) (match-string 1 v))))
+	      ((string= mode "num")
+	       (string-match "\\([0-9]+\\)" v)
+	       (string-to-number (match-string 1 v)))
+	      ((string= mode "date")
+	       (or (mew-summary-sort-encode-time v)
+		   (mew-file-get-time (car msgs))))
+	      (v)
+	      ("")))
+	 (error (or (cdr (assoc mode '(("date" 0 0) ("num" . 0)))) ""))))
+      (setq msgs (cdr msgs) i (1+ i)))
+    ;; sort index
+    (sort
+     (let ((i len) index)		; (0 1 2 3 ... len-1)
+       (while (> i 0) (setq index (cons (setq i (1- i)) index))) index)
+     (cond ((string= mode "date")
+	    (function
+	     (lambda (a b)
+	       (setq a (aref param a) b (aref param b))
+	       (or (< (car a) (car b))
+		   (and (= (car a) (car b))
+			(< (car (cdr a)) (car (cdr b))))))))
+	   ((string= mode "num")
+	    (function
+	     (lambda (a b) (< (aref param a) (aref param b)))))
+	   (t
+	    (function
+	     (lambda (a b) (string< (aref param a) (aref param b)))))))))
+  
 (defun mew-summary-sort-subr (msgs &optional method from)
-  (if (not (mew-summary-exclusive-p))
+  (if (or (not (mew-summary-exclusive-p))
+	  (not (mew-folder-localp (buffer-name))))
       ()
     (mew-mark-clean)
     (let* ((folder (buffer-name))
@@ -22,18 +112,42 @@
 	   (field (car field-mode))
 	   (mode (cdr field-mode))
 	   rbeg)
-      (if (not (listp msgs)) (setq msgs (list msgs)))
-      (setq mew-summary-buffer-process t)
-      (message "Sorting %s by %s (%s mode) ... " folder field mode)
-      (apply (function call-process)
-	     mew-prog-imsort
-	     nil nil nil
-	     (concat "--src=" folder)
-	     (concat "--field=" field)
-	     (concat "--mode=" mode)
-	     (append mew-prog-im-arg msgs)) ;; xxx
-      (message "Sorting %s by %s ... done" folder field)
-      (setq mew-summary-buffer-process nil)
+      (let ((mew-summary-buffer-process t))
+	(message "Sorting %s by %s (%s mode) ... " folder field mode)
+	(if mew-use-imsort
+	    (apply (function call-process)
+		   mew-prog-imsort
+		   nil nil nil
+		   (concat "--src=" folder)
+		   (concat "--field=" field)
+		   (concat "--mode=" mode)
+		   (append mew-prog-im-arg
+			   (if (listp msgs) msgs (list msgs)))) ;; xxx
+	  (let* ((default-directory
+		   (file-name-as-directory (mew-expand-folder folder)))
+		 (len (length msgs))
+		 (sorted-index
+		  (vconcat (mew-summary-sort-index msgs field mode len)
+			   '(nil)))
+		 (msg-paths (vconcat msgs '(nil)))
+		 (hole-path (mew-folder-new-message folder t))
+		 (i 0) (tmp len) to from)
+	    (while (< i len)
+	      (cond ((and (not (eq i (aref sorted-index i)))
+			  (aref sorted-index i))
+		     (aset msg-paths tmp hole-path)
+		     (aset sorted-index tmp i)
+		     (setq to tmp)
+		     (while
+			 (progn (setq from (aref sorted-index to))
+				(or (aref sorted-index from) (setq from tmp))
+				(aset sorted-index to nil)
+				(rename-file (aref msg-paths from)
+					     (aref msg-paths to))
+				(not (eq (setq to from) tmp))))))
+	      (setq i (1+ i))))
+	  (mew-touch-folder folder))
+	(message "Sorting %s by %s ... done" folder field))
       (if from 
 	  (progn (mew-summary-jump-message from)
 		 (setq rbeg (point)))) ;; beginning of region
@@ -58,23 +172,38 @@
   "Sort messages in the region according to inputed key."
   (interactive "r")
   (mew-summary-only
-   (let (from to)
-     (save-excursion
-       (goto-char (min r1 r2))
-       (setq from
-	     (or (mew-summary-message-number)
-		 (progn
-		   (re-search-backward mew-summary-message-regex nil t)
-		   (mew-summary-message-number))))
-       (goto-char (max r1 r2))
-       (setq to
-	     (or (mew-summary-message-number)
-		 (progn
-		   (re-search-backward mew-summary-message-regex nil t)
-		   (mew-summary-message-number))))
-       (goto-char (min r1 r2))
-       (beginning-of-line)
-       (mew-summary-sort-subr (concat from "-" to) method from)))))
+   (if mew-use-imsort
+       (let (from to)
+	 (save-excursion
+	   (goto-char (min r1 r2))
+	   (setq from
+		 (or (mew-summary-message-number)
+		     (progn
+		       (re-search-backward mew-summary-message-regex nil t)
+		       (mew-summary-message-number))))
+	   (goto-char (max r1 r2))
+	   (setq to
+		 (or (mew-summary-message-number)
+		     (progn
+		       (re-search-backward mew-summary-message-regex nil t)
+		       (mew-summary-message-number))))
+	   (goto-char (min r1 r2))
+	   (beginning-of-line)
+	   (mew-summary-sort-subr (concat from "-" to) method from)))
+     (let ((end (if (> r1 r2) r1 r2))
+	   msgs from)
+       (save-excursion
+	 (goto-char (min r1 r2))
+	 (setq from
+	       (or (mew-summary-message-number)
+		   (progn
+		     (re-search-backward mew-summary-message-regex nil t)
+		     (mew-summary-message-number))))
+	 (while (re-search-forward mew-summary-message-regex end t)
+	   (setq msgs (cons (match-string 1) msgs)))
+	 (goto-char (min r1 r2))
+	 (beginning-of-line)
+	 (mew-summary-sort-subr (nreverse msgs) method from))))))
 
 (defun mew-summary-mark-sort (&optional r1 r2)
   (interactive)
diff -u -r ../mew-1.95b16/mew-vars.el ./mew-vars.el
--- ../mew-1.95b16/mew-vars.el	Tue Dec 28 17:00:38 1999
+++ ./mew-vars.el	Tue Dec 28 20:07:24 1999
@@ -964,6 +964,10 @@
   "*If non-nil, Mew uses 'immv' for refile. Otherwise, Mew 
 refiles messages by Elisp-version code.")
 
+(defvar mew-use-imsort nil
+  "*If non-nil, Mew uses 'imsort' for sort. Otherwise, Mew 
+sorts messages by Elisp-version code.")
+
 (defvar mew-use-text/enriched (equal mew-mule-ver 3)
   "*If non-nil, Mew highlights enriched format text messages.")
 


Mew-dist メーリングリストの案内