From: Hannu Hartikainen <hannu@hrtk.in>
To: notmuch@notmuchmail.org
Cc: Hannu Hartikainen <hannu@hrtk.in>
Subject: [PATCH v2] cli/show: add --format=pretty
Date: Fri, 2 Jul 2021 23:31:53 +0300 [thread overview]
Message-ID: <20210702203153.47289-1-hannu@hrtk.in> (raw)
In-Reply-To: <20210619203838.275767-1-hannu@hrtk.in>
The rationale for this feature is twofold:
1. It is useful to be able to view messages in as human-friendly format
as possible.
2. The same format should still be machine-readable, too.
The email format is mostly human-readable as is. The things difficult
for a human eye are the huge amount of headers that are common these
days and telling different messages apart when there are many.
This commit adds the display format `pretty`. It recognizes if the
output is a TTY and if so, applies coloring to headers. This turns out
to be a good visual message separator. Additionally it only shows the
most important headers, similarly to `--format=text`, and only displays
plaintext parts (ie. text/* but not text/html).
While human readability is the main goal, another design goal was that
piping the output to `git am` works, at least for individual messages
sent with `git send-email`.
---
I wrote a v2 of this patch. I've been dogfooding for a while now and
wanted a couple of enhancements, and also had learned about the notmuch
test harness. The differences to the first version are:
- add a unit test
- show Message-ID, making replying etc. much easier
- print a newline after each part, which helps a lot with messages that
do not end in a newline
I'm using this as a daily driver and am happy with it.
NEWS | 7 ++++
completion/notmuch-completion.bash | 2 +-
completion/zsh/_notmuch | 2 +-
doc/man1/notmuch-show.rst | 8 +++-
notmuch-show.c | 67 ++++++++++++++++++++++++++++++
test/T520-show.sh | 32 ++++++++++++++
6 files changed, 115 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index 3e776009..f5142ff1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,13 @@
Notmuch 0.33 (UNRELEASED)
=========================
+CLI
+---
+
+`notmuch show` now has `--format=pretty`, optimized for reading plain
+text emails on the command line. It only shows the most important
+headers and plain text parts and uses colors for headers.
+
Emacs
-----
diff --git a/completion/notmuch-completion.bash b/completion/notmuch-completion.bash
index 15425697..86cbbcdc 100644
--- a/completion/notmuch-completion.bash
+++ b/completion/notmuch-completion.bash
@@ -514,7 +514,7 @@ _notmuch_show()
return
;;
--format)
- COMPREPLY=( $( compgen -W "text json sexp mbox raw" -- "${cur}" ) )
+ COMPREPLY=( $( compgen -W "text pretty json sexp mbox raw" -- "${cur}" ) )
return
;;
--exclude|--body)
diff --git a/completion/zsh/_notmuch b/completion/zsh/_notmuch
index e920f10b..5cc386e2 100644
--- a/completion/zsh/_notmuch
+++ b/completion/zsh/_notmuch
@@ -237,7 +237,7 @@ _notmuch_search() {
_notmuch_show() {
_arguments -S \
'--entire-thread=[output entire threads]:show thread:(true false)' \
- '--format=[set output format]:output format:(text json sexp mbox raw)' \
+ '--format=[set output format]:output format:(text pretty json sexp mbox raw)' \
'--format-version=[set output format version]:format version: ' \
'--part=[output a single decoded mime part]:part number: ' \
'--verify[verify signed MIME parts]' \
diff --git a/doc/man1/notmuch-show.rst b/doc/man1/notmuch-show.rst
index fc6bec62..1fe4dcc7 100644
--- a/doc/man1/notmuch-show.rst
+++ b/doc/man1/notmuch-show.rst
@@ -34,7 +34,7 @@ Supported options for **show** include
the matching messages. For ``--format=json`` and ``--format=sexp``
this defaults to true. For other formats, this defaults to false.
-.. option:: --format=(text|json|sexp|mbox|raw)
+.. option:: --format=(text|pretty|json|sexp|mbox|raw)
**text** (default for messages)
The default plain-text format has all text-content MIME parts
@@ -46,6 +46,12 @@ Supported options for **show** include
'}'), to either open or close the component. For a multipart
MIME message, these parts will be nested.
+ **pretty**
+ The plain-text parts of all matching messages are printed in a
+ format optimized for readability. Only the most important
+ headers are displayed. If the output is to a TTY, the headers
+ are colored.
+
**json**
The output is formatted with Javascript Object Notation
(JSON). This format is more robust than the text format for
diff --git a/notmuch-show.c b/notmuch-show.c
index 232557d5..c417ec00 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -606,6 +606,65 @@ format_part_text (const void *ctx, sprinter_t *sp, mime_node_t *node,
return NOTMUCH_STATUS_SUCCESS;
}
+static notmuch_status_t
+format_part_pretty (const void *ctx, sprinter_t *sp, mime_node_t *node,
+ int indent, const notmuch_show_params_t *params)
+{
+ /* The disposition and content-type metadata are associated with
+ * the envelope for message parts */
+ GMimeObject *meta = node->envelope_part ? (
+ GMIME_OBJECT (node->envelope_part) ) : node->part;
+ GMimeContentType *content_type = g_mime_object_get_content_type (meta);
+ GMimeStream *stream = params->out_stream;
+ int i;
+ bool color = isatty (fileno (stdout));
+
+ if (GMIME_IS_MESSAGE (node->part)) {
+ GMimeMessage *message = GMIME_MESSAGE (node->part);
+ char *recipients_string;
+ char *date_string;
+
+ if (color)
+ g_mime_stream_printf (stream, "\e[36m");
+ g_mime_stream_printf (stream, "Subject: %s\n", g_mime_message_get_subject (message));
+ if (color)
+ g_mime_stream_printf (stream, "\e[33m");
+ g_mime_stream_printf (stream, "From: %s\n", g_mime_message_get_from_string (message));
+ if (color)
+ g_mime_stream_printf (stream, "\e[31m");
+ recipients_string = g_mime_message_get_address_string (message, GMIME_ADDRESS_TYPE_TO);
+ if (recipients_string)
+ g_mime_stream_printf (stream, "To: %s\n", recipients_string);
+ g_free (recipients_string);
+ recipients_string = g_mime_message_get_address_string (message, GMIME_ADDRESS_TYPE_CC);
+ if (recipients_string)
+ g_mime_stream_printf (stream, "Cc: %s\n", recipients_string);
+ g_free (recipients_string);
+ date_string = g_mime_message_get_date_string (node, message);
+ if (color)
+ g_mime_stream_printf (stream, "\e[35m");
+ g_mime_stream_printf (stream, "Date: %s\n", date_string);
+ if (color)
+ g_mime_stream_printf (stream, "\e[32m");
+ g_mime_stream_printf (stream, "Message-ID: <%s>\n\n", g_mime_message_get_message_id (
+ message));
+ if (color)
+ g_mime_stream_printf (stream, "\e[0m");
+ }
+
+ if (GMIME_IS_PART (node->part) &&
+ g_mime_content_type_is_type (content_type, "text", "*") &&
+ ! g_mime_content_type_is_type (content_type, "text", "html")) {
+ show_text_part_content (node->part, stream, 0);
+ g_mime_stream_printf (stream, "\n");
+ }
+
+ for (i = 0; i < node->nchildren; i++)
+ format_part_pretty (ctx, sp, mime_node_child (node, i), indent, params);
+
+ return NOTMUCH_STATUS_SUCCESS;
+}
+
static void
format_omitted_part_meta_sprinter (sprinter_t *sp, GMimeObject *meta, GMimePart *part)
{
@@ -1192,6 +1251,7 @@ enum {
NOTMUCH_FORMAT_JSON,
NOTMUCH_FORMAT_SEXP,
NOTMUCH_FORMAT_TEXT,
+ NOTMUCH_FORMAT_PRETTY,
NOTMUCH_FORMAT_MBOX,
NOTMUCH_FORMAT_RAW
};
@@ -1211,6 +1271,11 @@ static const notmuch_show_format_t format_text = {
.part = format_part_text,
};
+static const notmuch_show_format_t format_pretty = {
+ .new_sprinter = sprinter_text_create,
+ .part = format_part_pretty,
+};
+
static const notmuch_show_format_t format_mbox = {
.new_sprinter = sprinter_text_create,
.part = format_part_mbox,
@@ -1225,6 +1290,7 @@ static const notmuch_show_format_t *formatters[] = {
[NOTMUCH_FORMAT_JSON] = &format_json,
[NOTMUCH_FORMAT_SEXP] = &format_sexp,
[NOTMUCH_FORMAT_TEXT] = &format_text,
+ [NOTMUCH_FORMAT_PRETTY] = &format_pretty,
[NOTMUCH_FORMAT_MBOX] = &format_mbox,
[NOTMUCH_FORMAT_RAW] = &format_raw,
};
@@ -1254,6 +1320,7 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
{ .opt_keyword = &format, .name = "format", .keywords =
(notmuch_keyword_t []){ { "json", NOTMUCH_FORMAT_JSON },
{ "text", NOTMUCH_FORMAT_TEXT },
+ { "pretty", NOTMUCH_FORMAT_PRETTY },
{ "sexp", NOTMUCH_FORMAT_SEXP },
{ "mbox", NOTMUCH_FORMAT_MBOX },
{ "raw", NOTMUCH_FORMAT_RAW },
diff --git a/test/T520-show.sh b/test/T520-show.sh
index 16222650..e555b284 100755
--- a/test/T520-show.sh
+++ b/test/T520-show.sh
@@ -10,4 +10,36 @@ notmuch show foo..
exit_code=$?
test_expect_equal 1 $exit_code
+test_begin_subtest "--format=pretty"
+output=$(notmuch show --format=pretty id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com 2>&1 && echo OK)
+test_expect_equal "$output" "Subject: [notmuch] preliminary FreeBSD support
+From: Alex Botero-Lowry <alex.boterolowry@gmail.com>
+To: notmuch@notmuchmail.org
+Date: Tue, 17 Nov 2009 11:36:14 -0800
+Message-ID: <cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com>
+
+I saw the announcement this morning, and was very excited, as I had been
+hoping sup would be turned into a library,
+since I like the concept more than the UI (I'd rather an emacs interface).
+
+I did a preliminary compile which worked out fine, but
+sysconf(_SC_SC_GETPW_R_SIZE_MAX) returns -1 on
+FreeBSD, so notmuch_config_open segfaulted.
+
+Attached is a patch that supplies a default buffer size of 64 in cases where
+-1 is returned.
+
+http://www.opengroup.org/austin/docs/austin_328.txt - seems to indicate this
+is acceptable behavior,
+and http://mail-index.netbsd.org/pkgsrc-bugs/2006/06/07/msg016808.htmlspecifically
+uses 64 as the
+buffer size.
+
+_______________________________________________
+notmuch mailing list
+notmuch@notmuchmail.org
+http://notmuchmail.org/mailman/listinfo/notmuch
+
+OK"
+
test_done
--
2.32.0
next prev parent reply other threads:[~2021-07-02 20:32 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-19 20:38 [PATCH] cli/show: add --format=pretty Hannu Hartikainen
2021-06-22 12:34 ` [PATCH] cli/show: add --color/--no-color Hannu Hartikainen
2021-07-12 8:38 ` Yet another revision of --format=pretty Hannu Hartikainen
2021-07-12 8:38 ` [PATCH v3 1/2] cli/show: add --format=pretty Hannu Hartikainen
2021-07-12 23:40 ` David Bremner
2021-07-13 10:24 ` David Bremner
2021-07-13 11:50 ` Hannu Hartikainen
2021-07-12 8:38 ` [PATCH v3 2/2] cli/show: add color for --format=pretty Hannu Hartikainen
2021-07-12 23:19 ` Yet another revision of --format=pretty David Bremner
2021-07-13 12:07 ` Hannu Hartikainen
2021-07-02 20:31 ` Hannu Hartikainen [this message]
2021-07-04 9:40 ` [PATCH v2] cli/show: add --format=pretty Tomi Ollila
2021-07-04 11:54 ` Hannu Hartikainen
2021-07-04 14:38 ` [PATCH] " David Bremner
2021-07-05 13:31 ` Hannu Hartikainen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://notmuchmail.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210702203153.47289-1-hannu@hrtk.in \
--to=hannu@hrtk.in \
--cc=notmuch@notmuchmail.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://yhetil.org/notmuch.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).