(defvar notmuch-search-history nil
"Variable to store notmuch searches history.")
-(defcustom notmuch-saved-searches nil
+(defcustom notmuch-saved-searches '(("inbox" . "tag:inbox")
+ ("unread" . "tag:unread"))
"A list of saved searches to display."
:type '(alist :key-type string :value-type string)
:group 'notmuch-hello)
:group 'notmuch-search
:group 'notmuch-show)
-(defvar notmuch-folders nil
- "Deprecated name for what is now known as `notmuch-saved-searches'.")
-
-(defun notmuch-saved-searches ()
- "Common function for querying the notmuch-saved-searches variable.
-
-We do this as a function to support the old name of the
-variable (`notmuch-folders') as well as for the default value if
-the user hasn't set this variable with the old or new value."
- (if notmuch-saved-searches
- notmuch-saved-searches
- (if notmuch-folders
- notmuch-folders
- '(("inbox" . "tag:inbox")
- ("unread" . "tag:unread")))))
-
(defun notmuch-version ()
"Return a string with the notmuch version number."
(let ((long-string
"[No Subject]"
subject)))
+(defun notmuch-escape-boolean-term (term)
+ "Escape a boolean term for use in a query.
+
+The caller is responsible for prepending the term prefix and a
+colon. This performs minimal escaping in order to produce
+user-friendly queries."
+
+ (save-match-data
+ (if (or (equal term "")
+ (string-match "[ ()]\\|^\"" term))
+ ;; Requires escaping
+ (concat "\"" (replace-regexp-in-string "\"" "\"\"" term t t) "\"")
+ term)))
+
(defun notmuch-id-to-query (id)
"Return a query that matches the message with id ID."
- (concat "id:\"" (replace-regexp-in-string "\"" "\"\"" id t t) "\""))
+ (concat "id:" (notmuch-escape-boolean-term id)))
;;
(defun notmuch-common-do-stash (text)
"Common function to stash text in kill ring, and display in minibuffer."
- (kill-new text)
- (message "Stashed: %s" text))
+ (if text
+ (progn
+ (kill-new text)
+ (message "Stashed: %s" text))
+ ;; There is nothing to stash so stash an empty string so the user
+ ;; doesn't accidentally paste something else somewhere.
+ (kill-new "")
+ (message "Nothing to stash!")))
;;
;; 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.
(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)
;; Local Variables: