~whereswaldon/rosebud

43d4c58efd58a3a86cd516f44c3c006840aafa15 — Chris Waldon 9 months ago 5b78fa3
cmd/rosebud: rewrite ledger file to include new txs

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
1 files changed, 71 insertions(+), 5 deletions(-)

M cmd/rosebud/main.go
M cmd/rosebud/main.go => cmd/rosebud/main.go +71 -5
@@ 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)