- (assert (eq (notmuch-json-next jp) 'expect-value))
- (setf (notmuch-json-next jp) 'value)
- nil))))
-
-(defun notmuch-json-begin-compound (jp)
- "Parse the beginning of a compound value and traverse inside it.
-
-Returns 'retry if there is insufficient input to parse the
-beginning of the compound. If this is able to parse the
-beginning of a compound, it moves point past the token that opens
-the compound and returns t. Later calls to `notmuch-json-read'
-will return the compound's elements.
-
-Entering JSON objects is currently unimplemented."
-
- (with-current-buffer (notmuch-json-buffer jp)
- ;; Disallow terminators
- (setf (notmuch-json-allow-term jp) nil)
- ;; Save "next" so we can restore it if there's a syntax error
- (let ((saved-next (notmuch-json-next jp)))
- (or (notmuch-json-scan-to-value jp)
- (if (/= (char-after) ?\[)
- (progn
- (setf (notmuch-json-next jp) saved-next)
- (signal 'json-readtable-error (list "expected '['")))
- (forward-char)
- (push ?\] (notmuch-json-term-stack jp))
- ;; Expect a value or terminator next
- (setf (notmuch-json-next jp) 'expect-value
- (notmuch-json-allow-term jp) t)
- t)))))
-
-(defun notmuch-json-read (jp)
- "Parse the value at point in JP's buffer.
-
-Returns 'retry if there is insufficient input to parse a complete
-JSON value (though it may still move point over separators or
-whitespace). If the parser is currently inside a compound value
-and the next token ends the list or object, this moves point just
-past the terminator and returns 'end. Otherwise, this moves
-point to just past the end of the value and returns the value."
-
- (with-current-buffer (notmuch-json-buffer jp)
- (or
- ;; Get to a value state
- (notmuch-json-scan-to-value jp)
-
- ;; Can we parse a complete value?
- (let ((complete
- (if (looking-at "[-+0-9tfn]")
- ;; This is a number or a keyword, so the partial
- ;; parser isn't going to help us because a truncated
- ;; number or keyword looks like a complete symbol to
- ;; it. Look for something that clearly ends it.
- (save-excursion
- (skip-chars-forward "^]},: \t\r\n")
- (not (eobp)))
-
- ;; We're looking at a string, object, or array, which we
- ;; can partial parse. If we just reached the value, set
- ;; up the partial parser.
- (when (null (notmuch-json-partial-state jp))
- (setf (notmuch-json-partial-pos jp) (point-marker)))
-
- ;; Extend the partial parse until we either reach EOB or
- ;; get the whole value
- (save-excursion
- (let ((pstate
- (with-syntax-table notmuch-json-syntax-table
- (parse-partial-sexp
- (notmuch-json-partial-pos jp) (point-max) 0 nil
- (notmuch-json-partial-state jp)))))
- ;; A complete value is available if we've reached
- ;; depth 0 or less and encountered a complete
- ;; subexpression.
- (if (and (<= (first pstate) 0) (third pstate))
- t
- ;; Not complete. Update the partial parser state
- (setf (notmuch-json-partial-pos jp) (point-marker)
- (notmuch-json-partial-state jp) pstate)
- nil))))))
-
- (if (not complete)
- 'retry
- ;; We have a value. Reset the partial parse state and expect
- ;; a comma or terminator after the value.
- (setf (notmuch-json-next jp) 'expect-comma
- (notmuch-json-allow-term jp) t
- (notmuch-json-partial-pos jp) nil
- (notmuch-json-partial-state jp) nil)
- ;; Parse the value
- (let ((json-object-type 'plist)
- (json-array-type 'list)
- (json-false nil))
- (json-read)))))))
-
-(defun notmuch-json-eof (jp)
- "Signal a json-error if there is more data in JP's buffer.
-
-Moves point to the beginning of any trailing data or to the end
-of the buffer if there is only trailing whitespace."
-
- (with-current-buffer (notmuch-json-buffer jp)
- (skip-chars-forward " \t\r\n")
- (unless (eobp)
- (signal 'json-error (list "Trailing garbage following JSON data")))))
-
-(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-json-parser) 'retry)
- (setq done t)
- (setq notmuch-json-state 'result)))
- ((result)
- ;; Parse a result
- (let ((result (notmuch-json-read notmuch-json-parser)))
- (case 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-json-parser)
- (setq done t)))
- (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))))
-
-
-
+ ;; Invoke the sub-sentinel, if any
+ (when sub-sentinel
+ (funcall sub-sentinel proc event))
+ ;; Check the exit status. This will signal an error if the
+ ;; exit status is non-zero. Don't do this if the process
+ ;; buffer is dead since that means Emacs killed the process
+ ;; and there's no point in telling the user that (but we
+ ;; still check for and report stderr output below).
+ (when (buffer-live-p (process-buffer proc))
+ (notmuch-check-async-exit-status proc event nil err))
+ ;; If that didn't signal an error, then any error output was
+ ;; really warning output. Show warnings, if any.
+ (let ((warnings
+ (and err
+ (with-current-buffer err-buffer
+ (goto-char (point-min))
+ (end-of-line)
+ ;; Show first line; stuff remaining lines in the
+ ;; errors buffer.
+ (let ((l1 (buffer-substring (point-min) (point))))
+ (skip-chars-forward "\n")
+ (cons l1 (and (not (eobp))
+ (buffer-substring (point)
+ (point-max)))))))))
+ (when warnings
+ (notmuch-logged-error (car warnings) (cdr warnings)))))
+ (error
+ ;; Emacs behaves strangely if an error escapes from a sentinel,
+ ;; so turn errors into messages.
+ (message "%s" (error-message-string err))))))
+
+(defun notmuch-start-notmuch-error-sentinel (proc _event)
+ (unless (process-live-p proc)
+ (let ((buffer (process-buffer proc)))
+ (when (buffer-live-p buffer)
+ (kill-buffer buffer)))))
+
+(defvar-local notmuch-show-process-crypto nil)
+
+(defun notmuch--run-show (search-terms &optional duplicate)
+ "Return a list of threads of messages matching SEARCH-TERMS.
+
+A thread is a forest or list of trees. A tree is a two element
+list where the first element is a message, and the second element
+is a possibly empty forest of replies."
+ (let ((args '("show" "--format=sexp" "--format-version=5")))
+ (when notmuch-show-process-crypto
+ (setq args (append args '("--decrypt=true"))))
+ (when duplicate
+ (setq args (append args (list (format "--duplicate=%d" duplicate)))))
+ (setq args (append args search-terms))
+ (apply #'notmuch-call-notmuch-sexp args)))
+
+;;; Generic Utilities
+
+(defun notmuch-interactive-region ()
+ "Return the bounds of the current interactive region.
+
+This returns (BEG END), where BEG and END are the bounds of the
+region if the region is active, or both `point' otherwise."
+ (if (region-active-p)
+ (list (region-beginning) (region-end))
+ (list (point) (point))))
+
+(define-obsolete-function-alias
+ 'notmuch-search-interactive-region
+ 'notmuch-interactive-region
+ "notmuch 0.29")
+
+(defun notmuch--inline-override-types ()
+ "Override mm-inline-override-types to stop application/*
+parts from being displayed unless the user has customized
+it themselves."
+ (if (equal mm-inline-override-types
+ (eval (car (get 'mm-inline-override-types 'standard-value))))
+ (cons "application/.*" mm-inline-override-types)
+ mm-inline-override-types))
+;;; _