Try the most specific rule first, not the topmost
File order decided precedence, so a narrow rule had to be written above the broad one it carves an exception out of -- an ordering constraint the file cannot show and the user has to remember. *NIKOLA* below *NIK* silently matched nothing, and a catch-all * could only ever be the last line. Engine.New now sorts once and MatchIndex walks that order: most literal characters first, then fewest *, then account-scoped over unscoped. Literals are what a rule commits to and a * is what it gives up, so a bare * is tried last wherever it sits. The sort is stable, so equally specific rules keep file order and the earlier one wins -- which is all position decides now, and why AppendRule can keep appending without displacing a rule written by hand. The two orders must not be confused: Rules(), Usage and MatchIndex still speak in file positions, because that is what the rules screen numbers and what DeleteRules deletes by. A shadowed rule still reports zero usage, but a zero no longer says anything about where the rule sits. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -664,8 +664,9 @@ func acceptCompletion(in *textinput.Model) bool {
|
||||
|
||||
// reloadRuleList counts, for every rule, how many transactions it actually
|
||||
// claims. A rule can match nothing because no description fits it, or because
|
||||
// an earlier rule already took everything it would have caught; both show up
|
||||
// here as a zero.
|
||||
// a more specific rule already took everything it would have caught; both show
|
||||
// up here as a zero. The rows stay in file order — that is the number the user
|
||||
// can find in rules.toml, and precedence is not read off it any more.
|
||||
func (m *Model) reloadRuleList() error {
|
||||
txns, err := m.db.Transactions(store.Filter{})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user