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() likes := []ledger.Like{} if likePattern != "" { like := ledger.LikeName(likePattern) transactions = transactions.Like(like) likes = append(likes, like) } if notLikePattern != "" { like := ledger.NotLikeName(notLikePattern) transactions = transactions.NotLike(like) likes = append(likes, like) } for _, transaction := range transactions { fmt.Println(transaction[0].Date) FPrintBalances(os.Stdout, ledger.Deltas(transaction).Like(likes...).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]) } } }