sw

simple wallet
git clone git://git.bitsmanent.org/sw
Log | Files | Refs | README | LICENSE

commit bb2bc4a2804560f96b36e080c108b77f05cda564
parent 744907c0ac4e3333c209a4c552cf87a396db83e2
Author: Claudio Alessi <smoppy@gmail.com>
Date:   Sat, 29 Jun 2024 15:03:54 +0200

Compute totals outside of render. Also handle -l with no arguments (default 25).

Diffstat:
Marg.h | 44+++++++++++++++++++++++++-------------------
Msw.1 | 7++++---
Msw.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
3 files changed, 85 insertions(+), 49 deletions(-)

diff --git a/arg.h b/arg.h @@ -3,39 +3,45 @@ * by 20h */ -#ifndef __ARG_H__ -#define __ARG_H__ +#ifndef ARG_H__ +#define ARG_H__ extern char *argv0; -#define USED(x) ((void)(x)) - +/* use main(int argc, char *argv[]) */ #define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][1]\ - && argv[0][0] == '-';\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ argc--, argv++) {\ - char _argc;\ - char **_argv;\ + char argc_;\ + char **argv_;\ + int brk_;\ if (argv[0][1] == '-' && argv[0][2] == '\0') {\ argv++;\ argc--;\ break;\ }\ - for (argv[0]++, _argv = argv; argv[0][0];\ + for (brk_ = 0, argv[0]++, argv_ = argv;\ + argv[0][0] && !brk_;\ argv[0]++) {\ - if (_argv != argv)\ + if (argv_ != argv)\ break;\ - _argc = argv[0][0];\ - switch (_argc) + argc_ = argv[0][0];\ + switch (argc_) #define ARGEND }\ - USED(_argc);\ - }\ - USED(argv);\ - USED(argc); + } -#define EARGF(x) ((argv[1] == NULL)? ((x), abort(), (char *)0) :\ - (argc--, argv++, argv[0])) +#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) -#endif +#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) +#endif diff --git a/sw.1 b/sw.1 @@ -3,7 +3,7 @@ sw \- simple wallet .SH SYNOPSIS .B sw -.RB [ \-v ]\ [ \-defilt \ <arg>]\ [<date>\ <amount>\ <note>] +.RB [ \-v ]\ [ \-defit \ <arg>]\ [ \-l \ [arg] ]\ [<date>\ <amount>\ <note>] .SH DESCRIPTION sw is a simple wallet management tool which features a simple yet powerful interface to keep track of your money movements. @@ -18,5 +18,6 @@ remove the specified movement, then exits. .B \-f\ <file> use the given file as movements database. .TP -.B \-l\ <limit> -limit the number of movements in the listing. +.B \-l\ [limit] +limit the number of movements in the listing. In no argument is specified then +assume a value of 25. diff --git a/sw.c b/sw.c @@ -23,6 +23,13 @@ struct Movement { Movement *next; }; +typedef struct { + float amount, pamount; + float income, pincome; + float expense, pexpense; + int count, pcount; +} Totals; + /* function declarations */ int addmov(char *date, float amount, char *note); void attach(Movement *m); @@ -34,16 +41,19 @@ void *ecalloc(size_t nmemb, size_t size); void filtermovs(int from, int to, char *txt); void freemovs(void); void loadmovs(void); +void refresh(void); void savemovs(void); -void showmovs(int limit); +void showmovs(void); void sortmovs(void); int strtots(char *s); void usage(void); /* variables */ Movement *movs; +Totals totals; FILE *movsfile; char movsfilename[256]; +int limit = INT_MAX; /* function implementations */ int @@ -171,6 +181,31 @@ loadmovs(void) { } void +refresh(void) { + Movement *m; + + totals.amount = totals.income = totals.expense = totals.count = 0; + totals.pamount = totals.pincome = totals.pexpense = totals.pcount = 0; + for(m = movs; m; m = m->next) { + totals.amount += m->amount; + if(m->amount >= 0) + totals.income += m->amount; + else + totals.expense += m->amount; + ++totals.count; + + if(totals.pcount >= limit) + continue; + totals.pamount += m->amount; + if(m->amount >= 0) + totals.pincome += m->amount; + else + totals.pexpense += m->amount; + ++totals.pcount; + } +} + +void savemovs(void) { Movement *m; @@ -181,40 +216,28 @@ savemovs(void) { } void -showmovs(int limit) { +showmovs(void) { Movement *m; time_t ts; - float tot = 0, partial = 0, in = 0, ex = 0, pin = 0, pex = 0; - int nmovs = 0, pmovs = 0; char time[32]; + int showpartials = limit < totals.count ? 1 : 0; + int count = 0; - if(limit) + if(limit >= 1 && showpartials) printf("%5s | %16s | %8s | %s\n", "id", "date time", "amount", "note"); for(m = movs; m; m = m->next) { - ++nmovs; - tot += m->amount; - if(m->amount >= 0) - in += m->amount; - else - ex += m->amount; - if(pmovs >= limit || m->filtered) + if(m->filtered || count >= limit) continue; + ++count; ts = m->ts; - ++pmovs; - partial += m->amount; - if(m->amount >= 0) - pin += m->amount; - else - pex += m->amount; strftime(time, sizeof time, "%d/%m/%Y %H:%M", localtime(&ts)); printf("%5d | %16s | %8.2f | %s\n", m->id, time, m->amount, m->note); } - if(limit > 1) { - printf("%5s | %17s: %8.2f | income=%.2f expenses=%.2f movements=%d\n", "", - "Partial", partial, pin, pex, pmovs); - } - printf("%5s | %17s: %8.2f | income=%.2f expenses=%.2f movements=%d\n", - "", "Total", tot, in, ex, nmovs); + if(limit > 1 && showpartials) + printf("%5s | %17s: %8.2f | income=%.2f expense=%.2f movements=%d\n", "", + "Partial", totals.pamount, totals.pincome, totals.pexpense, totals.pcount); + printf("%5s | %17s: %8.2f | income=%.2f expense=%.2f movements=%d\n", + "", "Total", totals.amount, totals.income, totals.expense, totals.count); } void @@ -247,16 +270,21 @@ usage(void) { int main(int argc, char *argv[]) { - int delid = 0, limit = INT_MAX; + int delid = 0; int from = 0, to = 0; char *txt = NULL; + char *num; ARGBEGIN { case 'd': delid = atoi(EARGF(usage())); break; case 'e': txt = EARGF(usage()); break; case 'f': from = strtots(EARGF(usage())); break; case 'i': snprintf(movsfilename, sizeof movsfilename, "%s", EARGF(usage())); break; - case 'l': limit = atoi(EARGF(usage())); break; + case 'l': + //limit = atoi(EARGF(usage())); + num = ARGF(); + limit = num ? atoi(num) : 25; + break; case 't': to = strtots(EARGF(usage())); break; case 'v': die("sw-"VERSION"\n"); default: usage(); @@ -284,7 +312,8 @@ main(int argc, char *argv[]) { } filtermovs(from, to, txt); sortmovs(); - showmovs(limit); + refresh(); + showmovs(); freemovs(); return 0; }