mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-22 02:48:08 +01:00
emacs: dropped rest of now-unused JSON functionality
Notmuch cli provides all structured data previously provided in json format now in s-expression format, rendering all current json functionality obsolete.
This commit is contained in:
parent
3553b0a288
commit
2bd374c91e
4 changed files with 3 additions and 271 deletions
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
(require 'mm-view)
|
(require 'mm-view)
|
||||||
(require 'mm-decode)
|
(require 'mm-decode)
|
||||||
(require 'json)
|
|
||||||
(require 'cl)
|
(require 'cl)
|
||||||
|
|
||||||
(defvar notmuch-command "notmuch"
|
(defvar notmuch-command "notmuch"
|
||||||
|
@ -258,7 +257,7 @@ the given type."
|
||||||
parts))
|
parts))
|
||||||
|
|
||||||
;; Helper for parts which are generally not included in the default
|
;; Helper for parts which are generally not included in the default
|
||||||
;; JSON output.
|
;; SEXP output.
|
||||||
(defun notmuch-get-bodypart-internal (query part-number process-crypto)
|
(defun notmuch-get-bodypart-internal (query part-number process-crypto)
|
||||||
(let ((args '("show" "--format=raw"))
|
(let ((args '("show" "--format=raw"))
|
||||||
(part-arg (format "--part=%s" part-number)))
|
(part-arg (format "--part=%s" part-number)))
|
||||||
|
@ -559,271 +558,6 @@ status."
|
||||||
(defvar notmuch-show-process-crypto nil)
|
(defvar notmuch-show-process-crypto nil)
|
||||||
(make-variable-buffer-local 'notmuch-show-process-crypto)
|
(make-variable-buffer-local 'notmuch-show-process-crypto)
|
||||||
|
|
||||||
;; Incremental JSON parsing
|
|
||||||
|
|
||||||
;; 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-parser nil
|
|
||||||
"Internal incremental JSON parser object: local to the buffer being parsed.")
|
|
||||||
|
|
||||||
(defvar notmuch-json-state nil
|
|
||||||
"State of the internal JSON parser: local to the buffer being parsed.")
|
|
||||||
|
|
||||||
(defun notmuch-json-create-parser (buffer)
|
|
||||||
"Return a streaming JSON parser that consumes input from BUFFER.
|
|
||||||
|
|
||||||
This parser is designed to read streaming JSON whose structure is
|
|
||||||
known to the caller. Like a typical JSON parsing interface, it
|
|
||||||
provides a function to read a complete JSON value from the input.
|
|
||||||
However, it extends this with an additional function that
|
|
||||||
requires the next value in the input to be a compound value and
|
|
||||||
descends into it, allowing its elements to be read one at a time
|
|
||||||
or further descended into. Both functions can return 'retry to
|
|
||||||
indicate that not enough input is available.
|
|
||||||
|
|
||||||
The parser always consumes input from BUFFER's point. Hence, the
|
|
||||||
caller is allowed to delete and data before point and may
|
|
||||||
resynchronize after an error by moving point."
|
|
||||||
|
|
||||||
(list buffer
|
|
||||||
;; Terminator stack: a stack of characters that indicate the
|
|
||||||
;; end of the compound values enclosing point
|
|
||||||
'()
|
|
||||||
;; Next: One of
|
|
||||||
;; * 'expect-value if the next token must be a value, but a
|
|
||||||
;; value has not yet been reached
|
|
||||||
;; * 'value if point is at the beginning of a value
|
|
||||||
;; * 'expect-comma if the next token must be a comma
|
|
||||||
'expect-value
|
|
||||||
;; Allow terminator: non-nil if the next token may be a
|
|
||||||
;; terminator
|
|
||||||
nil
|
|
||||||
;; Partial parse position: If state is 'value, a marker for
|
|
||||||
;; the position of the partial parser or nil if no partial
|
|
||||||
;; parsing has happened yet
|
|
||||||
nil
|
|
||||||
;; Partial parse state: If state is 'value, the current
|
|
||||||
;; `parse-partial-sexp' state
|
|
||||||
nil))
|
|
||||||
|
|
||||||
(defmacro notmuch-json-buffer (jp) `(first ,jp))
|
|
||||||
(defmacro notmuch-json-term-stack (jp) `(second ,jp))
|
|
||||||
(defmacro notmuch-json-next (jp) `(third ,jp))
|
|
||||||
(defmacro notmuch-json-allow-term (jp) `(fourth ,jp))
|
|
||||||
(defmacro notmuch-json-partial-pos (jp) `(fifth ,jp))
|
|
||||||
(defmacro notmuch-json-partial-state (jp) `(sixth ,jp))
|
|
||||||
|
|
||||||
(defvar notmuch-json-syntax-table
|
|
||||||
(let ((table (make-syntax-table)))
|
|
||||||
;; The standard syntax table is what we need except that "." needs
|
|
||||||
;; to have word syntax instead of punctuation syntax.
|
|
||||||
(modify-syntax-entry ?. "w" table)
|
|
||||||
table)
|
|
||||||
"Syntax table used for incremental JSON parsing.")
|
|
||||||
|
|
||||||
(defun notmuch-json-scan-to-value (jp)
|
|
||||||
;; Helper function that consumes separators, terminators, and
|
|
||||||
;; whitespace from point. Returns nil if it successfully reached
|
|
||||||
;; the beginning of a value, 'end if it consumed a terminator, or
|
|
||||||
;; 'retry if not enough input was available to reach a value. Upon
|
|
||||||
;; nil return, (notmuch-json-next jp) is always 'value.
|
|
||||||
|
|
||||||
(if (eq (notmuch-json-next jp) 'value)
|
|
||||||
;; We're already at a value
|
|
||||||
nil
|
|
||||||
;; Drive the state toward 'expect-value
|
|
||||||
(skip-chars-forward " \t\r\n")
|
|
||||||
(or (when (eobp) 'retry)
|
|
||||||
;; Test for the terminator for the current compound
|
|
||||||
(when (and (notmuch-json-allow-term jp)
|
|
||||||
(eq (char-after) (car (notmuch-json-term-stack jp))))
|
|
||||||
;; Consume it and expect a comma or terminator next
|
|
||||||
(forward-char)
|
|
||||||
(setf (notmuch-json-term-stack jp) (cdr (notmuch-json-term-stack jp))
|
|
||||||
(notmuch-json-next jp) 'expect-comma
|
|
||||||
(notmuch-json-allow-term jp) t)
|
|
||||||
'end)
|
|
||||||
;; Test for a separator
|
|
||||||
(when (eq (notmuch-json-next jp) 'expect-comma)
|
|
||||||
(when (/= (char-after) ?,)
|
|
||||||
(signal 'json-readtable-error (list "expected ','")))
|
|
||||||
;; Consume it, switch to 'expect-value, and disallow a
|
|
||||||
;; terminator
|
|
||||||
(forward-char)
|
|
||||||
(skip-chars-forward " \t\r\n")
|
|
||||||
(setf (notmuch-json-next jp) 'expect-value
|
|
||||||
(notmuch-json-allow-term jp) nil)
|
|
||||||
;; We moved point, so test for eobp again and fall through
|
|
||||||
;; to the next test if there's more input
|
|
||||||
(when (eobp) 'retry))
|
|
||||||
;; Next must be 'expect-value and we know this isn't
|
|
||||||
;; whitespace, EOB, or a terminator, so point must be on a
|
|
||||||
;; value
|
|
||||||
(progn
|
|
||||||
(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))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(provide 'notmuch-lib)
|
(provide 'notmuch-lib)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
;;
|
;;
|
||||||
;; Authors: David Edmondson <dme@dme.org>
|
;; Authors: David Edmondson <dme@dme.org>
|
||||||
|
|
||||||
(require 'json)
|
|
||||||
(require 'message)
|
(require 'message)
|
||||||
(require 'mm-view)
|
(require 'mm-view)
|
||||||
(require 'format-spec)
|
(require 'format-spec)
|
||||||
|
@ -157,7 +156,7 @@ list."
|
||||||
(setq args (append args '("--reply-to=sender"))))
|
(setq args (append args '("--reply-to=sender"))))
|
||||||
(setq args (append args (list query-string)))
|
(setq args (append args (list query-string)))
|
||||||
|
|
||||||
;; Get the reply object as JSON, and parse it into an elisp object.
|
;; Get the reply object as SEXP, and parse it into an elisp object.
|
||||||
(setq reply (apply #'notmuch-call-notmuch-sexp args))
|
(setq reply (apply #'notmuch-call-notmuch-sexp args))
|
||||||
|
|
||||||
;; Extract the original message to simplify the following code.
|
;; Extract the original message to simplify the following code.
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
;; Authors: David Bremner <david@tethera.net>
|
;; Authors: David Bremner <david@tethera.net>
|
||||||
|
|
||||||
(require 'notmuch-lib)
|
(require 'notmuch-lib)
|
||||||
(require 'json)
|
|
||||||
|
|
||||||
(defun notmuch-query-get-threads (search-terms)
|
(defun notmuch-query-get-threads (search-terms)
|
||||||
"Return a list of threads of messages matching SEARCH-TERMS.
|
"Return a list of threads of messages matching SEARCH-TERMS.
|
||||||
|
|
|
@ -2042,7 +2042,7 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')."
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(setq notmuch-show-process-crypto process-crypto)
|
(setq notmuch-show-process-crypto process-crypto)
|
||||||
;; Always acquires the part via `notmuch part', even if it is
|
;; Always acquires the part via `notmuch part', even if it is
|
||||||
;; available in the JSON output.
|
;; available in the SEXP output.
|
||||||
(insert (notmuch-get-bodypart-internal message-id nth notmuch-show-process-crypto)))
|
(insert (notmuch-get-bodypart-internal message-id nth notmuch-show-process-crypto)))
|
||||||
buf))
|
buf))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue