Consult-mu provides a dynamically updated search interface to mu4e. It uses the awesome package consult by Daniel Mendler and mu/mu4e by Dirk-Jan C. Binnema, and optionally Embark by Omar Antolín Camarena to improve the search experience of mu4e.
There two main interactive commands:
consult-mu-dynamic
: Provides a dynamic version ofmu4e-search
. As the user types inputs, the result gets updated. This command uses a modified version ofmu4e-search
and then takes the content ofmu4e-headers
buffer to populate minibuffer completion table. This allows the user to change the query or search properties (such as number of results, sort-field, sort-direction, …) dynamically by changing the input in the minibuffer. In addition previews of the results can be viewed similar to other consult functions. Once a candidate is selected, the user will see the search result sinmu4e-headers
, andmu4e-view
buffers similar to mu4e-search results.consult-mu-async
: This function provides a very fast search without loading mu4e-headers, which means mu4e functionalities (like marks, reply, forwards, etc.) are not available in the preview buffer. This is very useful for finding individual emails or threads in a large pool quickly (in other words “a needle in a haystack” scenarios!). Previews can be seen while the results are being populated asynchronously (without populating mu4e-headers buffer). Upon selection of a candidate, mu4e-headers buffer is populated with only an individual email (or thread). From here all the normal functionalities of mu4e is again available.consult-mu
: This is simply a wrapper that callsconsult-mu-default-command
, which can be set to either the dynamic or async command for quick access. In other words, setconsult-mu-default-command
to either 1 or 2 above depending on your use case and then useconsult-mu
for convinience and you don’t need to remember the difference between the two anymore.
The advantage of consult-mu-async
over consult-mu-dynamic
is that it is very fast for searching several thousands of messages (even faster than consult-notmuch!), but cannot populate a mu4e-headers buffer with all the results. On the other hand, consult-mu-dynamic
is slower when there are thousands of hits for the search term but provides full functionality for all the results (provides full functionality of mu4e-search
). Therefore, depending on the use case, the user can chose which functions serves the purpose better.
Furthermore, consult-mu
, also provides a number of useful Embark actions that can be called from within minibuffer (see examples below). However, when using embark actions, be advised that sometimes you may get an error especially when using consult-mu-async
. These are likely not critical errors hapening when the databse is out of sync with the results. In such cases syncing the database should resolve the issue.
Before you start, make sure you understand that this is work in progress in its early stage and bugs and breaks are very much expected.
note that: Because mu4e tends to take over buffer/windows management, I had to reimplement (a.k.a. hack) some of the functionalities in order to provide quick previews that stay out of your way when the minibuffer command is done (or canceled), and as a result there is a good chance that errors will arise in edge cases that I have not tested.
In order to use consult-mu, you need the following requirements:
mu4e:
You can access the official documentation for mu4e here: mu4e official manual. If you need step-by-step instructions or prefer videos, there are many useful tutorials online. Here are a few good links:
- EmacsWiki: EmacsWiki: mu4e
- SystemCrafters Videos: Streamline Your E-mail Management with mu4e - Emacs Mail - YouTube & Managing Multiple Email Accounts with mu4e and mbsync - Emacs Mail - YouTube
- Setting Mu4e on MacOS: Email setup in Emacs with Mu4e on macOS | macOS & (open-source) Software
To install consult follow the official instructions here: Configuration of Consult.
Also, make sure you review Consult’s README since it recommends some other packages and useful configurations for different settings. Some of those may improve your experience of consult-mu as well. In particular, the section about asynchronous search is important for learning how to use inputs to search for result and narrow down in minibuffer.
consult-mu is not currently on ELPA or MELPA. Therefore, you need to install it using an alternative non-standard package manager such as straight.el or use manual installation.
To install consult-mu with straight.el you can use the following command. Make sure you load consult-mu after loading mu4e and consult (e.g. require consult
, require mu4e
).
(straight-use-package
'(consult-mu :type git :host github :repo "armindarvish/consult-mu" :branch "main" :files (:defaults "extras/*.el")))
or if you use use-package
macro with straight, you can do:
(use-package consult-mu
:straight (consult-mu :type git :host github :repo "armindarvish/consult-mu" :files (:defaults "extras/*.el"))
:after (mu4e consult)
)
You can also fork this repository and use your own repo.
Clone this repo and make sure the files are on your load path, as described on EmacsWiki.
Make sure you load consult and mu4e (e.g. require consult
, require mu4e
) before you load consult-mu.
consult-mu is built with the idea that the user should be able to customize everything based on their use-case, therefore the user is very much expected to configure consult-mu.
I recommend you read through this section and understand how to configure the package according to your needs and for your specific use-case, but if you just want a drop-in minimal config, look at the snippet below (for snippet with extended settings see extended feature config).
(use-package consult-mu
:straight (consult-mu :type git :host github :repo "armindarvish/consult-mu" :branch "main")
:after (consult mu4e)
:custom
;;maximum number of results shown in minibuffer
(consult-mu-maxnum 200)
;;show preview when pressing any keys
(consult-mu-preview-key 'any)
;;do not mark email as read when previewed
(consult-mu-mark-previewed-as-read nil)
;;do not amrk email as read when selected. This is a good starting point to ensure you would not miss important emails marked as read by mistake especially when trying this package out. Later you can change this to t.
(consult-mu-mark-viewed-as-read nil)
;; open the message in mu4e-view-buffer when selected.
(consult-mu-action #'consult-mu--view-action)
)
Here is a customization that gives you the full feature experience including utilities for attaching/detaching files and searching contacts, etc.
(use-package consult-mu
:straight (consult-mu :type git :host github :repo "armindarvish/consult-mu" :branch "develop" :files (:defaults "extras/*.el"))
:after (consult mu4e)
:custom
;;maximum number of results shown in minibuffer
(consult-mu-maxnum 200)
;;show preview when pressing any keys
(consult-mu-preview-key 'any)
;;do not mark email as read when previewed. If you turn this to t, be aware that the auto-loaded preview if the preview-key above is 'any would also get marked as read!
(consult-mu-mark-previewed-as-read nil)
;;mark email as read when selected.
(consult-mu-mark-viewed-as-read t)
;;use reply to all when composing reply emails
(consult-mu-use-wide-reply t)
;; define a template for headers view in minibuffer. The example below adjusts the width based on the width of the screen.
(consult-mu-headers-template (lambda () (concat "%f" (number-to-string (floor (* (frame-width) 0.15))) "%s" (number-to-string (floor (* (frame-width) 0.5))) "%d13" "%g" "%x")))
:config
;;create a list of saved searches for quick access using `histroy-next-element' with `M-n' in minibuffer. Note the "#" character at the beginning of each query! Change these according to
(setq consult-mu-saved-searches-dynamics '("#flag:unread"))
(setq consult-mu-saved-searches-async '("#flag:unread"))
;; require embark actions for marking, replying, forwarding, etc. directly from minibuffer
(require 'consult-mu-embark)
;; require extra module for composing (e.g. for interactive attachment) as well as embark actions
(require 'consult-mu-compose)
(require 'consult-mu-compose-embark)
;; require extra module for searching contacts and runing embark actions on contacts
(require 'consult-mu-contacts)
(require 'consult-mu-contacts-embark)
;; change the prefiew key for compose so you don't open a preview of every file when selecting files to attach
(setq consult-mu-compose-preview-key "M-o")
;; pick a key to bind to consult-mu-compose-attach in embark-file-map
(setq consult-mu-embark-attach-file-key "C-a")
(setq consult-mu-contacts-ignore-list '("^.*no.*reply.*"))
(setq consult-mu-contacts-ignore-case-fold-search t)
(consult-mu-compose-embark-bind-attach-file-key)
;; choose if you want to use dired for attaching files (choice of 'always, 'in-dired, or nil)
(setq consult-mu-compose-use-dired-attachment 'in-dired)
)
The following customizable variables are provided:
A command function that is called when M-x consult-mu
is called. This is useful for defining special conditions to use consult-mu-dynamics
or consult-mu-async
. By default it is bound to consult-mu-dynamics
, therefore M-x consult-mu
simply calls consult-mu-dynamics
.
This is the default name for HEADERS buffer explicitly for consult-mu. It is, by default, set to "**consult-mu-headers**"
. Note that currently, the header-buffer name is a constant string and shared between all instances of consult-mu calls. This is to prevent running operations in parallel that cause out-of-sync issues.
This is the default name for VIEW buffer explicitly for consult-mu. It is, by default, set to "**consult-mu-view**"
. Note that currently, the view-buffer name is a constant string and shared between all instances of consult-mu calls. This is to prevent creating too many preview buffers and executing operations (such as marking) in parallel that cause out-of-sync issues.
This is the default name of the mu
command line argument. It is set to "mu"
by default, but can be modified for example if mu is at a different path on your system.
Maximum number of messages shown in search results (in consult-mu minibuffer completion table). This is a global option for consult-mu and consult-mu-async, but can be overriden by providing command line arguments in input for example, the following search would fetch up to 1000 results
#github -- --maxnum 1000
This variable is used to format the headers inside minibuffer. This takes a similar format to mu4e-headers-fields
and changes the format of the header only in minibuffer (consult-mu-dynamic
or consult-mu-async
).
Note that it is generally recommended to use consult-mu-headers-template
below because it has more options and does not affect the consult-mu-headers buffer.
consult-mu-headers-field
and is generally the recommended approach to make custom headers.
Special chaacters in the string (either “%[char]” or “%[char][integer]”) in the string get expanded to create headers. Each character represents a different field and the integer defines the length of the field. For exmaple “%d15%s50” means 15 characters for date and 50 charcters for subject.
The list of available fields are:
%f sender(s) (e.g. from: field of email) %t receivers(s) (i.e. to: field of email) %s subject (i.e. title of email) %d date (i.e. the date email was sent/received) with the format “Thu 09 Nov 23” %p priority %z size %i message-id (as defined by mu) %g flags (as defined by mu) %G pretty flags (this uses mu4e~headers-flags-str to pretify flags) %x tags (as defined by mu) %c cc (i.e. cc: field of the email) %h bcc (i.e. bcc: field of the email) %r date chaged (as defined by :changed in mu4e)
For example, the string "%d13%s50%f17%G"
would make a header containing 13
characters for date
, 50
characters for subject
, and 20
characters for from
field, making headers that looks like this:
This defines the field that is used for sorting the results (refer to documentation on the variable mu4e-search-sort-field
for more info). It has to be one of the keywords:
:date
sort by date:subject
sort by title of the email:size
sort by file size:prio
sort by priority:from
sort by name/email of the sender(s):to
sort by name/email of receivers:list
sort by mailing list
Note that the sort field can dynamically be changed by providing command line arguments in the minibuffer input.
For example the following input in the minibuffer will search for emails that are flagged unread but then overrides the sort field and change it t subject
. For details on how to use command line arguments refer to mu manual (e.g. by running mu find --help
in the command line)
#flag:unread -- -s s
Direction of sort. It can either be 'ascending
for A->Z (low number to high number) or 'descending
for Z->A (high number to low number). Note that if a command line argument for reverse order (either -z or –reverse) is provided in the minibuffer, the order will be reverse of the setting defined by this variable.
For example, if consult-mu-search-sort-field
is set to :date
and consult-mu-search-sort-direction
is set to 'descending
the messages are sortes chronologically from the newest on top to the oldest. Then providing a reverse order argument in the minibuffer can dynamically reverse the sort direction:
For example the following input in the minibuffer searches for all unread
emails under "./inbox"
path then reverses the sort direction (because of -z
command line argument)
#(maildir:/inbox) AND flag:unread -- -z
This variable determines whether threads are calculated for search results or not similar to the mu4e-search-threads
variable.
Note that per mu4e docs: When threading is enabled, the headers are exclusively sorted chronologically (:date) by the newest message in the thread.
When this variable is set to nil, it can still be truned on by adding command line arguments (i.e. -t
or --thread
) in the input. For example the following input in the minibuffer will ensure that threads are on even if consult-mu-search-threads
is set to nil.
#flag:unread -- -t
This variable determines what field is used to group messages. This aloows quick movement between groups (For example with vertico-next-group
if you use vertico)
By default it is set to :date. But can be any of the following keywords:
:subject
group by mail title:from
group by name/email of the sender(s):to
group by name/email of the receiver(s):date
group by date in the format “Thu 09 Nov 23”:time
group by the time of email in the format “20:30:07”:datetime
group by date and time of the email with the format “2023-11-04 08:30:07 PM”:year
group by the year of the email (i.e. 2023, 2022, …):month
group by the month of the email (i.e. Jan, Feb, …, Dec):week
group by the week number of the email (.i.e. 1, 2, 3, …, 52):day-of-week
group by the day email was sent (i.e. Monday, Tuesday, …):size
group by the file size of the email:flags
group by flags (as defined by mu):tags
group by tags (as defined by mu):changed
group by the date changed (as defined by :changed field in mu4e)
Note that grouping works alongside sorting. For example if consult-mu-group-by
is set to :day-of-week
and consult-mu-search-sort-field
is set to :date
, then the messages are grouped by day of week (e.g. all emails on Tuesdays will be in one group) then ordered chronologically within each group. The screenshot below shows some examples:
This determines whether a message is marked as read
when it is simply previewed (see consult-mu-preview-key
above and documentation on consult-preview-key
).
Note that when consult-mu-preview-key
is set to 'any
, then as soon as consult-mu
or consult-mu-async
retrieve some results a preview for the first message is shown and this can be marked as read if consult-mu-mark-previewed-as-read
is set to t.
This determines whether a message is marked as read
when it is viewed (i.e. when the minibuffer candidate is selected by hitting RET
).
This is similar to consult-preview-key
but only for consult-mu
. By default, it is set to the value of consult-preview-key to keep consistent experience across different consult packages, but you can set this variable explicitly for consult-mu.
The recommended option is to set this to 'any
so as you naviagte over the candidates you see previews updated.
(setq consult-mu-preview-key 'any)
If the option above slows down your system, and you only want to load previews on demand, then you can set it to a specific key such as "M-o"
.
(setq consult-mu-preview-key "M-o")
You can also turn previews off by setting this variable to nil
, but this is not generally recommended.
This variable determines if consult-mu highlights search queries in minibuffer or preview buffers. By default it is set to t.
When it is set to t, all matches of the search term are highlighted in the minibuffer allowing you to notice why the email is a search hit.
For example in the screenshot below, I am searching for the term consult
and all the matches of consult are highlighted in the titles.
Furthermore if I look at a preview, all the instances of consult-gh matches in the preview buffer are also highlighted:
Note that when the candidate is selected (i.e. by pressing RET
), the highlight overlay is turned off, so you can see the orignial message as is, but you can call consult-mu-overlays-toggle
(i.e. M-x consult-mu-overlays-toggle
) to see the highlights of the query again.
This variable stores the function that is called when a message is selected (i.e. RET
is pressed in the minibuffer). By default it is bound to consult-mu--view-action
which opens both the headers buffer and view buffer and shows the content of the selected message.
These variables are only available after loading the compose module;
(require 'consult-mu-compose)
This variable defines, whether consult-mu
uses dired buffers for selecting files to attach. If it is set to 'always
, consult-mu will always jump to a dired buffer for selecting files to attach. It it is set to 'in-dired
, consult-mu only uses dired (a.k.a. file at point or marked files) for attaching files when already inside a dired buffer. If it is set to nil
, consult-mu uses minibuffer completion for file selection for attachments.
A threshold to make sure very large files are not accidentally opened when previewing files that the user wants to attach to an email. If file is larger than this threshold, the user is asked to confirm before loading the file buffer.
This is similar to consult-mu-preview-key
but only for consult-mu-compose
. This is used to preview files when selecting files for attachments. By default, it is set to the follow the value of consult-mu-preview-key
to keep consistent experience across the package. *But it is recommended to change this to something other than 'any
becuase otherweise every file is previewd as the user is navigating through folders to select files to attach to an email.
(setq consult-mu-compose-preview-key "M-o")
This variable defines a key that can be bound to consult-mu-compose-attach
in emabrk-file-map
, therefore one can call embark on any file and use this key to attach it to an email. This can be bound to “a” or “C-a”:
(setq consult-mu-embark-attach-file-key "C-a")
Running the function consult-mu-compose-embark-bind-attach-file-key
binds this key, but any other key can be passed to this function as well to override the customization variable:
(consult-mu-compose-embark-bind-attach-file-key)
These variables are only available after loading the contacts module;
(require 'consult-mu-contacts)
This variable determines what field is used to group contacts, which allows quick movement between groups (For example with vertico-next-group
if you use vertico)
By default it is set to name. But can be any of the following keywords:
:name
group by contact name:email
group by email of the contact:domain
group by the domain of the contact’s email (e.g. domain.com in user@domain.com):user
group by the ncontact’s user name (e.g. user in user@domain.com)
For example if consult-mu-contacts-group-by
is set to :domain
then the domain of the email address is used to group contacts. This is useful for example if you are looking for all emails from a specific company!
This variable stores the function that is called when a contact is selected (i.e. RET
is pressed in the minibuffer). By default it is bound to consult-mu-contacts--list-messages-action
which searches for all the messages from that contact by calling consult-mu
. You can also set this action to other functions such consult-mu-contacts--insert-email-action
or consult-mu-contacts--copy-email-action
for inserting or copying the email from contact.
Note that the default action for consult-mu-contacts-embark
is inserting the email. This is useful for quickly adding contacts when composing messages. You cna also use embark-collect
or embark-export
to select multiple contacts and act on all of them (e.g. insert all in “To:” field in a compose buffer).
This is a list of rgexp that gets ignored when searching contacts. This is useful to filter certain invalid addreses (e.g. “no-reply” addresses from contacts). For example you can remove no-reply adresses by setting this variable as follows;
(setq consult-mu-contacts-ignore-list '("^.*no.*reply.*$"))
This variable defines whether consult-mu-contacts
uses case insensitive search when matching against consult-mu-contacts-ignore-list
(see above). if you set this to t
, it will preform case *in*sensitive match.
For a detailed description of why this package is useful, and some useful screenshosts showing work flows, you can read my blog post here:
https://www.armindarvish.com/post/improve_your_mu4e_workflow_with_consult-mu/
consult-mu uses consult’s asynchronous search feature. In order to search a query you can type your standard Mu4e query after #
sign in the minibuffer. Here are some examples:
#tickets #flag:unread #(flag:unread AND maildir:/inbox) #(maildir:/drafts OR maildir:/sent)
In addition, you can pass command line arguments that you can normally pass to mu
(see mu find --help
) in the command line to consult-mu by using a --
separator like this:
#tickets -- --maxnum 500 -s s
In the example above, the maximum number of results to retrieve are set to 500 (--maxnum 500
) and the result are sorted by the subject (-s s
). For more details on command line options, you can refer to mu’s help (i.e. run mu find --help
in terminal).
Once consult-mu retrieves a list of results, you can further narrow down the list of candidates by using a second #
.
#tickets -- -z #concert
In the example above, we first run a search for tickets and sort the results with reverse order (using -z
option) then narrow down the list of candidates by the word, concert.
Note that narrow downs are similar to other narrow downs in the minibuffer, therefore here you cannot use mu4e search syntax but you can use regular expressions. Also, the narrow down searches in the entire header string, therefore you can use any information available in the headers (date, title, email addresses, flags,…) for narrow down. (to change the format of the header, take a look at =consult-mu-headers-template=. Here is a screenshot for doing a search and narrow:
consult-mu does have a history variable and keeps record of your previous searches. These searches can quickly be accessed using previous-history-element
(bound to M-p
by default). In addition, you can have a list of saved searches for quick access by modifying the variable consult-mu-saved-searches-dynamic
or consult-mu-saved-searches-async
for consult-mu-dynamic
and consult-mu-async
, respectively. These are lists of mu4e query strings that get added to future-history when you run consult-mu-dynamic or consult-mu-async. By default, consult-mu-saved-searches-async
is set to inherit from consult-mu-saved-searches-dynamic
, but you can modify them independently. This allows separating saved searches that are more suitable for async search from those that are better done with dynamic collection.
Similarly consult-mu-compose-attach
, consult-mu-compose-detach
, and consult-mu-contacts
have their own history elements as wels future history elemetns (for example email in the current message buffer gets added to future-history for searching contacts).
consult-mu provides integration with embark defined in consult-mu-embark.el
If you use embark, you can use these commands to run actions on the search results directly from minibuffer. For example, you can call consult-mu-embark-reply
to reply to a message or consult-mu-embark-mark-for-refile
to refile (a.k.a. archive) the message and so on.
For marking, note that, by default when consult-mu-embark is loaded, it creates a function for every item in the mu4e-marks
and binds them to the :char
for that mark in consult-mu-embark-messages-actions-map
.
You can also use embark-select
and embark-act-all
to run the same command on multiple messages, but this only works in consult-mu-dynamic and not so well with consult-mu-async because with consult-my-async, only one message at a time is added to the headers view and therefore running commands on multiple candidates with embark is not supported.
In addition to improvements for searching, consult-mu also provides extra features for composing, contacts, … These features are defined in the files under the extras
folder.
By default, attaching files to emails with mu4e is not very intuitive or interactive. If you use org-msg, it provides an interactive command for attaching files, but it is only for one file at a time and for each file you need to go through some menus. Some emacs configs, like doomemacs, do provide their own commands to allow using a dired buffer to attach multiple files to an email (see +mu4e/attach-files). Personally, I prefer using a minibuffer completion (instead of switching to a dired buffer) unless I am already in a dired buffer. The consult-mu-compose provides the utilities and customization settings to achieve interactive multi-file attachment.
To use attachment extras, you need to load the compose module by:
(require 'consult-mu-compose)
(require 'consult-mu-compose-embark) ;;optionally load embark actions for compose
It is highly recommended that you also change the preview key binding for consult-mu-compose
to something other than 'any
because seeing a preview of every file when you are navigating through the minibuffer may be slow and annoying. It’s easier to get a preview of the files you are interested in with a key binding like M-o
than to see a preview of every file.
(setq consult-mu-compose-preview-key "M-o")
consult-mu-compose-attach
provides an interactive command to attach files to an email and it tries its best to provide an intuitive interface.
Here are some features:
- interactively selecitng draft compose buffer:
In a compose buffer (e.g. mu4e-compose-mode
, message-mode
, org-msg-edit-mode
), it assumes that the user wants to attach files to the current message. In other buffers it asks the user to select a current compose buffer or creates a new one if noe exists.
- interactively selecting files:
For selecting files, it can either use minibuffer completion or a dired buffer. If the customization variable consult-mu-compose-use-dired-attachment
is set to always
, it always uses dired buffer similar to what dom emacs does. If it is set to 'in-dired
it only uses dired when inside a dired-mode buffer. and if it is set to nil
, it will always use minibuffer completion.
When using dired to chose files, one can mark multiple files to attach to a message. Furthermore, if the command consult-mu-compose-attach
is called from within a compose buffer (e.g. mu4e-compose-mode
, message-mode
, org-msg-edit-mode
), runing embrak-dwim
on the file will attach the file to the current message. This is specially useful if you use embark-dwim
with no-quit
option (embark#quitting-the-minibuffer-after-an-action). Here is an example on how to define embark-dwim-noquit
:
(defun embark-dwim-noquit ()
"Run action but don't quit the minibuffer afterwards."
(interactive)
(let ((embark-quit-after-action nil))
(embark-dwim)))
Then you can just attach multiple files to the same message from any folder by using the minibuffer completion. See the screenshot in my blog post here: https://www.armindarvish.com/post/improve_your_mu4e_workflow_with_consult-mu/
Similarly, consult-mu-compose-detach
provides an interactive command to remove files that are already attached to the current message. It uses minibuffer completion to select a file to remove. Similar to what mentioned above, embark-dwim (or a no-quit version of it) can be used to remove multiple files from the same message. note that the minibuffer completion list does not get dynamically updated when a file is removed (This is something I may improve in the future but for now it works just fine I think).
See the screenshot in my blog post here: https://www.armindarvish.com/post/improve_your_mu4e_workflow_with_consult-mu/
consult-mu-contacts
provides an interactive way to search mu contacs. By default, when a candidate is selected, all the emails form the contact is searched by using consult-mu
. This can be customized to oyher functions (e.g. compose an email to the contact) by seeting consult-mu-contacts-action
. Note that mu does not have a stored list of contacts. Rather, contacts are generated dynamically from the email fields in all messages in the database, including email fields that might be invalid! To use consult-mu-contacts
, you need to load the contacts module by:
(require 'consult-mu-contacts)
(require 'consult-mu-contacts-embark) ;;optionally load embark actions for contacts
See the screenshot in my blog post here: https://www.armindarvish.com/post/improve_your_mu4e_workflow_with_consult-mu/
To report bug, first check if it is already reported in the *issue tracker* and see if there is an existing solution or add relevant comments and discussion under the same issue. If not file a new issue following these steps:
- Make sure the dependencies are installed, and both
mu4e
andconsult
work as expected. - Remove the package and install the latest version (along with dependencies) and see if the issue persists.
- In a bare bone vanilla Emacs (>=28) (e.g.
emacs -Q
), install the latest version of consult-mu (and its dependencies) without any configuration or other packages and see if the issue still persists. - File an issue and provide important information and context in as much detail as possible in your bug report. Important information can include:
- Your operating system, version of Emacs (or the version of emacsen you are using), version of mu/mu4e and consult (see pkg-info).
- The installation method and the configuration you are using with your consult-mu.
- If there is an error message, turn debug-on-error on (by
M-x toggle-debug-on-error
) and include the backtrace content in your report. - If the error only exists when you have some other packages installed, list those packages (e.g. problem happens when evil is installed)
- It would be useful, if you can look at consult-mu buffers while the minibuffer command is active (by default they are named
*consult-mu-headers*
and*consult-mu-view*
buffers) and report whether theya re getting populated properly or not.
This is an open source package, and I appreciate feedback, suggestions, ideas, etc. There are lots of functionalities that can be added to this package to improve different user’s workflows, so if you have some ideas, feel free to file an issue for a feature request.
If you want to contribute to the code, please note that the main branch is currently stable (as stable as a work in progress like this can be) and the develop branch is the current work in progress. So, start from the develop branch to get the latest work-in-progress updates and create a new branch with names such as feature/name-of-the-feature or fix/issue, … Do the edits and then create a new pull request to merge back with the develop branch when you are done with your edits.
Importantly, keep in mind that I am using a literate programming approach (given that this is a small project with very limited number of files) where everything goes into consult-mu.org and then gets tangled to appropriate files (for now that includes consult-mu.el and consult-mu-embark.el). If you open a pull-request where you directly edited the .el files, I will likely not approve it because that will then get overwritten later when I tangle from the .org file. In other words, Do Not Edit The .el Files! only edit the .org file and tangle to .el files.
While mu4e’s built-in search is great and provides ways to edit search terms (e.g. mu4e-search-edit
) or toggle search properties (e.g. mu4e-search-toggle-property
), the interface is not really intuitive. We are simply too impatient in 2024 to use a static search field and edit in steps. A dynamically updated search results is somewhat expected with any modern tools. Try searching in Thunderbird, or Outlook, and you instantly see suggestions and results. This is what consult-mu provides. Hopefully, in the future a dynamics search approach comes built-in with mu4e but until then, this package intends to fill the gap.
What about alternative approaches like counsel-mu or consult-notmuch?
You can read my blog post for some thoughts on this: https://www.armindarvish.com/post/improve_your_mu4e_workflow_with_consult-mu/
Both counsel-mu and consult-notmuch inspired this package. But this package provides soemthing more than those packages. Here is the comparison:
- counsel-mu: counsel-mu provides an async search for mu, and when the candidate is selected, the single message is loaded by using
mu4e-view-message-with-message-id
.consult-mu
takes a similar approach inconsult-mu-async
but expands on that with the following features:a. ability to dynamically add command line options (e.g. using
query -- -s s -z
as input). This includes dynamically changing the number of results. This is important because with counsel-mu, one ha to change the variablemu4e-search-results-limit
globally to see many results, which then affects every mu4e-search that is done.b. ability to load a preview without leaving minibuffer search
c. ability to use emabrk actions on candidates from the minibuffer with
consult-mu-embark
d. ability to see whole threads when selecting a candidate rather than just single messages
In addition,
consult-mu
provides theconsult-mu-dynamic
interactive command that uses dynamic collection usingmu4e-search
(and notmu
commands). This allows doing dynamic search in the minibuffer and then getting a full list of results similar to the built-in mu4e-search.
- consult-notmuch: consult-notmuch is great IF you use notmuch-emacs. consult-mu on the other hand provides similar functionality for mu/mu4e. The comparison therefore comes down to comparing mu4e and notmuch. While notmuch is light and fast, I think it lacks lots of basic functionalities of an email client. It is supposed to be not much after all! As a result, using notmuch as an everyday email client can be challenging especially if you want to use it along with other IMAP-based email clients (e.g. mobile apps). This is because the philosophy of using tags instead of folders requires a complete redesign of some workflows. While some services, like Gmail, use labels, others may not and even if they do, in IMAP-based clients labels are treated as different folders and therefore syncing back custom notmuch labels everywhere (e.g. between notmuch on your desktop machine and your mobile app client) becomes tricky. Of course, in Emacs nothing is impossible and there are ways to improve the experience by adding additional custom elisp (see Emacs: Notmuch demo (notmuch.el) - YouTube and Notmuch as an alternative to mu4e : emacs for some examples), but at the end, the results will still likely lack some important features (like multi-account contexts, …).
More importantly, a common reason to choose notmuch over mu4e is its speed, but using the underlying mu
server and command line can also be very fast. In fact, at least in my own tests, consult-mu-async
, which uses the command line mu
commands was faster than consult-notmuch
. With the latest release of mu4e (version 1.12), even consult-mu-dynamics
(a.k.a. built-in mu4e-search) is now very fast. Therefore, using mu4e
with consult-mu
provides the best of both worlds to me. When I need speed and simplicity, I can use consult-mu-async
to do a fast search (and find thousands of hits) and quickly narrow down to what I am looking for; and when I need a more complete and full-feature client I can use mu4e
built-in functionalities, and with addition of dynamically built searches with consult-mu-dynamic
, I have a modern intuitive interface as well.
Obviously this package would not have been possible without the fabulous mu/mu4e, and consult packages. It also took inspiration from other packages including but not limited to counsel-mu, consult-notmuch, and doomemacs.