[PATCH v2 (Draft)] emacs: split async json parser into utility function
authorMark Walters <markwalters1009@gmail.com>
Mon, 30 Jul 2012 20:39:15 +0000 (21:39 +0100)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:48:41 +0000 (09:48 -0800)
5f/83ee81ba52510bb93bcdd1271f0b7254ee8ca0 [new file with mode: 0644]

diff --git a/5f/83ee81ba52510bb93bcdd1271f0b7254ee8ca0 b/5f/83ee81ba52510bb93bcdd1271f0b7254ee8ca0
new file mode 100644 (file)
index 0000000..1a4a90e
--- /dev/null
@@ -0,0 +1,221 @@
+Return-Path: <m.walters@qmul.ac.uk>\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 B1D12431FBD\r
+       for <notmuch@notmuchmail.org>; Mon, 30 Jul 2012 13:39:18 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -1.098\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-1.098 tagged_above=-999 required=5\r
+       tests=[DKIM_ADSP_CUSTOM_MED=0.001, FREEMAIL_FROM=0.001,\r
+       NML_ADSP_CUSTOM_MED=1.2, RCVD_IN_DNSWL_MED=-2.3] 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 f39rU0JAFBxS for <notmuch@notmuchmail.org>;\r
+       Mon, 30 Jul 2012 13:39:18 -0700 (PDT)\r
+Received: from mail2.qmul.ac.uk (mail2.qmul.ac.uk [138.37.6.6])\r
+       (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id DD908431FAE\r
+       for <notmuch@notmuchmail.org>; Mon, 30 Jul 2012 13:39:17 -0700 (PDT)\r
+Received: from smtp.qmul.ac.uk ([138.37.6.40])\r
+       by mail2.qmul.ac.uk with esmtp (Exim 4.71)\r
+       (envelope-from <m.walters@qmul.ac.uk>)\r
+       id 1SvwkG-0002PL-4Q; Mon, 30 Jul 2012 21:39:16 +0100\r
+Received: from 94-192-233-223.zone6.bethere.co.uk ([94.192.233.223]\r
+       helo=localhost)\r
+       by smtp.qmul.ac.uk with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69)\r
+       (envelope-from <m.walters@qmul.ac.uk>)\r
+       id 1SvwkF-0002Fs-IZ; Mon, 30 Jul 2012 21:39:15 +0100\r
+From: Mark Walters <markwalters1009@gmail.com>\r
+To: Austin Clements <amdragon@MIT.EDU>\r
+Subject: [PATCH v2 (Draft)] emacs: split async json parser into utility\r
+       function\r
+In-Reply-To: <87obmxyokt.fsf@qmul.ac.uk>\r
+References: <87k3xo85tv.fsf@qmul.ac.uk> <20120730013506.GF8502@mit.edu>\r
+       <87obmxyokt.fsf@qmul.ac.uk>\r
+User-Agent: Notmuch/0.13.2+96~g634443c (http://notmuchmail.org) Emacs/23.4.1\r
+       (x86_64-pc-linux-gnu)\r
+Date: Mon, 30 Jul 2012 21:39:15 +0100\r
+Message-ID: <87k3xlyoek.fsf@qmul.ac.uk>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain; charset=us-ascii\r
+X-Sender-Host-Address: 94.192.233.223\r
+X-QM-SPAM-Info: Sender has good ham record.  :)\r
+X-QM-Body-MD5: b2244b3c95e352eb68571d6b4d806deb (of first 20000 bytes)\r
+X-SpamAssassin-Score: -1.8\r
+X-SpamAssassin-SpamBar: -\r
+X-SpamAssassin-Report: The QM spam filters have analysed this message to\r
+       determine if it is\r
+       spam. We require at least 5.0 points to mark a message as spam.\r
+       This message scored -1.8 points.\r
+       Summary of the scoring: \r
+       * -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/,\r
+       *      medium trust\r
+       *      [138.37.6.40 listed in list.dnswl.org]\r
+       * 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail\r
+       provider *      (markwalters1009[at]gmail.com)\r
+       * -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay\r
+       *      domain\r
+       *  0.5 AWL AWL: From: address is in the auto white-list\r
+X-QM-Scan-Virus: ClamAV says the message is clean\r
+Cc: notmuch@notmuchmail.org\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: Mon, 30 Jul 2012 20:39:18 -0000\r
+\r
+\r
+Split out the json parser into a utility function.\r
+---\r
+\r
+Most of this patch is code movement: but I don't see how to arrange the\r
+patch to show that.\r
+\r
+Best wishes\r
+\r
+Mark\r
+\r
+ emacs/notmuch.el |  101 +++++++++++++++++++++++++++++++-----------------------\r
+ 1 files changed, 58 insertions(+), 43 deletions(-)\r
+\r
+diff --git a/emacs/notmuch.el b/emacs/notmuch.el\r
+index fd1836f..23ab499 100644\r
+--- a/emacs/notmuch.el\r
++++ b/emacs/notmuch.el\r
+@@ -809,11 +809,60 @@ non-authors is found, assume that all of the authors match."\r
+     (insert (apply #'format string objects))\r
+     (insert "\n")))\r
+ \r
+-(defvar notmuch-search-process-state nil\r
+-  "Parsing state of the search process filter.")\r
+-\r
+-(defvar notmuch-search-json-parser nil\r
+-  "Incremental JSON parser for the search process filter.")\r
++(defvar notmuch-json-state nil\r
++  "State of the JSON parser.")\r
++\r
++(defvar notmuch-json-parser nil\r
++  "Incremental JSON parser.")\r
++\r
++(defun notmuch-json-parse-partial-list (result-function error-function results-buf)\r
++  "Parse a partial JSON list from current buffer.\r
++\r
++This function consumes a JSON list from the current buffer,\r
++applying RESULT-FUNCTION in buffer RESULT-BUFFER to each complete\r
++value in the list.  It operates incrementally and should be\r
++called whenever the buffer has been extended with additional\r
++data.\r
++\r
++If there is a syntax error, this will attempt to resynchronize\r
++with the input and will apply ERROR-FUNCTION in buffer\r
++RESULT-BUFFER to any input that was skipped."\r
++  (let (done)\r
++    (unless (local-variable-p 'notmuch-json-parser)\r
++      (set (make-local-variable 'notmuch-json-parser)\r
++         (notmuch-json-create-parser (current-buffer)))\r
++      (set (make-local-variable 'notmuch-json-state) 'begin))\r
++    (while (not done)\r
++      (condition-case nil\r
++        (case notmuch-json-state\r
++              ((begin)\r
++               ;; Enter the results list\r
++               (if (eq (notmuch-json-begin-compound\r
++                        notmuch-json-parser) 'retry)\r
++                   (setq done t)\r
++                 (setq notmuch-json-state 'result)))\r
++              ((result)\r
++               ;; Parse a result\r
++               (let ((result (notmuch-json-read notmuch-json-parser)))\r
++                 (case result\r
++                       ((retry) (setq done t))\r
++                       ((end) (setq notmuch-json-state 'end))\r
++                       (otherwise (with-current-buffer results-buf\r
++                                    (funcall result-function result))))))\r
++              ((end)\r
++               ;; Any trailing data is unexpected\r
++               (notmuch-json-eof notmuch-json-parser)\r
++               (setq done t)))\r
++      (json-error\r
++       ;; Do our best to resynchronize and ensure forward\r
++       ;; progress\r
++       (let ((bad (buffer-substring (line-beginning-position)\r
++                                    (line-end-position))))\r
++         (forward-line)\r
++         (with-current-buffer results-buf\r
++           (funcall error-function bad))))))\r
++    ;; Clear out what we've parsed\r
++    (delete-region (point-min) (point))))\r
+ \r
+ (defun notmuch-search-process-filter (proc string)\r
+   "Process and filter the output of \"notmuch search\""\r
+@@ -827,41 +876,10 @@ non-authors is found, assume that all of the authors match."\r
+       ;; Insert new data\r
+       (save-excursion\r
+         (goto-char (point-max))\r
+-        (insert string)))\r
+-      (with-current-buffer results-buf\r
+-      (while (not done)\r
+-        (condition-case nil\r
+-            (case notmuch-search-process-state\r
+-              ((begin)\r
+-               ;; Enter the results list\r
+-               (if (eq (notmuch-json-begin-compound\r
+-                        notmuch-search-json-parser) 'retry)\r
+-                   (setq done t)\r
+-                 (setq notmuch-search-process-state 'result)))\r
+-              ((result)\r
+-               ;; Parse a result\r
+-               (let ((result (notmuch-json-read notmuch-search-json-parser)))\r
+-                 (case result\r
+-                   ((retry) (setq done t))\r
+-                   ((end) (setq notmuch-search-process-state 'end))\r
+-                   (otherwise (notmuch-search-show-result result)))))\r
+-              ((end)\r
+-               ;; Any trailing data is unexpected\r
+-               (notmuch-json-eof notmuch-search-json-parser)\r
+-               (setq done t)))\r
+-          (json-error\r
+-           ;; Do our best to resynchronize and ensure forward\r
+-           ;; progress\r
+-           (notmuch-search-show-error\r
+-            "%s"\r
+-            (with-current-buffer parse-buf\r
+-              (let ((bad (buffer-substring (line-beginning-position)\r
+-                                           (line-end-position))))\r
+-                (forward-line)\r
+-                bad))))))\r
+-      ;; Clear out what we've parsed\r
+-      (with-current-buffer parse-buf\r
+-        (delete-region (point-min) (point)))))))\r
++        (insert string))\r
++      (notmuch-json-parse-partial-list 'notmuch-search-show-result\r
++                                       'notmuch-search-show-error\r
++                                       results-buf)))))\r
+ \r
+ (defun notmuch-search-tag-all (&optional tag-changes)\r
+   "Add/remove tags from all messages in current search buffer.\r
+@@ -973,9 +991,6 @@ Other optional parameters are used as follows:\r
+             ;; This buffer will be killed by the sentinel, which\r
+             ;; should be called no matter how the process dies.\r
+             (parse-buf (generate-new-buffer " *notmuch search parse*")))\r
+-        (set (make-local-variable 'notmuch-search-process-state) 'begin)\r
+-        (set (make-local-variable 'notmuch-search-json-parser)\r
+-             (notmuch-json-create-parser parse-buf))\r
+         (process-put proc 'parse-buf parse-buf)\r
+         (set-process-sentinel proc 'notmuch-search-process-sentinel)\r
+         (set-process-filter proc 'notmuch-search-process-filter)\r
+-- \r
+1.7.9.1\r
+\r