@@ 2,6 2,7 @@ package main
import (
"bytes"
+ "context"
"fmt"
"image"
"io"
@@ 97,6 98,7 @@ type UI struct {
Balances []*ledger.Account
OutFilePath string
CacheFilePath string
+ reload future.Single
// Layout state.
Divider component.Resize
@@ 240,6 242,67 @@ func (ui *UI) requestFiles() {
})
}
+func (ui *UI) rewriteAndLoad() {
+ txCopies := make([]*ledger.Transaction, len(ui.Txs))
+ for i := range txCopies {
+ txCopies[i] = &(*ui.Txs[i])
+ }
+ filterCopies := make([]int, len(ui.Filtered))
+ copy(filterCopies, ui.Filtered)
+ targetFile := ui.OutFilePath
+ type reloadInfo struct {
+ Txs []*ledger.Transaction
+ Filtered []int
+ Balances []*ledger.Account
+ Tree *AccountTreeNode
+ OutFilePath string
+ CacheFilePath string
+ }
+ ui.Stage = LoadingFiles
+ future.RunSingle(&ui.reload, ui.Conn,
+ func(ctx context.Context) (li reloadInfo, err error) {
+ var b bytes.Buffer
+ for _, tx := range txCopies {
+ b.Write(toTxBytes(*tx))
+ }
+ if err := os.WriteFile(targetFile, b.Bytes(), 0o644); err != nil {
+ return reloadInfo{}, fmt.Errorf("failed rewriting input file: %w", err)
+ }
+ transactions, err := ledger.ParseLedgerFile(targetFile)
+ if err != nil {
+ return reloadInfo{}, fmt.Errorf("failed parsing input file: %w", err)
+ }
+ filtered := make([]int, len(transactions))
+ for i := range filtered {
+ filtered[i] = i
+ }
+ // sort the elements of filtered by the dates of the transactions they refer to.
+ sort.Slice(filtered, func(i, j int) bool {
+ return transactions[filtered[i]].Date.After(transactions[filtered[j]].Date)
+ })
+ balances := ledger.GetBalances(transactions, nil)
+ tree := BuildAccountTree(balances)
+ return reloadInfo{
+ Txs: transactions,
+ Filtered: filtered,
+ Balances: balances,
+ Tree: tree,
+ }, nil
+ },
+ func(ctx context.Context, li reloadInfo, err error) bool {
+ if err != nil {
+ log.Printf("failed loading: %v", err)
+ } else {
+ ui.Txs = li.Txs
+ ui.Filtered = li.Filtered
+ ui.Tree = li.Tree
+ ui.Balances = li.Balances
+ ui.Stage = Ready
+ }
+ return true
+ })
+}
+
func (ui *UI) layout(gtx C) D {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx C) D {
@@ 343,8 406,8 @@ func toTxBytes(tx ledger.Transaction) []byte {
b.WriteString(tx.Payee)
b.WriteString("\n")
for i, change := range tx.AccountChanges {
- if i < len(tx.Comments) {
- b.WriteString("\t; ")
+ if i < len(tx.Comments) && len(tx.Comments[i]) > 0 {
+ b.WriteString("\t")
b.WriteString(tx.Comments[i])
b.WriteString("\n")
}
@@ 352,8 415,10 @@ func toTxBytes(tx ledger.Transaction) []byte {
b.WriteString(change.Name)
b.WriteString(" ")
b.WriteString(change.Balance.StringFixedBank())
- b.WriteString(" ; ")
- b.WriteString(change.Comment)
+ if len(change.Comment) > 0 {
+ b.WriteString(" ")
+ b.WriteString(change.Comment)
+ }
b.WriteString("\n")
}
return b.Bytes()
@@ 370,7 435,8 @@ func (u *UI) layoutTransactions(gtx C) D {
suggestions := fuzzy.FindFold(e.Text, maps.Keys(u.AccountRegistry.elements))
u.TxEditor.SetAccountSuggestions(suggestions)
case appwidget.TransactionSubmittedEvent:
- log.Println(string(toTxBytes(e.Value)))
+ u.Txs = append(u.Txs, &e.Value)
+ u.rewriteAndLoad()
}
}
return layout.UniformInset(4).Layout(gtx, apptheme.TxForm(u.Theme, &u.TxEditor).Layout)