From b7b97212ce30057a5bdf37bae2c6d9fe4ab134ad Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 31 Dec 2022 12:43:08 +0200 Subject: [PATCH] mu4e: move search functionality to mu4e-search Move out of mu4e-headers; rename variables and callers. --- mu4e/meson.build | 1 + mu4e/mu4e-actions.el | 2 +- mu4e/mu4e-draft.el | 3 +- mu4e/mu4e-headers.el | 122 +++------------------------------ mu4e/mu4e-obsolete.el | 14 ++++ mu4e/mu4e-search.el | 153 ++++++++++++++++++++++++++++++++++++++---- mu4e/mu4e-vars.el | 18 ----- mu4e/mu4e-view.el | 4 -- 8 files changed, 166 insertions(+), 151 deletions(-) diff --git a/mu4e/meson.build b/mu4e/meson.build index fe061ff8..bd591148 100644 --- a/mu4e/meson.build +++ b/mu4e/meson.build @@ -84,6 +84,7 @@ foreach src : mu4e_srcs '--no-init-file', '--batch', '--eval', '(setq load-prefer-newer t)', + '--eval', '(require \'mu4e-obsolete)', '--eval', target_func, '--directory', meson.current_build_dir(), '--directory', meson.current_source_dir(), diff --git a/mu4e/mu4e-actions.el b/mu4e/mu4e-actions.el index 473a2df2..c10b2ed8 100644 --- a/mu4e/mu4e-actions.el +++ b/mu4e/mu4e-actions.el @@ -241,7 +241,7 @@ the message." (let ((msgid (mu4e-message-field msg :message-id))) (when msgid (let ((mu4e-search-threads t) - (mu4e-headers-include-related t)) + (mu4e-search-include-related t)) (mu4e-search (format "msgid:%s" msgid) nil nil nil diff --git a/mu4e/mu4e-draft.el b/mu4e/mu4e-draft.el index ca012a40..1454d32e 100644 --- a/mu4e/mu4e-draft.el +++ b/mu4e/mu4e-draft.el @@ -248,8 +248,7 @@ This function uses `mu4e-compose-cite-function', and as such all its settings apply." (with-temp-buffer (when (fboundp 'mu4e-view-message-text) ;; keep bytecompiler happy - (let ((mu4e-view-date-format "%Y-%m-%dT%T%z")) - (insert (mu4e-view-message-text msg))) + (insert (mu4e-view-message-text msg)) (message-yank-original) (goto-char (point-min)) (push-mark (point-max)) diff --git a/mu4e/mu4e-headers.el b/mu4e/mu4e-headers.el index 7c133b8e..03a20072 100644 --- a/mu4e/mu4e-headers.el +++ b/mu4e/mu4e-headers.el @@ -177,20 +177,6 @@ query have been received and are displayed." :group 'mu4e-headers) ;;; Public variables - -(defvar mu4e-headers-sort-field :date - "Field to sort the headers by. A symbol: -one of: `:date', `:subject', `:size', `:prio', `:from', `:to.', -`:list'. - -Note that when threading is enabled (through -`mu4e-search-threads'), the headers are exclusively sorted -chronologically (`:date') by the newest message in the thread.") - -(defvar mu4e-headers-sort-direction 'descending - "Direction to sort by; a symbol either `descending' (sorting - Z->A) or `ascending' (sorting A->Z).") - (defcustom mu4e-headers-from-or-to-prefix '("" . "To ") "Prefix for the :from-or-to field when it is showing, respectively, From: or To:. It is a cons cell with the car @@ -321,18 +307,6 @@ followed by the docid, followed by `mu4e~headers-docid-post'.") "Each header starts (invisibly) with the `mu4e~headers-docid-pre', followed by the docid, followed by `mu4e~headers-docid-post'.") -(defvar mu4e~headers-sort-field-choices - '( ("date" . :date) - ("from" . :from) - ("list" . :list) - ("maildir" . :maildir) - ("prio" . :prio) - ("zsize" . :size) - ("subject" . :subject) - ("to" . :to)) - "List of cells describing the various sort-options. -In the format needed for `mu4e-read-option'.") - (defvar mu4e~headers-search-start nil) (defvar mu4e~headers-render-start nil) @@ -867,11 +841,11 @@ true, do *not* update the query history stack." (mu4e--server-find rewritten-expr mu4e-search-threads - mu4e-headers-sort-field - mu4e-headers-sort-direction + mu4e-search-sort-field + mu4e-search-sort-direction maxnum - mu4e-headers-skip-duplicates - mu4e-headers-include-related))) + mu4e-search-skip-duplicates + mu4e-search-include-related))) (defun mu4e~headers-benchmark-message (count) "Get some report message for messaging search and rendering speed." @@ -960,8 +934,6 @@ after the end of the search results." (let ((map (make-sparse-keymap))) (define-key map "j" 'mu4e~headers-jump-to-maildir) - (define-key map "O" 'mu4e-headers-change-sorting) - (define-key map "P" 'mu4e-headers-toggle-property) (define-key map "q" 'mu4e~headers-quit-buffer) (define-key map "g" 'mu4e-search-rerun) ;; for compatibility @@ -1083,26 +1055,14 @@ after the end of the search results." (define-key menumap [compose-new] '("Compose new" . mu4e-compose-new)) (define-key menumap [sepa3] '("--")) - - (define-key menumap [query-next] - '("Next query" . mu4e-headers-query-next)) - (define-key menumap [query-prev] '("Previous query" . - mu4e-headers-query-prev)) - (define-key menumap [narrow-search] '("Narrow search" . - mu4e-headers-search-narrow)) - (define-key menumap [bookmark] '("Search bookmark" . - mu4e-headers-search-bookmark)) (define-key menumap [jump] '("Jump to maildir" . mu4e~headers-jump-to-maildir)) - (define-key menumap [refresh] '("Refresh" . mu4e-search-rerun)) (define-key menumap [search] '("Search" . mu4e-headers-search)) - (define-key menumap [sepa4] '("--")) (define-key menumap [view] '("View" . mu4e-headers-view-message)) (define-key menumap [next] '("Next" . mu4e-headers-next)) - (define-key menumap [previous] '("Previous" . mu4e-headers-prev)) - (define-key menumap [sepa5] '("--"))) + (define-key menumap [previous] '("Previous" . mu4e-headers-prev))) map))) (fset 'mu4e-headers-mode-map mu4e-headers-mode-map) @@ -1116,7 +1076,7 @@ after the end of the search results." (mapcar (lambda (item) (let* ( ;; with threading enabled, we're necessarily sorting by date. - (sort-field (if mu4e-search-threads :date mu4e-headers-sort-field)) + (sort-field (if mu4e-search-threads :date mu4e-search-sort-field)) (field (car item)) (width (cdr item)) (info (cdr (assoc field (append mu4e-header-info mu4e-header-info-custom)))) @@ -1128,7 +1088,7 @@ after the end of the search results." ;; triangle to mark the sorted-by column (arrow (when (and sortable (eq this-field sort-field)) - (if (eq mu4e-headers-sort-direction 'descending) downarrow uparrow))) + (if (eq mu4e-search-sort-direction 'descending) downarrow uparrow))) (name (concat (plist-get info :shortname) arrow)) (map (make-sparse-keymap))) (when sortable @@ -1141,7 +1101,7 @@ after the end of the search results." (and obj (get-text-property 0 'field (car obj))))) ;; "t": if we're already sorted by field, the sort-order is ;; changed - (mu4e-headers-change-sorting field t))))) + (mu4e-search-change-sorting field t))))) (concat (propertize (if width @@ -1310,9 +1270,9 @@ message plist, or nil if not found." (if mu4e-use-fancy-chars (cddr flag-cell) (cadr flag-cell) ) "")) `((,mu4e-search-full . ,mu4e-headers-full-label) - (,mu4e-headers-include-related . ,mu4e-headers-related-label) + (,mu4e-search-include-related . ,mu4e-headers-related-label) (,mu4e-search-threads . ,mu4e-headers-threaded-label) - (,mu4e-headers-skip-duplicates + (,mu4e-search-skip-duplicates . ,mu4e-headers-skip-duplicates-label) (,mu4e-headers-hide-enabled . ,mu4e-headers-hide-label)) "")) @@ -1509,68 +1469,6 @@ descendants." (call-interactively 'mu4e-headers-mark-thread)))) -;;; Interactive functions -(defun mu4e-headers-change-sorting (&optional field dir) - "Change the sorting/threading parameters. -FIELD is the field to sort by; DIR is a symbol: either -`ascending', `descending', t (meaning: if FIELD is the same as -the current sortfield, change the sort-order) or nil (ask the -user)." - (interactive) - (let* ((field - (or field - (mu4e-read-option "Sortfield: " mu4e~headers-sort-field-choices))) - ;; note: 'sortable' is either a boolean (meaning: if non-nil, this is - ;; sortable field), _or_ another field (meaning: sort by this other - ;; field). - (sortable (plist-get (cdr (assoc field mu4e-header-info)) :sortable)) - ;; error check - (sortable - (if sortable - sortable - (mu4e-error "Not a sortable field"))) - (sortfield (if (booleanp sortable) field sortable)) - (dir - (cl-case dir - ((ascending descending) dir) - ;; change the sort order if field = curfield - (t - (if (eq sortfield mu4e-headers-sort-field) - (if (eq mu4e-headers-sort-direction 'ascending) - 'descending 'ascending) - 'descending))))) - (setq - mu4e-headers-sort-field sortfield - mu4e-headers-sort-direction dir) - (mu4e-message "Sorting by %s (%s)" - (symbol-name sortfield) - (symbol-name mu4e-headers-sort-direction)) - (mu4e-search-rerun))) - -(defun mu4e-headers-toggle-property (&optional dont-refresh key) - "Toggle some aspect of headers display. -When prefix-argument DONT-REFRESH is non-nil, do not refresh the -last search with the new setting. -If KEY is provided, use it instead of asking user." - (interactive "P") - (let* ((toggles '(("fFull-search" . mu4e-search-full) - ("rInclude-related" . mu4e-headers-include-related) - ("tShow threads" . mu4e-search-threads) - ("uSkip duplicates" . mu4e-headers-skip-duplicates) - ("pHide-predicate" . mu4e-headers-hide-enabled))) - (toggles (seq-map - (lambda (cell) - (cons - (concat (car cell) - (format" (%s)" - (if (symbol-value (cdr cell)) "on" "off"))) - (cdr cell))) toggles)) - (choice (mu4e-read-option "Toggle property " toggles key))) - (when choice - (set choice (not (symbol-value choice))) - (mu4e-message "Set `%s' to %s" (symbol-name choice) (symbol-value choice)) - (unless dont-refresh - (mu4e-search-rerun))))) (defun mu4e-headers-view-message () "View message at point." diff --git a/mu4e/mu4e-obsolete.el b/mu4e/mu4e-obsolete.el index 9f9d00be..40df184e 100644 --- a/mu4e/mu4e-obsolete.el +++ b/mu4e/mu4e-obsolete.el @@ -164,6 +164,20 @@ (define-obsolete-function-alias 'mu4e-headers-toggle-skip-duplicates 'mu4e-headers-toggle-property "1.9.5") +(define-obsolete-function-alias 'mu4e-headers-change-sorting + 'mu4e-search-change-sorting "1.9.11") +(define-obsolete-function-alias 'mu4e-headers-toggle-property + 'mu4e-search-toggle-property "1.9.11") + +(make-obsolete-variable 'mu4e-headers-include-related + 'mu4e-search-include-related "1.9.11") +(make-obsolete-variable 'mu4e-headers-skip-duplicates + 'mu4e-search-skip-duplicates "1.9.11") +(make-obsolete-variable 'mu4e-headers-sort-field + 'mu4e-search-sort-field "1.9.11") +(make-obsolete-variable 'mu4e-headers-sort-direction + 'mu4e-search-sort-direction "1.9.11") + ;; mu4e-main (define-obsolete-variable-alias diff --git a/mu4e/mu4e-search.el b/mu4e/mu4e-search.el index fe150e47..d345dbf7 100644 --- a/mu4e/mu4e-search.el +++ b/mu4e/mu4e-search.el @@ -46,15 +46,54 @@ This affects performance, especially when `mu4e-summary-include-related' is non-nil. Set to -1 for no limits." :type '(choice (const :tag "Unlimited" -1) - (integer :tag "Limit")) + (integer :tag "Limit")) :group 'mu4e-search) -(defvar mu4e-search-full nil +(defcustom mu4e-search-full nil "Whether to search for all results. -If this is nil, search for up to `mu4e-search-results-limit')") +If this is nil, search for up to `mu4e-search-results-limit')" + :type 'boolean + :group 'mu4e-search) -(defvar mu4e-search-threads t - "Whether to calculate threads for the search results.") +(defcustom mu4e-search-threads t + "Whether to calculate threads for the search results." + :type 'boolean + :group 'mu4e-search) + +(defcustom mu4e-search-include-related t + "Whether to include \"related\" messages in queries. +With this option set to non-nil, not just return the matches for +a searches, but also messages that are related (through their +references) to these messages. This can be useful e.g. to include +sent messages into message threads." + :type 'boolean + :group 'mu4e-search) + +(defcustom mu4e-search-skip-duplicates t + "Whether to skip duplicate messages. +With this option set to non-nil, show only one of duplicate +messages. This is useful when you have multiple copies of the same +message, which is a common occurrence for example when using Gmail +and offlineimap." + :type 'boolean + :group 'mu4e-search) + +(defcustom mu4e-search-sort-field :date + "Field to sort the headers by. A symbol: +one of: `:date', `:subject', `:size', `:prio', `:from', `:to.', +`:list'. + +Note that when threading is enabled (through +`mu4e-search-threads'), the headers are exclusively sorted +chronologically (`:date') by the newest message in the thread." + :type 'symbol + :group 'mu4e-search) + +(defcustom mu4e-search-sort-direction 'descending + "Direction to sort by; a symbol either `descending' (sorting + Z->A) or `ascending' (sorting A->Z)." + :type 'symbol + :group 'mu4e-search) (defcustom mu4e-query-rewrite-function 'identity "Function to rewrite a query. @@ -330,6 +369,77 @@ status, STATUS." (match-end 1) mu4e--lists-hash)))) +;;; Interactive functions +(defun mu4e-search-change-sorting (&optional field dir) + "Change the sorting/threading parameters. +FIELD is the field to sort by; DIR is a symbol: either +`ascending', `descending', t (meaning: if FIELD is the same as +the current sortfield, change the sort-order) or nil (ask the +user)." + (interactive) + (let* ((choices '(("date" . :date) + ("from" . :from) + ("list" . :list) + ("maildir" . :maildir) + ("prio" . :prio) + ("zsize" . :size) + ("subject" . :subject) + ("to" . :to))) + (field + (or field + (mu4e-read-option "Sortfield: " choices))) + ;; note: 'sortable' is either a boolean (meaning: if non-nil, this is + ;; sortable field), _or_ another field (meaning: sort by this other + ;; field). + (sortable (plist-get (cdr (assoc field mu4e-header-info)) :sortable)) + ;; error check + (sortable + (if sortable + sortable + (mu4e-error "Not a sortable field"))) + (sortfield (if (booleanp sortable) field sortable)) + (dir + (cl-case dir + ((ascending descending) dir) + ;; change the sort order if field = curfield + (t + (if (eq sortfield mu4e-search-sort-field) + (if (eq mu4e-search-sort-direction 'ascending) + 'descending 'ascending) + 'descending))))) + (setq + mu4e-search-sort-field sortfield + mu4e-search-sort-direction dir) + (mu4e-message "Sorting by %s (%s)" + (symbol-name sortfield) + (symbol-name mu4e-search-sort-direction)) + (mu4e-search-rerun))) + +(defun mu4e-search-toggle-property (&optional dont-refresh key) + "Toggle some aspect of search. +When prefix-argument DONT-REFRESH is non-nil, do not refresh the +last search with the new setting. +If KEY is provided, use it instead of asking user." + (interactive "P") + (let* ((toggles '(("fFull-search" . mu4e-search-full) + ("rInclude-related" . mu4e-headers-include-related) + ("tShow threads" . mu4e-search-threads) + ("uSkip duplicates" . mu4e-headers-skip-duplicates) + ("pHide-predicate" . mu4e-headers-hide-enabled))) + (toggles (seq-map + (lambda (cell) + (cons + (concat (car cell) + (format" (%s)" + (if (symbol-value (cdr cell)) "on" "off"))) + (cdr cell))) toggles)) + (choice (mu4e-read-option "Toggle property " toggles key))) + (when choice + (set choice (not (symbol-value choice))) + (mu4e-message "Set `%s' to %s" (symbol-name choice) (symbol-value choice)) + (unless dont-refresh + (mu4e-search-rerun))))) + (define-minor-mode mu4e-search-minor-mode "Mode for searching for messages." :global nil @@ -338,17 +448,32 @@ status, STATUS." :lighter "" :keymap (let ((map (make-sparse-keymap))) - (define-key map "s" 'mu4e-search) - (define-key map "S" 'mu4e-search-edit) - (define-key map "/" 'mu4e-search-narrow) + (define-key map "s" #'mu4e-search) + (define-key map "S" #'mu4e-search-edit) + (define-key map "/" #'mu4e-search-narrow) ;;(define-key map "j" 'mu4e~headers-jump-to-maildir) - (define-key map (kbd "") 'mu4e-search-prev) - (define-key map (kbd "\\") 'mu4e-search-prev) - (define-key map (kbd "") 'mu4e-search-next) + (define-key map (kbd "") #'mu4e-search-prev) + (define-key map (kbd "\\") #'mu4e-search-prev) + (define-key map (kbd "") #'mu4e-search-next) - (define-key map "b" 'mu4e-search-bookmark) - (define-key map "B" 'mu4e-search-bookmark-edit) - map)) + (define-key map "O" #'mu4e-search-change-sorting) + (define-key map "P" #'mu4e-search-toggle-property) + + (define-key map "b" #'mu4e-search-bookmark) + (define-key map "B" #'mu4e-search-bookmark-edit) + + (let ((menumap (make-sparse-keymap))) + (define-key map [menu-bar search] (cons "Mu4e" menumap)) + (define-key menumap [query-next] + '("Next query" . mu4e-search-next)) + (define-key menumap [query-prev] '("Previous query" . + mu4e-search-prev)) + (define-key menumap [narrow-search] '("Narrow search" . + mu4e-search-narrow)) + (define-key menumap [bookmark] '("Search bookmark" . + mu4e-search-bookmark)) + (define-key menumap [refresh] '("Refresh" . mu4e-search-rerun)) + map))) (provide 'mu4e-search) ;;; mu4e-search.el ends here diff --git a/mu4e/mu4e-vars.el b/mu4e/mu4e-vars.el index 2283f191..8307a823 100644 --- a/mu4e/mu4e-vars.el +++ b/mu4e/mu4e-vars.el @@ -32,24 +32,6 @@ "Mu4e - an email-client for Emacs." :group 'mail) -(defcustom mu4e-headers-include-related t - "Wether to include \"related\" messages in queries. -With this option set to non-nil, not just return the matches for -a searches, but also messages that are related (through their -references) to these messages. This can be useful e.g. to include -sent messages into message threads." - :type 'boolean - :group 'mu4e-headers) - -(defcustom mu4e-headers-skip-duplicates t - "Whether to skip duplicate messages. -With this option set to non-nil, show only one of duplicate -messages. This is useful when you have multiple copies of the same -message, which is a common occurrence for example when using Gmail -and offlineimap." - :type 'boolean - :group 'mu4e-headers) - (defcustom mu4e-date-format-long "%c" "Date format to use in the message view. Follows the format of `format-time-string'." diff --git a/mu4e/mu4e-view.el b/mu4e/mu4e-view.el index 88e8e593..f201682f 100644 --- a/mu4e/mu4e-view.el +++ b/mu4e/mu4e-view.el @@ -884,10 +884,6 @@ This is useful for advising some Gnus-functionality that does not work in mu4e." (define-key map "A" #'mu4e-view-mime-part-action) (define-key map "e" #'mu4e-view-save-attachments) - ;; toggle header settings - (define-key map "O" #'mu4e-headers-change-sorting) - (define-key map "P" #'mu4e-headers-toggle-property) - ;; change the number of headers (define-key map (kbd "C-+") #'mu4e-headers-split-view-grow) (define-key map (kbd "C--") #'mu4e-headers-split-view-shrink)