From 17b7790686810c41123d3f17f8777fd643e97a8e Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 7 Jan 2023 10:37:35 +0200 Subject: [PATCH] mu4e: handle the new queries command responses --- mu4e/mu4e-helpers.el | 100 ------------------------------------------- mu4e/mu4e-server.el | 65 +++++++++++++++++++++++++--- mu4e/mu4e.el | 16 +++++++ 3 files changed, 74 insertions(+), 107 deletions(-) diff --git a/mu4e/mu4e-helpers.el b/mu4e/mu4e-helpers.el index 15f2d794..01ab60f8 100644 --- a/mu4e/mu4e-helpers.el +++ b/mu4e/mu4e-helpers.el @@ -65,11 +65,6 @@ You can customize the exact fancy characters used with :type 'boolean :group 'mu4e) -(defcustom mu4e-display-update-status-in-modeline nil - "Non-nil value will display the update status in the modeline." - :group 'mu4e - :type 'boolean) - ;; maybe move the next ones... but they're convenient ;; here because they're needed in multiple buffers. @@ -234,101 +229,6 @@ Function returns the cdr of the list element." (cdr chosen) (mu4e-warn "Unknown shortcut '%c'" response)))) - - -;;; Server properties -(defvar mu4e--server-props nil - "Metadata we receive from the mu4e server. -Use `mu4e--update-server-props' to update.") - -;; XXX: we could make these session-persistent - -(defvar mu4e--baseline-query-results nil - "Some previous version of the query-results. -This is used as the baseline to track updates by comparing it to -the latest query-results.") - -(defvar mu4e--baseline-query-results-tstamp nil - "Timestamp for when the query-results baseline was updated.") - -(defun mu4e-reset-baseline-query-results () - "Reset the baseline query-results." - (interactive) - (setq mu4e--baseline-query-results nil - mu4e--baseline-query-results-tstamp nil)) - -(defun mu4e--update-server-props (props) - "Update server props and possibly the baseline query results." - (setq mu4e--server-props props) - (when-let ((queries (plist-get mu4e--server-props :queries))) - (unless mu4e--baseline-query-results - (setq mu4e--baseline-query-results queries - mu4e--baseline-query-results-tstamp (current-time))))) - -(defun mu4e-server-properties () - "Get the server metadata plist." - mu4e--server-props) - -(defun mu4e-root-maildir() - "Get the root maildir." - (or (and mu4e--server-props - (plist-get mu4e--server-props :root-maildir)) - (mu4e-error "Root maildir unknown; did you start mu4e?"))) - -(defun mu4e-database-path() - "Get the root maildir." - (or (and mu4e--server-props - (plist-get mu4e--server-props :database-path)) - (mu4e-error "Root maildir unknown; did you start mu4e?"))) - -(defun mu4e-server-version() - "Get the root maildir." - (or (and mu4e--server-props - (plist-get mu4e--server-props :version)) - (mu4e-error "Version unknown; did you start mu4e?"))) - -(defun mu4e-last-query-results () - "Get the results (counts) of the last cached queries. - -The cached queries are the bookmark / maildir queries that are -used to populated the read/unread counts in the main view. They -are refreshed when calling `(mu4e)', i.e., when going to the main -view. - -When available, the based-line results are added as well. - -The results are a list of elements of the form - (:query \"query string\" - :count - :unread - :baseline ( ;; baseline results - :count - :unread )) The -baseline part is optional (see -`mu4e-reset-baseline-query-results') for more details)." - (unless mu4e--baseline-query-results - (mu4e-reset-baseline-query-results)) - (seq-map (lambda (qres) - (let* ((query (plist-get qres :query)) - (bres (seq-find ;; find the corresponding baseline entry - (lambda (bq) (string= query (plist-get bq :query))) - mu4e--baseline-query-results))) - (when bres - (plist-put qres :baseline - `(:count ,(plist-get bres :count) - :unread ,(plist-get bres :unread)))) - qres)) - (plist-get mu4e--server-props :queries))) - -(defun mu4e-last-query-result (query) - "Get the last result for some QUERY or nil if not found. -See `mu4e-last-query-results' for the format." - (seq-find - (lambda (elm) ;;; XXX do we need the decoding? - (let ((qstring (decode-coding-string (plist-get elm :query) 'utf-8 t))) - (string= query qstring))) - (mu4e-last-query-results))) - ;;; Logging / debugging diff --git a/mu4e/mu4e-server.el b/mu4e/mu4e-server.el index 214591a5..96f0cf14 100644 --- a/mu4e/mu4e-server.el +++ b/mu4e/mu4e-server.el @@ -132,12 +132,55 @@ from the server process.") (defvar mu4e-pong-func nil "Function called for each (:pong type ....) sexp received.") +(defvar mu4e-queries-func nil + "Function called for each (:queries type ....) sexp received.") + (defvar mu4e-contacts-func nil "A function called for each (:contacts ()) sexp received from the server process.") -;;; Internal vars +;;; Dealing with Server properties +(defvar mu4e--server-props nil + "Metadata we receive from the mu4e server.") + +(defun mu4e-server-properties () + "Get the server metadata plist." + mu4e--server-props) + +(defun mu4e-root-maildir() + "Get the root maildir." + (or (and mu4e--server-props + (plist-get mu4e--server-props :root-maildir)) + (mu4e-error "Root maildir unknown; did you start mu4e?"))) + +(defun mu4e-database-path() + "Get the root maildir." + (or (and mu4e--server-props + (plist-get mu4e--server-props :database-path)) + (mu4e-error "Root maildir unknown; did you start mu4e?"))) + +(defun mu4e-server-version() + "Get the root maildir." + (or (and mu4e--server-props + (plist-get mu4e--server-props :version)) + (mu4e-error "Version unknown; did you start mu4e?"))) + +;; +;; server-query-results are the results from the counting-queries +;; we do for bookmarks etc. to populate the main view with unread +;; counts. + +;;; remember queries result. +(defvar mu4e--server-query-results nil + "Metadata we receive from the mu4e server.") + +(defun mu4e-server-query-results () + "Get the latest server queries list." + mu4e--server-query-results) + + +;;; Handling raw server data (defvar mu4e--server-buf nil "Buffer (string) for data received from the backend.") @@ -164,8 +207,7 @@ Match 1 will be the length (in hex).") Checks whether the server process is live." (and mu4e--server-process (memq (process-status mu4e--server-process) - '(run open listen connect stop)) - t)) + '(run open listen connect stop)) t)) (defsubst mu4e--server-eat-sexp-from-buf () "'Eat' the next s-expression from `mu4e--server-buf'. @@ -286,9 +328,14 @@ The server output is as follows: ;; received a pong message ((plist-get sexp :pong) - (mu4e--update-server-props (plist-get sexp :props)) + (setq mu4e--server-props (plist-get sexp :props)) (funcall mu4e-pong-func sexp)) + ;; receive queries info + ((plist-get sexp :queries) + (setq mu4e--server-query-results (plist-get sexp :queries)) + (funcall mu4e-queries-func sexp)) + ;; received a contacts message ;; note: we use 'member', to match (:contacts nil) ((plist-member sexp :contacts) @@ -562,11 +609,15 @@ Returns either (:update ... ) or (:error ) sexp, which are handled my :rename ,(and maildir mu4e-change-filenames-when-moving t) :no-view ,(and no-view t)))) -(defun mu4e--server-ping (&optional queries) - "Sends a ping to the mu server, expecting a (:pong ...) in response. +(defun mu4e--server-ping () + "Sends a ping to the mu server, expecting a (:pong ...) in response." + (mu4e--server-call-mu `(ping))) + +(defun mu4e--server-queries (queries) + "Sends queries to the mu server, expecting a (:queries ...) in response. QUERIES is a list of queries for the number of results with read/unread status are returned in the pong-response." - (mu4e--server-call-mu `(ping :queries ,queries))) + (mu4e--server-call-mu `(queries :queries ,queries))) (defun mu4e--server-remove (docid) "Remove message with DOCID. diff --git a/mu4e/mu4e.el b/mu4e/mu4e.el index dfc88fa4..86a85fe4 100644 --- a/mu4e/mu4e.el +++ b/mu4e/mu4e.el @@ -138,6 +138,21 @@ Invoke FUNC if non-nil." (lambda () (mu4e-update-mail-and-index mu4e-index-update-in-background))))))) +(defun mu4e--queries-handler (_sexp) + ;; we've received new server-queries; so update the main view + ;; (if any) and the modeline. + + ;; 1. update the query results (i.e. process the new server queries) + (mu4e-last-query-results 'force-update) + (unless mu4e--baseline + (mu4e--reset-baseline)) + (mu4e--modeline-update) + + ;; 2. update the main view, if any + (when (buffer-live-p mu4e-main-buffer-name) + (with-current-buffer mu4e-main-buffer-name + (revert-buffer)))) + (defun mu4e--start (&optional func) "Start mu4e. If `mu4e-contexts' have been defined, but we don't have a context @@ -258,6 +273,7 @@ chance." (mu4e-setq-if-nil mu4e-contacts-func #'mu4e--update-contacts) (mu4e-setq-if-nil mu4e-info-func #'mu4e--info-handler) (mu4e-setq-if-nil mu4e-pong-func #'mu4e--default-handler)) + (mu4e-setq-if-nil mu4e-queries-func #'mu4e--queries-handler)) (defun mu4e-clear-caches () "Clear any cached resources."