mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-25 04:18:08 +01:00
lib/parse-sexp: add '*' as syntactic sugar for '(starts-with "")'
Users that insist on using a literal '*' as a tag, can continue to do so by quoting it when searching.
This commit is contained in:
parent
011d06f4d6
commit
0ca4ad2670
3 changed files with 70 additions and 2 deletions
|
@ -36,8 +36,11 @@ An s-expression query is either an atom, the empty list, or a
|
||||||
a *field*, *logical operation*, or *modifier*, and 0 or more
|
a *field*, *logical operation*, or *modifier*, and 0 or more
|
||||||
subqueries.
|
subqueries.
|
||||||
|
|
||||||
``*`` ``()``
|
``*``
|
||||||
Match all messages.
|
"*" matches any non-empty string in the current field.
|
||||||
|
|
||||||
|
``()``
|
||||||
|
The empty list matches all messages
|
||||||
|
|
||||||
*term*
|
*term*
|
||||||
|
|
||||||
|
@ -138,6 +141,15 @@ from terms, operators, and modifiers, but not other fields.
|
||||||
MODIFIERS
|
MODIFIERS
|
||||||
`````````
|
`````````
|
||||||
|
|
||||||
|
*Modifiers* refer to any prefixes (first elements of compound queries)
|
||||||
|
that are neither operators nor fields.
|
||||||
|
|
||||||
|
``(starts-with`` *subword* ``)``
|
||||||
|
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 "")``.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
========
|
========
|
||||||
|
|
||||||
|
@ -181,6 +193,9 @@ EXAMPLES
|
||||||
"mallory@example.org", and also "bob@example.com.au" since it
|
"mallory@example.org", and also "bob@example.com.au" since it
|
||||||
contains the adjacent triple "bob", "example", "com".
|
contains the adjacent triple "bob", "example", "com".
|
||||||
|
|
||||||
|
``(not (to *))``
|
||||||
|
Match messages with an empty or invalid 'To' and 'Cc' field.
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
|
|
@ -176,6 +176,11 @@ _sexp_to_xapian_query (notmuch_database_t *notmuch, const _sexp_prefix_t *parent
|
||||||
std::string term = Xapian::Unicode::tolower (sx->val);
|
std::string term = Xapian::Unicode::tolower (sx->val);
|
||||||
Xapian::Stem stem = *(notmuch->stemmer);
|
Xapian::Stem stem = *(notmuch->stemmer);
|
||||||
std::string term_prefix = parent ? _find_prefix (parent->name) : "";
|
std::string term_prefix = parent ? _find_prefix (parent->name) : "";
|
||||||
|
|
||||||
|
if (sx->aty == SEXP_BASIC && strcmp (sx->val, "*") == 0) {
|
||||||
|
return _sexp_parse_wildcard (notmuch, parent, "", output);
|
||||||
|
}
|
||||||
|
|
||||||
if (parent && (parent->flags & SEXP_FLAG_BOOLEAN)) {
|
if (parent && (parent->flags & SEXP_FLAG_BOOLEAN)) {
|
||||||
output = Xapian::Query (term_prefix + sx->val);
|
output = Xapian::Query (term_prefix + sx->val);
|
||||||
return NOTMUCH_STATUS_SUCCESS;
|
return NOTMUCH_STATUS_SUCCESS;
|
||||||
|
|
|
@ -386,6 +386,46 @@ thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unr
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "wildcard search for 'is'"
|
||||||
|
notmuch search not id:${notag_mid} > EXPECTED
|
||||||
|
notmuch search --query=sexp '(is *)' > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "negated wildcard search for 'is'"
|
||||||
|
notmuch search id:${notag_mid} > EXPECTED
|
||||||
|
notmuch search --query=sexp '(not (is *))' > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "wildcard search for 'property'"
|
||||||
|
notmuch search property:foo=bar > EXPECTED
|
||||||
|
notmuch search --query=sexp '(property *)' > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "wildcard search for 'tag'"
|
||||||
|
notmuch search not id:${notag_mid} > EXPECTED
|
||||||
|
notmuch search --query=sexp '(tag *)' > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "negated wildcard search for 'tag'"
|
||||||
|
notmuch search id:${notag_mid} > EXPECTED
|
||||||
|
notmuch search --query=sexp '(not (tag *))' > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
add_message '[subject]="message with tag \"*\""'
|
||||||
|
notmuch tag '+*' id:${gen_msg_id}
|
||||||
|
|
||||||
|
test_begin_subtest "search for 'tag' \"*\""
|
||||||
|
output=$(notmuch search --query=sexp --output=messages '(tag "*")')
|
||||||
|
test_expect_equal "$output" "id:$gen_msg_id"
|
||||||
|
|
||||||
|
test_begin_subtest "search for missing / empty to"
|
||||||
|
add_message [to]="undisclosed-recipients:"
|
||||||
|
notmuch search --query=sexp '(not (to *))' | notmuch_search_sanitize > OUTPUT
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; search for missing / empty to (inbox unread)
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "Unbalanced parens"
|
test_begin_subtest "Unbalanced parens"
|
||||||
# A code 1 indicates the error was handled (a crash will return e.g. 139).
|
# A code 1 indicates the error was handled (a crash will return e.g. 139).
|
||||||
test_expect_code 1 "notmuch search --query=sexp '('"
|
test_expect_code 1 "notmuch search --query=sexp '('"
|
||||||
|
@ -454,4 +494,12 @@ notmuch search: Syntax error in query
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "wildcard, illegal field"
|
||||||
|
notmuch search --query=sexp '(body *)' >OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
'body' does not support wildcard queries
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
Loading…
Reference in a new issue