- (notmuch-pop-up-error
- (concat
- (format "Error invoking notmuch. %s exited with %s%s.\n"
- (mapconcat #'identity command " ")
- ;; Signal strings look like "Terminated", hence the
- ;; colon.
- (if (integerp exit-status) "status " "signal: ")
- exit-status)
- (when err-file
- (concat "Error:\n"
- (with-temp-buffer
- (insert-file-contents err-file)
- (if (eobp)
- "(no error output)\n"
- (buffer-string)))))
- (when (and output (not (equal output "")))
- (format "Output:\n%s" output))))
- ;; Mimic `process-lines'
- (error "%s exited with status %s" (car command) exit-status))))
+ (let* ((err (when err-file
+ (with-temp-buffer
+ (insert-file-contents err-file)
+ (unless (eobp)
+ (buffer-string)))))
+ (extra
+ (concat
+ "command: " (mapconcat #'shell-quote-argument command " ") "\n"
+ (if (integerp exit-status)
+ (format "exit status: %s\n" exit-status)
+ (format "exit signal: %s\n" exit-status))
+ (when err
+ (concat "stderr:\n" err))
+ (when output
+ (concat "stdout:\n" output)))))
+ (if err
+ ;; We have an error message straight from the CLI.
+ (notmuch-logged-error
+ (replace-regexp-in-string "\\s $" "" err) extra)
+ ;; We only have combined output from the CLI; don't inundate
+ ;; the user with it. Mimic `process-lines'.
+ (notmuch-logged-error (format "%s exited with status %s"
+ (car command) exit-status)
+ extra))
+ ;; `notmuch-logged-error' does not return.
+ ))))
+
+(defun notmuch-call-notmuch-json (&rest args)
+ "Invoke `notmuch-command' with `args' and return the parsed JSON output.
+
+The returned output will represent objects using property lists
+and arrays as lists. If notmuch exits with a non-zero status,
+this will pop up a buffer containing notmuch's output and signal
+an error."
+
+ (with-temp-buffer
+ (let ((err-file (make-temp-file "nmerr")))
+ (unwind-protect
+ (let ((status (apply #'call-process
+ notmuch-command nil (list t err-file) nil args)))
+ (notmuch-check-exit-status status (cons notmuch-command args)
+ (buffer-string) err-file)
+ (goto-char (point-min))
+ (let ((json-object-type 'plist)
+ (json-array-type 'list)
+ (json-false 'nil))
+ (json-read)))
+ (delete-file err-file)))))