[notmuch] [PATCH 2/3] Add 'notmuch count' command to show the count of matching messages
authorKeith Packard <keithp@keithp.com>
Sat, 21 Nov 2009 07:15:07 +0000 (23:15 +1600)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:35:37 +0000 (09:35 -0800)
f3/70088534d5dc13db6cb1b9ee0df71296bd3a22 [new file with mode: 0644]

diff --git a/f3/70088534d5dc13db6cb1b9ee0df71296bd3a22 b/f3/70088534d5dc13db6cb1b9ee0df71296bd3a22
new file mode 100644 (file)
index 0000000..3abc664
--- /dev/null
@@ -0,0 +1,314 @@
+Return-Path: <keithp@keithp.com>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id D65B1431FBF\r
+       for <notmuch@notmuchmail.org>; Fri, 20 Nov 2009 23:15:21 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id gqoniYFNYKxp for <notmuch@notmuchmail.org>;\r
+       Fri, 20 Nov 2009 23:15:17 -0800 (PST)\r
+Received: from keithp.com (home.keithp.com [63.227.221.253])\r
+       by olra.theworths.org (Postfix) with ESMTP id 64B03431FAE\r
+       for <notmuch@notmuchmail.org>; Fri, 20 Nov 2009 23:15:17 -0800 (PST)\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by keithp.com (Postfix) with ESMTP id CC404760222\r
+       for <notmuch@notmuchmail.org>; Fri, 20 Nov 2009 23:15:16 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at keithp.com\r
+Received: from keithp.com ([127.0.0.1])\r
+       by localhost (keithp.com [127.0.0.1]) (amavisd-new, port 10024)\r
+       with LMTP id H3w9F2ijbayT; Fri, 20 Nov 2009 23:15:12 -0800 (PST)\r
+Received: by keithp.com (Postfix, from userid 1033)\r
+       id C5AC1B9404C; Fri, 20 Nov 2009 23:15:12 -0800 (PST)\r
+Received: from koto.keithp.com (localhost [127.0.0.1])\r
+       by keithp.com (Postfix) with ESMTP id C0C9076012C;\r
+       Fri, 20 Nov 2009 23:15:12 -0800 (PST)\r
+Received: by koto.keithp.com (Postfix, from userid 1488)\r
+       id 6C3681982A8; Fri, 20 Nov 2009 23:15:12 -0800 (PST)\r
+From: Keith Packard <keithp@keithp.com>\r
+To: notmuch@notmuchmail.org\r
+Date: Fri, 20 Nov 2009 23:15:07 -0800\r
+Message-Id: <1258787708-21121-2-git-send-email-keithp@keithp.com>\r
+X-Mailer: git-send-email 1.6.5.2\r
+In-Reply-To: <1258787708-21121-1-git-send-email-keithp@keithp.com>\r
+References: <1258787708-21121-1-git-send-email-keithp@keithp.com>\r
+Subject: [notmuch] [PATCH 2/3] Add 'notmuch count' command to show the count\r
+       of matching messages\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.12\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Sat, 21 Nov 2009 07:15:22 -0000\r
+\r
+Getting the count of matching threads or messages is a fairly\r
+expensive operation. Xapian provides a very efficient mechanism that\r
+returns an approximate value, so use that for this new command.\r
+\r
+This returns the number of matching messages, not threads, as that is\r
+cheap to compute.\r
+\r
+Signed-off-by: Keith Packard <keithp@keithp.com>\r
+---\r
+ Makefile.local   |    1 +\r
+ lib/notmuch.h    |    8 ++++\r
+ lib/query.cc     |   52 ++++++++++++++++++++++++++\r
+ notmuch-client.h |    3 +\r
+ notmuch-count.c  |  109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ notmuch.c        |   11 +++++\r
+ 6 files changed, 184 insertions(+), 0 deletions(-)\r
+ create mode 100644 notmuch-count.c\r
+\r
+diff --git a/Makefile.local b/Makefile.local\r
+index 3c99624..cbd75ce 100644\r
+--- a/Makefile.local\r
++++ b/Makefile.local\r
+@@ -5,6 +5,7 @@ emacs: notmuch.elc\r
+ notmuch_client_srcs =         \\r
+       notmuch.c               \\r
+       notmuch-config.c        \\r
++      notmuch-count.c         \\r
+       notmuch-dump.c          \\r
+       notmuch-new.c           \\r
+       notmuch-reply.c         \\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index cc713a3..937f3b6 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -459,6 +459,14 @@ notmuch_threads_advance (notmuch_threads_t *threads);\r
+ void\r
+ notmuch_threads_destroy (notmuch_threads_t *threads);\r
\r
++/* Return an estimate of the number of messages matching a search\r
++ *\r
++ * This function performs a search and returns Xapian's best\r
++ * guess as to number of matching messages.\r
++ */\r
++unsigned\r
++notmuch_query_count_messages (notmuch_query_t *query);\r
++ \r
+ /* Get the thread ID of 'thread'.\r
+  *\r
+  * The returned string belongs to 'thread' and as such, should not be\r
+diff --git a/lib/query.cc b/lib/query.cc\r
+index ea521dd..dff9634 100644\r
+--- a/lib/query.cc\r
++++ b/lib/query.cc\r
+@@ -278,3 +278,55 @@ notmuch_threads_destroy (notmuch_threads_t *threads)\r
+ {\r
+     talloc_free (threads);\r
+ }\r
++\r
++unsigned\r
++notmuch_query_count_messages (notmuch_query_t *query)\r
++{\r
++    notmuch_database_t *notmuch = query->notmuch;\r
++    const char *query_string = query->query_string;\r
++    Xapian::doccount count;\r
++\r
++    try {\r
++      Xapian::Enquire enquire (*notmuch->xapian_db);\r
++      Xapian::Query mail_query (talloc_asprintf (query, "%s%s",\r
++                                                 _find_prefix ("type"),\r
++                                                 "mail"));\r
++      Xapian::Query string_query, final_query;\r
++      Xapian::MSet mset;\r
++      unsigned int flags = (Xapian::QueryParser::FLAG_BOOLEAN |\r
++                            Xapian::QueryParser::FLAG_PHRASE |\r
++                            Xapian::QueryParser::FLAG_LOVEHATE |\r
++                            Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE |\r
++                            Xapian::QueryParser::FLAG_WILDCARD |\r
++                            Xapian::QueryParser::FLAG_PURE_NOT);\r
++\r
++      if (strcmp (query_string, "") == 0) {\r
++          final_query = mail_query;\r
++      } else {\r
++          string_query = notmuch->query_parser->\r
++              parse_query (query_string, flags);\r
++          final_query = Xapian::Query (Xapian::Query::OP_AND,\r
++                                       mail_query, string_query);\r
++      }\r
++\r
++      enquire.set_weighting_scheme(Xapian::BoolWeight());\r
++      enquire.set_docid_order(Xapian::Enquire::ASCENDING);\r
++\r
++#if DEBUG_QUERY\r
++      fprintf (stderr, "Final query is:\n%s\n", final_query.get_description().c_str());\r
++#endif\r
++\r
++      enquire.set_query (final_query);\r
++\r
++      mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ());\r
++\r
++      count = mset.get_matches_estimated();\r
++\r
++    } catch (const Xapian::Error &error) {\r
++      fprintf (stderr, "A Xapian exception occurred: %s\n",\r
++               error.get_msg().c_str());\r
++      fprintf (stderr, "Query string was: %s\n", query->query_string);\r
++    }\r
++\r
++    return count;\r
++}\r
+diff --git a/notmuch-client.h b/notmuch-client.h\r
+index b65aa77..9884497 100644\r
+--- a/notmuch-client.h\r
++++ b/notmuch-client.h\r
+@@ -91,6 +91,9 @@ chomp_newline (char *str)\r
+ }\r
\r
+ int\r
++notmuch_count_command (void *ctx, int argc, char *argv[]);\r
++\r
++int\r
+ notmuch_dump_command (void *ctx, int argc, char *argv[]);\r
\r
+ int\r
+diff --git a/notmuch-count.c b/notmuch-count.c\r
+new file mode 100644\r
+index 0000000..68e428f\r
+--- /dev/null\r
++++ b/notmuch-count.c\r
+@@ -0,0 +1,109 @@\r
++/* notmuch - Not much of an email program, (just index and search)\r
++ *\r
++ * Copyright © 2009 Carl Worth\r
++ * Copyright © 2009 Keith Packard\r
++ *\r
++ * This program is free software: you can redistribute it and/or modify\r
++ * it under the terms of the GNU General Public License as published by\r
++ * the Free Software Foundation, either version 3 of the License, or\r
++ * (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program.  If not, see http://www.gnu.org/licenses/ .\r
++ *\r
++ * Author: Keith Packard <keithp@keithp.com>\r
++ */\r
++\r
++#include "notmuch-client.h"\r
++\r
++int\r
++notmuch_count_command (void *ctx, int argc, char *argv[])\r
++{\r
++    notmuch_config_t *config;\r
++    notmuch_database_t *notmuch;\r
++    notmuch_query_t *query;\r
++    char *query_str;\r
++    char *opt, *end;\r
++    int i;\r
++#if 0\r
++    int i, first = 0, max_threads = -1;\r
++    notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;\r
++#endif\r
++\r
++    for (i = 0; i < argc && argv[i][0] == '-'; i++) {\r
++      if (strcmp (argv[i], "--") == 0) {\r
++          i++;\r
++          break;\r
++      }\r
++#if 0\r
++      if (STRNCMP_LITERAL (argv[i], "--first=") == 0) {\r
++          opt = argv[i] + sizeof ("--first=") - 1;\r
++          first = strtoul (opt, &end, 10);\r
++          if (*opt == '\0' || *end != '\0') {\r
++              fprintf (stderr, "Invalid value for --first: %s\n", opt);\r
++              return 1;\r
++          }\r
++      } else if (STRNCMP_LITERAL (argv[i], "--max-threads=") == 0) {\r
++          opt = argv[i] + sizeof ("--max-threads=") - 1;\r
++          max_threads = strtoul (opt, &end, 10);\r
++          if (*opt == '\0' || *end != '\0') {\r
++              fprintf (stderr, "Invalid value for --max-threads: %s\n", opt);\r
++              return 1;\r
++          }\r
++      } else if (STRNCMP_LITERAL (argv[i], "--sort=") == 0) {\r
++          opt = argv[i] + sizeof ("--sort=") - 1;\r
++          if (strcmp (opt, "oldest-first") == 0) {\r
++              sort = NOTMUCH_SORT_OLDEST_FIRST;\r
++          } else if (strcmp (opt, "newest-first") == 0) {\r
++              sort = NOTMUCH_SORT_NEWEST_FIRST;\r
++          } else {\r
++              fprintf (stderr, "Invalid value for --sort: %s\n", opt);\r
++              return 1;\r
++          }\r
++      } else\r
++#endif\r
++      {\r
++          fprintf (stderr, "Unrecognized option: %s\n", argv[i]);\r
++          return 1;\r
++      }\r
++    }\r
++\r
++    argc -= i;\r
++    argv += i;\r
++\r
++    config = notmuch_config_open (ctx, NULL, NULL);\r
++    if (config == NULL)\r
++      return 1;\r
++\r
++    notmuch = notmuch_database_open (notmuch_config_get_database_path (config));\r
++    if (notmuch == NULL)\r
++      return 1;\r
++\r
++    query_str = query_string_from_args (ctx, argc, argv);\r
++    if (query_str == NULL) {\r
++      fprintf (stderr, "Out of memory.\n");\r
++      return 1;\r
++    }\r
++    if (*query_str == '\0') {\r
++      fprintf (stderr, "Error: notmuch count requires at least one count term.\n");\r
++      return 1;\r
++    }\r
++\r
++    query = notmuch_query_create (notmuch, query_str);\r
++    if (query == NULL) {\r
++      fprintf (stderr, "Out of memory\n");\r
++      return 1;\r
++    }\r
++\r
++    printf ("%u\n", notmuch_query_count_messages(query));\r
++\r
++    notmuch_query_destroy (query);\r
++    notmuch_database_close (notmuch);\r
++\r
++    return 0;\r
++}\r
+diff --git a/notmuch.c b/notmuch.c\r
+index 5cc8e4c..8387692 100644\r
+--- a/notmuch.c\r
++++ b/notmuch.c\r
+@@ -179,6 +179,17 @@ command_t commands[] = {\r
+       "\n"\r
+       "\t\tSee \"notmuch help search-terms\" for details of the search\n"\r
+       "\t\tterms syntax." },\r
++    { "count", notmuch_count_command,\r
++      "<search-terms> [...]",\r
++      "\t\tCount messages matching the search terms.",\r
++      "\t\tThe number of matching messages is output to stdout.\n"\r
++      "\n"\r
++      "\t\tA common use of \"notmuch count\" is to display the count\n"\r
++      "\t\tof messages matching both a specific tag and either inbox\n"\r
++      "\t\tor unread\n"\r
++      "\n"\r
++      "\t\tSee \"notmuch help search-terms\" for details of the search\n"\r
++      "\t\tterms syntax." },\r
+     { "reply", notmuch_reply_command,\r
+       "<search-terms> [...]",\r
+       "\t\tConstruct a reply template for a set of messages.",\r
+-- \r
+1.6.5.2\r
+\r