main
Bel LaPointe 2023-10-24 12:31:42 -06:00
parent 6f9ccea0d2
commit aed990fa2c
1 changed files with 75 additions and 5 deletions

View File

@ -7,6 +7,8 @@ import (
"io"
"os"
"regexp"
"strconv"
"unicode"
)
type transaction struct {
@ -69,11 +71,28 @@ func readTransaction(r *bufio.Reader) (transaction, error) {
} else if len(dateDescriptionMatches[0]) != 3 {
return transaction{}, fmt.Errorf("bad first line: %v submatches: %q", len(dateDescriptionMatches[0]), firstLine)
}
result := transaction{
date: string(dateDescriptionMatches[0][1]),
description: string(dateDescriptionMatches[0][2]),
}
date := string(dateDescriptionMatches[0][1])
description := string(dateDescriptionMatches[0][2])
return transaction{}, fmt.Errorf("need to parse more of %q/%q", date, description)
for {
name, value, currency, err := readTransactionAccount(r)
if name != "" {
if currency == "" {
result.payee = name
} else {
result.recipients = append(result.recipients, transactionRecipient{
name: name,
value: value,
currency: currency,
})
}
}
if name == "" || err != nil {
return result, err
}
}
}
func readTransactionLeadingWhitespace(r *bufio.Reader) {
@ -96,8 +115,17 @@ func readTransactionLeadingWhitespace(r *bufio.Reader) {
}
func readTransactionLine(r *bufio.Reader) ([]byte, error) {
for {
b, err := _readTransactionLine(r)
if err != nil || (len(bytes.TrimSpace(b)) > 0 && bytes.TrimSpace(b)[0] != '#') {
return b, err
}
}
}
func _readTransactionLine(r *bufio.Reader) ([]byte, error) {
b, err := r.Peek(2048)
if err != nil && err != io.EOF {
if len(b) == 0 {
return nil, err
}
@ -108,5 +136,47 @@ func readTransactionLine(r *bufio.Reader) ([]byte, error) {
b2 := make([]byte, endOfLine)
n, err := r.Read(b2)
if err == io.EOF {
err = nil
}
if check, _ := r.Peek(1); len(check) == 1 && check[0] == '\n' {
r.Read(make([]byte, 1))
}
return b2[:n], err
}
func readTransactionAccount(r *bufio.Reader) (string, float64, string, error) {
line, err := readTransactionLine(r)
if err != nil {
return "", 0, "", err
}
if len(line) > 0 && !unicode.IsSpace(rune(line[0])) {
r2 := *r
*r = *bufio.NewReader(io.MultiReader(bytes.NewReader(line), &r2))
return "", 0, "", nil
}
fields := bytes.Fields(line)
switch len(fields) {
case 1: // payee
return string(fields[0]), 0, "", nil
case 2: // $00.00
b := bytes.TrimLeft(fields[1], "$")
value, err := strconv.ParseFloat(string(b), 64)
if err != nil {
return "", 0, "", err
}
return string(fields[0]), value, string(USD), nil
case 3: // 00.00 XYZ
value, err := strconv.ParseFloat(string(fields[2]), 64)
if err != nil {
return "", 0, "", err
}
return string(fields[0]), value, string(fields[3]), nil
default:
return "", 0, "", fmt.Errorf("cannot interpret %q", line)
}
}