Emacs Frontend for Notmuch¶
About this Manual¶
This manual covers only the Emacs interface to Notmuch. For information on the command line interface, see section “Description” in the Notmuch Manual Pages. To save typing, we will sometimes use notmuch in this manual to refer to the Emacs interface to Notmuch. When this distinction is important, we’ll refer to the Emacs interface as notmuch-emacs.
Notmuch-emacs is highly customizable via the Emacs customization framework (or just by setting the appropriate variables). We try to point out relevant variables in this manual, but in order to avoid duplication of information, you can usually find the most detailed description in the variables’ docstring.
notmuch-hello¶
notmuch-hello
is the main entry point for Notmuch. You can start it
with M-x notmuch
or M-x notmuch-hello
. The startup screen looks
something like the following. There are some hints at the bottom of the
screen. There are three main parts to the notmuch-hello screen,
discussed below. The bold text indicates buttons you can click with
a mouse or by positioning the cursor and pressing <return>
You can change the overall appearance of the notmuch-hello screen by customizing the variables
- defcustom notmuch-hello-sections¶
Sections for notmuch-hello.
The list contains functions which are used to construct sections in notmuch-hello buffer. When notmuch-hello buffer is constructed, these functions are run in the order they appear in this list. Each function produces a section simply by adding content to the current buffer. A section should not end with an empty line, because a newline will be inserted after each section by notmuch-hello.
Each function should take no arguments. The return value is ignored.
For convenience an element can also be a list of the form (FUNC ARG1 ARG2 .. ARGN) in which case FUNC will be applied to the rest of the list.
A “Customized tag-list section” item in the customize-interface displays a list of all tags, optionally hiding some of them. It is also possible to filter the list of messages matching each tag by an additional filter query. Similarly, the count of messages displayed next to the buttons can be generated by applying a different filter to the tag query. These filters are also supported for “Customized queries section” items.
- defcustom notmuch-hello-thousands-separator¶
The string used as a thousands separator.
Typically “,” in the US and UK and “.” or “ “ in Europe. The latter is recommended in the SI/ISO 31-0 standard and by the International Bureau of Weights and Measures.
- defcustom notmuch-show-logo¶
Should the notmuch logo be shown?
- defcustom notmuch-column-control¶
Controls the number of columns for saved searches/tags in notmuch view.
This variable has three potential types of values:
- t
Automatically calculate the number of columns possible based on the tags to be shown and the window width.
- integer <n>
A lower bound on the number of characters that will be used to display each column.
- float <f>
A fraction of the window width that is the lower bound on the number of characters that should be used for each column.
So:
if you would like two columns of tags, set this to 0.5.
if you would like a single column of tags, set this to 1.0.
if you would like tags to be 30 characters wide, set this to 30.
if you don’t want to worry about all of this nonsense, leave this set to t.
- defcustom notmuch-show-empty-saved-searches¶
Should saved searches with no messages be listed?
notmuch-hello key bindings¶
- <tab>¶
Move to the next widget (button or text entry field)
- <backtab>¶
Move to the previous widget.
- <return>¶
Activate the current widget.
- G¶
Import mail, See Importing Mail
- m¶
Compose a message
- s¶
Search the notmuch database using notmuch-search
- v¶
Print notmuch version
- q¶
Quit
Saved Searches¶
Since notmuch is entirely search-based, it’s often useful to organize
mail around common searches. To facilitate this, the first section of
notmuch-hello presents a customizable set of saved searches. Saved
searches can also be accessed from anywhere in notmuch by pressing
j
to access notmuch-jump.
The saved searches default to various common searches such as
tag:inbox
to access the inbox and tag:unread
to access all
unread mail, but there are several options for customization:
- defcustom notmuch-saved-searches¶
The list of saved searches, including names, queries, and additional per-query options.
- defcustom notmuch-saved-search-sort-function¶
This variable controls how saved searches should be sorted. A value of
nil
displays the saved searches in the order they are stored in ‘notmuch-saved-searches’.
Search Box¶
The search box lets the user enter a Notmuch query. See section “Description” in Notmuch Query Syntax, for more info on Notmuch query syntax. A history of recent searches is also displayed by default. The latter is controlled by the variable notmuch-hello-recent-searches-max.
- defcustom notmuch-hello-recent-searches-max¶
The number of recent searches to display.
notmuch-search¶
notmuch-search-mode
is used to display the results from executing
a query via notmuch-search
. The syntax for these queries is the
the same as Saved Searches. For details of this syntax see
info:notmuch-search-terms
By default the output approximates that of the command line See section “Description” in notmuch search command.
The main purpose of the notmuch-search-mode
buffer is to act as a
menu of results that the user can explore further by pressing
<return>
on the appropriate line.
- <return>
Open thread on current line in notmuch-show mode
- g
- =
Refresh the buffer
- ?¶
Display full set of key bindings
The presentation of results can be controlled by the following variables.
- defcustom notmuch-search-result-format¶
Search result formatting.
List of pairs of (field . format-string). Supported field strings are: “date”, “count”, “authors”, “subject”, “tags”. It is also supported to pass a function in place of a field name. In this case the function is passed the thread object (plist) and format string.
Line breaks are permitted in format strings (though this is currently experimental). Note that a line break at the end of an “authors” field will get elided if the authors list is long; place it instead at the beginning of the following field. To enter a line break when setting this variable with setq, use n. To enter a line break in customize, press [quoted-insert] C-j.If the car of an element in notmuch-search-result-format is a function, insert the result of calling the function into the buffer.
This allows a user to generate custom fields in the output of a search result. For example, with the following settings, the first few characters on each line of the search result are used to show information about some significant tags associated with the thread.
(defun -notmuch-result-flags (format-string result) (let ((tags-to-letters '(("flagged" . "!") ("unread" . "u") ("mine" . "m") ("sent" . "s") ("replied" . "r"))) (tags (plist-get result :tags))) (format format-string (mapconcat (lambda (t2l) (if (member (car t2l) tags) (cdr t2l) " ")) tags-to-letters "")))) (setq notmuch-search-result-format '((-notmuch-result-flags . "%s ") ("date" . "%12s ") ("count" . "%9s ") ("authors" . "%-30s ") ("subject" . "%s ") ("tags" . "(%s)")))
See also
notmuch-tree-result-format
andnotmuch-unthreaded-result-format
.
- defcustom notmuch-search-oldest-first¶
Display the oldest threads at the top of the buffer
It is also possible to customize how the name of buffers containing search results is formatted using the following variables:
- defcustom notmuch-search-buffer-name-format¶
Format for the name of search results buffers.
In this spec, %s will be replaced by a description of the search query and %t by its type (search, tree or unthreaded). The buffer name is formatted using format-spec: see its docstring for additional parameters for the s and t format specifiers.
See also notmuch-saved-search-buffer-name-format
- defcustom notmuch-saved-search-buffer-name-format¶
Format for the name of search results buffers for saved searches.
In this spec, %s will be replaced by the saved search name and %t by its type (search, tree or unthreaded). The buffer name is formatted using format-spec: see its docstring for additional parameters for the s and t format specifiers.
See also notmuch-search-buffer-name-format
notmuch-show¶
notmuch-show-mode
is used to display a single thread of email from
your email archives.
By default, various components of email messages, (citations, signatures, already-read messages), are hidden. You can make these parts visible by clicking with the mouse button or by pressing RET after positioning the cursor on a hidden part.
- <space>¶
Scroll the current message (if necessary), advance to the next message, or advance to the next thread (if already on the last message of a thread).
- N¶
Move to next message
- P¶
Move to previous message (or start of current message)
- n
Move to next matching message
- p
Move to previous matching message
- !¶
Toggle the display of non-matching messages.
- ?
Display full set of key bindings
Display of messages can be controlled by the following variables; see also Dealing with large messages and threads.
- defcustom notmuch-message-headers¶
Headers that should be shown in a message, in this order.
For an open message, all of these headers will be made visible according to notmuch-message-headers-visible or can be toggled with notmuch-show-toggle-visibility-headers. For a closed message, only the first header in the list will be visible.
- defcustom notmuch-message-headers-visible¶
Should the headers be visible by default?
If this value is non-nil, then all of the headers defined in notmuch-message-headers will be visible by default in the display of each message. Otherwise, these headers will be hidden and notmuch-show-toggle-visibility-headers can be used to make them visible for any given message.
- defcustom notmuch-show-header-line¶
Show a header line in notmuch show buffers.
If t (the default), the header line will contain the current message’s subject.
If a string, this value is interpreted as a format string to be passed to format-spec with %s as the substitution variable for the message’s subject. E.g., to display the subject trimmed to a maximum of 80 columns, you could use “%>-80s” as format.
If you assign to this variable a function, it will be called with the subject as argument, and the return value will be used as the header line format. Since the function is called with the message buffer as the current buffer, it is also possible to access any other properties of the message, using for instance notmuch-show functions such as notmuch-show-get-message-properties.
Finally, if this variable is set to nil, no header is displayed.
- defcustom notmuch-multipart/alternative-discouraged¶
Which mime types to hide by default for multipart messages.
Can either be a list of mime types (as strings) or a function mapping a plist representing the current message to such a list. The following example function would discourage text/html and multipart/related generally, but discourage text/plain should the message be sent from whatever@example.com.
(defun my--determine-discouraged (msg) (let* ((headers (plist-get msg :headers)) (from (or (plist-get headers :From) ""))) (cond ((string-match "whatever@example.com" from) (list "text/plain")) (t (list "text/html" "multipart/related")))))
Dealing with large messages and threads¶
If you are finding notmuch-show is annoyingly slow displaying
large messages, you can customize
notmuch-show-max-text-part-size
. If you want to speed up the
display of large threads (with or without large messages), there are
several options. First, you can display the same query in one of the
other modes. notmuch-unthreaded is the most robust for
extremely large queries, but notmuch-tree is also be faster
than notmuch-show in general, since it only renders a single
message a time. If you prefer to stay with the rendered thread
(“conversation”) view of notmuch-show, you can customize the
variables notmuch-show-depth-limit
,
notmuch-show-height-limit
and
notmuch-show-max-text-part-size
to limit the amount of
rendering done initially. Note that these limits are implicitly
OR-ed together, and combinations might have surprising effects.
- defcustom notmuch-show-depth-limit¶
Depth beyond which message bodies are displayed lazily.
If bound to an integer, any message with tree depth greater than this will have its body display lazily, initially inserting only a button.
If this variable is set to nil (the default) no such lazy insertion is done.
- defcustom notmuch-show-height-limit¶
Height (from leaves) beyond which message bodies are displayed lazily.
If bound to an integer, any message with height in the message tree greater than this will have its body displayed lazily, initially only a button.
If this variable is set to nil (the default) no such lazy display is done.
- defcustom notmuch-show-max-text-part-size¶
Maximum size of a text part to be shown by default in characters.
Set to 0 to show the part regardless of size.
Copy to kill-ring¶
You can use the usually Emacs ways of copying text to the kill-ring, but notmuch also provides some shortcuts. These keys are available in notmuch-show, and notmuch-tree. A subset are available in notmuch-search.
- c G¶
- M-x notmuch-show-stash-git-send-email¶
Copy From/To/Cc/Message-Id of current message to kill-ring. Use a form suitable for pasting to git send-email command line.
If invoked with a prefix argument (or NO-IN-REPLY-TO is non-nil), omit –in-reply-to=<Message-Id>.
- c I¶
- M-x notmuch-show-stash-message-id-stripped¶
Copy message ID of current message (sans id: prefix) to kill-ring.
- c L¶
- M-x notmuch-show-stash-mlarchive-link-and-go¶
Copy an ML Archive URI for the current message to the kill-ring and visit it.
This presumes that the message is available at the selected Mailing List Archive.
If optional argument MLA is non-nil, use the provided key instead of prompting the user (see notmuch-show-stash-mlarchive-link-alist).
- c T¶
- M-x notmuch-show-stash-tags¶
Copy tags of current message to kill-ring as a comma separated list.
- c d¶
- M-x notmuch-show-stash-date¶
Copy date of current message to kill-ring.
If invoked with a prefix argument, copy timestamp of current message to kill-ring.
- c i¶
- M-x notmuch-show-stash-message-id¶
Copy id: query matching the current message to kill-ring.
If invoked with a prefix argument (or STASH-THREAD-ID is non-nil), copy thread: query matching the current thread to kill-ring.
- c l¶
- M-x notmuch-show-stash-mlarchive-link¶
Copy an ML Archive URI for the current message to the kill-ring.
This presumes that the message is available at the selected Mailing List Archive.
If optional argument MLA is non-nil, use the provided key instead of prompting the user (see notmuch-show-stash-mlarchive-link-alist).
Dealing with duplicates¶
If there are multiple files with the same Message-ID (see DUPLICATE MESSAGE FILES), then notmuch-show displays the number of duplicates and identifies the current duplicate. In the following example duplicate 3 of 5 is displayed.
M. Mustermann <max@example.com> (Sat, 30 Jul 2022 10:33:10 -0300) (inbox signed) 3/5
Subject: Re: Multiple files per message in emacs
To: notmuch@notmuchmail.org
- %¶
- M-x notmuch-show-choose-duplicate¶
Display message file with index DUPLICATE in place of the current one.
Message file indices are based on the order the files are discovered by notmuch new (and hence are somewhat arbitrary), and correspond to those passed to the “--duplicate” arguments to the CLI.
When called interactively, the function will prompt for the index of the file to display. An error will be signaled if the index is out of range.
notmuch-tree¶
notmuch-tree-mode
displays the results of a “notmuch tree” of your
email archives. Each line in the buffer represents a single
message giving the relative date, the author, subject, and any
tags.
- <return>
Displays that message.
- N
Move to next message
- P
Move to previous message
- n
Move to next matching message
- p
Move to previous matching message
- o¶
- M-x notmuch-tree-toggle-order¶
Toggle the current search order.
This command toggles the sort order for the current search. The default sort order is defined by notmuch-search-oldest-first.
- l¶
- M-x notmuch-tree-filter¶
Filter or LIMIT the current search results based on an additional query string
- g
- =
Refresh the buffer
- ?
Display full set of key bindings
As is the case with notmuch-search, the presentation of results
can be controlled by the variable notmuch-search-oldest-first
.
- defcustom notmuch-tree-result-format¶
Result formatting for tree view.
List of pairs of (field . format-string). Supported field strings are: “date”, “authors”, “subject”, “tree”, “tags”. It is also supported to pass a function in place of a field-name. In this case the function is passed the thread object (plist) and format string.
Tree means the thread tree box graphics. The field may also be a list in which case the formatting rules are applied recursively and then the output of all the fields in the list is inserted according to format-string.
Note that the author string should not contain whitespace (put it in the neighbouring fields instead).The following example shows how to optionally display recipients instead of authors for sent mail (assuming the user is named Mustermann).
(defun -notmuch-authors-or-to (format-string result) (let* ((headers (plist-get result :headers)) (to (plist-get headers :To)) (author (plist-get headers :From)) (face (if (plist-get result :match) 'notmuch-tree-match-author-face 'notmuch-tree-no-match-author-face))) (propertize (format format-string (if (string-match "Mustermann" author) (concat "To:" (notmuch-tree-clean-address to)) author)) 'face face))) (setq notmuch-tree-result-format '(("date" . "%12s ") (-notmuch-authors-or-to . "%-20.20s") ((("tree" . "%s") ("subject" . "%s")) . " %-54s ") ("tags" . "(%s)")))
See also
notmuch-search-result-format
andnotmuch-unthreaded-result-format
.
notmuch-tree-outline¶
When this mode is set, each thread and subthread in the results list is treated as a foldable section, with its first message as its header.
The mode just makes available in the tree buffer all the keybindings in info:emacs#Outline_Mode, and binds the following additional keys:
- <tab>
Cycle visibility state of the current message’s tree.
- <M-tab>¶
Cycle visibility state of all trees in the buffer.
The behaviour of this minor mode is affected by the following customizable variables:
- defcustom notmuch-tree-outline-enabled¶
Whether to automatically activate notmuch-tree-outline-mode in tree views.
- defcustom notmuch-tree-outline-visibility¶
Default state of the forest outline for notmuch-tree-outline-mode.
This variable controls the state of a forest initially and after a movement command. If set to nil, all trees are displayed while the symbol hide-all indicates that all trees in the forest should be folded and hide-other that only the first one should be unfolded.
- defcustom notmuch-tree-outline-auto-close¶
Close message and tree windows when moving past the last message.
- defcustom notmuch-tree-outline-open-on-next¶
Open new messages under point if they are closed when moving to next one.
When this flag is set, using the command notmuch-tree-outline-next with point on a header for a new message that is not shown will open its notmuch-show buffer instead of moving point to next matching message.
notmuch-unthreaded¶
notmuch-unthreaded-mode
is similar to notmuch-tree in that
each line corresponds to a single message, but no thread information
is presented.
Keybindings are the same as notmuch-tree.
- defcustom notmuch-unthreaded-result-format¶
Result formatting for unthreaded tree view.
List of pairs of (field . format-string). Supported field strings are: “date”, “authors”, “subject”, “tree”, “tags”. It is also supported to pass a function in place of a field-name. In this case the function is passed the thread object (plist) and format string.
Tree means the thread tree box graphics. The field may also be a list in which case the formatting rules are applied recursively and then the output of all the fields in the list is inserted according to format-string.
Note that the author string should not contain whitespace (put it in the neighbouring fields instead).See also
notmuch-search-result-format
andnotmuch-tree-result-format
.
Global key bindings¶
Several features are accessible from most places in notmuch through the following key bindings:
- j¶
Jump to saved searches using notmuch-jump.
- k¶
Tagging operations using notmuch-tag-jump
- C-_¶
- C-/¶
- C-x u¶
Undo previous tagging operation using
notmuch-tag-undo
notmuch-jump¶
Saved searches configured through Saved Searches can
include a “shortcut key” that’s accessible through notmuch-jump.
Pressing j
anywhere in notmuch followed by the configured shortcut
key of a saved search will immediately jump to that saved search. For
example, in the default configuration j i
jumps immediately to the
inbox search. When you press j
, notmuch-jump shows the saved
searches and their shortcut keys in the mini-buffer.
notmuch-tag-jump¶
Tagging operations configured through notmuch-tagging-keys
can
be accessed via k in notmuch-show,
notmuch-search and notmuch-tree. With a
prefix (C-u k), notmuch displays a menu of the reverses of the
operations specified in notmuch-tagging-keys
; i.e. each
+tag
is replaced by -tag
and vice versa.
- defcustom notmuch-tagging-keys¶
A list of keys and corresponding tagging operations.
For each key (or key sequence) you can specify a sequence of tagging operations to apply, or a variable which contains a list of tagging operations such as notmuch-archive-tags. The final element is a name for this tagging operation. If the name is omitted or empty then the list of tag changes, or the variable name is used as the name.
The key notmuch-tag-jump-reverse-key (k by default) should not be used (either as a key, or as the start of a key sequence) as it is already bound: it switches the menu to a menu of the reverse tagging operations. The reverse of a tagging operation is the same list of individual tag-ops but with +tag replaced by -tag and vice versa.
If setting this variable outside of customize then it should be a list of triples (lists of three elements). Each triple should be of the form (key-binding tagging-operations name). KEY-BINDING can be a single character or a key sequence; TAGGING-OPERATIONS should either be a list of individual tag operations each of the form +tag or -tag, or the variable name of a variable that is a list of tagging operations; NAME should be a name for the tagging operation, if omitted or empty than then name is taken from TAGGING-OPERATIONS.
notmuch-tag-undo¶
Each notmuch buffer supporting tagging operations (i.e. buffers in
notmuch-show, notmuch-search, notmuch-tree, and
notmuch-unthreaded mode) keeps a local stack of tagging
operations. These can be undone via notmuch-tag-undo
. By default
this is bound to the usual Emacs keys for undo.
- C-_
- C-/
- C-x u
- M-x notmuch-tag-undo¶
Undo the previous tagging operation in the current buffer. Uses buffer local variable notmuch-tag-history to determine what that operation was.
Configuration¶
Importing Mail¶
- M-x notmuch-poll¶
Run “notmuch new” or an external script to import mail.
Invokes notmuch-poll-script, “notmuch new”, or does nothing depending on the value of notmuch-poll-script.
- defcustom notmuch-poll-script¶
[Deprecated] Command to run to incorporate new mail into the notmuch database.
This option has been deprecated in favor of “notmuch new” hooks (see man notmuch-hooks). To change the path to the notmuch binary, customize notmuch-command.
This variable controls the action invoked by notmuch-poll-and-refresh-this-buffer (bound by default to ‘G’) to incorporate new mail into the notmuch database.
If set to nil (the default), new mail is processed by invoking “notmuch new”. Otherwise, this should be set to a string that gives the name of an external script that processes new mail. If set to the empty string, no command will be run.
The external script could do any of the following depending on the user’s needs:
1. Invoke a program to transfer mail to the local mail store 2. Invoke “notmuch new” to incorporate the new mail 3. Invoke one or more “notmuch tag” commands to classify the mail
Sending Mail¶
- defcustom mail-user-agent¶
Emacs consults the variable
mail-user-agent
to choose a mail sending package for commands likereport-emacs-bug
andcompose-mail
. To usenotmuch
for this, customize this variable to the symbolnotmuch-user-agent
.
- defcustom message-dont-reply-to-names¶
When composing mail replies, Emacs’s message mode uses the variable
message-dont-reply-to-names
to exclude recipients matching a given collection of regular expressions or satisfying an arbitrary predicate. Notmuch’s MUA inherits this standard mechanism and will honour your customization of this variable.
Init File¶
When Notmuch is loaded, it will read the notmuch-init-file
(~/.emacs.d/notmuch-config
by default) file. This is normal Emacs Lisp
file and can be used to avoid cluttering your ~/.emacs
with Notmuch
stuff. If the file with .elc
, .elc.gz
, .el
or .el.gz
suffix exist it will be read instead (just one of these, chosen in this
order). Most often users create ~/.emacs.d/notmuch-config.el
and just
work with it. If Emacs was invoked with the -q
or --no-init-file
options, notmuch-init-file
is not read.