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 E2FAF431FB6
\r
6 for <notmuch@notmuchmail.org>; Fri, 26 Nov 2010 05:13:31 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\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 gAKFKoxnirMU for <notmuch@notmuchmail.org>;
\r
16 Fri, 26 Nov 2010 05:13:31 -0800 (PST)
\r
17 Received: from mail-wy0-f181.google.com (mail-wy0-f181.google.com
\r
19 by olra.theworths.org (Postfix) with ESMTP id A0B26431FB5
\r
20 for <notmuch@notmuchmail.org>; Fri, 26 Nov 2010 05:13:30 -0800 (PST)
\r
21 Received: by wyf22 with SMTP id 22so2113175wyf.26
\r
22 for <notmuch@notmuchmail.org>; Fri, 26 Nov 2010 05:13:28 -0800 (PST)
\r
23 Received: by 10.216.15.10 with SMTP id e10mr152512wee.21.1290777208145;
\r
24 Fri, 26 Nov 2010 05:13:28 -0800 (PST)
\r
25 Received: from ut.hh.sledj.net (host81-149-164-25.in-addr.btopenworld.com
\r
27 by mx.google.com with ESMTPS id x3sm906001wes.22.2010.11.26.05.13.26
\r
28 (version=TLSv1/SSLv3 cipher=RC4-MD5);
\r
29 Fri, 26 Nov 2010 05:13:27 -0800 (PST)
\r
30 Received: by ut.hh.sledj.net (Postfix, from userid 1000)
\r
31 id CF36B594058; Fri, 26 Nov 2010 13:13:23 +0000 (GMT)
\r
32 From: David Edmondson <dme@dme.org>
\r
33 To: notmuch@notmuchmail.org
\r
34 Subject: [RFC] [PATCH] emacs: Use JSON output for search.
\r
35 Date: Fri, 26 Nov 2010 13:13:22 +0000
\r
36 Message-Id: <1290777202-14040-1-git-send-email-dme@dme.org>
\r
37 X-Mailer: git-send-email 1.7.2.3
\r
38 X-BeenThere: notmuch@notmuchmail.org
\r
39 X-Mailman-Version: 2.1.13
\r
41 List-Id: "Use and development of the notmuch mail system."
\r
42 <notmuch.notmuchmail.org>
\r
43 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
44 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
45 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
46 List-Post: <mailto:notmuch@notmuchmail.org>
\r
47 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
48 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
49 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
50 X-List-Received-Date: Fri, 26 Nov 2010 13:13:32 -0000
\r
52 Modify the `notmuch search' JSON output to remove the outer list
\r
53 wrappers and item separators between elements. Add `date_relative' to
\r
54 the JSON search output.
\r
56 Replace the emacs use of the text based search output with the
\r
57 modified JSON output, including incremental parsing of the individual
\r
58 threads in the JSON.
\r
60 emacs/notmuch.el | 70 ++++++++++++++++++++++++++++++-----------------------
\r
61 notmuch-search.c | 8 ++++--
\r
62 2 files changed, 45 insertions(+), 33 deletions(-)
\r
64 Proper incremental parsing of the JSON output was hard, so I punted
\r
65 and got rid of the array wrappings around the search output. This may
\r
66 well break some other tools as a result (hence 'RFC'). Display of the
\r
67 thread can be a bit 'flashy' due to the incremental implementation,
\r
68 but it doesn't seem too off-putting on reasonable hardware - it may
\r
69 well be annoying on slower systems.
\r
71 diff --git a/emacs/notmuch.el b/emacs/notmuch.el
\r
72 index 5933747..0bbdf16 100644
\r
73 --- a/emacs/notmuch.el
\r
74 +++ b/emacs/notmuch.el
\r
75 @@ -698,40 +698,50 @@ foreground and blue background."
\r
76 do (notmuch-search-insert-field field date count authors subject tags)))
\r
79 +(defvar notmuch-search-parse-start nil)
\r
80 +(make-variable-buffer-local 'notmuch-show-parse-start)
\r
82 (defun notmuch-search-process-filter (proc string)
\r
83 - "Process and filter the output of \"notmuch search\""
\r
84 + "Process and filter the output of `notmuch search'."
\r
86 (let ((buffer (process-buffer proc))
\r
87 - (found-target nil))
\r
89 (if (buffer-live-p buffer)
\r
90 (with-current-buffer buffer
\r
94 - (inhibit-read-only t))
\r
96 - (if (string-match "^\\(thread:[0-9A-Fa-f]*\\) \\([^][]*\\) \\(\\[[0-9/]*\\]\\) \\([^;]*\\); \\(.*\\) (\\([^()]*\\))$" string line)
\r
97 - (let* ((thread-id (match-string 1 string))
\r
98 - (date (match-string 2 string))
\r
99 - (count (match-string 3 string))
\r
100 - (authors (match-string 4 string))
\r
101 - (subject (match-string 5 string))
\r
102 - (tags (match-string 6 string))
\r
103 - (tag-list (if tags (save-match-data (split-string tags)))))
\r
104 - (goto-char (point-max))
\r
105 - (let ((beg (point-marker)))
\r
106 + (let ((inhibit-read-only t)
\r
107 + (inhibit-redisplay t))
\r
109 + ;; Insert the text, advancing the process marker
\r
110 + (goto-char (point-max))
\r
112 + (set-marker (process-mark proc) (point-max)))
\r
115 + (condition-case nil
\r
117 + (goto-char notmuch-search-parse-start)
\r
118 + (while (and (not (eobp))
\r
119 + (setq object (json-read-object)))
\r
121 + (delete-region notmuch-search-parse-start (point))
\r
123 + (let* ((thread-id (concat "thread:" (cdr (assoc 'thread object))))
\r
124 + (date (format "%12s" (cdr (assoc 'date_relative object))))
\r
125 + (count (format "[%d/%d]"
\r
126 + (cdr (assoc 'matched object))
\r
127 + (cdr (assoc 'total object))))
\r
128 + (authors (cdr (assoc 'authors object)))
\r
129 + (subject (cdr (assoc 'subject object)))
\r
130 + (tag-list (cdr (assoc 'tags object)))
\r
131 + (tags (mapconcat 'identity tag-list " "))
\r
132 + (beg (point-marker)))
\r
133 (notmuch-search-show-result date count authors subject tags)
\r
134 (notmuch-search-color-line beg (point-marker) tag-list)
\r
135 (put-text-property beg (point-marker) 'notmuch-search-thread-id thread-id)
\r
136 (put-text-property beg (point-marker) 'notmuch-search-authors authors)
\r
137 - (put-text-property beg (point-marker) 'notmuch-search-subject subject)
\r
138 - (if (string= thread-id notmuch-search-target-thread)
\r
140 - (set 'found-target beg)
\r
141 - (set 'notmuch-search-target-thread "found"))))
\r
142 - (set 'line (match-end 0)))
\r
143 - (set 'more nil)))))
\r
145 - (goto-char found-target)))
\r
146 + (put-text-property beg (point-marker) 'notmuch-search-subject subject))
\r
147 + (setq notmuch-search-parse-start (point))))
\r
149 (delete-process proc))))
\r
151 (defun notmuch-search-operate-all (action)
\r
152 @@ -806,15 +816,15 @@ The optional parameters are used as follows:
\r
153 (set 'notmuch-search-continuation continuation)
\r
154 (let ((proc (get-buffer-process (current-buffer)))
\r
155 (inhibit-read-only t))
\r
157 - (error "notmuch search process already running for query `%s'" query)
\r
160 + (error "notmuch search process already running for query `%s'" query))
\r
162 - (goto-char (point-min))
\r
163 + (setq notmuch-search-parse-start (point-min))
\r
165 (let ((proc (start-process
\r
166 "notmuch-search" buffer
\r
167 notmuch-command "search"
\r
170 "--sort=oldest-first"
\r
171 "--sort=newest-first")
\r
172 diff --git a/notmuch-search.c b/notmuch-search.c
\r
173 index c628b36..1b07aa7 100644
\r
174 --- a/notmuch-search.c
\r
175 +++ b/notmuch-search.c
\r
176 @@ -89,15 +89,15 @@ format_thread_json (const void *ctx,
\r
177 const char *authors,
\r
178 const char *subject);
\r
179 static const search_format_t format_json = {
\r
183 format_item_id_json,
\r
184 format_thread_json,
\r
195 @@ -152,12 +152,14 @@ format_thread_json (const void *ctx,
\r
197 printf ("\"thread\": %s,\n"
\r
198 "\"timestamp\": %ld,\n"
\r
199 + "\"date_relative\": %s,\n"
\r
200 "\"matched\": %d,\n"
\r
202 "\"authors\": %s,\n"
\r
203 "\"subject\": %s,\n",
\r
204 json_quote_str (ctx_quote, thread_id),
\r
206 + json_quote_str (ctx_quote, notmuch_time_relative_date (ctx, date)),
\r
209 json_quote_str (ctx_quote, authors),
\r