Modify the `notmuch search' JSON output to remove the outer list
wrappers and item separators between elements. Add `date_relative' to
the JSON search output.

Replace the emacs use of the text based search output with the
modified JSON output, including incremental parsing of the individual
threads in the JSON.
---
 emacs/notmuch.el |   70 ++++++++++++++++++++++++++++++-----------------------
 notmuch-search.c |    8 ++++--
 2 files changed, 45 insertions(+), 33 deletions(-)

Proper incremental parsing of the JSON output was hard, so I punted
and got rid of the array wrappings around the search output. This may
well break some other tools as a result (hence 'RFC'). Display of the
thread can be a bit 'flashy' due to the incremental implementation,
but it doesn't seem too off-putting on reasonable hardware - it may
well be annoying on slower systems.

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 5933747..0bbdf16 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -698,40 +698,50 @@ foreground and blue background."
          do (notmuch-search-insert-field field date count authors subject 
tags)))
   (insert "\n"))

+(defvar notmuch-search-parse-start nil)
+(make-variable-buffer-local 'notmuch-show-parse-start)
+
 (defun notmuch-search-process-filter (proc string)
-  "Process and filter the output of \"notmuch search\""
+  "Process and filter the output of `notmuch search'."
+
   (let ((buffer (process-buffer proc))
-       (found-target nil))
+       object)
     (if (buffer-live-p buffer)
        (with-current-buffer buffer
-         (save-excursion
-           (let ((line 0)
-                 (more t)
-                 (inhibit-read-only t))
-             (while more
-               (if (string-match "^\\(thread:[0-9A-Fa-f]*\\) \\([^][]*\\) 
\\(\\[[0-9/]*\\]\\) \\([^;]*\\); \\(.*\\) (\\([^()]*\\))$" string line)
-                   (let* ((thread-id (match-string 1 string))
-                          (date (match-string 2 string))
-                          (count (match-string 3 string))
-                          (authors (match-string 4 string))
-                          (subject (match-string 5 string))
-                          (tags (match-string 6 string))
-                          (tag-list (if tags (save-match-data (split-string 
tags)))))
-                     (goto-char (point-max))
-                     (let ((beg (point-marker)))
+         (let ((inhibit-read-only t)
+               (inhibit-redisplay t))
+           (save-excursion
+             ;; Insert the text, advancing the process marker
+             (goto-char (point-max))
+             (insert string)
+             (set-marker (process-mark proc) (point-max)))
+
+           (save-excursion
+             (condition-case nil
+                 (progn
+                   (goto-char notmuch-search-parse-start)
+                   (while (and (not (eobp))
+                               (setq object (json-read-object)))
+                     (forward-char)
+                     (delete-region notmuch-search-parse-start (point))
+
+                     (let* ((thread-id (concat "thread:" (cdr (assoc 'thread 
object))))
+                            (date (format "%12s" (cdr (assoc 'date_relative 
object))))
+                            (count (format "[%d/%d]"
+                                           (cdr (assoc 'matched object))
+                                           (cdr (assoc 'total object))))
+                            (authors (cdr (assoc 'authors object)))
+                            (subject (cdr (assoc 'subject object)))
+                            (tag-list (cdr (assoc 'tags object)))
+                            (tags (mapconcat 'identity tag-list " "))
+                            (beg (point-marker)))
                        (notmuch-search-show-result date count authors subject 
tags)
                        (notmuch-search-color-line beg (point-marker) tag-list)
                        (put-text-property beg (point-marker) 
'notmuch-search-thread-id thread-id)
                        (put-text-property beg (point-marker) 
'notmuch-search-authors authors)
-                       (put-text-property beg (point-marker) 
'notmuch-search-subject subject)
-                       (if (string= thread-id notmuch-search-target-thread)
-                           (progn
-                             (set 'found-target beg)
-                             (set 'notmuch-search-target-thread "found"))))
-                     (set 'line (match-end 0)))
-                 (set 'more nil)))))
-         (if found-target
-             (goto-char found-target)))
+                       (put-text-property beg (point-marker) 
'notmuch-search-subject subject))
+                     (setq notmuch-search-parse-start (point))))
+               (error nil)))))
       (delete-process proc))))

 (defun notmuch-search-operate-all (action)
@@ -806,15 +816,15 @@ The optional parameters are used as follows:
     (set 'notmuch-search-continuation continuation)
     (let ((proc (get-buffer-process (current-buffer)))
          (inhibit-read-only t))
-      (if proc
-         (error "notmuch search process already running for query `%s'" query)
-       )
+      (when proc
+       (error "notmuch search process already running for query `%s'" query))
       (erase-buffer)
-      (goto-char (point-min))
+      (setq notmuch-search-parse-start (point-min))
       (save-excursion
        (let ((proc (start-process
                     "notmuch-search" buffer
                     notmuch-command "search"
+                    "--format=json"
                     (if oldest-first
                         "--sort=oldest-first"
                       "--sort=newest-first")
diff --git a/notmuch-search.c b/notmuch-search.c
index c628b36..1b07aa7 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -89,15 +89,15 @@ format_thread_json (const void *ctx,
                    const char *authors,
                    const char *subject);
 static const search_format_t format_json = {
-    "[",
+    "",
        "{",
            format_item_id_json,
            format_thread_json,
            "\"tags\": [",
                "\"%s\"", ", ",
-           "]", ",\n",
+           "]", "\n",
        "}",
-    "]\n",
+    "\n",
 };

 static void
@@ -152,12 +152,14 @@ format_thread_json (const void *ctx,

     printf ("\"thread\": %s,\n"
            "\"timestamp\": %ld,\n"
+           "\"date_relative\": %s,\n"
            "\"matched\": %d,\n"
            "\"total\": %d,\n"
            "\"authors\": %s,\n"
            "\"subject\": %s,\n",
            json_quote_str (ctx_quote, thread_id),
            date,
+           json_quote_str (ctx_quote, notmuch_time_relative_date (ctx, date)),
            matched,
            total,
            json_quote_str (ctx_quote, authors),
-- 
1.7.2.3

Reply via email to