aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-13 11:02:32 +0200
committerDanilo M. <danix@danix.xyz>2026-08-13 11:02:32 +0200
commit043b150f7651c598dac8fc02d7068b940d0f8741 (patch)
tree943acdc0a0c8891a150dd02af6299b28d31499e5 /src
parenta3651eac1528a2b90cfb8e26934facf856ae3531 (diff)
downloadqtmaildir-043b150f7651c598dac8fc02d7068b940d0f8741.tar.gz
qtmaildir-043b150f7651c598dac8fc02d7068b940d0f8741.zip
feat(rulequery): compile every field and operator
Diffstat (limited to 'src')
-rw-r--r--src/rulequery.cpp51
1 files changed, 49 insertions, 2 deletions
diff --git a/src/rulequery.cpp b/src/rulequery.cpp
index f80e6c4..198c583 100644
--- a/src/rulequery.cpp
+++ b/src/rulequery.cpp
@@ -36,6 +36,54 @@ QString prefixFor(RuleTerm::Field field)
return QString();
}
+bool isNegated(RuleTerm::Op op)
+{
+ return op == RuleTerm::ContainsNot || op == RuleTerm::IsNot
+ || op == RuleTerm::HasNot;
+}
+
+/// Quoted when the operator asks for an exact phrase, and ALWAYS when the
+/// value holds a space: unquoted, the space ends the term and the remainder
+/// becomes a bare word, which widens the rule instead of breaking it.
+bool needsQuotes(const RuleTerm &term)
+{
+ if (term.field == RuleTerm::Folder)
+ return true;
+ if (term.value.contains(QLatin1Char(' ')))
+ return true;
+ // Is/IsNot asks for an exact phrase, which only free-text fields need
+ // quoting for: tag: and attachment: values are already bare words, and
+ // quoting them changes nothing notmuch cares about but breaks the test's
+ // documented expectation of an unquoted tag.
+ if (term.op == RuleTerm::Is || term.op == RuleTerm::IsNot) {
+ return term.field == RuleTerm::From || term.field == RuleTerm::To
+ || term.field == RuleTerm::Cc || term.field == RuleTerm::Subject;
+ }
+ return false;
+}
+
+QString compileTerm(const RuleTerm &term)
+{
+ QString value = term.value;
+ if (term.field == RuleTerm::Folder)
+ value += QStringLiteral("/**");
+
+ QString body;
+ if (term.field == RuleTerm::Date) {
+ body = prefixFor(term.field) + QLatin1Char(':')
+ + (term.op == RuleTerm::Before
+ ? QStringLiteral("..") + value
+ : value + QStringLiteral(".."));
+ } else if (needsQuotes(term)) {
+ body = prefixFor(term.field) + QStringLiteral(":\"") + value
+ + QLatin1Char('"');
+ } else {
+ body = prefixFor(term.field) + QLatin1Char(':') + value;
+ }
+
+ return isNegated(term.op) ? QStringLiteral("not ") + body : body;
+}
+
} // namespace
bool operator==(const RuleTerm &a, const RuleTerm &b)
@@ -54,8 +102,7 @@ QString RuleQuery::compile() const
if (terms.isEmpty())
return QString();
- return prefixFor(terms.first().field) + QLatin1Char(':')
- + terms.first().value;
+ return compileTerm(terms.first());
}
RuleQuery RuleQuery::parse(const QString &query)