]> git.cworth.org Git - notmuch/blob - doc/man7/notmuch-sexp-queries.rst
lib/message-property: sync removed properties to the database
[notmuch] / doc / man7 / notmuch-sexp-queries.rst
1 .. _notmuch-sexp-queries(7):
2
3 ====================
4 notmuch-sexp-queries
5 ====================
6
7 SYNOPSIS
8 ========
9
10 **notmuch** *subcommand* ``--query=sexp`` [option ...]  ``--`` '(and (to santa) (date december))'
11
12 DESCRIPTION
13 ===========
14
15 Notmuch supports an alternative query syntax based on `S-expressions
16 <https://en.wikipedia.org/wiki/S-expression>`_ . It can be selected
17 with the command line ``--query=sexp`` or with the appropriate option
18 to the library function :c:func:`notmuch_query_create_with_syntax`.
19 Support for this syntax is currently optional, you can test if your
20 build of notmuch supports it with
21
22 ::
23
24    $ notmuch config get built_with.sexp_queries
25
26
27 S-EXPRESSIONS
28 -------------
29
30 An *s-expression* is either an atom, or list of whitespace delimited
31 s-expressions inside parentheses. Atoms are either
32
33 *basic value*
34
35     A basic value is an unquoted string containing no whitespace, double quotes, or
36     parentheses.
37
38 *quoted string*
39
40     Double quotes (") delimit strings possibly containing whitespace
41     or parentheses. These can contain double quote characters by
42     escaping with backslash. E.g. ``"this is a quote \""``.
43
44 S-EXPRESSION QUERIES
45 --------------------
46
47 An s-expression query is either an atom, the empty list, or a
48 *compound query* consisting of a prefix atom (first element) defining
49 a *field*, *logical operation*, or *modifier*, and 0 or more
50 subqueries.
51
52 ``*``
53
54    "*" matches any non-empty string in the current field.
55
56 ``()``
57
58     The empty list matches all messages
59
60 *term*
61
62     Match all messages containing *term*, possibly after stemming or
63     phrase splitting. For discussion of stemming in notmuch see
64     :any:`notmuch-search-terms(7)`. Stemming only applies to unquoted
65     terms (basic values) in s-expression queries.  For information on
66     phrase splitting see :any:`fields`.
67
68 ``(`` *field* |q1| |q2| ... |qn| ``)``
69
70     Restrict the queries |q1| to |qn| to *field*, and combine with *and*
71     (for most fields) or *or*. See :any:`fields` for more information.
72
73 ``(`` *operator* |q1| |q2| ... |qn| ``)``
74
75     Combine queries |q1| to |qn|. Currently supported operators are
76     ``and``, ``or``, and ``not``. ``(not`` |q1| ... |qn| ``)`` is equivalent
77     to ``(and (not`` |q1| ``) ... (not`` |qn| ``))``.
78
79 ``(`` *modifier* |q1| |q2| ... |qn| ``)``
80
81     Combine queries |q1| to |qn|, and reinterpret the result (e.g. as a regular expression).
82     See :any:`modifiers` for more information.
83
84 ``(macro (`` |p1| ... |pn| ``) body)``
85
86     Define saved query with parameter substitution. The syntax is
87     recognized only in saved s-expression queries (see ``squery.*`` in
88     :any:`notmuch-config(1)`). Parameter names in ``body`` must be
89     prefixed with ``,`` to be expanded (see :any:`macro_examples`).
90     Macros may refer to other macros, but only to their own
91     parameters [#macro-details]_.
92
93 .. _fields:
94
95 FIELDS
96 ``````
97
98 *Fields* [#aka-pref]_
99 correspond to attributes of mail messages. Some are inherent (and
100 immutable) like ``subject``, while others ``tag`` and ``property`` are
101 settable by the user.  Each concrete field in
102 :any:`the table below <field-table>`
103 is discussed further under "Search prefixes" in
104 :any:`notmuch-search-terms(7)`. The row *user* refers to user defined
105 fields, described in :any:`notmuch-config(1)`.
106
107 Most fields are either *phrase fields* [#aka-prob]_ (which match
108 sequences of words), or *term fields* [#aka-bool]_ (which match exact
109 strings). *Phrase splitting* breaks the term (basic value or quoted
110 string) into words, ignore punctuation. Phrase splitting is applied to
111 terms in phrase (probabilistic) fields. Both phrase splitting and
112 stemming apply only in phrase fields.
113
114 Each term or phrase field has an associated combining operator
115 (``and`` or ``or``) used to combine the queries from each element of
116 the tail of the list. This is generally ``or`` for those fields where
117 a message has one such attribute, and ``and`` otherwise.
118
119 Term or phrase fields can contain arbitrarily complex queries made up
120 from terms, operators, and modifiers, but not other fields.
121
122 Range fields take one or two arguments specifying lower and upper
123 bounds.  One argument is interpreted as identical upper and lower
124 bounds. Either upper or lower bound may be specified as ``""`` or
125 ``*`` to specify the lowest possible lower bound or highest possible
126 upper bound.
127
128 ``lastmod`` ranges support negative arguments, interpreted relative to
129 the most recent database revision (see :option:`count --lastmod`).
130
131 .. _field-table:
132
133 .. table:: Fields with supported modifiers
134
135   +------------+-----------+-----------+-----------+-----------+----------+
136   |   field    |  combine  |   type    |  expand   | wildcard  |  regex   |
137   +============+===========+===========+===========+===========+==========+
138   |   *none*   |    and    |           |    no     |    yes    |    no    |
139   +------------+-----------+-----------+-----------+-----------+----------+
140   |   *user*   |    and    |  phrase   |    no     |    yes    |    no    |
141   +------------+-----------+-----------+-----------+-----------+----------+
142   | attachment |    and    |  phrase   |    yes    |    yes    |    no    |
143   +------------+-----------+-----------+-----------+-----------+----------+
144   |    body    |    and    |  phrase   |    no     |    no     |    no    |
145   +------------+-----------+-----------+-----------+-----------+----------+
146   |    date    |           |   range   |    no     |    no     |    no    |
147   +------------+-----------+-----------+-----------+-----------+----------+
148   |   folder   |    or     |  phrase   |    yes    |    yes    |   yes    |
149   +------------+-----------+-----------+-----------+-----------+----------+
150   |    from    |    and    |  phrase   |    yes    |    yes    |   yes    |
151   +------------+-----------+-----------+-----------+-----------+----------+
152   |     id     |    or     |   term    |    no     |    yes    |   yes    |
153   +------------+-----------+-----------+-----------+-----------+----------+
154   |     is     |    and    |   term    |    yes    |    yes    |   yes    |
155   +------------+-----------+-----------+-----------+-----------+----------+
156   |  lastmod   |           |   range   |    no     |    no     |    no    |
157   +------------+-----------+-----------+-----------+-----------+----------+
158   |    mid     |    or     |   term    |    no     |    yes    |   yes    |
159   +------------+-----------+-----------+-----------+-----------+----------+
160   |  mimetype  |    or     |  phrase   |    yes    |    yes    |    no    |
161   +------------+-----------+-----------+-----------+-----------+----------+
162   |    path    |    or     |   term    |    no     |    yes    |   yes    |
163   +------------+-----------+-----------+-----------+-----------+----------+
164   |  property  |    and    |   term    |    yes    |    yes    |   yes    |
165   +------------+-----------+-----------+-----------+-----------+----------+
166   |  subject   |    and    |  phrase   |    yes    |    yes    |   yes    |
167   +------------+-----------+-----------+-----------+-----------+----------+
168   |    tag     |    and    |   term    |    yes    |    yes    |   yes    |
169   +------------+-----------+-----------+-----------+-----------+----------+
170   |   thread   |    or     |   term    |    yes    |    yes    |   yes    |
171   +------------+-----------+-----------+-----------+-----------+----------+
172   |     to     |    and    |  phrase   |    yes    |    yes    |    no    |
173   +------------+-----------+-----------+-----------+-----------+----------+
174
175 .. _modifiers:
176
177 MODIFIERS
178 `````````
179
180 *Modifiers* refer to any prefixes (first elements of compound queries)
181 that are neither operators nor fields.
182
183 ``(infix`` *atom* ``)``
184
185     Interpret *atom* as an infix notmuch query (see
186     :any:`notmuch-search-terms(7)`). Not supported inside fields.
187
188 ``(matching`` |q1| |q2| ... |qn| ``)`` ``(of`` |q1| |q2| ... |qn|  ``)``
189
190     Match all messages have the same values of the current field as
191     those matching all of |q1| ... |qn|. Supported in most term [#not-path]_ or
192     phrase fields. Most commonly used in the ``thread`` field.
193
194 ``(query`` *atom* ``)``
195
196     Expand to the saved query named by *atom*. See
197     :any:`notmuch-config(1)` for more. Note that the saved query must
198     be in infix syntax (:any:`notmuch-search-terms(7)`). Not supported
199     inside fields.
200
201 ``(regex`` *atom* ``)`` ``(rx`` *atom* ``)``
202
203     Interpret *atom* as a POSIX.2 regular expression (see
204     :manpage:`regex(7)`). This applies in term fields and a subset [#not-phrase]_ of
205     phrase fields (see :any:`field-table`).
206
207 ``(starts-with`` *subword* ``)``
208
209     Matches any term starting with *subword*.  This applies in either
210     phrase or term :any:`fields <fields>`, or outside of fields [#not-body]_. Note that
211     a ``starts-with`` query cannot be part of a phrase. The
212     atom ``*`` is a synonym for ``(starts-with "")``.
213
214 EXAMPLES
215 ========
216
217 ``Wizard``
218
219     Match all messages containing the word "wizard", ignoring case.
220
221 ``added``
222
223     Match all messages containing "added", but also those containing "add", "additional",
224     "Additional", "adds", etc... via stemming.
225
226 ``(and Bob Marley)``
227
228     Match messages containing words "Bob" and "Marley", or their stems
229     The words need not be adjacent.
230
231 ``(not Bob Marley)``
232
233     Match messages containing neither "Bob" nor "Marley", nor their stems.
234
235 ``"quick fox"`` ``quick-fox`` ``quick@fox``
236
237     Match the *phrase* "quick" followed by "fox" in phrase fields (or
238     outside a field). Match the literal string in a term field.
239
240 ``(folder (of (id 1234@invalid)))``
241
242     Match any message in the same folder as the one with Message-Id "1234\@invalid".
243
244 ``(id 1234@invalid blah@test)``
245
246     Matches Message-Id "1234\@invalid" *or* Message-Id "blah\@test".
247
248 ``(and (infix "date:2009-11-18..2009-11-18") (tag unread))``
249
250     Match messages in the given date range with tag unread.
251
252 ``(and (date 2009-11-18 2009-11-18) (tag unread))``
253
254     Match messages in the given date range with tag unread.
255
256 ``(and (date 2009-11-18 *) (tag unread))``
257
258     Match messages from 2009-11-18 or later with tag unread.
259
260 ``(and (date * 2009-11-18) (tag unread))``
261
262     Match messages from 2009-11-18 or earlier with tag unread.
263
264 ``(starts-with prelim)``
265
266     Match any words starting with "prelim".
267
268 ``(subject quick "brown fox")``
269
270     Match messages whose subject contains "quick" (anywhere, stemmed) and
271     the phrase "brown fox".
272
273 ``(subject (starts-with prelim))``
274
275     Matches any word starting with "prelim", inside a message subject.
276
277 ``(subject (starts-wih quick) "brown fox")``
278
279     Match messages whose subject contains "quick brown fox", but also
280     "brown fox quicksand".
281
282 ``(thread (of (id 1234@invalid)))``
283
284     Match any message in the same thread as the one with Message-Id "1234\@invalid".
285
286 ``(thread (matching (from bob@example.com) (to bob@example.com)))``
287
288     Match any (messages in) a thread containing a message from
289     "bob\@example.com" and a (possibly distinct) message to
290     "bob\@example.com".
291
292 ``(to (or bob@example.com mallory@example.org))`` ``(or (to bob@example.com) (to mallory@example.org))``
293
294     Match in the "To" or "Cc" headers, "bob\@example.com",
295     "mallory\@example.org", and also "bob\@example.com.au" since it
296     contains the adjacent triple "bob", "example", "com".
297
298 ``(not (to *))``
299
300     Match messages with an empty or invalid 'To' and 'Cc' field.
301
302 ``(List *)``
303
304     Match messages with a non-empty List-Id header, assuming
305     configuration ``index.header.List=List-Id``.
306
307 .. _macro_examples:
308
309 MACRO EXAMPLES
310 --------------
311
312 A macro that takes two parameters and applies different fields to them.
313
314 ::
315
316    $ notmuch config set squery.TagSubject '(macro (tagname subj) (and (tag ,tagname) (subject ,subj)))'
317    $ notmuch search --query=sexp '(TagSubject inbox maildir)'
318
319 Nested macros are allowed.
320
321 ::
322
323     $ notmuch config set squery.Inner '(macro (x) (subject ,x))'
324     $ notmuch config set squery.Outer  '(macro (x y) (and (tag ,x) (Inner ,y)))'
325     $ notmuch search --query=sexp '(Outer inbox maildir)'
326
327 Parameters can be re-used to reduce boilerplate. Any field, including
328 user defined fields is permitted within a macro.
329
330 ::
331
332     $ notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
333     $ notmuch search --query=sexp '(About notmuch)'
334
335
336 NOTES
337 =====
338
339 .. [#macro-details] Technically macros impliment lazy evaluation and
340                     lexical scope. There is one top level scope
341                     containing all macro definitions, but all
342                     parameter definitions are local to a given macro.
343
344 .. [#aka-pref] a.k.a. prefixes
345
346 .. [#aka-prob] a.k.a. probabilistic prefixes
347
348 .. [#aka-bool] a.k.a. boolean prefixes
349
350 .. [#not-phrase] Due to the implemention of phrase fields in Xapian,
351                  regex queries could only match individual words.
352
353 .. [#not-body] Due the the way ``body`` is implemented in notmuch,
354                this modifier is not supported in the ``body`` field.
355
356 .. [#not-path] Due to the way recursive ``path`` queries are implemented
357                in notmuch, this modifier is not supported in the
358                ``path`` field.
359
360 .. |q1| replace:: `q`\ :sub:`1`
361 .. |q2| replace:: `q`\ :sub:`2`
362 .. |qn| replace:: `q`\ :sub:`n`
363
364 .. |p1| replace:: `p`\ :sub:`1`
365 .. |p2| replace:: `p`\ :sub:`2`
366 .. |pn| replace:: `p`\ :sub:`n`