Correct the docs against the code

Four removals in a row left both files describing things that are no longer
there, and one claim that was never true:

- The rules screen mock-up still had the transfer column, two commits after
  that column went. The keys table listed 4 twice, once as a view switch and
  once as the tagging row that replaced t; tagging is now a sentence saying
  plainly that no key does it and why 4 is the answer.
- The rule builder mock-up was missing the account field entirely while the
  prose below it described moving between four fields.
- glob was described as linear time with no backtracking. It is the two-pointer
  wildcard match, which backtracks by design -- the branch is right there in
  glob.go -- and is O(n*m) in the worst case. What it actually rules out is
  exponential blowup on patterns like *a*a*a*.
- r on the rules screen was undocumented. It recounts against the index, which
  is what an import makes stale; it does not re-read rules.toml, so an edit
  made elsewhere still needs a restart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 23:39:17 +02:00
co-authored by Claude Opus 5
parent 93491016cd
commit ef6a231d98
2 changed files with 23 additions and 11 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ This file covers what the code assumes and why.
cmd/money/main.go subcommands; the TUI is the default cmd/money/main.go subcommands; the TUI is the default
internal/config rules.toml, account.toml, XDG config, data-root resolution internal/config rules.toml, account.toml, XDG config, data-root resolution
internal/model Account, Transaction, amount formatting, description normalisation internal/model Account, Transaction, amount formatting, description normalisation
internal/glob the `*` / `?` matcher used by rules (linear time, no backtracking) internal/glob the `*` / `?` matcher used by rules (two-pointer, no exponential blowup)
internal/parser Parser interface + registry; nlb, revolut, traderepublic internal/parser Parser interface + registry; nlb, revolut, traderepublic
internal/store SQLite index (modernc.org/sqlite, no cgo) internal/store SQLite index (modernc.org/sqlite, no cgo)
internal/importer directory walk, dedupe, balance checks internal/importer directory walk, dedupe, balance checks
+22 -10
View File
@@ -13,7 +13,7 @@ tagged by glob rules you write.
rules.toml # tag rules, in order rules.toml # tag rules, in order
index.db # SQLite index (rebuildable; safe to delete*) index.db # SQLite index (rebuildable; safe to delete*)
checking/ checking/
account.toml # currency + how to parse this bank's exports account.toml # currency + which parser reads this bank's exports
2026-01.csv 2026-01.csv
2026-02.csv 2026-02.csv
savings/ savings/
@@ -63,7 +63,7 @@ money # open the TUI (default)
money import # extract new transactions from every statement money import # extract new transactions from every statement
money import --force # re-parse statements even if unchanged money import --force # re-parse statements even if unchanged
money retag # re-apply rules.toml to everything already imported money retag # re-apply rules.toml to everything already imported
money ls --untagged # what still needs a tag money ls --untagged # what no rule has claimed yet
money ls --wide # also show type and reported balance money ls --wide # also show type and reported balance
money ls --account checking --month 2026-01 money ls --account checking --month 2026-01
money report --month 2026-01 # spending by tag money report --month 2026-01 # spending by tag
@@ -82,12 +82,15 @@ imported — creating an `account.toml` is not enough on its own. Run
| --- | --- | | --- | --- |
| `1` `2` `3` `4` `5` / `tab` | accounts · transactions · report · rule builder · rules | | `1` `2` `3` `4` `5` / `tab` | accounts · transactions · report · rule builder · rules |
| `enter` | open the selected account (accounts view) | | `enter` | open the selected account (accounts view) |
| `4` | write a rule for what you are looking at — the only way to tag |
| `/` | filter by description | | `/` | filter by description |
| `u` | show only untagged transactions | | `u` | show only untagged transactions |
| `a` | clear the account filter | | `a` | clear the account filter |
| `i` | import · `r` re-apply rules · `q` quit | | `i` | import · `r` re-apply rules · `q` quit |
There is no key that tags a transaction. Tags come from `rules.toml` and
nowhere else, so tagging what you are looking at means writing a rule for it on
`4` — which is why that screen shows you what a glob catches before you save.
### Rule builder (`4`) ### Rule builder (`4`)
Writing rules by hand means guessing what a glob will catch. This screen shows Writing rules by hand means guessing what a glob will catch. This screen shows
@@ -103,6 +106,12 @@ a `▸` against each one the glob currently matches and a running
╰────────────────────────────╯ ▸ LIDL SOFIA 4412 2 ╰────────────────────────────╯ ▸ LIDL SOFIA 4412 2
vs. the description ▸ LIDL VARNA 9911 1 vs. the description ▸ LIDL VARNA 9911 1
ZARA MLADOST 1 ZARA MLADOST 1
account
╭────────────────────────────╮
│ blank = every account │
╰────────────────────────────╯
blank = all accounts
▸ tag ▸ tag
╭────────────────────────────╮ ╭────────────────────────────╮
│ groceries │ │ groceries │
@@ -148,12 +157,12 @@ Rules that claim none are marked `✗`.
``` ```
money · rules · 5 rules · 2 match nothing money · rules · 5 rules · 2 match nothing
# Pattern Account Tag T Txns Note # Pattern Account Tag Txns Note
1 *LIDL* (all) groceries 3 the weekly shop 1 *LIDL* (all) groceries 3 the weekly shop
2 ✗ *LIDL SOFIA* (all) shadowed 0 2 ✗ *LIDL SOFIA* (all) shadowed 0
3 ✗ *OLD BANK NAME* (all) dead 0 closed in 2025 3 ✗ *OLD BANK NAME* (all) dead 0 closed in 2025
4 *ZARA* (all) clothes 1 4 *ZARA* (all) clothes 1
5 *КАУФЛАНД* checking groceries 1 4412 is the branch 5 *КАУФЛАНД* checking groceries 1 4412 is the branch
``` ```
The count is how many transactions the rule *wins*, not how many its glob could The count is how many transactions the rule *wins*, not how many its glob could
@@ -163,7 +172,10 @@ can therefore reach zero either by matching nothing or by being shadowed, and
both are worth deleting. both are worth deleting.
`d` deletes the selected rule, `p` deletes every rule marked `✗` at once, and `d` deletes the selected rule, `p` deletes every rule marked `✗` at once, and
both ask for a `y` first. Deleting edits `rules.toml` textually, so your both ask for a `y` first. `r` recounts against what is currently in the index,
which is what you want after an import has added rows; `rules.toml` itself is
read at startup and whenever you save a rule from the builder, so an edit made
in another window needs a restart. Deleting edits `rules.toml` textually, so your
comments, ordering and formatting survive; a comment sitting directly above a comments, ordering and formatting survive; a comment sitting directly above a
deleted rule goes with it, while one separated by a blank line is treated as a deleted rule goes with it, while one separated by a blank line is treated as a
section heading and left alone. section heading and left alone.