cli: add options --offset and --limit to notmuch search

Add options --offset=[-]N and --limit=M to notmuch search to determine the
first result and maximum number of results to display.

Option --limit=M limits the maximum number of results to display to M.

Option --offset=[-]N skips the first N results; with the leading '-' skip
until the Nth result from the end.

Note that --offset with a negative N for thread or summary output requires
counting the number of matching threads in advance.

Signed-off-by: Jani Nikula <jani@nikula.org>
This commit is contained in:
Jani Nikula 2011-11-15 22:08:49 +02:00 committed by David Bremner
parent 00c60fbcb3
commit 796b629c3b
4 changed files with 87 additions and 14 deletions

5
NEWS
View file

@ -23,6 +23,11 @@ Add search terms to "notmuch dump"
search/show/tag. The output file argument of dump is deprecated in search/show/tag. The output file argument of dump is deprecated in
favour of using stdout. favour of using stdout.
Add "notmuch search" --offset and --limit options
The search command now takes options --offset=[-]N and --limit=N to limit
the number of results shown.
Optimizations Optimizations
------------- -------------

View file

@ -194,13 +194,22 @@ static int
do_search_threads (const search_format_t *format, do_search_threads (const search_format_t *format,
notmuch_query_t *query, notmuch_query_t *query,
notmuch_sort_t sort, notmuch_sort_t sort,
output_t output) output_t output,
int offset,
int limit)
{ {
notmuch_thread_t *thread; notmuch_thread_t *thread;
notmuch_threads_t *threads; notmuch_threads_t *threads;
notmuch_tags_t *tags; notmuch_tags_t *tags;
time_t date; time_t date;
int first_thread = 1; int first_thread = 1;
int i;
if (offset < 0) {
offset += notmuch_query_count_threads (query);
if (offset < 0)
offset = 0;
}
threads = notmuch_query_search_threads (query); threads = notmuch_query_search_threads (query);
if (threads == NULL) if (threads == NULL)
@ -208,17 +217,22 @@ do_search_threads (const search_format_t *format,
fputs (format->results_start, stdout); fputs (format->results_start, stdout);
for (; for (i = 0;
notmuch_threads_valid (threads); notmuch_threads_valid (threads) && (limit < 0 || i < offset + limit);
notmuch_threads_move_to_next (threads)) notmuch_threads_move_to_next (threads), i++)
{ {
int first_tag = 1; int first_tag = 1;
thread = notmuch_threads_get (threads);
if (i < offset) {
notmuch_thread_destroy (thread);
continue;
}
if (! first_thread) if (! first_thread)
fputs (format->item_sep, stdout); fputs (format->item_sep, stdout);
thread = notmuch_threads_get (threads);
if (output == OUTPUT_THREADS) { if (output == OUTPUT_THREADS) {
format->item_id (thread, "thread:", format->item_id (thread, "thread:",
notmuch_thread_get_thread_id (thread)); notmuch_thread_get_thread_id (thread));
@ -271,12 +285,21 @@ do_search_threads (const search_format_t *format,
static int static int
do_search_messages (const search_format_t *format, do_search_messages (const search_format_t *format,
notmuch_query_t *query, notmuch_query_t *query,
output_t output) output_t output,
int offset,
int limit)
{ {
notmuch_message_t *message; notmuch_message_t *message;
notmuch_messages_t *messages; notmuch_messages_t *messages;
notmuch_filenames_t *filenames; notmuch_filenames_t *filenames;
int first_message = 1; int first_message = 1;
int i;
if (offset < 0) {
offset += notmuch_query_count_messages (query);
if (offset < 0)
offset = 0;
}
messages = notmuch_query_search_messages (query); messages = notmuch_query_search_messages (query);
if (messages == NULL) if (messages == NULL)
@ -284,10 +307,13 @@ do_search_messages (const search_format_t *format,
fputs (format->results_start, stdout); fputs (format->results_start, stdout);
for (; for (i = 0;
notmuch_messages_valid (messages); notmuch_messages_valid (messages) && (limit < 0 || i < offset + limit);
notmuch_messages_move_to_next (messages)) notmuch_messages_move_to_next (messages), i++)
{ {
if (i < offset)
continue;
message = notmuch_messages_get (messages); message = notmuch_messages_get (messages);
if (output == OUTPUT_FILES) { if (output == OUTPUT_FILES) {
@ -394,6 +420,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
const search_format_t *format = &format_text; const search_format_t *format = &format_text;
int i, ret; int i, ret;
output_t output = OUTPUT_SUMMARY; output_t output = OUTPUT_SUMMARY;
int offset = 0;
int limit = -1; /* unlimited */
argc--; argv++; /* skip subcommand argument */ argc--; argv++; /* skip subcommand argument */
@ -412,6 +440,22 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
fprintf (stderr, "Invalid value for --sort: %s\n", opt); fprintf (stderr, "Invalid value for --sort: %s\n", opt);
return 1; return 1;
} }
} else if (STRNCMP_LITERAL (argv[i], "--offset=") == 0) {
char *p;
opt = argv[i] + sizeof ("--offset=") - 1;
offset = strtol (opt, &p, 10);
if (*opt == '\0' || p == opt || *p != '\0') {
fprintf (stderr, "Invalid value for --offset: %s\n", opt);
return 1;
}
} else if (STRNCMP_LITERAL (argv[i], "--limit=") == 0) {
char *p;
opt = argv[i] + sizeof ("--limit=") - 1;
limit = strtoul (opt, &p, 10);
if (*opt == '\0' || p == opt || *p != '\0') {
fprintf (stderr, "Invalid value for --limit: %s\n", opt);
return 1;
}
} else if (STRNCMP_LITERAL (argv[i], "--format=") == 0) { } else if (STRNCMP_LITERAL (argv[i], "--format=") == 0) {
opt = argv[i] + sizeof ("--format=") - 1; opt = argv[i] + sizeof ("--format=") - 1;
if (strcmp (opt, "text") == 0) { if (strcmp (opt, "text") == 0) {
@ -478,11 +522,11 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
default: default:
case OUTPUT_SUMMARY: case OUTPUT_SUMMARY:
case OUTPUT_THREADS: case OUTPUT_THREADS:
ret = do_search_threads (format, query, sort, output); ret = do_search_threads (format, query, sort, output, offset, limit);
break; break;
case OUTPUT_MESSAGES: case OUTPUT_MESSAGES:
case OUTPUT_FILES: case OUTPUT_FILES:
ret = do_search_messages (format, query, output); ret = do_search_messages (format, query, output, offset, limit);
break; break;
case OUTPUT_TAGS: case OUTPUT_TAGS:
ret = do_search_tags (notmuch, format, query); ret = do_search_tags (notmuch, format, query);

View file

@ -214,11 +214,26 @@ when sorting by
.B newest\-first .B newest\-first
the threads will be sorted by the newest message in each thread. the threads will be sorted by the newest message in each thread.
.RE
.RS 4
By default, results will be displayed in reverse chronological order, By default, results will be displayed in reverse chronological order,
(that is, the newest results will be displayed first). (that is, the newest results will be displayed first).
.RE
.RS 4
.TP 4
.BR \-\-offset=[\-]N
Skip displaying the first N results. With the leading '\-', start at the Nth
result from the end.
.RE
.RS 4
.TP 4
.BR \-\-limit=N
Limit the number of displayed results to N.
.RE
.RS 4
See the See the
.B "SEARCH SYNTAX" .B "SEARCH SYNTAX"
section below for details of the supported syntax for <search-terms>. section below for details of the supported syntax for <search-terms>.

View file

@ -222,6 +222,15 @@ static command_t commands[] = {
"\t\t(oldest-first) or reverse chronological order\n" "\t\t(oldest-first) or reverse chronological order\n"
"\t\t(newest-first), which is the default.\n" "\t\t(newest-first), which is the default.\n"
"\n" "\n"
"\t--offset=[-]N\n"
"\n"
"\t\tSkip displaying the first N results. With the leading '-',\n"
"\t\tstart at the Nth result from the end.\n"
"\n"
"\t--limit=N\n"
"\n"
"\t\tLimit the number of displayed results to N.\n"
"\n"
"\tSee \"notmuch help search-terms\" for details of the search\n" "\tSee \"notmuch help search-terms\" for details of the search\n"
"\tterms syntax." }, "\tterms syntax." },
{ "show", notmuch_show_command, { "show", notmuch_show_command,