]> git.cworth.org Git - notmuch/blobdiff - notmuch-show.c
emacs: Add new option notmuch-search-hide-excluded
[notmuch] / notmuch-show.c
index 2848c9c39372fcbad778231c625632119b8e4faa..7fb40ce9ab5d3f0179707a7c0ea88f9440673f25 100644 (file)
 #include "sprinter.h"
 #include "zlib-extra.h"
 
+static const char *
+_get_filename (notmuch_message_t *message, int index)
+{
+    notmuch_filenames_t *filenames = notmuch_message_get_filenames (message);
+    int i = 1;
+
+    for (;
+        notmuch_filenames_valid (filenames);
+        notmuch_filenames_move_to_next (filenames), i++) {
+       if (i >= index)
+           return notmuch_filenames_get (filenames);
+    }
+    return NULL;
+}
+
 static const char *
 _get_tags_as_string (const void *ctx, notmuch_message_t *message)
 {
@@ -209,6 +224,30 @@ _is_from_line (const char *line)
        return 0;
 }
 
+/* Output extra headers if configured with the `show.extra_headers'
+ * configuration option
+ */
+static void
+format_extra_headers_sprinter (sprinter_t *sp, GMimeMessage *message)
+{
+    GMimeHeaderList *header_list = g_mime_object_get_header_list (GMIME_OBJECT (message));
+
+    for (notmuch_config_values_t *extra_headers = notmuch_config_get_values (
+            sp->notmuch, NOTMUCH_CONFIG_EXTRA_HEADERS);
+        notmuch_config_values_valid (extra_headers);
+        notmuch_config_values_move_to_next (extra_headers)) {
+       GMimeHeader *header;
+       const char *header_name = notmuch_config_values_get (extra_headers);
+
+       header = g_mime_header_list_get_header (header_list, header_name);
+       if (header == NULL)
+           continue;
+
+       sp->map_key (sp, g_mime_header_get_name (header));
+       sp->string (sp, g_mime_header_get_value (header));
+    }
+}
+
 void
 format_headers_sprinter (sprinter_t *sp, GMimeMessage *message,
                         bool reply, const _notmuch_message_crypto_t *msg_crypto)
@@ -269,6 +308,9 @@ format_headers_sprinter (sprinter_t *sp, GMimeMessage *message,
        sp->string (sp, g_mime_message_get_date_string (sp, message));
     }
 
+    /* Output extra headers the user has configured, if any */
+    if (! reply)
+       format_extra_headers_sprinter (sp, message);
     sp->end (sp);
     talloc_free (local);
 }
@@ -631,6 +673,7 @@ format_omitted_part_meta_sprinter (sprinter_t *sp, GMimeObject *meta, GMimePart
 
 void
 format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
+                     int duplicate,
                      bool output_body,
                      bool include_html)
 {
@@ -642,10 +685,13 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
        sp->begin_map (sp);
        format_message_sprinter (sp, node->envelope_file);
 
+       sp->map_key (sp, "duplicate");
+       sp->integer (sp, duplicate > 0 ? duplicate : 1);
+
        if (output_body) {
            sp->map_key (sp, "body");
            sp->begin_list (sp);
-           format_part_sprinter (ctx, sp, mime_node_child (node, 0), true, include_html);
+           format_part_sprinter (ctx, sp, mime_node_child (node, 0), -1, true, include_html);
            sp->end (sp);
        }
 
@@ -809,7 +855,7 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
     }
 
     for (i = 0; i < node->nchildren; i++)
-       format_part_sprinter (ctx, sp, mime_node_child (node, i), true, include_html);
+       format_part_sprinter (ctx, sp, mime_node_child (node, i), -1, true, include_html);
 
     /* Close content structures */
     for (i = 0; i < nclose; i++)
@@ -823,7 +869,8 @@ format_part_sprinter_entry (const void *ctx, sprinter_t *sp,
                            mime_node_t *node, unused (int indent),
                            const notmuch_show_params_t *params)
 {
-    format_part_sprinter (ctx, sp, node, params->output_body, params->include_html);
+    format_part_sprinter (ctx, sp, node, params->duplicate, params->output_body,
+                         params->include_html);
 
     return NOTMUCH_STATUS_SUCCESS;
 }
@@ -898,7 +945,7 @@ format_part_raw (unused (const void *ctx), unused (sprinter_t *sp),
        char buf[4096];
        notmuch_status_t ret = NOTMUCH_STATUS_FILE_ERROR;
 
-       filename = notmuch_message_get_filename (node->envelope_file);
+       filename = _get_filename (node->envelope_file, params->duplicate);
        if (filename == NULL) {
            fprintf (stderr, "Error: Cannot get message filename.\n");
            goto DONE;
@@ -977,7 +1024,7 @@ show_message (void *ctx,
        session_key_count_error = notmuch_message_count_properties (message, "session-key",
                                                                    &session_keys);
 
-    status = mime_node_open (local, message, &(params->crypto), &root);
+    status = mime_node_open (local, message, params->duplicate, &(params->crypto), &root);
     if (status)
        goto DONE;
     part = mime_node_seek_dfs (root, (params->part < 0 ? 0 : params->part));
@@ -1112,6 +1159,18 @@ do_show_threaded (void *ctx,
     notmuch_thread_t *thread;
     notmuch_messages_t *messages;
     notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
+    int i;
+
+    if (params->offset < 0) {
+       unsigned count;
+       notmuch_status_t s = notmuch_query_count_threads (query, &count);
+       if (print_status_query ("notmuch show", query, s))
+           return 1;
+
+       params->offset += count;
+       if (params->offset < 0)
+           params->offset = 0;
+    }
 
     status = notmuch_query_search_threads (query, &threads);
     if (print_status_query ("notmuch show", query, status))
@@ -1119,11 +1178,16 @@ do_show_threaded (void *ctx,
 
     sp->begin_list (sp);
 
-    for (;
-        notmuch_threads_valid (threads);
-        notmuch_threads_move_to_next (threads)) {
+    for (i = 0;
+        notmuch_threads_valid (threads) && (params->limit < 0 || i < params->offset + params->limit);
+        notmuch_threads_move_to_next (threads), i++) {
        thread = notmuch_threads_get (threads);
 
+       if (i < params->offset) {
+           notmuch_thread_destroy (thread);
+           continue;
+       }
+
        messages = notmuch_thread_get_toplevel_messages (thread);
 
        if (messages == NULL)
@@ -1154,6 +1218,18 @@ do_show_unthreaded (void *ctx,
     notmuch_message_t *message;
     notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
     notmuch_bool_t excluded;
+    int i;
+
+    if (params->offset < 0) {
+       unsigned count;
+       notmuch_status_t s = notmuch_query_count_messages (query, &count);
+       if (print_status_query ("notmuch show", query, s))
+           return 1;
+
+       params->offset += count;
+       if (params->offset < 0)
+           params->offset = 0;
+    }
 
     status = notmuch_query_search_messages (query, &messages);
     if (print_status_query ("notmuch show", query, status))
@@ -1161,9 +1237,13 @@ do_show_unthreaded (void *ctx,
 
     sp->begin_list (sp);
 
-    for (;
-        notmuch_messages_valid (messages);
-        notmuch_messages_move_to_next (messages)) {
+    for (i = 0;
+        notmuch_messages_valid (messages) && (params->limit < 0 || i < params->offset + params->limit);
+        notmuch_messages_move_to_next (messages), i++) {
+       if (i < params->offset) {
+           continue;
+       }
+
        sp->begin_list (sp);
        sp->begin_list (sp);
 
@@ -1239,6 +1319,9 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
     sprinter_t *sprinter;
     notmuch_show_params_t params = {
        .part = -1,
+       .duplicate = 0,
+       .offset = 0,
+       .limit = -1, /* unlimited */
        .omit_excluded = true,
        .output_body = true,
        .crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
@@ -1279,6 +1362,9 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
        { .opt_bool = &params.crypto.verify, .name = "verify" },
        { .opt_bool = &params.output_body, .name = "body" },
        { .opt_bool = &params.include_html, .name = "include-html" },
+       { .opt_int = &params.duplicate, .name = "duplicate" },
+       { .opt_int = &params.limit, .name = "limit" },
+       { .opt_int = &params.offset, .name = "offset" },
        { .opt_inherit = notmuch_shared_options },
        { }
     };
@@ -1297,6 +1383,9 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
     /* specifying a part implies single message display */
     single_message = params.part >= 0;
 
+    /* specifying a duplicate also implies single message display */
+    single_message = single_message || (params.duplicate > 0);
+
     if (format == NOTMUCH_FORMAT_NOT_SPECIFIED) {
        /* if part was requested and format was not specified, use format=raw */
        if (params.part >= 0)