Complete account and tag names in the rule builder

Both fields are free text, and a slug or tag that is slightly wrong produces
a rule that silently catches nothing — or a second, near-identical tag. They
now complete against what already exists: accounts from the folders on disk
and the index, tags from every tag in use plus any named in rules.toml, so a
tag is completable from the moment a rule mentions it.

The completion is ghosted after the cursor and never committed until it is
accepted, so inventing a new tag still works. tab takes it and moves focus
only when there is nothing left to complete; ctrl+n/ctrl+p cycle an ambiguous
prefix, and the hint under the box says how many candidates are left.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 23:06:31 +02:00
co-authored by Claude Opus 5
parent 3eca8f5376
commit 73fefea96d
4 changed files with 305 additions and 18 deletions
+9
View File
@@ -55,6 +55,15 @@ rule builder cannot shadow a rule the user wrote by hand.
`viewRules`, or typing `q` would quit and `i` would start an import. Any new
full-screen input needs the same treatment.
**In the rule builder, `tab` completes first and moves focus second.** The
account and tag fields use `textinput.ShowSuggestions`, whose own `AcceptSuggestion`
key is `tab` and whose `NextSuggestion`/`PrevSuggestion` are `up`/`down` — all
three already meant something here. So `updateRules` intercepts `tab` and calls
`acceptCompletion` before falling back to `setRuleFocus`, keeps `up`/`down` on
field navigation, and lets `ctrl+n` / `ctrl+p` through to the input for cycling.
`SetValue` does not re-match the suggestion list, so `acceptCompletion` re-sets
it afterwards or `ctrl+n` would offer candidates that no longer fit the value.
**A rule's usage count is how many transactions it wins, not how many its glob
could match** — `Engine.Usage` counts by `MatchIndex`, so a rule shadowed by an
earlier one correctly reports zero. That is what makes the rules screen able to