Re: cli: add --include-html option to notmuch show
[notmuch-archives.git] / 43 / 914d1889d58ff6b0f685281ef464850913b901
1 Return-Path: <bremner@pivot.cs.unb.ca>\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 75E29431FBC\r
6         for <notmuch@notmuchmail.org>; Sun, 13 Dec 2009 15:31:26 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 Received: from olra.theworths.org ([127.0.0.1])\r
9         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
10         with ESMTP id p-ng2RJCiUhY for <notmuch@notmuchmail.org>;\r
11         Sun, 13 Dec 2009 15:31:25 -0800 (PST)\r
12 Received: from pivot.cs.unb.ca (pivot.cs.unb.ca [131.202.240.57])\r
13         by olra.theworths.org (Postfix) with ESMTP id 04CB2431FAE\r
14         for <notmuch@notmuchmail.org>; Sun, 13 Dec 2009 15:31:25 -0800 (PST)\r
15 Received: from\r
16         fctnnbsc30w-142167182194.pppoe-dynamic.high-speed.nb.bellaliant.net\r
17         ([142.167.182.194] helo=localhost)\r
18         by pivot.cs.unb.ca with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32)\r
19         (Exim 4.69) (envelope-from <bremner@pivot.cs.unb.ca>)\r
20         id 1NJxuO-00061k-5h; Sun, 13 Dec 2009 19:31:24 -0400\r
21 Received: from bremner by localhost with local (Exim 4.69)\r
22         (envelope-from <bremner@pivot.cs.unb.ca>)\r
23         id 1NJxuI-0001Du-C1; Sun, 13 Dec 2009 19:31:18 -0400\r
24 From: david@tethera.net\r
25 To: notmuch@notmuchmail.org\r
26 Date: Sun, 13 Dec 2009 19:31:11 -0400\r
27 Message-Id: <1260747071-4656-1-git-send-email-david@tethera.net>\r
28 X-Mailer: git-send-email 1.6.5.3\r
29 X-Sender-Verified: bremner@pivot.cs.unb.ca\r
30 Cc: David Bremner <bremner@unb.ca>\r
31 Subject: [notmuch] [PATCH] initial proof of concept patch to output a\r
32         message in json\r
33 X-BeenThere: notmuch@notmuchmail.org\r
34 X-Mailman-Version: 2.1.12\r
35 Precedence: list\r
36 List-Id: "Use and development of the notmuch mail system."\r
37         <notmuch.notmuchmail.org>\r
38 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
39         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
40 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
41 List-Post: <mailto:notmuch@notmuchmail.org>\r
42 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
43 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
44         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
45 X-List-Received-Date: Sun, 13 Dec 2009 23:31:26 -0000\r
46 \r
47 From: David Bremner <bremner@unb.ca>\r
48 \r
49 ---\r
50 \r
51 Like I said in the apology/introduction, I don't claim this patch is\r
52 ready for the master branch; hence the complete lack of sensible\r
53 commit message.  But it does give some idea about what would be\r
54 required. In particular definitely more things will have to be passed\r
55 around.\r
56 \r
57  configure        |    2 +-\r
58  notmuch-client.h |    2 +-\r
59  notmuch-reply.c  |    4 +-\r
60  notmuch-show.c   |  110 ++++++++++++++++++++++++++---------------------------\r
61  show-message.c   |   12 +++---\r
62  5 files changed, 64 insertions(+), 66 deletions(-)\r
63 \r
64 diff --git a/configure b/configure\r
65 index fa8e142..34587a5 100755\r
66 --- a/configure\r
67 +++ b/configure\r
68 @@ -291,5 +291,5 @@ CONFIGURE_CFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)      \\\r
69  CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)    \\\r
70                      \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\\r
71                      \$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS)\r
72 -CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS)\r
73 +CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS) -ljansson\r
74  EOF\r
75 diff --git a/notmuch-client.h b/notmuch-client.h\r
76 index 50a30fe..6600ed4 100644\r
77 --- a/notmuch-client.h\r
78 +++ b/notmuch-client.h\r
79 @@ -141,7 +141,7 @@ query_string_from_args (void *ctx, int argc, char *argv[]);\r
80  \r
81  notmuch_status_t\r
82  show_message_body (const char *filename,\r
83 -                  void (*show_part) (GMimeObject *part, int *part_count));\r
84 +                  void (*show_part) (GMimeObject *part, int *part_count, void *arg), void *output);\r
85  \r
86  /* notmuch-config.c */\r
87  \r
88 diff --git a/notmuch-reply.c b/notmuch-reply.c\r
89 index 0cda72d..29a6517 100644\r
90 --- a/notmuch-reply.c\r
91 +++ b/notmuch-reply.c\r
92 @@ -63,7 +63,7 @@ reply_part_content (GMimeObject *part)\r
93  }\r
94  \r
95  static void\r
96 -reply_part (GMimeObject *part, int *part_count)\r
97 +reply_part (GMimeObject *part, int *part_count, unused(void *arg))\r
98  {\r
99      GMimeContentDisposition *disposition;\r
100      GMimeContentType *content_type;\r
101 @@ -282,7 +282,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_\r
102                 notmuch_message_get_header (message, "date"),\r
103                 notmuch_message_get_header (message, "from"));\r
104  \r
105 -       show_message_body (notmuch_message_get_filename (message), reply_part);\r
106 +       show_message_body (notmuch_message_get_filename (message), reply_part,NULL);\r
107  \r
108         notmuch_message_destroy (message);\r
109      }\r
110 diff --git a/notmuch-show.c b/notmuch-show.c\r
111 index 376aacd..4f00675 100644\r
112 --- a/notmuch-show.c\r
113 +++ b/notmuch-show.c\r
114 @@ -18,8 +18,11 @@\r
115   * Author: Carl Worth <cworth@cworth.org>\r
116   */\r
117  \r
118 +#include <jansson.h>\r
119  #include "notmuch-client.h"\r
120  \r
121 +json_t *show_part_content (GMimeObject *part);\r
122 +\r
123  static const char *\r
124  _get_tags_as_string (void *ctx, notmuch_message_t *message)\r
125  {\r
126 @@ -66,19 +69,23 @@ _get_one_line_summary (void *ctx, notmuch_message_t *message)\r
127                             from, relative_date, tags);\r
128  }\r
129  \r
130 -static void\r
131 +json_t *\r
132  show_part_content (GMimeObject *part)\r
133  {\r
134 -    GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);\r
135 +    GMimeStream *stream_out = g_mime_stream_mem_new ();\r
136      GMimeStream *stream_filter = NULL;\r
137      GMimeDataWrapper *wrapper;\r
138 +    GByteArray *content_data;\r
139 +\r
140 +    guint8 terminator[]={0};\r
141      const char *charset;\r
142 +    json_t *content;\r
143  \r
144      charset = g_mime_object_get_content_type_parameter (part, "charset");\r
145 -\r
146 -    if (stream_stdout) {\r
147 -       g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);\r
148 -       stream_filter = g_mime_stream_filter_new(stream_stdout);\r
149 +    \r
150 +    if (stream_out) {\r
151 +       g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_out), FALSE);\r
152 +       stream_filter = g_mime_stream_filter_new(stream_out);\r
153         g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),\r
154                                  g_mime_filter_crlf_new(FALSE, FALSE));\r
155          if (charset) {\r
156 @@ -90,60 +97,50 @@ show_part_content (GMimeObject *part)\r
157      wrapper = g_mime_part_get_content_object (GMIME_PART (part));\r
158      if (wrapper && stream_filter)\r
159         g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);\r
160 +\r
161 +    content_data = g_mime_stream_mem_get_byte_array ((GMimeStreamMem *)stream_out);\r
162 +    g_byte_array_append(content_data, terminator,1);\r
163 +    content = json_string (content_data->data);\r
164      if (stream_filter)\r
165         g_object_unref(stream_filter);\r
166 -    if (stream_stdout)\r
167 -       g_object_unref(stream_stdout);\r
168 +    if (stream_out)\r
169 +       g_object_unref(stream_out);\r
170 +    \r
171 +    return content;\r
172  }\r
173  \r
174  static void\r
175 -show_part (GMimeObject *part, int *part_count)\r
176 +show_part (GMimeObject *part, int *part_count, void *output_arg)\r
177  {\r
178      GMimeContentDisposition *disposition;\r
179      GMimeContentType *content_type;\r
180 +    json_t *output = output_arg;\r
181 +    json_t *part_obj=json_object();\r
182  \r
183      disposition = g_mime_object_get_content_disposition (part);\r
184 +    content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));\r
185 +\r
186 +    json_object_set (part_obj, "id", json_integer (*part_count));\r
187 +    json_object_set (part_obj, "content-type", \r
188 +                    json_string(g_mime_content_type_to_string (content_type)));\r
189 +\r
190      if (disposition &&\r
191         strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)\r
192      {\r
193 -       const char *filename = g_mime_part_get_filename (GMIME_PART (part));\r
194 -       content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));\r
195 -\r
196 -       printf ("\fattachment{ ID: %d, Content-type: %s\n",\r
197 -               *part_count,\r
198 -               g_mime_content_type_to_string (content_type));\r
199 -       printf ("Attachment: %s (%s)\n", filename,\r
200 -               g_mime_content_type_to_string (content_type));\r
201 -\r
202 -       if (g_mime_content_type_is_type (content_type, "text", "*") &&\r
203 -           !g_mime_content_type_is_type (content_type, "text", "html"))\r
204 -       {\r
205 -           show_part_content (part);\r
206 -       }\r
207 +       const char *filename = g_mime_part_get_filename (GMIME_PART (part));\r
208  \r
209 -       printf ("\fattachment}\n");\r
210 +       json_object_set (part_obj, "filename", \r
211 +                        json_string (filename));\r
212  \r
213 -       return;\r
214 -    }\r
215 +    };\r
216  \r
217 -    content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));\r
218  \r
219 -    printf ("\fpart{ ID: %d, Content-type: %s\n",\r
220 -           *part_count,\r
221 -           g_mime_content_type_to_string (content_type));\r
222 +    if (g_mime_content_type_is_type (content_type, "text", "*"))\r
223 +       json_object_set (part_obj, "text", show_part_content (part));\r
224 +       \r
225  \r
226 -    if (g_mime_content_type_is_type (content_type, "text", "*") &&\r
227 -       !g_mime_content_type_is_type (content_type, "text", "html"))\r
228 -    {\r
229 -       show_part_content (part);\r
230 -    }\r
231 -    else\r
232 -    {\r
233 -       printf ("Non-text part: %s\n",\r
234 -               g_mime_content_type_to_string (content_type));\r
235 -    }\r
236 +    json_array_append(output,part_obj);\r
237  \r
238 -    printf ("\fpart}\n");\r
239  }\r
240  \r
241  static void\r
242 @@ -154,32 +151,33 @@ show_message (void *ctx, notmuch_message_t *message, int indent)\r
243      };\r
244      const char *name, *value;\r
245      unsigned int i;\r
246 +    json_t *message_obj=json_object();\r
247 +    json_t *header_obj=json_object();\r
248 +    json_t *parts=json_array();\r
249  \r
250 -    printf ("\fmessage{ id:%s depth:%d match:%d filename:%s\n",\r
251 -           notmuch_message_get_message_id (message),\r
252 -           indent,\r
253 -           notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH),\r
254 -           notmuch_message_get_filename (message));\r
255 +    // all of these calls need return-value checking\r
256 +    json_object_set(message_obj,"id",json_string (notmuch_message_get_message_id (message)));\r
257 +    json_object_set(message_obj,"depth",json_integer (indent));\r
258 +    json_object_set(message_obj,"match",\r
259 +                   notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH) ? json_true() : json_false());\r
260 +    json_object_set(message_obj,"filename",json_string (notmuch_message_get_filename (message)));\r
261  \r
262 -    printf ("\fheader{\n");\r
263 -\r
264 -    printf ("%s\n", _get_one_line_summary (ctx, message));\r
265 +    json_object_set(header_obj,"summary", json_string (_get_one_line_summary (ctx, message)));\r
266  \r
267      for (i = 0; i < ARRAY_SIZE (headers); i++) {\r
268         name = headers[i];\r
269         value = notmuch_message_get_header (message, name);\r
270         if (value)\r
271 -           printf ("%s: %s\n", name, value);\r
272 +         json_object_set (header_obj, name, json_string (value));\r
273      }\r
274  \r
275 -    printf ("\fheader}\n");\r
276 -    printf ("\fbody{\n");\r
277 -\r
278 -    show_message_body (notmuch_message_get_filename (message), show_part);\r
279 +    json_object_set (message_obj, "header", header_obj);\r
280  \r
281 -    printf ("\fbody}\n");\r
282 +    show_message_body (notmuch_message_get_filename (message), show_part, parts);\r
283 +    \r
284 +    json_object_set (message_obj, "parts", parts);\r
285 +    json_dumpf(message_obj,stdout,JSON_INDENT(4));\r
286  \r
287 -    printf ("\fmessage}\n");\r
288  }\r
289  \r
290  \r
291 diff --git a/show-message.c b/show-message.c\r
292 index 784981b..e41f51c 100644\r
293 --- a/show-message.c\r
294 +++ b/show-message.c\r
295 @@ -24,7 +24,7 @@\r
296  \r
297  static void\r
298  show_message_part (GMimeObject *part, int *part_count,\r
299 -                  void (*show_part) (GMimeObject *part, int *part_count))\r
300 +                  void (*show_part) (GMimeObject *part, int *part_count, void *argument), void *output)\r
301  {\r
302      *part_count = *part_count + 1;\r
303  \r
304 @@ -34,7 +34,7 @@ show_message_part (GMimeObject *part, int *part_count,\r
305  \r
306         for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {\r
307             show_message_part (g_mime_multipart_get_part (multipart, i),\r
308 -                              part_count, show_part);\r
309 +                              part_count, show_part, output);\r
310         }\r
311         return;\r
312      }\r
313 @@ -45,7 +45,7 @@ show_message_part (GMimeObject *part, int *part_count,\r
314         mime_message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (part));\r
315  \r
316         show_message_part (g_mime_message_get_mime_part (mime_message),\r
317 -                          part_count, show_part);\r
318 +                          part_count, show_part, output);\r
319  \r
320         return;\r
321      }\r
322 @@ -56,12 +56,12 @@ show_message_part (GMimeObject *part, int *part_count,\r
323         return;\r
324      }\r
325  \r
326 -    (*show_part) (part, part_count);\r
327 +    (*show_part) (part, part_count, output);\r
328  }\r
329  \r
330  notmuch_status_t\r
331  show_message_body (const char *filename,\r
332 -                  void (*show_part) (GMimeObject *part, int *part_count))\r
333 +                  void (*show_part) (GMimeObject *part, int *part_count, void *argument), void *output)\r
334  {\r
335      GMimeStream *stream = NULL;\r
336      GMimeParser *parser = NULL;\r
337 @@ -85,7 +85,7 @@ show_message_body (const char *filename,\r
338      mime_message = g_mime_parser_construct_message (parser);\r
339  \r
340      show_message_part (g_mime_message_get_mime_part (mime_message),\r
341 -                      &part_count, show_part);\r
342 +                      &part_count, show_part, output);\r
343  \r
344    DONE:\r
345      if (mime_message)\r
346 -- \r
347 1.6.5.3\r
348 \r