2021-08-24 17:17:16 +02:00
|
|
|
.. _notmuch-sexp-queries(7):
|
|
|
|
|
|
|
|
====================
|
|
|
|
notmuch-sexp-queries
|
|
|
|
====================
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
========
|
|
|
|
|
2021-08-24 17:17:45 +02:00
|
|
|
**notmuch** *subcommand* ``--query=sexp`` [option ...] ``--`` '(and (to santa) (date december))'
|
2021-08-24 17:17:16 +02:00
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
===========
|
|
|
|
|
2021-08-24 17:17:45 +02:00
|
|
|
Notmuch supports an alternative query syntax based on `S-expressions
|
|
|
|
<https://en.wikipedia.org/wiki/S-expression>`_ . It can be selected
|
|
|
|
with the command line ``--query=sexp`` or with the appropriate option
|
|
|
|
to the library function :c:func:`notmuch_query_create_with_syntax`.
|
|
|
|
Support for this syntax is currently optional, you can test if your
|
|
|
|
build of notmuch supports it with
|
|
|
|
|
|
|
|
::
|
|
|
|
|
2021-10-30 20:49:20 +02:00
|
|
|
$ notmuch config get built_with.sexp_queries
|
2021-08-24 17:17:45 +02:00
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
|
|
|
|
S-EXPRESSIONS
|
|
|
|
-------------
|
|
|
|
|
|
|
|
An *s-expression* is either an atom, or list of whitespace delimited
|
|
|
|
s-expressions inside parentheses. Atoms are either
|
|
|
|
|
|
|
|
*basic value*
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
A basic value is an unquoted string containing no whitespace, double quotes, or
|
|
|
|
parentheses.
|
|
|
|
|
|
|
|
*quoted string*
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
Double quotes (") delimit strings possibly containing whitespace
|
|
|
|
or parentheses. These can contain double quote characters by
|
|
|
|
escaping with backslash. E.g. ``"this is a quote \""``.
|
|
|
|
|
|
|
|
S-EXPRESSION QUERIES
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
An s-expression query is either an atom, the empty list, or a
|
|
|
|
*compound query* consisting of a prefix atom (first element) defining
|
|
|
|
a *field*, *logical operation*, or *modifier*, and 0 or more
|
|
|
|
subqueries.
|
|
|
|
|
2021-08-24 17:17:25 +02:00
|
|
|
``*``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:25 +02:00
|
|
|
"*" matches any non-empty string in the current field.
|
|
|
|
|
|
|
|
``()``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:25 +02:00
|
|
|
The empty list matches all messages
|
2021-08-24 17:17:16 +02:00
|
|
|
|
|
|
|
*term*
|
2021-08-24 17:17:22 +02:00
|
|
|
|
|
|
|
Match all messages containing *term*, possibly after stemming or
|
|
|
|
phrase splitting. For discussion of stemming in notmuch see
|
|
|
|
:any:`notmuch-search-terms(7)`. Stemming only applies to unquoted
|
|
|
|
terms (basic values) in s-expression queries. For information on
|
|
|
|
phrase splitting see :any:`fields`.
|
2021-08-24 17:17:16 +02:00
|
|
|
|
|
|
|
``(`` *field* |q1| |q2| ... |qn| ``)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
Restrict the queries |q1| to |qn| to *field*, and combine with *and*
|
|
|
|
(for most fields) or *or*. See :any:`fields` for more information.
|
|
|
|
|
|
|
|
``(`` *operator* |q1| |q2| ... |qn| ``)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:19 +02:00
|
|
|
Combine queries |q1| to |qn|. Currently supported operators are
|
|
|
|
``and``, ``or``, and ``not``. ``(not`` |q1| ... |qn| ``)`` is equivalent
|
|
|
|
to ``(and (not`` |q1| ``) ... (not`` |qn| ``))``.
|
2021-08-24 17:17:16 +02:00
|
|
|
|
|
|
|
``(`` *modifier* |q1| |q2| ... |qn| ``)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
Combine queries |q1| to |qn|, and reinterpret the result (e.g. as a regular expression).
|
|
|
|
See :any:`modifiers` for more information.
|
|
|
|
|
2021-08-24 17:17:41 +02:00
|
|
|
``(macro (`` |p1| ... |pn| ``) body)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:41 +02:00
|
|
|
Define saved query with parameter substitution. The syntax is
|
|
|
|
recognized only in saved s-expression queries (see ``squery.*`` in
|
|
|
|
:any:`notmuch-config(1)`). Parameter names in ``body`` must be
|
|
|
|
prefixed with ``,`` to be expanded (see :any:`macro_examples`).
|
|
|
|
Macros may refer to other macros, but only to their own
|
|
|
|
parameters [#macro-details]_.
|
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
.. _fields:
|
|
|
|
|
|
|
|
FIELDS
|
|
|
|
``````
|
|
|
|
|
2021-08-24 17:17:22 +02:00
|
|
|
*Fields* [#aka-pref]_
|
2021-08-24 17:17:20 +02:00
|
|
|
correspond to attributes of mail messages. Some are inherent (and
|
|
|
|
immutable) like ``subject``, while others ``tag`` and ``property`` are
|
|
|
|
settable by the user. Each concrete field in
|
|
|
|
:any:`the table below <field-table>`
|
|
|
|
is discussed further under "Search prefixes" in
|
|
|
|
:any:`notmuch-search-terms(7)`. The row *user* refers to user defined
|
|
|
|
fields, described in :any:`notmuch-config(1)`.
|
|
|
|
|
2021-08-24 17:17:22 +02:00
|
|
|
Most fields are either *phrase fields* [#aka-prob]_ (which match
|
|
|
|
sequences of words), or *term fields* [#aka-bool]_ (which match exact
|
|
|
|
strings). *Phrase splitting* breaks the term (basic value or quoted
|
|
|
|
string) into words, ignore punctuation. Phrase splitting is applied to
|
|
|
|
terms in phrase (probabilistic) fields. Both phrase splitting and
|
|
|
|
stemming apply only in phrase fields.
|
|
|
|
|
2021-08-24 17:17:23 +02:00
|
|
|
Each term or phrase field has an associated combining operator
|
|
|
|
(``and`` or ``or``) used to combine the queries from each element of
|
|
|
|
the tail of the list. This is generally ``or`` for those fields where
|
|
|
|
a message has one such attribute, and ``and`` otherwise.
|
|
|
|
|
|
|
|
Term or phrase fields can contain arbitrarily complex queries made up
|
|
|
|
from terms, operators, and modifiers, but not other fields.
|
|
|
|
|
2021-08-24 17:17:20 +02:00
|
|
|
.. _field-table:
|
|
|
|
|
|
|
|
.. table:: Fields with supported modifiers
|
|
|
|
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| field | combine | type | expand | wildcard | regex |
|
|
|
|
+============+===========+===========+===========+===========+==========+
|
|
|
|
| *none* | and | | no | yes | no |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| *user* | and | phrase | no | yes | no |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| attachment | and | phrase | yes | yes | no |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| body | and | phrase | no | no | no |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| date | | range | no | no | no |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| folder | or | phrase | yes | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| from | and | phrase | yes | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| id | or | term | no | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| is | and | term | yes | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| lastmod | | range | no | no | no |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| mid | or | term | no | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| mimetype | or | phrase | yes | yes | no |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
2021-08-24 17:17:23 +02:00
|
|
|
| path | or | term | no | yes | yes |
|
2021-08-24 17:17:20 +02:00
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| property | and | term | yes | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| subject | and | phrase | yes | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| tag | and | term | yes | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| thread | or | term | yes | yes | yes |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
| to | and | phrase | yes | yes | no |
|
|
|
|
+------------+-----------+-----------+-----------+-----------+----------+
|
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
.. _modifiers:
|
|
|
|
|
|
|
|
MODIFIERS
|
|
|
|
`````````
|
|
|
|
|
2021-08-24 17:17:25 +02:00
|
|
|
*Modifiers* refer to any prefixes (first elements of compound queries)
|
|
|
|
that are neither operators nor fields.
|
|
|
|
|
2021-08-24 17:17:34 +02:00
|
|
|
``(infix`` *atom* ``)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:34 +02:00
|
|
|
Interpret *atom* as an infix notmuch query (see
|
|
|
|
:any:`notmuch-search-terms(7)`). Not supported inside fields.
|
|
|
|
|
2021-08-24 17:17:33 +02:00
|
|
|
``(matching`` |q1| |q2| ... |qn| ``)`` ``(of`` |q1| |q2| ... |qn| ``)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:33 +02:00
|
|
|
Match all messages have the same values of the current field as
|
|
|
|
those matching all of |q1| ... |qn|. Supported in most term [#not-path]_ or
|
|
|
|
phrase fields. Most commonly used in the ``thread`` field.
|
|
|
|
|
2021-08-24 17:17:37 +02:00
|
|
|
``(query`` *atom* ``)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:37 +02:00
|
|
|
Expand to the saved query named by *atom*. See
|
|
|
|
:any:`notmuch-config(1)` for more. Note that the saved query must
|
|
|
|
be in infix syntax (:any:`notmuch-search-terms(7)`). Not supported
|
|
|
|
inside fields.
|
|
|
|
|
2021-08-24 17:17:29 +02:00
|
|
|
``(regex`` *atom* ``)`` ``(rx`` *atom* ``)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:29 +02:00
|
|
|
Interpret *atom* as a POSIX.2 regular expression (see
|
|
|
|
:manpage:`regex(7)`). This applies in term fields and a subset [#not-phrase]_ of
|
|
|
|
phrase fields (see :any:`field-table`).
|
|
|
|
|
2021-08-24 17:17:25 +02:00
|
|
|
``(starts-with`` *subword* ``)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:25 +02:00
|
|
|
Matches any term starting with *subword*. This applies in either
|
|
|
|
phrase or term :any:`fields <fields>`, or outside of fields [#not-body]_. Note that
|
|
|
|
a ``starts-with`` query cannot be part of a phrase. The
|
|
|
|
atom ``*`` is a synonym for ``(starts-with "")``.
|
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
EXAMPLES
|
|
|
|
========
|
|
|
|
|
|
|
|
``Wizard``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:16 +02:00
|
|
|
Match all messages containing the word "wizard", ignoring case.
|
|
|
|
|
2021-08-24 17:17:18 +02:00
|
|
|
``added``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:18 +02:00
|
|
|
Match all messages containing "added", but also those containing "add", "additional",
|
|
|
|
"Additional", "adds", etc... via stemming.
|
|
|
|
|
2021-08-24 17:17:19 +02:00
|
|
|
``(and Bob Marley)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:19 +02:00
|
|
|
Match messages containing words "Bob" and "Marley", or their stems
|
|
|
|
The words need not be adjacent.
|
|
|
|
|
|
|
|
``(not Bob Marley)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:19 +02:00
|
|
|
Match messages containing neither "Bob" nor "Marley", nor their stems,
|
|
|
|
|
2021-08-24 17:17:22 +02:00
|
|
|
``"quick fox"`` ``quick-fox`` ``quick@fox``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:22 +02:00
|
|
|
Match the *phrase* "quick" followed by "fox" in phrase fields (or
|
|
|
|
outside a field). Match the literal string in a term field.
|
|
|
|
|
2021-08-24 17:17:33 +02:00
|
|
|
``(folder (of (id 1234@invalid)))``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2022-04-29 01:46:07 +02:00
|
|
|
Match any message in the same folder as the one with Message-Id "1234\@invalid"
|
2021-08-24 17:17:33 +02:00
|
|
|
|
2021-08-24 17:17:23 +02:00
|
|
|
``(id 1234@invalid blah@test)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2022-04-29 01:46:07 +02:00
|
|
|
Matches Message-Id "1234\@invalid" *or* Message-Id "blah\@test"
|
2021-08-24 17:17:23 +02:00
|
|
|
|
2021-08-24 17:17:34 +02:00
|
|
|
``(and (infix "date:2009-11-18..2009-11-18") (tag unread))``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:34 +02:00
|
|
|
Match messages in the given date range with tag unread.
|
|
|
|
|
2021-08-24 17:17:24 +02:00
|
|
|
``(starts-with prelim)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:24 +02:00
|
|
|
Match any words starting with "prelim".
|
|
|
|
|
2021-08-24 17:17:20 +02:00
|
|
|
``(subject quick "brown fox")``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:20 +02:00
|
|
|
Match messages whose subject contains "quick" (anywhere, stemmed) and
|
|
|
|
the phrase "brown fox".
|
|
|
|
|
2021-08-24 17:17:24 +02:00
|
|
|
``(subject (starts-with prelim))``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:24 +02:00
|
|
|
Matches any word starting with "prelim", inside a message subject.
|
|
|
|
|
|
|
|
``(subject (starts-wih quick) "brown fox")``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:24 +02:00
|
|
|
Match messages whose subject contains "quick brown fox", but also
|
|
|
|
"brown fox quicksand".
|
|
|
|
|
2021-08-24 17:17:33 +02:00
|
|
|
``(thread (of (id 1234@invalid)))``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2022-04-29 01:46:07 +02:00
|
|
|
Match any message in the same thread as the one with Message-Id "1234\@invalid"
|
2021-08-24 17:17:33 +02:00
|
|
|
|
|
|
|
``(thread (matching (from bob@example.com) (to bob@example.com)))``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:33 +02:00
|
|
|
Match any (messages in) a thread containing a message from
|
2022-04-29 01:46:07 +02:00
|
|
|
"bob\@example.com" and a (possibly distinct) message to "bob at
|
2021-08-24 17:17:33 +02:00
|
|
|
example.com")
|
|
|
|
|
2021-08-24 17:17:23 +02:00
|
|
|
``(to (or bob@example.com mallory@example.org))`` ``(or (to bob@example.com) (to mallory@example.org))``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2022-04-29 01:46:07 +02:00
|
|
|
Match in the "To" or "Cc" headers, "bob\@example.com",
|
|
|
|
"mallory\@example.org", and also "bob\@example.com.au" since it
|
2021-08-24 17:17:23 +02:00
|
|
|
contains the adjacent triple "bob", "example", "com".
|
|
|
|
|
2021-08-24 17:17:25 +02:00
|
|
|
``(not (to *))``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:25 +02:00
|
|
|
Match messages with an empty or invalid 'To' and 'Cc' field.
|
|
|
|
|
2021-08-24 17:17:35 +02:00
|
|
|
``(List *)``
|
2021-10-11 14:56:15 +02:00
|
|
|
|
2021-08-24 17:17:35 +02:00
|
|
|
Match messages with a non-empty List-Id header, assuming
|
|
|
|
configuration ``index.header.List=List-Id``
|
|
|
|
|
2021-08-24 17:17:41 +02:00
|
|
|
.. _macro_examples:
|
|
|
|
|
|
|
|
MACRO EXAMPLES
|
|
|
|
--------------
|
|
|
|
|
|
|
|
A macro that takes two parameters and applies different fields to them.
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
$ notmuch config set squery.TagSubject '(macro (tagname subj) (and (tag ,tagname) (subject ,subj)))'
|
|
|
|
$ notmuch search --query=sexp '(TagSubject inbox maildir)'
|
|
|
|
|
|
|
|
Nested macros are allowed.
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
$ notmuch config set squery.Inner '(macro (x) (subject ,x))'
|
|
|
|
$ notmuch config set squery.Outer '(macro (x y) (and (tag ,x) (Inner ,y)))'
|
|
|
|
$ notmuch search --query=sexp '(Outer inbox maildir)'
|
|
|
|
|
|
|
|
Parameters can be re-used to reduce boilerplate. Any field, including
|
|
|
|
user defined fields is permitted within a macro.
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
$ notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
|
|
|
|
$ notmuch search --query=sexp '(About notmuch)'
|
|
|
|
|
|
|
|
|
2021-08-24 17:17:22 +02:00
|
|
|
NOTES
|
|
|
|
=====
|
|
|
|
|
2021-08-24 17:17:41 +02:00
|
|
|
.. [#macro-details] Technically macros impliment lazy evaluation and
|
|
|
|
lexical scope. There is one top level scope
|
|
|
|
containing all macro definitions, but all
|
|
|
|
parameter definitions are local to a given macro.
|
|
|
|
|
2021-08-24 17:17:22 +02:00
|
|
|
.. [#aka-pref] a.k.a. prefixes
|
|
|
|
|
|
|
|
.. [#aka-prob] a.k.a. probabilistic prefixes
|
|
|
|
|
|
|
|
.. [#aka-bool] a.k.a. boolean prefixes
|
|
|
|
|
2021-08-24 17:17:29 +02:00
|
|
|
.. [#not-phrase] Due to the implemention of phrase fields in Xapian,
|
|
|
|
regex queries could only match individual words.
|
|
|
|
|
2021-08-24 17:17:24 +02:00
|
|
|
.. [#not-body] Due the the way ``body`` is implemented in notmuch,
|
|
|
|
this modifier is not supported in the ``body`` field.
|
|
|
|
|
2021-08-24 17:17:33 +02:00
|
|
|
.. [#not-path] Due to the way recursive ``path`` queries are implemented
|
|
|
|
in notmuch, this modifier is not supported in the
|
|
|
|
``path`` field.
|
|
|
|
|
2022-01-26 14:30:45 +01:00
|
|
|
.. |q1| replace:: `q`\ :sub:`1`
|
|
|
|
.. |q2| replace:: `q`\ :sub:`2`
|
|
|
|
.. |qn| replace:: `q`\ :sub:`n`
|
2021-08-24 17:17:41 +02:00
|
|
|
|
2022-01-26 14:30:45 +01:00
|
|
|
.. |p1| replace:: `p`\ :sub:`1`
|
|
|
|
.. |p2| replace:: `p`\ :sub:`2`
|
|
|
|
.. |pn| replace:: `p`\ :sub:`n`
|