diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-12 11:43:36 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-12 11:43:36 +0200 |
| commit | f479318ea8f890122f2f28a7a224802dbf4e870b (patch) | |
| tree | af0bfba5dde4e1ad07560fa8e937393ae856ff95 | |
| parent | f1890fc7b5fe1094445ce8b83c2d2f15258fceec (diff) | |
| download | mailctl-f479318ea8f890122f2f28a7a224802dbf4e870b.tar.gz mailctl-f479318ea8f890122f2f28a7a224802dbf4e870b.zip | |
feat(rules): dry-run counts what a rule matches
Two numbers per rule: what it matches across all mail, and what it
would tag on the next sync. The first is what decides whether a rule
is still earning its place.
| -rwxr-xr-x | mailctl.py | 27 |
1 files changed, 27 insertions, 0 deletions
@@ -509,6 +509,27 @@ def cmd_rules_show(args): sys.exit(1) +def cmd_rules_dry_run(args): + """What each rule matches right now. Two numbers, because they answer + different questions: the corpus count says whether a rule is still doing + anything and whether it would bury real correspondence, the pending count + says what the next sync would tag.""" + store = mailrules.load() + rules = [r for r in store.rules if not args.id or r.id == args.id] + if not rules: + print(f"No rule with id '{args.id}'", file=sys.stderr) + sys.exit(1) + + print(f"{'rule':<28} {'corpus':>8} {'pending':>8}") + for rule in rules: + corpus = run_notmuch(["count", mailrules.scoped_query(rule, None)]) + pending = run_notmuch(["count", + mailrules.scoped_query(rule, "tag:new")]) + state = "" if rule.enabled else " (disabled)" + print(f"{rule.id:<28.28} {corpus.strip():>8} " + f"{pending.strip():>8}{state}") + + def build_parser(): p = argparse.ArgumentParser( prog="mailctl", @@ -600,6 +621,12 @@ def build_parser(): rp.add_argument("id") rp.set_defaults(func=cmd_rules_show) + rp = rules_sub.add_parser("dry-run", + help="count what each rule matches, changing " + "nothing") + rp.add_argument("id", nargs="?", help="one rule, default is all") + rp.set_defaults(func=cmd_rules_dry_run) + return p |
