diff --git a/internal/engine/config/v1alpha3/config.go b/internal/engine/config/v1alpha3/config.go index e48854d1..84e0b369 100644 --- a/internal/engine/config/v1alpha3/config.go +++ b/internal/engine/config/v1alpha3/config.go @@ -88,8 +88,9 @@ func (f FilterNode) NonEmptyFields() []string { // For every email, if the filter applies correctly, then the specified actions // will be applied to it. type Rule struct { - Filter FilterNode `json:"filter"` - Actions Actions `json:"actions"` + Filter FilterNode `json:"filter"` + Actions Actions `json:"actions"` + AvoidSplitting bool `json:"avoidSplitting,omitempty"` } // Author represents the owner of the gmail account. diff --git a/internal/engine/filter/convert.go b/internal/engine/filter/convert.go index 34dd1da2..8cc35acd 100644 --- a/internal/engine/filter/convert.go +++ b/internal/engine/filter/convert.go @@ -34,7 +34,7 @@ func FromRulesWithLimit(rs []parser.Rule, sizeLimit int) (Filters, error) { // FromRule translates a rule into entries that map directly into Gmail filters. func FromRule(rule parser.Rule, sizeLimit int) (Filters, error) { var crits []Criteria - for _, c := range splitCriteria(rule.Criteria, sizeLimit) { + for _, c := range splitCriteria(rule.Criteria, sizeLimit, rule.AvoidSplitting) { criteria, err := GenerateCriteria(c) if err != nil { return nil, fmt.Errorf("generating criteria: %w", err) @@ -258,9 +258,9 @@ func quote(a string) string { return a } -func splitCriteria(tree parser.CriteriaAST, limit int) []parser.CriteriaAST { +func splitCriteria(tree parser.CriteriaAST, limit int, avoidSplitting bool) []parser.CriteriaAST { var res []parser.CriteriaAST - for _, c := range splitRootOr(tree) { + for _, c := range splitRootOr(tree, avoidSplitting) { res = append(res, splitBigCriteria(c, limit)...) } return res @@ -420,7 +420,7 @@ func countNodes(tree parser.CriteriaAST) int { return cv.res } -func splitRootOr(tree parser.CriteriaAST) []parser.CriteriaAST { +func splitRootOr(tree parser.CriteriaAST, avoidSplitting bool) []parser.CriteriaAST { // Since Gmail filters are all applied when they match, we can reduce // the size of a rule and make it more readable by splitting a single // rule where wee have an OR as the top-level operation, with a set of @@ -432,7 +432,7 @@ func splitRootOr(tree parser.CriteriaAST) []parser.CriteriaAST { // - to:b => archive // - list:c => archive root, ok := tree.(*parser.Node) - if !ok || root.Operation != parser.OperationOr { + if !ok || root.Operation != parser.OperationOr || avoidSplitting { return []parser.CriteriaAST{tree} } return root.Children diff --git a/internal/engine/parser/parser.go b/internal/engine/parser/parser.go index 86d6e22f..d4ace614 100644 --- a/internal/engine/parser/parser.go +++ b/internal/engine/parser/parser.go @@ -11,8 +11,9 @@ import ( // Rule is an intermediate representation of a Gmail filter. type Rule struct { - Criteria CriteriaAST - Actions Actions + Criteria CriteriaAST + Actions Actions + AvoidSplitting bool } // Actions contains the actions to be applied to a set of emails. @@ -53,8 +54,9 @@ func parseRule(rule cfg.Rule) (Rule, error) { } return Rule{ - Criteria: scrit, - Actions: Actions(rule.Actions), + Criteria: scrit, + Actions: Actions(rule.Actions), + AvoidSplitting: rule.AvoidSplitting, }, nil }