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