almost
parent
6f9ccea0d2
commit
aed990fa2c
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue