Rename "notmuch cat" to "notmuch show --format=raw"

This is part of an effort to avoid proliferation of excessive
top-level notmuch commands. Also, "raw" better captures the
functionality here, (as opposed to "cat" which is a fairly oblique
reference to a bad Unix abbreviation whose metaphor doesn't work here
since "notmuch cat" operates only on a single message and hence cannot
"con'cat'enate" anything).
This commit is contained in:
Carl Worth 2010-11-06 12:03:51 -07:00
parent 581ea7c8d3
commit 81d3bd3670
6 changed files with 124 additions and 137 deletions

View file

@ -88,7 +88,7 @@ any given message."
(let ((id (notmuch-show-get-message-id))) (let ((id (notmuch-show-get-message-id)))
(let ((buf (generate-new-buffer (concat "*notmuch-msg-" id "*")))) (let ((buf (generate-new-buffer (concat "*notmuch-msg-" id "*"))))
(with-current-buffer buf (with-current-buffer buf
(call-process notmuch-command nil t nil "cat" id) (call-process notmuch-command nil t nil "show" "--format=raw" id)
,@body) ,@body)
(kill-buffer buf))))) (kill-buffer buf)))))
@ -921,7 +921,7 @@ any effects from previous calls to
(let ((buf (get-buffer-create (concat "*notmuch-raw-" id "*")))) (let ((buf (get-buffer-create (concat "*notmuch-raw-" id "*"))))
(switch-to-buffer buf) (switch-to-buffer buf)
(save-excursion (save-excursion
(call-process notmuch-command nil t nil "cat" id))))) (call-process notmuch-command nil t nil "show" "--format=raw" id)))))
(defun notmuch-show-pipe-message (entire-thread command) (defun notmuch-show-pipe-message (entire-thread command)
"Pipe the contents of the current message (or thread) to the given command. "Pipe the contents of the current message (or thread) to the given command.
@ -942,7 +942,7 @@ than only the current message."
(mapconcat 'identity (notmuch-show-get-message-ids-for-open-messages) " OR ")) (mapconcat 'identity (notmuch-show-get-message-ids-for-open-messages) " OR "))
" | " command)) " | " command))
(setq shell-command (setq shell-command
(concat "notmuch cat " (shell-quote-argument (notmuch-show-get-message-id)) " | " command))) (concat "notmuch show --format=raw " (shell-quote-argument (notmuch-show-get-message-id)) " | " command)))
(start-process-shell-command "notmuch-pipe-command" "*notmuch-pipe*" shell-command))) (start-process-shell-command "notmuch-pipe-command" "*notmuch-pipe*" shell-command)))
(defun notmuch-show-add-tags-worker (current-tags add-tags) (defun notmuch-show-add-tags-worker (current-tags add-tags)

View file

@ -528,21 +528,105 @@ show_messages (void *ctx, const show_format_t *format, notmuch_messages_t *messa
fputs (format->message_set_end, stdout); fputs (format->message_set_end, stdout);
} }
/* Support for --format=raw */
static int
do_show_raw (unused(void *ctx), notmuch_query_t *query)
{
notmuch_messages_t *messages;
notmuch_message_t *message;
const char *filename;
FILE *file;
size_t size;
char buf[4096];
if (notmuch_query_count_messages (query) != 1) {
fprintf (stderr, "Error: search term did not match precisely one message.\n");
return 1;
}
messages = notmuch_query_search_messages (query);
message = notmuch_messages_get (messages);
if (message == NULL) {
fprintf (stderr, "Error: Cannot find matching message.\n");
return 1;
}
filename = notmuch_message_get_filename (message);
if (filename == NULL) {
fprintf (stderr, "Error: Cannot message filename.\n");
return 1;
}
file = fopen (filename, "r");
if (file == NULL) {
fprintf (stderr, "Error: Cannot open file %s: %s\n", filename, strerror (errno));
return 1;
}
while (!feof (file)) {
size = fread (buf, 1, sizeof (buf), file);
fwrite (buf, size, 1, stdout);
}
fclose (file);
return 0;
}
/* Support for --format=text|json|mbox */
static int
do_show (void *ctx,
notmuch_query_t *query,
const show_format_t *format,
int entire_thread)
{
notmuch_threads_t *threads;
notmuch_thread_t *thread;
notmuch_messages_t *messages;
int first_toplevel = 1;
fputs (format->message_set_start, stdout);
for (threads = notmuch_query_search_threads (query);
notmuch_threads_valid (threads);
notmuch_threads_move_to_next (threads))
{
thread = notmuch_threads_get (threads);
messages = notmuch_thread_get_toplevel_messages (thread);
if (messages == NULL)
INTERNAL_ERROR ("Thread %s has no toplevel messages.\n",
notmuch_thread_get_thread_id (thread));
if (!first_toplevel)
fputs (format->message_set_sep, stdout);
first_toplevel = 0;
show_messages (ctx, format, messages, 0, entire_thread);
notmuch_thread_destroy (thread);
}
fputs (format->message_set_end, stdout);
return 0;
}
int int
notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
{ {
notmuch_config_t *config; notmuch_config_t *config;
notmuch_database_t *notmuch; notmuch_database_t *notmuch;
notmuch_query_t *query; notmuch_query_t *query;
notmuch_threads_t *threads;
notmuch_thread_t *thread;
notmuch_messages_t *messages;
char *query_string; char *query_string;
char *opt; char *opt;
const show_format_t *format = &format_text; const show_format_t *format = &format_text;
int entire_thread = 0; int entire_thread = 0;
int i; int i;
int first_toplevel = 1; int raw = 0;
for (i = 0; i < argc && argv[i][0] == '-'; i++) { for (i = 0; i < argc && argv[i][0] == '-'; i++) {
if (strcmp (argv[i], "--") == 0) { if (strcmp (argv[i], "--") == 0) {
@ -558,6 +642,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
entire_thread = 1; entire_thread = 1;
} else if (strcmp (opt, "mbox") == 0) { } else if (strcmp (opt, "mbox") == 0) {
format = &format_mbox; format = &format_mbox;
} else if (strcmp (opt, "raw") == 0) {
raw = 1;
} else { } else {
fprintf (stderr, "Invalid value for --format: %s\n", opt); fprintf (stderr, "Invalid value for --format: %s\n", opt);
return 1; return 1;
@ -599,115 +685,11 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
return 1; return 1;
} }
fputs (format->message_set_start, stdout); if (raw)
return do_show_raw (ctx, query);
else
return do_show (ctx, query, format, entire_thread);
for (threads = notmuch_query_search_threads (query);
notmuch_threads_valid (threads);
notmuch_threads_move_to_next (threads))
{
thread = notmuch_threads_get (threads);
messages = notmuch_thread_get_toplevel_messages (thread);
if (messages == NULL)
INTERNAL_ERROR ("Thread %s has no toplevel messages.\n",
notmuch_thread_get_thread_id (thread));
if (!first_toplevel)
fputs (format->message_set_sep, stdout);
first_toplevel = 0;
show_messages (ctx, format, messages, 0, entire_thread);
notmuch_thread_destroy (thread);
}
fputs (format->message_set_end, stdout);
notmuch_query_destroy (query);
notmuch_database_close (notmuch);
return 0;
}
int
notmuch_cat_command (void *ctx, unused (int argc), unused (char *argv[]))
{
notmuch_config_t *config;
notmuch_database_t *notmuch;
notmuch_query_t *query;
notmuch_messages_t *messages;
notmuch_message_t *message;
char *query_string;
int i;
const char *filename;
FILE *file;
size_t size;
char buf[4096];
for (i = 0; i < argc && argv[i][0] == '-'; i++) {
fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
return 1;
}
config = notmuch_config_open (ctx, NULL, NULL);
if (config == NULL)
return 1;
query_string = query_string_from_args (ctx, argc, argv);
if (query_string == NULL) {
fprintf (stderr, "Out of memory\n");
return 1;
}
if (*query_string == '\0') {
fprintf (stderr, "Error: notmuch cat requires at least one search term.\n");
return 1;
}
notmuch = notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_ONLY);
if (notmuch == NULL)
return 1;
query = notmuch_query_create (notmuch, query_string);
if (query == NULL) {
fprintf (stderr, "Error: Out of memory\n");
return 1;
}
if (notmuch_query_count_messages (query) != 1) {
fprintf (stderr, "Error: search term did not match precisely one message.\n");
return 1;
}
messages = notmuch_query_search_messages (query);
message = notmuch_messages_get (messages);
if (message == NULL) {
fprintf (stderr, "Error: Cannot find matching message.\n");
return 1;
}
filename = notmuch_message_get_filename (message);
if (filename == NULL) {
fprintf (stderr, "Error: Cannot message filename.\n");
return 1;
}
file = fopen (filename, "r");
if (file == NULL) {
fprintf (stderr, "Error: Cannot open file %s: %s\n", filename, strerror (errno));
return 1;
}
while (!feof (file)) {
size = fread (buf, 1, sizeof (buf), file);
fwrite (buf, size, 1, stdout);
}
fclose (file);
notmuch_query_destroy (query); notmuch_query_destroy (query);
notmuch_database_close (notmuch); notmuch_database_close (notmuch);

View file

@ -248,7 +248,7 @@ matched message will be displayed.
.RS 4 .RS 4
.TP 4 .TP 4
.B \-\-format=(text|json|mbox) .B \-\-format=(text|json|mbox|raw)
.RS 4 .RS 4
.TP 4 .TP 4
@ -286,6 +286,16 @@ beginning with "From " (preceded by zero or more '>' characters) have
an additional '>' character added. This reversible escaping an additional '>' character added. This reversible escaping
is termed "mboxrd" format and described in detail here: is termed "mboxrd" format and described in detail here:
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html
.RE
.RS 4
.TP 4
.B raw
The original, raw content of the email message is displayed.
Consumers of this format should expect to implement MIME decoding and
similar functions. This format must only be used with search terms
matching a single message.
.RE .RE
A common use of A common use of
.B notmuch show .B notmuch show
@ -300,10 +310,6 @@ See the
section below for details of the supported syntax for <search-terms>. section below for details of the supported syntax for <search-terms>.
.RE .RE
.TP .TP
.BR cat " <search-term>..."
Output raw content of a single message matched by the search term.
.TP
.BR count " <search-term>..." .BR count " <search-term>..."
Count messages matching the search terms. Count messages matching the search terms.

View file

@ -222,7 +222,7 @@ command_t commands[] = {
"\t\tall messages in the same thread as any matched\n" "\t\tall messages in the same thread as any matched\n"
"\t\tmessage will be displayed.\n" "\t\tmessage will be displayed.\n"
"\n" "\n"
"\t--format=(text|json|mbox)\n" "\t--format=(text|json|mbox|raw)\n"
"\n" "\n"
"\t\ttext (default)\n" "\t\ttext (default)\n"
"\n" "\n"
@ -254,6 +254,13 @@ command_t commands[] = {
"\n" "\n"
"\t\thttp://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html\n" "\t\thttp://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html\n"
"\n" "\n"
"\t\traw\n"
"\n"
"\t\tThe original, raw content of the email message is displayed.\n"
"\t\tConsumers of this format should expect to implement MIME\n"
"\t\tdecoding and similar functions. This format must only\n"
"\t\tbe used with search terms matching a single message.\n"
"\n"
"\tA common use of \"notmuch show\" is to display a single\n" "\tA common use of \"notmuch show\" is to display a single\n"
"\tthread of email messages. For this, use a search term of\n" "\tthread of email messages. For this, use a search term of\n"
"\t\"thread:<thread-id>\" as can be seen in the first column\n" "\t\"thread:<thread-id>\" as can be seen in the first column\n"
@ -343,10 +350,6 @@ command_t commands[] = {
"\tcontain tags only from messages that match the search-term(s).\n" "\tcontain tags only from messages that match the search-term(s).\n"
"\n" "\n"
"\tIn both cases the list will be alphabetically sorted." }, "\tIn both cases the list will be alphabetically sorted." },
{ "cat", notmuch_cat_command,
"<search-terms>",
"Output raw content of a single message matched by the search term.",
"" },
{ "part", notmuch_part_command, { "part", notmuch_part_command,
"--part=<num> <search-terms>", "--part=<num> <search-terms>",
"Output a single MIME part of a message.", "Output a single MIME part of a message.",

View file

@ -16,7 +16,7 @@ fi
cd $(dirname "$0") cd $(dirname "$0")
TESTS="basic new search json thread-naming reply cat dump-restore uuencode thread-order author-order from-guessing long-id encoding emacs" TESTS="basic new search json thread-naming raw reply dump-restore uuencode thread-order author-order from-guessing long-id encoding emacs"
# Clean up any results from a previous run # Clean up any results from a previous run
rm -r test-results >/dev/null 2>/dev/null rm -r test-results >/dev/null 2>/dev/null

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
test_description='notmuch cat' test_description='notmuch show --format=raw'
. ./test-lib.sh . ./test-lib.sh
test_begin_subtest "Generate some messages" test_begin_subtest "Generate some messages"
@ -9,16 +9,12 @@ generate_message
output=$(NOTMUCH_NEW) output=$(NOTMUCH_NEW)
test_expect_equal "$output" "Added 2 new messages to the database." test_expect_equal "$output" "Added 2 new messages to the database."
test_begin_subtest "Without arguments" test_begin_subtest "Attempt to show multiple raw messages"
output=$(notmuch cat 2>&1) output=$(notmuch show --format=raw "*" 2>&1)
test_expect_equal "$output" "Error: notmuch cat requires at least one search term."
test_begin_subtest "Attempt to cat multiple messages"
output=$(notmuch cat "*" 2>&1)
test_expect_equal "$output" "Error: search term did not match precisely one message." test_expect_equal "$output" "Error: search term did not match precisely one message."
test_begin_subtest "Cat a message" test_begin_subtest "Show a raw message"
output=$(notmuch cat id:msg-001@notmuch-test-suite) output=$(notmuch show --format=raw id:msg-001@notmuch-test-suite)
test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org> test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
To: Notmuch Test Suite <test_suite@notmuchmail.org> To: Notmuch Test Suite <test_suite@notmuchmail.org>
Message-Id: <msg-001@notmuch-test-suite> Message-Id: <msg-001@notmuch-test-suite>
@ -27,8 +23,8 @@ Date: Tue, 05 Jan 2001 15:43:57 -0000
This is just a test message (#1)" This is just a test message (#1)"
test_begin_subtest "Cat another message" test_begin_subtest "Show another raw message"
output=$(notmuch cat id:msg-002@notmuch-test-suite) output=$(notmuch show --format=raw id:msg-002@notmuch-test-suite)
test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org> test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
To: Notmuch Test Suite <test_suite@notmuchmail.org> To: Notmuch Test Suite <test_suite@notmuchmail.org>
Message-Id: <msg-002@notmuch-test-suite> Message-Id: <msg-002@notmuch-test-suite>