139 lines
3.0 KiB
Go
139 lines
3.0 KiB
Go
package cli
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"slices"
|
|
|
|
"gogs.inhome.blapointe.com/ana-ledger/src/ledger"
|
|
)
|
|
|
|
func Main() {
|
|
var config Config
|
|
|
|
fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
|
fs.Var(&config.Files, "f", "paths to files")
|
|
fs.Var(&config.Query.Period, "period", "period")
|
|
fs.StringVar(&config.Query.Sort, "S", "", "sort ie date")
|
|
fs.BoolVar(&config.Query.NoRounding, "no-rounding", false, "no rounding")
|
|
fs.IntVar(&config.Query.Depth, "depth", 0, "depth grouping")
|
|
if err := fs.Parse(os.Args[1:]); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
files := config.Files.Strings()
|
|
if len(files) == 0 {
|
|
panic("must specify at least one file")
|
|
}
|
|
ledgerFiles, err := ledger.NewFiles(files[0], files[1:]...)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
positional := fs.Args()
|
|
if len(positional) == 0 || len(positional[0]) < 3 {
|
|
panic("positional arguments required, ie bal|reg PATTERN MATCHING")
|
|
}
|
|
cmd := positional[0]
|
|
|
|
likePattern := ""
|
|
notLikePattern := ""
|
|
i := 1
|
|
for i < len(positional) {
|
|
switch positional[i] {
|
|
case "not":
|
|
_ = notLikePattern
|
|
panic(positional[i:])
|
|
case "and":
|
|
panic(positional[i:])
|
|
default:
|
|
if likePattern == "" {
|
|
likePattern = positional[i]
|
|
} else {
|
|
likePattern = fmt.Sprintf("%s|%s", likePattern, positional[i])
|
|
}
|
|
}
|
|
i += 1
|
|
}
|
|
|
|
deltas, err := ledgerFiles.Deltas()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if period := config.Query.Period; !period.Empty() {
|
|
after := period.Start.Format("2006-01-02")
|
|
before := period.Stop.Format("2006-01-02")
|
|
deltas = deltas.Like(
|
|
ledger.LikeAfter(after),
|
|
ledger.LikeBefore(before),
|
|
)
|
|
}
|
|
|
|
if depth := config.Query.Depth; depth > 0 {
|
|
panic(depth)
|
|
}
|
|
|
|
switch cmd[:3] {
|
|
case "bal":
|
|
balances := deltas.Balances()
|
|
if likePattern != "" {
|
|
balances = balances.Like(likePattern)
|
|
}
|
|
if notLikePattern != "" {
|
|
balances = balances.NotLike(notLikePattern)
|
|
}
|
|
|
|
FPrintBalances(os.Stdout, balances)
|
|
case "reg":
|
|
transactions := deltas.Transactions()
|
|
if likePattern != "" {
|
|
transactions = transactions.Like(ledger.LikeName(likePattern))
|
|
}
|
|
if notLikePattern != "" {
|
|
transactions = transactions.NotLike(ledger.NotLikeName(notLikePattern))
|
|
}
|
|
|
|
for _, transaction := range transactions {
|
|
fmt.Println(transaction[0].Date)
|
|
FPrintBalances(os.Stdout, ledger.Deltas(transaction).Balances())
|
|
}
|
|
default:
|
|
panic("unknown command " + positional[0])
|
|
}
|
|
}
|
|
|
|
func FPrintBalances(w io.Writer, balances ledger.Balances) {
|
|
keys := []string{}
|
|
for k := range balances {
|
|
keys = append(keys, k)
|
|
}
|
|
slices.Sort(keys)
|
|
|
|
max := 0
|
|
for _, k := range keys {
|
|
if n := len(k); n > max {
|
|
max = n
|
|
}
|
|
}
|
|
|
|
format := fmt.Sprintf("%%-%ds\t%%s%%.2f\n", max)
|
|
for _, key := range keys {
|
|
currencies := []ledger.Currency{}
|
|
for currency := range balances[key] {
|
|
currencies = append(currencies, currency)
|
|
}
|
|
slices.Sort(currencies)
|
|
|
|
for _, currency := range currencies {
|
|
printableCurrency := currency
|
|
if printableCurrency != "$" {
|
|
printableCurrency += " "
|
|
}
|
|
fmt.Fprintf(w, format, key, printableCurrency, balances[key][currency])
|
|
}
|
|
}
|
|
}
|