diff --git a/mu4e/mu4e-headers.el b/mu4e/mu4e-headers.el index 86236d59..c55d5044 100644 --- a/mu4e/mu4e-headers.el +++ b/mu4e/mu4e-headers.el @@ -127,14 +127,6 @@ sent messages into message threads." :type 'boolean :group 'mu4e-headers) -(defcustom mu4e-headers-include-related-maxnum 800 - "Ignore `mu4e-headers-includer-related' when -`mu4e-headers-results-limit' is greater than this value (including -'unlimited')" - :type 'boolean - :group 'mu4e-headers) - - ;; marks for headers of the form; each is a cons-cell (basic . fancy) ;; each of which is basic ascii char and something fancy, respectively (defvar mu4e-headers-draft-mark (purecopy '("D" . "⚒")) "Draft.") @@ -508,18 +500,18 @@ after the end of the search results." (define-key map "O" 'mu4e-headers-change-sorting) (define-key map "P" 'mu4e-headers-toggle-threading) (define-key map "Q" 'mu4e-headers-toggle-full-search) + (define-key map "W" 'mu4e-headers-toggle-include-related) + (define-key map "V" 'mu4e-headers-toggle-skip-duplicates) (define-key map "q" 'mu4e~headers-quit-buffer) (define-key map "z" 'mu4e~headers-quit-buffer) - (define-key map "r" 'mu4e-headers-rerun-search) (define-key map "g" 'mu4e-headers-rerun-search) ;; for compatibility (define-key map "%" 'mu4e-headers-mark-pattern) (define-key map "t" 'mu4e-headers-mark-subthread) (define-key map "T" 'mu4e-headers-mark-thread) - ;; navigation between messages (define-key map "p" 'mu4e-headers-prev) (define-key map "n" 'mu4e-headers-next) @@ -861,10 +853,7 @@ the query history stack." (mu4e-hide-other-mu4e-buffers) (let* ((buf (get-buffer-create mu4e~headers-buffer-name)) (inhibit-read-only t) - (maxnum (unless mu4e-headers-full-search mu4e-headers-results-limit)) - (include-related - (when (and maxnum (<= maxnum mu4e-headers-include-related-maxnum)) - mu4e-headers-include-related))) + (maxnum (unless mu4e-headers-full-search mu4e-headers-results-limit))) (with-current-buffer buf (mu4e-headers-mode) (unless ignore-history @@ -885,7 +874,7 @@ the query history stack." mu4e~headers-sort-direction maxnum mu4e-headers-skip-duplicates - include-related))) + mu4e-headers-include-related))) (defun mu4e~headers-redraw-get-view-window () "Close all windows, redraw the headers buffer based on the value @@ -1178,31 +1167,45 @@ sortfield, change the sort-order) or nil (ask the user)." (symbol-name mu4e~headers-sort-direction)) (mu4e-headers-rerun-search))) -(defun mu4e-headers-toggle-threading (&optional dont-refresh) - "Toggle threading on/off for the search results. -With prefix-argument, do _not_ refresh the last search with the -new setting for threading." - (interactive "P") - (setq mu4e-headers-show-threads (not mu4e-headers-show-threads)) - (mu4e-message "Threading turned %s%s" - (if mu4e-headers-show-threads "on" "off") +(defun mu4e~headers-toggle (name togglevar dont-refresh) + "Toggle variable TOGGLEVAR for feature NAME. Unless DONT-REFRESH is non-nil, +re-run the last search." + (set togglevar (not (symbol-value togglevar))) + (mu4e-message "%s turned %s%s" + name + (if (symbol-value togglevar) "on" "off") (if dont-refresh - " (press 'g' to refresh)" "")) + " (press 'g' to refresh)" "")) (unless dont-refresh (mu4e-headers-rerun-search))) -(defun mu4e-headers-toggle-full-search (&optional dont-refresh) - "Toggle full-search on/off for the search results. -With prefix-argument, do _not_ refresh the last search with the -new setting for threading." +(defun mu4e-headers-toggle-threading (&optional dont-refresh) + "Toggle `mu4e-headers-show-threads'. With prefix-argument, do +_not_ refresh the last search with the new setting for threading." (interactive "P") - (setq mu4e-headers-full-search (not mu4e-headers-full-search)) - (mu4e-message "Full search turned %s%s" - (if mu4e-headers-full-search "on" "off") - (if dont-refresh - " (press 'g' to refresh)" "")) - (unless dont-refresh - (mu4e-headers-rerun-search))) + (mu4e~headers-toggle "Threading" 'mu4e-headers-show-threads dont-refresh)) + +(defun mu4e-headers-toggle-full-search (&optional dont-refresh) + "Toggle `mu4e-headers-full-search'. With prefix-argument, do +_not_ refresh the last search with the new setting for threading." + (interactive "P") + (mu4e~headers-toggle "Full-search" + 'mu4e-headers-full-search dont-refresh)) + +(defun mu4e-headers-toggle-include-related (&optional dont-refresh) + "Toggle `mu4e-headers-include-related'. With prefix-argument, do +_not_ refresh the last search with the new setting for threading." + (interactive "P") + (mu4e~headers-toggle "Include-related" + 'mu4e-headers-include-related dont-refresh)) + +(defun mu4e-headers-toggle-skip-duplicates (&optional dont-refresh) + "Toggle `mu4e-headers-skip-duplicates'. With prefix-argument, do +_not_ refresh the last search with the new setting for threading." + (interactive "P") + (mu4e~headers-toggle "Skip-duplicates" + 'mu4e-headers-duplicates dont-refresh)) + (defvar mu4e~headers-loading-buf nil "A buffer for loading a message view.") diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index 08e34ce1..2735cbf4 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -770,7 +770,8 @@ M-right next query O change sort order P toggle threading Q toggle full-search - +V toggle skip-duplicates +W toggle include-related marking ------- @@ -1673,7 +1674,7 @@ jumping to a maildir (@kbd{M-x mu4e-headers-jump-to-maildir}, @key{j}) or because you followed some bookmark (@kbd{M-x mu4e-headers-search-bookmark}, @key{b}). Now, you want to narrow things down to only those messages that have attachments. - +1 This is when @kbd{M-x mu4e-headers-search-narrow} (@key{/}) comes in handy. It asks for an additional search pattern, which is appended to the current search query, in effect getting you the subset of the currently shown headers that @@ -1687,26 +1688,26 @@ of @code{mu4e-headers-results-limit}, may show up in the narrowed query. @subsection Including related messages @anchor{Including related messages} -It can be useful to include @emph{related} messages in your search results -- -that is, messages that belong to the message threads that one or more of the -matched messages belong to, too. With this option, results are somewhat like -the discussion threads in Gmail. - -To enable this, set @code{mu4e-headers-include-related} to @code{t}. Since -this can significanlty affect performance when there are many results, -@code{mu4e-headers-include-related} is automatically disabled (for the next -query) when the @code{mu4e-headers-results-limit} exceeds -@code{mu4e-headers-include-related-maxnum}. +It can be useful to not only show the messages that directly match a certain +query, but also include messages that are related to these messages. That is, +messages that belong to the same discussion thread are included in the +results, just like e.g. Gmail does it. You can enable this behavior by setting +@code{mu4e-headers-include-related} to @code{t}, and you can toggle between +including/not-including with @key{W}. @subsection Skipping duplicates @anchor{Skipping duplicates} -It is possible to show only one of multiple, duplicate messages (messages with -the same Message-ID). This can be useful when you have copies of the same -message, which is a common case, for example, when using Gmail and -@t{offlineimap}. +Another useful features is skipping duplicate messages. When you have copies +of messages, there's usually little value in including more than one in search +results. A common reason for having multiple copies of messages in the +combination of Gmail and @t{offlineimap}, since that is the way the labels / +virtual folders in Gmail are represented. You can enable skipping duplicates +by setting @code{mu4e-headers-skip-duplicates} to @code{t}, and you can toggle +between the skipping/not skipping with @key{V}. -To skip duplicates, set @code{mu4e-headers-skip-duplicates} to @code{t}. +Note, messages are considered duplicates when they have the same +@t{Message-Id}. @node Marking @chapter Marking @@ -2627,6 +2628,9 @@ with @t{mu4e}. Since we are using @abbr{IMAP}, you must enable that in the Gmail web interface (in the settings, under the ``Forwarding and POP/IMAP''-tab). +Gmail users may also be interested in @ref{Including related messages, +skipping duplicates}. + @subsection Setting up offlineimap First of all, we need a program to get the e-mail from Gmail to our local