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