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:
M | arg.h | | | 44 | +++++++++++++++++++++++++------------------- |
M | sw.1 | | | 7 | ++++--- |
M | sw.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;
}