Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / d7 / 851f752f058d404d613cba4edbc95570f91c06
1 Return-Path: <craven@gmx.net>\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 633D1431FC3\r
6         for <notmuch@notmuchmail.org>; Mon, 16 Jul 2012 23:04:44 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 0.001\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0.001 tagged_above=-999 required=5\r
12         tests=[FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001]\r
13         autolearn=disabled\r
14 Received: from olra.theworths.org ([127.0.0.1])\r
15         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
16         with ESMTP id MnJuyUM6qyfy for <notmuch@notmuchmail.org>;\r
17         Mon, 16 Jul 2012 23:04:39 -0700 (PDT)\r
18 Received: from mailout-de.gmx.net (mailout-de.gmx.net [213.165.64.23])\r
19         by olra.theworths.org (Postfix) with SMTP id 1A2D1431FBC\r
20         for <notmuch@notmuchmail.org>; Mon, 16 Jul 2012 23:04:36 -0700 (PDT)\r
21 Received: (qmail invoked by alias); 17 Jul 2012 06:04:32 -0000\r
22 Received: from gw.arelion.cust.net.lagis.at (EHLO dodekanex.arelion.at)\r
23         [83.164.197.182]\r
24         by mail.gmx.net (mp027) with SMTP; 17 Jul 2012 08:04:32 +0200\r
25 X-Authenticated: #201305\r
26 X-Provags-ID: V01U2FsdGVkX1+PMTxuD7ePHfL+12nx6ttMCnC+sQvlSywu8iSV78\r
27         HWKN8R/YkgxO+D\r
28 Received: by dodekanex.arelion.at (Postfix, from userid 1000)\r
29         id 1287A303542; Mon, 16 Jul 2012 10:35:05 +0200 (CEST)\r
30 From: <craven@gmx.net>\r
31 To: notmuch@notmuchmail.org\r
32 Subject: [PATCH v6 3/3] Use the structured formatters in notmuch-search.c.\r
33 Date: Mon, 16 Jul 2012 10:35:02 +0200\r
34 Message-Id: <1342427702-23316-4-git-send-email-craven@gmx.net>\r
35 X-Mailer: git-send-email 1.7.11.1\r
36 In-Reply-To: <1342427702-23316-1-git-send-email-craven@gmx.net>\r
37 References: <20120714020954.GD31670@mit.edu>\r
38         <1342427702-23316-1-git-send-email-craven@gmx.net>\r
39 MIME-Version: 1.0\r
40 Content-Type: text/plain; charset=UTF-8\r
41 Content-Transfer-Encoding: 8bit\r
42 X-Y-GMX-Trusted: 0\r
43 X-BeenThere: notmuch@notmuchmail.org\r
44 X-Mailman-Version: 2.1.13\r
45 Precedence: list\r
46 List-Id: "Use and development of the notmuch mail system."\r
47         <notmuch.notmuchmail.org>\r
48 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
49         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
50 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
51 List-Post: <mailto:notmuch@notmuchmail.org>\r
52 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
53 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
54         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
55 X-List-Received-Date: Tue, 17 Jul 2012 06:04:44 -0000\r
56 \r
57 This patch switches from the current ad-hoc printer to the structured\r
58 formatters in sprinter.h, sprinter-text-search.c and sprinter-json.c.\r
59 \r
60 The JSON tests are changed slightly in order to make them PASS for the\r
61 new structured output formatter.\r
62 \r
63 The text tests pass without adaptation.\r
64 ---\r
65  notmuch-search.c | 300 ++++++++++++++++---------------------------------------\r
66  test/json        |  18 +---\r
67  2 files changed, 86 insertions(+), 232 deletions(-)\r
68 \r
69 diff --git a/notmuch-search.c b/notmuch-search.c\r
70 index 3be296d..cf927e6 100644\r
71 --- a/notmuch-search.c\r
72 +++ b/notmuch-search.c\r
73 @@ -19,6 +19,7 @@\r
74   */\r
75  \r
76  #include "notmuch-client.h"\r
77 +#include "sprinter.h"\r
78  \r
79  typedef enum {\r
80      OUTPUT_SUMMARY,\r
81 @@ -28,92 +29,6 @@ typedef enum {\r
82      OUTPUT_TAGS\r
83  } output_t;\r
84  \r
85 -typedef struct search_format {\r
86 -    const char *results_start;\r
87 -    const char *item_start;\r
88 -    void (*item_id) (const void *ctx,\r
89 -                    const char *item_type,\r
90 -                    const char *item_id);\r
91 -    void (*thread_summary) (const void *ctx,\r
92 -                           const char *thread_id,\r
93 -                           const time_t date,\r
94 -                           const int matched,\r
95 -                           const int total,\r
96 -                           const char *authors,\r
97 -                           const char *subject);\r
98 -    const char *tag_start;\r
99 -    const char *tag;\r
100 -    const char *tag_sep;\r
101 -    const char *tag_end;\r
102 -    const char *item_sep;\r
103 -    const char *item_end;\r
104 -    const char *results_end;\r
105 -    const char *results_null;\r
106 -} search_format_t;\r
107 -\r
108 -static void\r
109 -format_item_id_text (const void *ctx,\r
110 -                    const char *item_type,\r
111 -                    const char *item_id);\r
112 -\r
113 -static void\r
114 -format_thread_text (const void *ctx,\r
115 -                   const char *thread_id,\r
116 -                   const time_t date,\r
117 -                   const int matched,\r
118 -                   const int total,\r
119 -                   const char *authors,\r
120 -                   const char *subject);\r
121 -static const search_format_t format_text = {\r
122 -    "",\r
123 -       "",\r
124 -           format_item_id_text,\r
125 -           format_thread_text,\r
126 -           " (",\r
127 -               "%s", " ",\r
128 -           ")", "\n",\r
129 -       "",\r
130 -    "\n",\r
131 -    "",\r
132 -};\r
133 -\r
134 -static void\r
135 -format_item_id_json (const void *ctx,\r
136 -                    const char *item_type,\r
137 -                    const char *item_id);\r
138 -\r
139 -static void\r
140 -format_thread_json (const void *ctx,\r
141 -                   const char *thread_id,\r
142 -                   const time_t date,\r
143 -                   const int matched,\r
144 -                   const int total,\r
145 -                   const char *authors,\r
146 -                   const char *subject);\r
147 -\r
148 -/* Any changes to the JSON format should be reflected in the file\r
149 - * devel/schemata. */\r
150 -static const search_format_t format_json = {\r
151 -    "[",\r
152 -       "{",\r
153 -           format_item_id_json,\r
154 -           format_thread_json,\r
155 -           "\"tags\": [",\r
156 -               "\"%s\"", ", ",\r
157 -           "]", ",\n",\r
158 -       "}",\r
159 -    "]\n",\r
160 -    "]\n",\r
161 -};\r
162 -\r
163 -static void\r
164 -format_item_id_text (unused (const void *ctx),\r
165 -                    const char *item_type,\r
166 -                    const char *item_id)\r
167 -{\r
168 -    printf ("%s%s", item_type, item_id);\r
169 -}\r
170 -\r
171  static char *\r
172  sanitize_string (const void *ctx, const char *str)\r
173  {\r
174 @@ -131,72 +46,8 @@ sanitize_string (const void *ctx, const char *str)\r
175      return out;\r
176  }\r
177  \r
178 -static void\r
179 -format_thread_text (const void *ctx,\r
180 -                   const char *thread_id,\r
181 -                   const time_t date,\r
182 -                   const int matched,\r
183 -                   const int total,\r
184 -                   const char *authors,\r
185 -                   const char *subject)\r
186 -{\r
187 -    void *ctx_quote = talloc_new (ctx);\r
188 -\r
189 -    printf ("thread:%s %12s [%d/%d] %s; %s",\r
190 -           thread_id,\r
191 -           notmuch_time_relative_date (ctx, date),\r
192 -           matched,\r
193 -           total,\r
194 -           sanitize_string (ctx_quote, authors),\r
195 -           sanitize_string (ctx_quote, subject));\r
196 -\r
197 -    talloc_free (ctx_quote);\r
198 -}\r
199 -\r
200 -static void\r
201 -format_item_id_json (const void *ctx,\r
202 -                    unused (const char *item_type),\r
203 -                    const char *item_id)\r
204 -{\r
205 -    void *ctx_quote = talloc_new (ctx);\r
206 -\r
207 -    printf ("%s", json_quote_str (ctx_quote, item_id));\r
208 -\r
209 -    talloc_free (ctx_quote);\r
210 -    \r
211 -}\r
212 -\r
213 -static void\r
214 -format_thread_json (const void *ctx,\r
215 -                   const char *thread_id,\r
216 -                   const time_t date,\r
217 -                   const int matched,\r
218 -                   const int total,\r
219 -                   const char *authors,\r
220 -                   const char *subject)\r
221 -{\r
222 -    void *ctx_quote = talloc_new (ctx);\r
223 -\r
224 -    printf ("\"thread\": %s,\n"\r
225 -           "\"timestamp\": %ld,\n"\r
226 -           "\"date_relative\": \"%s\",\n"\r
227 -           "\"matched\": %d,\n"\r
228 -           "\"total\": %d,\n"\r
229 -           "\"authors\": %s,\n"\r
230 -           "\"subject\": %s,\n",\r
231 -           json_quote_str (ctx_quote, thread_id),\r
232 -           date,\r
233 -           notmuch_time_relative_date (ctx, date),\r
234 -           matched,\r
235 -           total,\r
236 -           json_quote_str (ctx_quote, authors),\r
237 -           json_quote_str (ctx_quote, subject));\r
238 -\r
239 -    talloc_free (ctx_quote);\r
240 -}\r
241 -\r
242  static int\r
243 -do_search_threads (const search_format_t *format,\r
244 +do_search_threads (sprinter_t *format,\r
245                    notmuch_query_t *query,\r
246                    notmuch_sort_t sort,\r
247                    output_t output,\r
248 @@ -207,7 +58,6 @@ do_search_threads (const search_format_t *format,\r
249      notmuch_threads_t *threads;\r
250      notmuch_tags_t *tags;\r
251      time_t date;\r
252 -    int first_thread = 1;\r
253      int i;\r
254  \r
255      if (offset < 0) {\r
256 @@ -220,14 +70,12 @@ do_search_threads (const search_format_t *format,\r
257      if (threads == NULL)\r
258         return 1;\r
259  \r
260 -    fputs (format->results_start, stdout);\r
261 +    format->begin_list (format);\r
262  \r
263      for (i = 0;\r
264          notmuch_threads_valid (threads) && (limit < 0 || i < offset + limit);\r
265          notmuch_threads_move_to_next (threads), i++)\r
266      {\r
267 -       int first_tag = 1;\r
268 -\r
269         thread = notmuch_threads_get (threads);\r
270  \r
271         if (i < offset) {\r
272 @@ -235,60 +83,96 @@ do_search_threads (const search_format_t *format,\r
273             continue;\r
274         }\r
275  \r
276 -       if (! first_thread)\r
277 -           fputs (format->item_sep, stdout);\r
278 -\r
279         if (output == OUTPUT_THREADS) {\r
280 -           format->item_id (thread, "thread:",\r
281 -                            notmuch_thread_get_thread_id (thread));\r
282 +           format->set_prefix (format, "thread");\r
283 +           format->string (format,\r
284 +                           notmuch_thread_get_thread_id (thread));\r
285 +           format->separator (format);\r
286         } else { /* output == OUTPUT_SUMMARY */\r
287 -           fputs (format->item_start, stdout);\r
288 +           void *ctx_quote = talloc_new (thread);\r
289 +           const char *authors = notmuch_thread_get_authors (thread);\r
290 +           const char *subject = notmuch_thread_get_subject (thread);\r
291 +           const char *thread_id = notmuch_thread_get_thread_id (thread);\r
292 +           int matched = notmuch_thread_get_matched_messages (thread);\r
293 +           int total = notmuch_thread_get_total_messages (thread);\r
294 +           const char *relative_date = NULL;\r
295 +           notmuch_bool_t first_tag = TRUE;\r
296 +\r
297 +           format->begin_map (format);\r
298  \r
299             if (sort == NOTMUCH_SORT_OLDEST_FIRST)\r
300                 date = notmuch_thread_get_oldest_date (thread);\r
301             else\r
302                 date = notmuch_thread_get_newest_date (thread);\r
303  \r
304 -           format->thread_summary (thread,\r
305 -                                   notmuch_thread_get_thread_id (thread),\r
306 -                                   date,\r
307 -                                   notmuch_thread_get_matched_messages (thread),\r
308 -                                   notmuch_thread_get_total_messages (thread),\r
309 -                                   notmuch_thread_get_authors (thread),\r
310 -                                   notmuch_thread_get_subject (thread));\r
311 +           relative_date = notmuch_time_relative_date (ctx_quote, date);\r
312 +\r
313 +           if (format->is_text_printer (format)) {\r
314 +                /* Special case for the text formatter */\r
315 +               printf ("thread:%s %12s [%d/%d] %s; %s (",\r
316 +                       thread_id,\r
317 +                       relative_date,\r
318 +                       matched,\r
319 +                       total,\r
320 +                       sanitize_string (ctx_quote, authors),\r
321 +                       sanitize_string (ctx_quote, subject));\r
322 +           } else { /* Structured Output */\r
323 +               format->map_key (format, "thread");\r
324 +               format->string (format, thread_id);\r
325 +               format->map_key (format, "timestamp");\r
326 +               format->integer (format, date);\r
327 +               format->map_key (format, "date_relative");\r
328 +               format->string (format, relative_date);\r
329 +               format->map_key (format, "matched");\r
330 +               format->integer (format, matched);\r
331 +               format->map_key (format, "total");\r
332 +               format->integer (format, total);\r
333 +               format->map_key (format, "authors");\r
334 +               format->string (format, authors);\r
335 +               format->map_key (format, "subject");\r
336 +               format->string (format, subject);\r
337 +           }\r
338 +\r
339 +           talloc_free (ctx_quote);\r
340  \r
341 -           fputs (format->tag_start, stdout);\r
342 +           format->map_key (format, "tags");\r
343 +           format->begin_list (format);\r
344  \r
345             for (tags = notmuch_thread_get_tags (thread);\r
346                  notmuch_tags_valid (tags);\r
347                  notmuch_tags_move_to_next (tags))\r
348             {\r
349 -               if (! first_tag)\r
350 -                   fputs (format->tag_sep, stdout);\r
351 -               printf (format->tag, notmuch_tags_get (tags));\r
352 -               first_tag = 0;\r
353 +               const char *tag = notmuch_tags_get (tags);\r
354 +\r
355 +               if (format->is_text_printer (format)) {\r
356 +                  /* Special case for the text formatter */\r
357 +                   if (first_tag)\r
358 +                       first_tag = FALSE;\r
359 +                   else\r
360 +                       fputc (' ', stdout);\r
361 +                   fputs (tag, stdout);\r
362 +               } else /* Structured Output */\r
363 +                   format->string (format, tag);\r
364             }\r
365  \r
366 -           fputs (format->tag_end, stdout);\r
367 +           if (format->is_text_printer (format))\r
368 +               printf (")");\r
369  \r
370 -           fputs (format->item_end, stdout);\r
371 +           format->end (format);\r
372 +           format->end (format);\r
373 +           format->separator (format);\r
374         }\r
375  \r
376 -       first_thread = 0;\r
377 -\r
378         notmuch_thread_destroy (thread);\r
379      }\r
380  \r
381 -    if (first_thread)\r
382 -       fputs (format->results_null, stdout);\r
383 -    else\r
384 -       fputs (format->results_end, stdout);\r
385 +    format->end (format);\r
386  \r
387      return 0;\r
388  }\r
389  \r
390  static int\r
391 -do_search_messages (const search_format_t *format,\r
392 +do_search_messages (sprinter_t *format,\r
393                     notmuch_query_t *query,\r
394                     output_t output,\r
395                     int offset,\r
396 @@ -297,7 +181,6 @@ do_search_messages (const search_format_t *format,\r
397      notmuch_message_t *message;\r
398      notmuch_messages_t *messages;\r
399      notmuch_filenames_t *filenames;\r
400 -    int first_message = 1;\r
401      int i;\r
402  \r
403      if (offset < 0) {\r
404 @@ -310,7 +193,7 @@ do_search_messages (const search_format_t *format,\r
405      if (messages == NULL)\r
406         return 1;\r
407  \r
408 -    fputs (format->results_start, stdout);\r
409 +    format->begin_list (format);\r
410  \r
411      for (i = 0;\r
412          notmuch_messages_valid (messages) && (limit < 0 || i < offset + limit);\r
413 @@ -328,24 +211,17 @@ do_search_messages (const search_format_t *format,\r
414                  notmuch_filenames_valid (filenames);\r
415                  notmuch_filenames_move_to_next (filenames))\r
416             {\r
417 -               if (! first_message)\r
418 -                   fputs (format->item_sep, stdout);\r
419 -\r
420 -               format->item_id (message, "",\r
421 -                                notmuch_filenames_get (filenames));\r
422 -\r
423 -               first_message = 0;\r
424 +               format->string (format, notmuch_filenames_get (filenames));\r
425 +               format->separator (format);\r
426             }\r
427             \r
428             notmuch_filenames_destroy( filenames );\r
429  \r
430         } else { /* output == OUTPUT_MESSAGES */\r
431 -           if (! first_message)\r
432 -               fputs (format->item_sep, stdout);\r
433 -\r
434 -           format->item_id (message, "id:",\r
435 -                            notmuch_message_get_message_id (message));\r
436 -           first_message = 0;\r
437 +           format->set_prefix (format, "id");\r
438 +           format->string (format,\r
439 +                           notmuch_message_get_message_id (message));\r
440 +           format->separator (format);\r
441         }\r
442  \r
443         notmuch_message_destroy (message);\r
444 @@ -353,23 +229,19 @@ do_search_messages (const search_format_t *format,\r
445  \r
446      notmuch_messages_destroy (messages);\r
447  \r
448 -    if (first_message)\r
449 -       fputs (format->results_null, stdout);\r
450 -    else\r
451 -       fputs (format->results_end, stdout);\r
452 +    format->end (format);\r
453  \r
454      return 0;\r
455  }\r
456  \r
457  static int\r
458  do_search_tags (notmuch_database_t *notmuch,\r
459 -               const search_format_t *format,\r
460 +               sprinter_t *format,\r
461                 notmuch_query_t *query)\r
462  {\r
463      notmuch_messages_t *messages = NULL;\r
464      notmuch_tags_t *tags;\r
465      const char *tag;\r
466 -    int first_tag = 1;\r
467  \r
468      /* should the following only special case if no excluded terms\r
469       * specified? */\r
470 @@ -387,7 +259,7 @@ do_search_tags (notmuch_database_t *notmuch,\r
471      if (tags == NULL)\r
472         return 1;\r
473  \r
474 -    fputs (format->results_start, stdout);\r
475 +    format->begin_list (format);\r
476  \r
477      for (;\r
478          notmuch_tags_valid (tags);\r
479 @@ -395,12 +267,9 @@ do_search_tags (notmuch_database_t *notmuch,\r
480      {\r
481         tag = notmuch_tags_get (tags);\r
482  \r
483 -       if (! first_tag)\r
484 -           fputs (format->item_sep, stdout);\r
485 +       format->string (format, tag);\r
486 +       format->separator (format);\r
487  \r
488 -       format->item_id (tags, "", tag);\r
489 -\r
490 -       first_tag = 0;\r
491      }\r
492  \r
493      notmuch_tags_destroy (tags);\r
494 @@ -408,10 +277,7 @@ do_search_tags (notmuch_database_t *notmuch,\r
495      if (messages)\r
496         notmuch_messages_destroy (messages);\r
497  \r
498 -    if (first_tag)\r
499 -       fputs (format->results_null, stdout);\r
500 -    else\r
501 -       fputs (format->results_end, stdout);\r
502 +    format->end (format);\r
503  \r
504      return 0;\r
505  }\r
506 @@ -430,7 +296,7 @@ notmuch_search_command (void *ctx, int argc, char *argv[])\r
507      notmuch_query_t *query;\r
508      char *query_str;\r
509      notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;\r
510 -    const search_format_t *format = &format_text;\r
511 +    sprinter_t *format = NULL;\r
512      int opt_index, ret;\r
513      output_t output = OUTPUT_SUMMARY;\r
514      int offset = 0;\r
515 @@ -475,10 +341,10 @@ notmuch_search_command (void *ctx, int argc, char *argv[])\r
516  \r
517      switch (format_sel) {\r
518      case NOTMUCH_FORMAT_TEXT:\r
519 -       format = &format_text;\r
520 +       format = sprinter_text_search_create (ctx, stdout);\r
521         break;\r
522      case NOTMUCH_FORMAT_JSON:\r
523 -       format = &format_json;\r
524 +       format = sprinter_json_create (ctx, stdout);\r
525         break;\r
526      }\r
527  \r
528 @@ -546,5 +412,7 @@ notmuch_search_command (void *ctx, int argc, char *argv[])\r
529      notmuch_query_destroy (query);\r
530      notmuch_database_destroy (notmuch);\r
531  \r
532 +    talloc_free (format);\r
533 +\r
534      return ret;\r
535  }\r
536 diff --git a/test/json b/test/json\r
537 index 6439788..f0ebf08 100755\r
538 --- a/test/json\r
539 +++ b/test/json\r
540 @@ -10,14 +10,7 @@ test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"e\r
541  test_begin_subtest "Search message: json"\r
542  add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\""\r
543  output=$(notmuch search --format=json "json-search-message" | notmuch_search_sanitize)\r
544 -test_expect_equal "$output" "[{\"thread\": \"XXX\",\r
545 -\"timestamp\": 946728000,\r
546 -\"date_relative\": \"2000-01-01\",\r
547 -\"matched\": 1,\r
548 -\"total\": 1,\r
549 -\"authors\": \"Notmuch Test Suite\",\r
550 -\"subject\": \"json-search-subject\",\r
551 -\"tags\": [\"inbox\", \"unread\"]}]"\r
552 +test_expect_equal "$output" "[{\"thread\": \"XXX\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"matched\": 1, \"total\": 1, \"authors\": \"Notmuch Test Suite\", \"subject\": \"json-search-subject\", \"tags\": [\"inbox\", \"unread\"]}]"\r
553  \r
554  test_begin_subtest "Show message: json, utf-8"\r
555  add_message "[subject]=\"json-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""\r
556 @@ -40,13 +33,6 @@ test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"excluded\":\r
557  test_begin_subtest "Search message: json, utf-8"\r
558  add_message "[subject]=\"json-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""\r
559  output=$(notmuch search --format=json "jsön-search-méssage" | notmuch_search_sanitize)\r
560 -test_expect_equal "$output" "[{\"thread\": \"XXX\",\r
561 -\"timestamp\": 946728000,\r
562 -\"date_relative\": \"2000-01-01\",\r
563 -\"matched\": 1,\r
564 -\"total\": 1,\r
565 -\"authors\": \"Notmuch Test Suite\",\r
566 -\"subject\": \"json-search-utf8-body-sübjéct\",\r
567 -\"tags\": [\"inbox\", \"unread\"]}]"\r
568 +test_expect_equal "$output" "[{\"thread\": \"XXX\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"matched\": 1, \"total\": 1, \"authors\": \"Notmuch Test Suite\", \"subject\": \"json-search-utf8-body-sübjéct\", \"tags\": [\"inbox\", \"unread\"]}]"\r
569  \r
570  test_done\r
571 -- \r
572 1.7.11.1\r
573 \r