X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;f=emacs%2Fnotmuch.el;h=428b0117fadcba0a00b0526a685a3ba09e142292;hb=294667871a30b86790f7dd19c13a4da6806bf52a;hp=1c43d3ee19358fd9e891c53c9c60d3c6e818af4e;hpb=c62126238b2ce6194b3c6511553951497aedf295;p=notmuch diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 1c43d3ee..428b0117 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -593,12 +593,20 @@ See `notmuch-tag' for information on the format of TAG-CHANGES." (interactive) (notmuch-search-tag "-")) -(defun notmuch-search-archive-thread () - "Archive the currently selected thread (remove its \"inbox\" tag). +(defun notmuch-search-archive-thread (&optional unarchive) + "Archive the currently selected thread. + +Archive each message in the currently selected thread by applying +the tag changes in `notmuch-archive-tags' to each (remove the +\"inbox\" tag by default). If a prefix argument is given, the +messages will be \"unarchived\" (i.e. the tag changes in +`notmuch-archive-tags' will be reversed). This function advances the next thread when finished." - (interactive) - (notmuch-search-tag '("-inbox")) + (interactive "P") + (when notmuch-archive-tags + (notmuch-search-tag + (notmuch-tag-change-list notmuch-archive-tags unarchive))) (notmuch-search-next-thread)) (defun notmuch-search-update-result (result &optional pos) @@ -812,11 +820,15 @@ non-authors is found, assume that all of the authors match." (insert (apply #'format string objects)) (insert "\n"))) -(defvar notmuch-search-process-state nil - "Parsing state of the search process filter.") +;; These two variables are internal variables to the parsing +;; routines. They are always used buffer local but need to be declared +;; globally to avoid compiler warnings. + +(defvar notmuch-json-state nil + "Internal incremental JSON parser object: local to the buffer being parsed.") -(defvar notmuch-search-json-parser nil - "Incremental JSON parser for the search process filter.") +(defvar notmuch-json-parser nil + "State of the internal JSON parser: local to the buffer being parsed.") (defun notmuch-search-process-filter (proc string) "Process and filter the output of \"notmuch search\"" @@ -830,41 +842,63 @@ non-authors is found, assume that all of the authors match." ;; Insert new data (save-excursion (goto-char (point-max)) - (insert string))) - (with-current-buffer results-buf - (while (not done) - (condition-case nil - (case notmuch-search-process-state + (insert string)) + (notmuch-json-parse-partial-list 'notmuch-search-show-result + 'notmuch-search-show-error + results-buf))))) + +(defun notmuch-json-parse-partial-list (result-function error-function results-buf) + "Parse a partial JSON list from current buffer. + +This function consumes a JSON list from the current buffer, +applying RESULT-FUNCTION in buffer RESULT-BUFFER to each complete +value in the list. It operates incrementally and should be +called whenever the buffer has been extended with additional +data. + +If there is a syntax error, this will attempt to resynchronize +with the input and will apply ERROR-FUNCTION in buffer +RESULT-BUFFER to any input that was skipped. + +It sets up all the needed internal variables: the caller just +needs to call it with point in the same place that the parser +left it." + (let (done) + (unless (local-variable-p 'notmuch-json-parser) + (set (make-local-variable 'notmuch-json-parser) + (notmuch-json-create-parser (current-buffer))) + (set (make-local-variable 'notmuch-json-state) 'begin)) + (while (not done) + (condition-case nil + (case notmuch-json-state ((begin) ;; Enter the results list (if (eq (notmuch-json-begin-compound - notmuch-search-json-parser) 'retry) + notmuch-json-parser) 'retry) (setq done t) - (setq notmuch-search-process-state 'result))) + (setq notmuch-json-state 'result))) ((result) ;; Parse a result - (let ((result (notmuch-json-read notmuch-search-json-parser))) + (let ((result (notmuch-json-read notmuch-json-parser))) (case result - ((retry) (setq done t)) - ((end) (setq notmuch-search-process-state 'end)) - (otherwise (notmuch-search-show-result result))))) + ((retry) (setq done t)) + ((end) (setq notmuch-json-state 'end)) + (otherwise (with-current-buffer results-buf + (funcall result-function result)))))) ((end) ;; Any trailing data is unexpected - (notmuch-json-eof notmuch-search-json-parser) + (notmuch-json-eof notmuch-json-parser) (setq done t))) - (json-error - ;; Do our best to resynchronize and ensure forward - ;; progress - (notmuch-search-show-error - "%s" - (with-current-buffer parse-buf - (let ((bad (buffer-substring (line-beginning-position) - (line-end-position)))) - (forward-line) - bad)))))) - ;; Clear out what we've parsed - (with-current-buffer parse-buf - (delete-region (point-min) (point))))))) + (json-error + ;; Do our best to resynchronize and ensure forward + ;; progress + (let ((bad (buffer-substring (line-beginning-position) + (line-end-position)))) + (forward-line) + (with-current-buffer results-buf + (funcall error-function "%s" bad)))))) + ;; Clear out what we've parsed + (delete-region (point-min) (point)))) (defun notmuch-search-tag-all (&optional tag-changes) "Add/remove tags from all messages in current search buffer. @@ -909,7 +943,7 @@ PROMPT is the string to prompt with." (append (list "folder:" "thread:" "id:" "date:" "from:" "to:" "subject:" "attachment:") (mapcar (lambda (tag) - (concat "tag:" tag)) + (concat "tag:" (notmuch-escape-boolean-term tag))) (process-lines notmuch-command "search" "--output=tags" "*"))))) (let ((keymap (copy-keymap minibuffer-local-map)) (minibuffer-completion-table @@ -976,9 +1010,6 @@ Other optional parameters are used as follows: ;; This buffer will be killed by the sentinel, which ;; should be called no matter how the process dies. (parse-buf (generate-new-buffer " *notmuch search parse*"))) - (set (make-local-variable 'notmuch-search-process-state) 'begin) - (set (make-local-variable 'notmuch-search-json-parser) - (notmuch-json-create-parser parse-buf)) (process-put proc 'parse-buf parse-buf) (set-process-sentinel proc 'notmuch-search-process-sentinel) (set-process-filter proc 'notmuch-search-process-filter)