mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-21 18:38:08 +01:00
cli: add options --offset and --limit to notmuch show
notmuch search does not output header values. However, when browsing
through a large email corpus, it can be time saving to be able to
paginate without running notmuch show for each message/thread.
Add --offset and --limit options to notmuch show. This is inspired from
commit 796b629c3b
("cli: add options --offset and --limit to notmuch
search").
Update man page, shell completion and add a test case to ensure it works
as expected.
Cc: Tim Culverhouse <tim@timculverhouse.com>
Cc: Tomi Ollila <tomi.ollila@iki.fi>
Signed-off-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
parent
b6565c1c54
commit
793f298091
6 changed files with 138 additions and 7 deletions
|
@ -530,7 +530,7 @@ _notmuch_show()
|
||||||
! $split &&
|
! $split &&
|
||||||
case "${cur}" in
|
case "${cur}" in
|
||||||
-*)
|
-*)
|
||||||
local options="--entire-thread= --format= --exclude= --body= --format-version= --part= --verify --decrypt= --include-html ${_notmuch_shared_options}"
|
local options="--entire-thread= --format= --exclude= --body= --format-version= --part= --verify --decrypt= --include-html --limit= --offset= ${_notmuch_shared_options}"
|
||||||
compopt -o nospace
|
compopt -o nospace
|
||||||
COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
|
COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -245,6 +245,8 @@ _notmuch_show() {
|
||||||
'--exclude=[respect excluded tags setting]:exclude tags:(true false)' \
|
'--exclude=[respect excluded tags setting]:exclude tags:(true false)' \
|
||||||
'--body=[output body]:output body content:(true false)' \
|
'--body=[output body]:output body content:(true false)' \
|
||||||
'--include-html[include text/html parts in the output]' \
|
'--include-html[include text/html parts in the output]' \
|
||||||
|
'--limit=[limit the number of displayed results]:limit: ' \
|
||||||
|
'--offset=[skip displaying the first N results]:offset: ' \
|
||||||
'*::search term:_notmuch_search_term'
|
'*::search term:_notmuch_search_term'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,15 @@ Supported options for **show** include
|
||||||
By default, results will be displayed in reverse chronological
|
By default, results will be displayed in reverse chronological
|
||||||
order, (that is, the newest results will be displayed first).
|
order, (that is, the newest results will be displayed first).
|
||||||
|
|
||||||
|
.. option:: --offset=[-]N
|
||||||
|
|
||||||
|
Skip displaying the first N results. With the leading '-', start
|
||||||
|
at the Nth result from the end.
|
||||||
|
|
||||||
|
.. option:: --limit=N
|
||||||
|
|
||||||
|
Limit the number of displayed results to N.
|
||||||
|
|
||||||
.. option:: --verify
|
.. option:: --verify
|
||||||
|
|
||||||
Compute and report the validity of any MIME cryptographic
|
Compute and report the validity of any MIME cryptographic
|
||||||
|
|
|
@ -77,6 +77,8 @@ typedef struct notmuch_show_params {
|
||||||
bool output_body;
|
bool output_body;
|
||||||
int duplicate;
|
int duplicate;
|
||||||
int part;
|
int part;
|
||||||
|
int offset;
|
||||||
|
int limit;
|
||||||
_notmuch_crypto_t crypto;
|
_notmuch_crypto_t crypto;
|
||||||
bool include_html;
|
bool include_html;
|
||||||
GMimeStream *out_stream;
|
GMimeStream *out_stream;
|
||||||
|
|
|
@ -1159,6 +1159,18 @@ do_show_threaded (void *ctx,
|
||||||
notmuch_thread_t *thread;
|
notmuch_thread_t *thread;
|
||||||
notmuch_messages_t *messages;
|
notmuch_messages_t *messages;
|
||||||
notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
|
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);
|
status = notmuch_query_search_threads (query, &threads);
|
||||||
if (print_status_query ("notmuch show", query, status))
|
if (print_status_query ("notmuch show", query, status))
|
||||||
|
@ -1166,11 +1178,16 @@ do_show_threaded (void *ctx,
|
||||||
|
|
||||||
sp->begin_list (sp);
|
sp->begin_list (sp);
|
||||||
|
|
||||||
for (;
|
for (i = 0;
|
||||||
notmuch_threads_valid (threads);
|
notmuch_threads_valid (threads) && (params->limit < 0 || i < params->offset + params->limit);
|
||||||
notmuch_threads_move_to_next (threads)) {
|
notmuch_threads_move_to_next (threads), i++) {
|
||||||
thread = notmuch_threads_get (threads);
|
thread = notmuch_threads_get (threads);
|
||||||
|
|
||||||
|
if (i < params->offset) {
|
||||||
|
notmuch_thread_destroy (thread);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
messages = notmuch_thread_get_toplevel_messages (thread);
|
messages = notmuch_thread_get_toplevel_messages (thread);
|
||||||
|
|
||||||
if (messages == NULL)
|
if (messages == NULL)
|
||||||
|
@ -1201,6 +1218,18 @@ do_show_unthreaded (void *ctx,
|
||||||
notmuch_message_t *message;
|
notmuch_message_t *message;
|
||||||
notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
|
notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
|
||||||
notmuch_bool_t excluded;
|
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);
|
status = notmuch_query_search_messages (query, &messages);
|
||||||
if (print_status_query ("notmuch show", query, status))
|
if (print_status_query ("notmuch show", query, status))
|
||||||
|
@ -1208,9 +1237,13 @@ do_show_unthreaded (void *ctx,
|
||||||
|
|
||||||
sp->begin_list (sp);
|
sp->begin_list (sp);
|
||||||
|
|
||||||
for (;
|
for (i = 0;
|
||||||
notmuch_messages_valid (messages);
|
notmuch_messages_valid (messages) && (params->limit < 0 || i < params->offset + params->limit);
|
||||||
notmuch_messages_move_to_next (messages)) {
|
notmuch_messages_move_to_next (messages), i++) {
|
||||||
|
if (i < params->offset) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sp->begin_list (sp);
|
sp->begin_list (sp);
|
||||||
sp->begin_list (sp);
|
sp->begin_list (sp);
|
||||||
|
|
||||||
|
@ -1287,6 +1320,8 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
notmuch_show_params_t params = {
|
notmuch_show_params_t params = {
|
||||||
.part = -1,
|
.part = -1,
|
||||||
.duplicate = 0,
|
.duplicate = 0,
|
||||||
|
.offset = 0,
|
||||||
|
.limit = -1, /* unlimited */
|
||||||
.omit_excluded = true,
|
.omit_excluded = true,
|
||||||
.output_body = true,
|
.output_body = true,
|
||||||
.crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
|
.crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
|
||||||
|
@ -1328,6 +1363,8 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
{ .opt_bool = ¶ms.output_body, .name = "body" },
|
{ .opt_bool = ¶ms.output_body, .name = "body" },
|
||||||
{ .opt_bool = ¶ms.include_html, .name = "include-html" },
|
{ .opt_bool = ¶ms.include_html, .name = "include-html" },
|
||||||
{ .opt_int = ¶ms.duplicate, .name = "duplicate" },
|
{ .opt_int = ¶ms.duplicate, .name = "duplicate" },
|
||||||
|
{ .opt_int = ¶ms.limit, .name = "limit" },
|
||||||
|
{ .opt_int = ¶ms.offset, .name = "offset" },
|
||||||
{ .opt_inherit = notmuch_shared_options },
|
{ .opt_inherit = notmuch_shared_options },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
81
test/T131-show-limiting.sh
Executable file
81
test/T131-show-limiting.sh
Executable file
|
@ -0,0 +1,81 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
test_description='"notmuch show" --offset and --limit parameters'
|
||||||
|
. $(dirname "$0")/test-lib.sh || exit 1
|
||||||
|
|
||||||
|
add_email_corpus
|
||||||
|
|
||||||
|
show () {
|
||||||
|
local kind="$1"
|
||||||
|
shift
|
||||||
|
if [ "$kind" = messages ]; then
|
||||||
|
set -- --unthreaded "$@"
|
||||||
|
fi
|
||||||
|
notmuch show --body=false --format=text --entire-thread=false "$@" "*" |
|
||||||
|
sed -nre 's/^.message\{.*\<depth:0\>.*/&/p'
|
||||||
|
}
|
||||||
|
|
||||||
|
for outp in messages threads; do
|
||||||
|
test_begin_subtest "$outp: limit does the right thing"
|
||||||
|
show $outp | head -n 20 >expected
|
||||||
|
show $outp --limit=20 >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: concatenation of limited shows"
|
||||||
|
show $outp | head -n 20 >expected
|
||||||
|
show $outp --limit=10 >output
|
||||||
|
show $outp --limit=10 --offset=10 >>output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: limit larger than result set"
|
||||||
|
N=$(notmuch count --output=$outp "*")
|
||||||
|
show $outp >expected
|
||||||
|
show $outp --limit=$((1 + N)) >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: limit = 0"
|
||||||
|
test_expect_equal "$(show $outp --limit=0)" ""
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: offset does the right thing"
|
||||||
|
# note: tail -n +N is 1-based
|
||||||
|
show $outp | tail -n +21 >expected
|
||||||
|
show $outp --offset=20 >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: offset = 0"
|
||||||
|
show $outp >expected
|
||||||
|
show $outp --offset=0 >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: negative offset"
|
||||||
|
show $outp | tail -n 20 >expected
|
||||||
|
show $outp --offset=-20 >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: negative offset"
|
||||||
|
show $outp | tail -n 1 >expected
|
||||||
|
show $outp --offset=-1 >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: negative offset combined with limit"
|
||||||
|
show $outp | tail -n 20 | head -n 10 >expected
|
||||||
|
show $outp --offset=-20 --limit=10 >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: negative offset combined with equal limit"
|
||||||
|
show $outp | tail -n 20 >expected
|
||||||
|
show $outp --offset=-20 --limit=20 >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: negative offset combined with large limit"
|
||||||
|
show $outp | tail -n 20 >expected
|
||||||
|
show $outp --offset=-20 --limit=50 >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
|
test_begin_subtest "$outp: negative offset larger than results"
|
||||||
|
N=$(notmuch count --output=$outp "*")
|
||||||
|
show $outp >expected
|
||||||
|
show $outp --offset=-$((1 + N)) >output
|
||||||
|
test_expect_equal_file expected output
|
||||||
|
done
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in a new issue