[RFC] [PATCH] emacs: Use JSON output for search.
authorDavid Edmondson <dme@dme.org>
Fri, 26 Nov 2010 13:13:22 +0000 (13:13 +0000)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:37:37 +0000 (09:37 -0800)
b5/86665c0a2a7ad3cf68166a92ced5a2db89981f [new file with mode: 0644]

diff --git a/b5/86665c0a2a7ad3cf68166a92ced5a2db89981f b/b5/86665c0a2a7ad3cf68166a92ced5a2db89981f
new file mode 100644 (file)
index 0000000..6bea9b3
--- /dev/null
@@ -0,0 +1,212 @@
+Return-Path: <dme@dme.org>\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 E2FAF431FB6\r
+       for <notmuch@notmuchmail.org>; Fri, 26 Nov 2010 05:13:31 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5\r
+       tests=[RCVD_IN_DNSWL_NONE=-0.0001] autolearn=disabled\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 gAKFKoxnirMU for <notmuch@notmuchmail.org>;\r
+       Fri, 26 Nov 2010 05:13:31 -0800 (PST)\r
+Received: from mail-wy0-f181.google.com (mail-wy0-f181.google.com\r
+       [74.125.82.181])\r
+       by olra.theworths.org (Postfix) with ESMTP id A0B26431FB5\r
+       for <notmuch@notmuchmail.org>; Fri, 26 Nov 2010 05:13:30 -0800 (PST)\r
+Received: by wyf22 with SMTP id 22so2113175wyf.26\r
+       for <notmuch@notmuchmail.org>; Fri, 26 Nov 2010 05:13:28 -0800 (PST)\r
+Received: by 10.216.15.10 with SMTP id e10mr152512wee.21.1290777208145;\r
+       Fri, 26 Nov 2010 05:13:28 -0800 (PST)\r
+Received: from ut.hh.sledj.net (host81-149-164-25.in-addr.btopenworld.com\r
+       [81.149.164.25])\r
+       by mx.google.com with ESMTPS id x3sm906001wes.22.2010.11.26.05.13.26\r
+       (version=TLSv1/SSLv3 cipher=RC4-MD5);\r
+       Fri, 26 Nov 2010 05:13:27 -0800 (PST)\r
+Received: by ut.hh.sledj.net (Postfix, from userid 1000)\r
+       id CF36B594058; Fri, 26 Nov 2010 13:13:23 +0000 (GMT)\r
+From: David Edmondson <dme@dme.org>\r
+To: notmuch@notmuchmail.org\r
+Subject: [RFC] [PATCH] emacs: Use JSON output for search.\r
+Date: Fri, 26 Nov 2010 13:13:22 +0000\r
+Message-Id: <1290777202-14040-1-git-send-email-dme@dme.org>\r
+X-Mailer: git-send-email 1.7.2.3\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\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: Fri, 26 Nov 2010 13:13:32 -0000\r
+\r
+Modify the `notmuch search' JSON output to remove the outer list\r
+wrappers and item separators between elements. Add `date_relative' to\r
+the JSON search output.\r
+\r
+Replace the emacs use of the text based search output with the\r
+modified JSON output, including incremental parsing of the individual\r
+threads in the JSON.\r
+---\r
+ emacs/notmuch.el |   70 ++++++++++++++++++++++++++++++-----------------------\r
+ notmuch-search.c |    8 ++++--\r
+ 2 files changed, 45 insertions(+), 33 deletions(-)\r
+\r
+Proper incremental parsing of the JSON output was hard, so I punted\r
+and got rid of the array wrappings around the search output. This may\r
+well break some other tools as a result (hence 'RFC'). Display of the\r
+thread can be a bit 'flashy' due to the incremental implementation,\r
+but it doesn't seem too off-putting on reasonable hardware - it may\r
+well be annoying on slower systems.\r
+\r
+diff --git a/emacs/notmuch.el b/emacs/notmuch.el\r
+index 5933747..0bbdf16 100644\r
+--- a/emacs/notmuch.el\r
++++ b/emacs/notmuch.el\r
+@@ -698,40 +698,50 @@ foreground and blue background."\r
+         do (notmuch-search-insert-field field date count authors subject tags)))\r
+   (insert "\n"))\r
\r
++(defvar notmuch-search-parse-start nil)\r
++(make-variable-buffer-local 'notmuch-show-parse-start)\r
++\r
+ (defun notmuch-search-process-filter (proc string)\r
+-  "Process and filter the output of \"notmuch search\""\r
++  "Process and filter the output of `notmuch search'."\r
++\r
+   (let ((buffer (process-buffer proc))\r
+-      (found-target nil))\r
++      object)\r
+     (if (buffer-live-p buffer)\r
+       (with-current-buffer buffer\r
+-        (save-excursion\r
+-          (let ((line 0)\r
+-                (more t)\r
+-                (inhibit-read-only t))\r
+-            (while more\r
+-              (if (string-match "^\\(thread:[0-9A-Fa-f]*\\) \\([^][]*\\) \\(\\[[0-9/]*\\]\\) \\([^;]*\\); \\(.*\\) (\\([^()]*\\))$" string line)\r
+-                  (let* ((thread-id (match-string 1 string))\r
+-                         (date (match-string 2 string))\r
+-                         (count (match-string 3 string))\r
+-                         (authors (match-string 4 string))\r
+-                         (subject (match-string 5 string))\r
+-                         (tags (match-string 6 string))\r
+-                         (tag-list (if tags (save-match-data (split-string tags)))))\r
+-                    (goto-char (point-max))\r
+-                    (let ((beg (point-marker)))\r
++        (let ((inhibit-read-only t)\r
++              (inhibit-redisplay t))\r
++          (save-excursion\r
++            ;; Insert the text, advancing the process marker\r
++            (goto-char (point-max))\r
++            (insert string)\r
++            (set-marker (process-mark proc) (point-max)))\r
++\r
++          (save-excursion\r
++            (condition-case nil\r
++                (progn\r
++                  (goto-char notmuch-search-parse-start)\r
++                  (while (and (not (eobp))\r
++                              (setq object (json-read-object)))\r
++                    (forward-char)\r
++                    (delete-region notmuch-search-parse-start (point))\r
++\r
++                    (let* ((thread-id (concat "thread:" (cdr (assoc 'thread object))))\r
++                           (date (format "%12s" (cdr (assoc 'date_relative object))))\r
++                           (count (format "[%d/%d]"\r
++                                          (cdr (assoc 'matched object))\r
++                                          (cdr (assoc 'total object))))\r
++                           (authors (cdr (assoc 'authors object)))\r
++                           (subject (cdr (assoc 'subject object)))\r
++                           (tag-list (cdr (assoc 'tags object)))\r
++                           (tags (mapconcat 'identity tag-list " "))\r
++                           (beg (point-marker)))\r
+                       (notmuch-search-show-result date count authors subject tags)\r
+                       (notmuch-search-color-line beg (point-marker) tag-list)\r
+                       (put-text-property beg (point-marker) 'notmuch-search-thread-id thread-id)\r
+                       (put-text-property beg (point-marker) 'notmuch-search-authors authors)\r
+-                      (put-text-property beg (point-marker) 'notmuch-search-subject subject)\r
+-                      (if (string= thread-id notmuch-search-target-thread)\r
+-                          (progn\r
+-                            (set 'found-target beg)\r
+-                            (set 'notmuch-search-target-thread "found"))))\r
+-                    (set 'line (match-end 0)))\r
+-                (set 'more nil)))))\r
+-        (if found-target\r
+-            (goto-char found-target)))\r
++                      (put-text-property beg (point-marker) 'notmuch-search-subject subject))\r
++                    (setq notmuch-search-parse-start (point))))\r
++              (error nil)))))\r
+       (delete-process proc))))\r
\r
+ (defun notmuch-search-operate-all (action)\r
+@@ -806,15 +816,15 @@ The optional parameters are used as follows:\r
+     (set 'notmuch-search-continuation continuation)\r
+     (let ((proc (get-buffer-process (current-buffer)))\r
+         (inhibit-read-only t))\r
+-      (if proc\r
+-        (error "notmuch search process already running for query `%s'" query)\r
+-      )\r
++      (when proc\r
++      (error "notmuch search process already running for query `%s'" query))\r
+       (erase-buffer)\r
+-      (goto-char (point-min))\r
++      (setq notmuch-search-parse-start (point-min))\r
+       (save-excursion\r
+       (let ((proc (start-process\r
+                    "notmuch-search" buffer\r
+                    notmuch-command "search"\r
++                   "--format=json"\r
+                    (if oldest-first\r
+                        "--sort=oldest-first"\r
+                      "--sort=newest-first")\r
+diff --git a/notmuch-search.c b/notmuch-search.c\r
+index c628b36..1b07aa7 100644\r
+--- a/notmuch-search.c\r
++++ b/notmuch-search.c\r
+@@ -89,15 +89,15 @@ format_thread_json (const void *ctx,\r
+                   const char *authors,\r
+                   const char *subject);\r
+ static const search_format_t format_json = {\r
+-    "[",\r
++    "",\r
+       "{",\r
+           format_item_id_json,\r
+           format_thread_json,\r
+           "\"tags\": [",\r
+               "\"%s\"", ", ",\r
+-          "]", ",\n",\r
++          "]", "\n",\r
+       "}",\r
+-    "]\n",\r
++    "\n",\r
+ };\r
\r
+ static void\r
+@@ -152,12 +152,14 @@ format_thread_json (const void *ctx,\r
\r
+     printf ("\"thread\": %s,\n"\r
+           "\"timestamp\": %ld,\n"\r
++          "\"date_relative\": %s,\n"\r
+           "\"matched\": %d,\n"\r
+           "\"total\": %d,\n"\r
+           "\"authors\": %s,\n"\r
+           "\"subject\": %s,\n",\r
+           json_quote_str (ctx_quote, thread_id),\r
+           date,\r
++          json_quote_str (ctx_quote, notmuch_time_relative_date (ctx, date)),\r
+           matched,\r
+           total,\r
+           json_quote_str (ctx_quote, authors),\r
+-- \r
+1.7.2.3\r
+\r