[RFC] [PATCH] emacs: Use JSON output for search.
David Edmondson
dme at dme.org
Fri Nov 26 05:13:22 PST 2010
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
More information about the notmuch
mailing list