]> git.cworth.org Git - notmuch/blob - doc/man7/notmuch-sexp-queries.rst
bc8e5086f342be9568cfc3baafac3e700c5c623b
[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 .. _field-table:
123
124 .. table:: Fields with supported modifiers
125
126   +------------+-----------+-----------+-----------+-----------+----------+
127   |   field    |  combine  |   type    |  expand   | wildcard  |  regex   |
128   +============+===========+===========+===========+===========+==========+
129   |   *none*   |    and    |           |    no     |    yes    |    no    |
130   +------------+-----------+-----------+-----------+-----------+----------+
131   |   *user*   |    and    |  phrase   |    no     |    yes    |    no    |
132   +------------+-----------+-----------+-----------+-----------+----------+
133   | attachment |    and    |  phrase   |    yes    |    yes    |    no    |
134   +------------+-----------+-----------+-----------+-----------+----------+
135   |    body    |    and    |  phrase   |    no     |    no     |    no    |
136   +------------+-----------+-----------+-----------+-----------+----------+
137   |    date    |           |   range   |    no     |    no     |    no    |
138   +------------+-----------+-----------+-----------+-----------+----------+
139   |   folder   |    or     |  phrase   |    yes    |    yes    |   yes    |
140   +------------+-----------+-----------+-----------+-----------+----------+
141   |    from    |    and    |  phrase   |    yes    |    yes    |   yes    |
142   +------------+-----------+-----------+-----------+-----------+----------+
143   |     id     |    or     |   term    |    no     |    yes    |   yes    |
144   +------------+-----------+-----------+-----------+-----------+----------+
145   |     is     |    and    |   term    |    yes    |    yes    |   yes    |
146   +------------+-----------+-----------+-----------+-----------+----------+
147   |  lastmod   |           |   range   |    no     |    no     |    no    |
148   +------------+-----------+-----------+-----------+-----------+----------+
149   |    mid     |    or     |   term    |    no     |    yes    |   yes    |
150   +------------+-----------+-----------+-----------+-----------+----------+
151   |  mimetype  |    or     |  phrase   |    yes    |    yes    |    no    |
152   +------------+-----------+-----------+-----------+-----------+----------+
153   |    path    |    or     |   term    |    no     |    yes    |   yes    |
154   +------------+-----------+-----------+-----------+-----------+----------+
155   |  property  |    and    |   term    |    yes    |    yes    |   yes    |
156   +------------+-----------+-----------+-----------+-----------+----------+
157   |  subject   |    and    |  phrase   |    yes    |    yes    |   yes    |
158   +------------+-----------+-----------+-----------+-----------+----------+
159   |    tag     |    and    |   term    |    yes    |    yes    |   yes    |
160   +------------+-----------+-----------+-----------+-----------+----------+
161   |   thread   |    or     |   term    |    yes    |    yes    |   yes    |
162   +------------+-----------+-----------+-----------+-----------+----------+
163   |     to     |    and    |  phrase   |    yes    |    yes    |    no    |
164   +------------+-----------+-----------+-----------+-----------+----------+
165
166 .. _modifiers:
167
168 MODIFIERS
169 `````````
170
171 *Modifiers* refer to any prefixes (first elements of compound queries)
172 that are neither operators nor fields.
173
174 ``(infix`` *atom* ``)``
175
176     Interpret *atom* as an infix notmuch query (see
177     :any:`notmuch-search-terms(7)`). Not supported inside fields.
178
179 ``(matching`` |q1| |q2| ... |qn| ``)`` ``(of`` |q1| |q2| ... |qn|  ``)``
180
181     Match all messages have the same values of the current field as
182     those matching all of |q1| ... |qn|. Supported in most term [#not-path]_ or
183     phrase fields. Most commonly used in the ``thread`` field.
184
185 ``(query`` *atom* ``)``
186
187     Expand to the saved query named by *atom*. See
188     :any:`notmuch-config(1)` for more. Note that the saved query must
189     be in infix syntax (:any:`notmuch-search-terms(7)`). Not supported
190     inside fields.
191
192 ``(regex`` *atom* ``)`` ``(rx`` *atom* ``)``
193
194     Interpret *atom* as a POSIX.2 regular expression (see
195     :manpage:`regex(7)`). This applies in term fields and a subset [#not-phrase]_ of
196     phrase fields (see :any:`field-table`).
197
198 ``(starts-with`` *subword* ``)``
199
200     Matches any term starting with *subword*.  This applies in either
201     phrase or term :any:`fields <fields>`, or outside of fields [#not-body]_. Note that
202     a ``starts-with`` query cannot be part of a phrase. The
203     atom ``*`` is a synonym for ``(starts-with "")``.
204
205 EXAMPLES
206 ========
207
208 ``Wizard``
209
210     Match all messages containing the word "wizard", ignoring case.
211
212 ``added``
213
214     Match all messages containing "added", but also those containing "add", "additional",
215     "Additional", "adds", etc... via stemming.
216
217 ``(and Bob Marley)``
218
219     Match messages containing words "Bob" and "Marley", or their stems
220     The words need not be adjacent.
221
222 ``(not Bob Marley)``
223
224     Match messages containing neither "Bob" nor "Marley", nor their stems,
225
226 ``"quick fox"`` ``quick-fox`` ``quick@fox``
227
228     Match the *phrase* "quick" followed by "fox" in phrase fields (or
229     outside a field). Match the literal string in a term field.
230
231 ``(folder (of (id 1234@invalid)))``
232
233     Match any message in the same folder as the one with Message-Id "1234@invalid"
234
235 ``(id 1234@invalid blah@test)``
236
237     Matches Message-Id "1234@invalid" *or* Message-Id "blah@test"
238
239 ``(and (infix "date:2009-11-18..2009-11-18") (tag unread))``
240
241     Match messages in the given date range with tag unread.
242
243 ``(starts-with prelim)``
244
245     Match any words starting with "prelim".
246
247 ``(subject quick "brown fox")``
248
249     Match messages whose subject contains "quick" (anywhere, stemmed) and
250     the phrase "brown fox".
251
252 ``(subject (starts-with prelim))``
253
254     Matches any word starting with "prelim", inside a message subject.
255
256 ``(subject (starts-wih quick) "brown fox")``
257
258     Match messages whose subject contains "quick brown fox", but also
259     "brown fox quicksand".
260
261 ``(thread (of (id 1234@invalid)))``
262
263     Match any message in the same thread as the one with Message-Id "1234@invalid"
264
265 ``(thread (matching (from bob@example.com) (to bob@example.com)))``
266
267     Match any (messages in) a thread containing a message from
268     "bob@example.com" and a (possibly distinct) message to "bob at
269     example.com")
270
271 ``(to (or bob@example.com mallory@example.org))`` ``(or (to bob@example.com) (to mallory@example.org))``
272
273     Match in the "To" or "Cc" headers, "bob@example.com",
274     "mallory@example.org", and also "bob@example.com.au" since it
275     contains the adjacent triple "bob", "example", "com".
276
277 ``(not (to *))``
278
279     Match messages with an empty or invalid 'To' and 'Cc' field.
280
281 ``(List *)``
282
283     Match messages with a non-empty List-Id header, assuming
284     configuration ``index.header.List=List-Id``
285
286 .. _macro_examples:
287
288 MACRO EXAMPLES
289 --------------
290
291 A macro that takes two parameters and applies different fields to them.
292
293 ::
294
295    $ notmuch config set squery.TagSubject '(macro (tagname subj) (and (tag ,tagname) (subject ,subj)))'
296    $ notmuch search --query=sexp '(TagSubject inbox maildir)'
297
298 Nested macros are allowed.
299
300 ::
301
302     $ notmuch config set squery.Inner '(macro (x) (subject ,x))'
303     $ notmuch config set squery.Outer  '(macro (x y) (and (tag ,x) (Inner ,y)))'
304     $ notmuch search --query=sexp '(Outer inbox maildir)'
305
306 Parameters can be re-used to reduce boilerplate. Any field, including
307 user defined fields is permitted within a macro.
308
309 ::
310
311     $ notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
312     $ notmuch search --query=sexp '(About notmuch)'
313
314
315 NOTES
316 =====
317
318 .. [#macro-details] Technically macros impliment lazy evaluation and
319                     lexical scope. There is one top level scope
320                     containing all macro definitions, but all
321                     parameter definitions are local to a given macro.
322
323 .. [#aka-pref] a.k.a. prefixes
324
325 .. [#aka-prob] a.k.a. probabilistic prefixes
326
327 .. [#aka-bool] a.k.a. boolean prefixes
328
329 .. [#not-phrase] Due to the implemention of phrase fields in Xapian,
330                  regex queries could only match individual words.
331
332 .. [#not-body] Due the the way ``body`` is implemented in notmuch,
333                this modifier is not supported in the ``body`` field.
334
335 .. [#not-path] Due to the way recursive ``path`` queries are implemented
336                in notmuch, this modifier is not supported in the
337                ``path`` field.
338
339 .. |q1| replace:: `q`\ :sub:`1`
340 .. |q2| replace:: `q`\ :sub:`2`
341 .. |qn| replace:: `q`\ :sub:`n`
342
343 .. |p1| replace:: `p`\ :sub:`1`
344 .. |p2| replace:: `p`\ :sub:`2`
345 .. |pn| replace:: `p`\ :sub:`n`