Commit Graph
4 Commits
Author SHA1 Message Date
nikolaandClaude Opus 5 aeca203855 Add a rule builder screen with a live glob preview
Writing a glob by hand meant guessing what it would catch, then running retag
to find out. The new screen, on 4, puts the glob, account and tag fields on
the left and every still-untagged description on the right, sorted
alphabetically and grouped by description with an occurrence count.

Matches are marked as the glob is typed, along with a count, so the effect of
a rule is visible before it is written. Enter appends it to rules.toml via
config.AppendRule, reloads the engine from disk and retags, so the rows it
caught leave the list immediately.

Rules are appended rather than prepended, keeping the precedence of anything
already in the file. Since the preview only lists transactions no existing
rule has tagged, it reflects that precedence for free.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:41:24 +02:00
nikolaandClaude Opus 5 6d4266c224 Run imports in the background behind a spinner
Import ran inline in the update loop, so the whole interface froze for as
long as pdftotext took over a stack of statements, with no way to tell work
in progress apart from a hang.

It now runs as a command off the event loop, with a spinner and a note that
PDFs take a while. A repeat i press is ignored and retag is refused while an
import is running, so nothing writes to the index concurrently. The result
arrives as a message carrying the counts, the first failure, and the first
warning with a count of any others.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:12:48 +02:00
nikolaandClaude Opus 5 9ba3fe8fbe Explain empty TUI views instead of showing a bare table
An account folder is only registered in the index by an import, so a freshly
configured account.toml produced an empty accounts table with nothing to say
why or what to do about it.

Each view now explains its own emptiness and names the key that resolves it,
distinguishing configured-but-not-imported from no-folders-at-all, and
telling apart a filter that matched nothing from having no data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 01:04:14 +02:00
nikolaandClaude Opus 5 b0026c5a79 Add money: statement-driven personal finance tracker
A data directory holds one folder per account. Statements dropped into
those folders are parsed into a rebuildable SQLite index, categorised by
ordered glob rules in rules.toml, and browsed or hand-tagged in a Bubble
Tea TUI. Movements between the user's own accounts are marked as
transfers by the same rules and excluded from spending totals.

Manual tags and transfer marks are stored separately from the rule-derived
ones and always win, so editing rules.toml and re-running retag never
destroys hand edits.

Parsers are pluggable. Three are ported from the Python extractors they
replace -- nlb and traderepublic read PDFs via pdftotext -layout, revolut
reads the CSV export -- alongside a configurable-column CSV parser and a
cmd parser that shells out to an external script.

Both ports fix two latent bugs in the originals: the sign character class
rejected the typographic minus U+2212 that some PDF fonts emit, and NLB's
hardcoded continuation indent broke when pdftotext compressed runs of
spaces, so the threshold is now measured from the description column.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 00:37:20 +02:00