Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / 5d / ba53304bcae59de144a490b489e5288e774801
1 Return-Path: <dme@dme.org>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id A2480431FB5\r
6         for <notmuch@notmuchmail.org>; Mon, 29 Nov 2010 02:30:44 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 0\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_NONE=-0.0001] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id SgaAQyo4cs5B for <notmuch@notmuchmail.org>;\r
16         Mon, 29 Nov 2010 02:30:43 -0800 (PST)\r
17 Received: from mail-wy0-f181.google.com (mail-wy0-f181.google.com\r
18         [74.125.82.181])\r
19         by olra.theworths.org (Postfix) with ESMTP id 713B441A547\r
20         for <notmuch@notmuchmail.org>; Mon, 29 Nov 2010 02:30:43 -0800 (PST)\r
21 Received: by wyf22 with SMTP id 22so4656184wyf.26\r
22         for <notmuch@notmuchmail.org>; Mon, 29 Nov 2010 02:30:41 -0800 (PST)\r
23 Received: by 10.216.239.199 with SMTP id c49mr4762944wer.12.1291026641780;\r
24         Mon, 29 Nov 2010 02:30:41 -0800 (PST)\r
25 Received: from ut.hh.sledj.net (host81-149-164-25.in-addr.btopenworld.com\r
26         [81.149.164.25])\r
27         by mx.google.com with ESMTPS id o43sm2294205weq.47.2010.11.29.02.30.40\r
28         (version=TLSv1/SSLv3 cipher=RC4-MD5);\r
29         Mon, 29 Nov 2010 02:30:40 -0800 (PST)\r
30 Received: by ut.hh.sledj.net (Postfix, from userid 1000)\r
31         id E5629594245; Mon, 29 Nov 2010 10:30:07 +0000 (GMT)\r
32 From: David Edmondson <dme@dme.org>\r
33 To: notmuch@notmuchmail.org\r
34 Subject: [PATCH 3/3] emacs: Use JSON output for search.\r
35 Date: Mon, 29 Nov 2010 10:29:59 +0000\r
36 Message-Id: <1291026599-14795-4-git-send-email-dme@dme.org>\r
37 X-Mailer: git-send-email 1.7.2.3\r
38 In-Reply-To: <1291026599-14795-1-git-send-email-dme@dme.org>\r
39 References: <1291026599-14795-1-git-send-email-dme@dme.org>\r
40 X-BeenThere: notmuch@notmuchmail.org\r
41 X-Mailman-Version: 2.1.13\r
42 Precedence: list\r
43 List-Id: "Use and development of the notmuch mail system."\r
44         <notmuch.notmuchmail.org>\r
45 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
46         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
47 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
48 List-Post: <mailto:notmuch@notmuchmail.org>\r
49 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
50 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
51         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
52 X-List-Received-Date: Mon, 29 Nov 2010 10:30:44 -0000\r
53 \r
54 Switch to using the JSON format output of `notmuch search' to avoid\r
55 problems parsing the output text. In particular, a comma in the name\r
56 of an author would confuse the previous implementation.\r
57 ---\r
58  emacs/notmuch.el |  114 +++++++++++++++++++++++++++++++++++++-----------------\r
59  1 files changed, 78 insertions(+), 36 deletions(-)\r
60 \r
61 diff --git a/emacs/notmuch.el b/emacs/notmuch.el\r
62 index 5933747..bde8c47 100644\r
63 --- a/emacs/notmuch.el\r
64 +++ b/emacs/notmuch.el\r
65 @@ -50,6 +50,7 @@\r
66  (eval-when-compile (require 'cl))\r
67  (require 'mm-view)\r
68  (require 'message)\r
69 +(require 'json)\r
70  \r
71  (require 'notmuch-lib)\r
72  (require 'notmuch-show)\r
73 @@ -698,40 +699,81 @@ foreground and blue background."\r
74           do (notmuch-search-insert-field field date count authors subject tags)))\r
75    (insert "\n"))\r
76  \r
77 +(defun notmuch-search-process-insert-object (object)\r
78 +  (let* ((thread-id (concat "thread:" (cdr (assoc 'thread object))))\r
79 +        (date (format "%12s" (cdr (assoc 'date_relative object))))\r
80 +        (count (format "[%d/%d]"\r
81 +                       (cdr (assoc 'matched object))\r
82 +                       (cdr (assoc 'total object))))\r
83 +        (authors (cdr (assoc 'authors object)))\r
84 +        (subject (cdr (assoc 'subject object)))\r
85 +        (tag-list (cdr (assoc 'tags object)))\r
86 +        (tags (mapconcat 'identity tag-list " "))\r
87 +        (beg (point-marker)))\r
88 +    (notmuch-search-show-result date count authors subject tags)\r
89 +    (notmuch-search-color-line beg (point-marker) tag-list)\r
90 +    (put-text-property beg (point-marker) 'notmuch-search-thread-id thread-id)\r
91 +    (put-text-property beg (point-marker) 'notmuch-search-authors authors)\r
92 +    (put-text-property beg (point-marker) 'notmuch-search-subject subject)))\r
93 +\r
94 +(defvar notmuch-search-parse-start nil)\r
95 +(make-variable-buffer-local 'notmuch-show-parse-start)\r
96 +\r
97 +(defun notmuch-search-process-insert (proc buffer string)\r
98 +  (with-current-buffer buffer\r
99 +    (let ((inhibit-read-only t)\r
100 +         (inhibit-redisplay t)\r
101 +         ;; Vectors are not as useful here.\r
102 +         (json-array-type 'list)\r
103 +         object)\r
104 +      (save-excursion\r
105 +       ;; Insert the text, advancing the process marker\r
106 +       (goto-char (point-max))\r
107 +       (insert string)\r
108 +       (set-marker (process-mark proc) (point)))\r
109 +\r
110 +      (save-excursion\r
111 +       (goto-char notmuch-search-parse-start)\r
112 +       (condition-case nil\r
113 +           (while\r
114 +               (cond\r
115 +                ;; Opening bracket or comma separator between\r
116 +                ;; objects.\r
117 +                ((or (char-equal (json-peek) ?\[)\r
118 +                     (char-equal (json-peek) ?\,))\r
119 +                 (json-advance)\r
120 +                 (delete-region notmuch-search-parse-start (point))\r
121 +                 t)\r
122 +\r
123 +                ;; Closing array.\r
124 +                ((char-equal (json-peek) ?\])\r
125 +                 ;; Consume both the closing bracket and any trailing\r
126 +                 ;; whitespace (typically a carriage return).\r
127 +                 (json-advance)\r
128 +                 (json-skip-whitespace)\r
129 +                 (delete-region notmuch-search-parse-start (point))\r
130 +                 nil)\r
131 +\r
132 +                ;; Single object.\r
133 +                ((setq object (json-read-object))\r
134 +                 ;; Delete the object that we consumed.\r
135 +                 (delete-region notmuch-search-parse-start (point))\r
136 +                 ;; Insert the corresponding results.\r
137 +                 (notmuch-search-process-insert-object object)\r
138 +                 t))\r
139 +             ;; Consume any white space between terms.\r
140 +             (let ((p (point)))\r
141 +               (json-skip-whitespace)\r
142 +               (delete-region p (point)))\r
143 +             ;; Remember where we got up to.\r
144 +             (setq notmuch-search-parse-start (point)))\r
145 +         (error nil))))))\r
146 +\r
147  (defun notmuch-search-process-filter (proc string)\r
148 -  "Process and filter the output of \"notmuch search\""\r
149 -  (let ((buffer (process-buffer proc))\r
150 -       (found-target nil))\r
151 +  "Process and filter the output of `notmuch search'."\r
152 +  (let ((buffer (process-buffer proc)))\r
153      (if (buffer-live-p buffer)\r
154 -       (with-current-buffer buffer\r
155 -         (save-excursion\r
156 -           (let ((line 0)\r
157 -                 (more t)\r
158 -                 (inhibit-read-only t))\r
159 -             (while more\r
160 -               (if (string-match "^\\(thread:[0-9A-Fa-f]*\\) \\([^][]*\\) \\(\\[[0-9/]*\\]\\) \\([^;]*\\); \\(.*\\) (\\([^()]*\\))$" string line)\r
161 -                   (let* ((thread-id (match-string 1 string))\r
162 -                          (date (match-string 2 string))\r
163 -                          (count (match-string 3 string))\r
164 -                          (authors (match-string 4 string))\r
165 -                          (subject (match-string 5 string))\r
166 -                          (tags (match-string 6 string))\r
167 -                          (tag-list (if tags (save-match-data (split-string tags)))))\r
168 -                     (goto-char (point-max))\r
169 -                     (let ((beg (point-marker)))\r
170 -                       (notmuch-search-show-result date count authors subject tags)\r
171 -                       (notmuch-search-color-line beg (point-marker) tag-list)\r
172 -                       (put-text-property beg (point-marker) 'notmuch-search-thread-id thread-id)\r
173 -                       (put-text-property beg (point-marker) 'notmuch-search-authors authors)\r
174 -                       (put-text-property beg (point-marker) 'notmuch-search-subject subject)\r
175 -                       (if (string= thread-id notmuch-search-target-thread)\r
176 -                           (progn\r
177 -                             (set 'found-target beg)\r
178 -                             (set 'notmuch-search-target-thread "found"))))\r
179 -                     (set 'line (match-end 0)))\r
180 -                 (set 'more nil)))))\r
181 -         (if found-target\r
182 -             (goto-char found-target)))\r
183 +       (notmuch-search-process-insert proc buffer string)\r
184        (delete-process proc))))\r
185  \r
186  (defun notmuch-search-operate-all (action)\r
187 @@ -806,15 +848,15 @@ The optional parameters are used as follows:\r
188      (set 'notmuch-search-continuation continuation)\r
189      (let ((proc (get-buffer-process (current-buffer)))\r
190           (inhibit-read-only t))\r
191 -      (if proc\r
192 -         (error "notmuch search process already running for query `%s'" query)\r
193 -       )\r
194 +      (when proc\r
195 +       (error "notmuch search process already running for query `%s'" query))\r
196        (erase-buffer)\r
197 -      (goto-char (point-min))\r
198 +      (setq notmuch-search-parse-start (point-min))\r
199        (save-excursion\r
200         (let ((proc (start-process\r
201                      "notmuch-search" buffer\r
202                      notmuch-command "search"\r
203 +                    "--format=json"\r
204                      (if oldest-first\r
205                          "--sort=oldest-first"\r
206                        "--sort=newest-first")\r
207 -- \r
208 1.7.2.3\r
209 \r