From 42abbf53463cbbdcd319063fcbfb91cf6ed5bdc5 Mon Sep 17 00:00:00 2001 From: Lars Henriksen Date: Thu, 6 Dec 2018 09:56:45 +0100 Subject: Filter option: invert New filter option: --filter-invert. When present it inverts (negates) the other filter options combined. This is mostly useful with the -G option (with -Q the output is limited by the query range (day range)). The ouput from "calcurse -G " is the (set) complement of "calcurse -G --filter-invert". Here may be any combination of filter options. Signed-off-by: Lars Henriksen Signed-off-by: Lukas Fleischer --- src/apoint.c | 46 +++++++++++++------------- src/args.c | 10 ++++-- src/calcurse.h | 1 + src/event.c | 45 +++++++++++++------------ src/io.c | 46 ++++++++++++-------------- src/recur.c | 101 ++++++++++++++++++++++++++++++--------------------------- 6 files changed, 128 insertions(+), 121 deletions(-) diff --git a/src/apoint.c b/src/apoint.c index e8f9ee8..c195559 100644 --- a/src/apoint.c +++ b/src/apoint.c @@ -200,7 +200,8 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end, { char buf[BUFSIZ], *newline; time_t tstart, tend; - struct apoint *apt; + struct apoint *apt = NULL; + int cond; EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || !check_date(end.tm_year, end.tm_mon, end.tm_mday) || @@ -230,31 +231,30 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end, /* Filter item. */ if (filter) { - if (!(filter->type_mask & TYPE_MASK_APPT)) - return NULL; - if (filter->regex && regexec(filter->regex, buf, 0, 0, 0)) - return NULL; - if (filter->start_from != -1 && tstart < filter->start_from) - return NULL; - if (filter->start_to != -1 && tstart > filter->start_to) - return NULL; - if (filter->end_from != -1 && tend < filter->end_from) - return NULL; - if (filter->end_to != -1 && tend > filter->end_to) - return NULL; - } - - apt = apoint_new(buf, note, tstart, tend - tstart, state); + cond = ( + !(filter->type_mask & TYPE_MASK_APPT) || + (filter->regex && regexec(filter->regex, buf, 0, 0, 0)) || + (filter->start_from != -1 && tstart < filter->start_from) || + (filter->start_to != -1 && tstart > filter->start_to) || + (filter->end_from != -1 && tend < filter->end_from) || + (filter->end_to != -1 && tend > filter->end_to) + ); + if (filter->hash) { + apt = apoint_new( + buf, note, tstart, tend - tstart, state); + char *hash = apoint_hash(apt); + cond = cond || !hash_matches(filter->hash, hash); + mem_free(hash); + } - /* Filter by hash. */ - if (filter && filter->hash) { - char *hash = apoint_hash(apt); - if (!hash_matches(filter->hash, hash)) { - apoint_delete(apt); - apt = NULL; + if ((!filter->invert && cond) || (filter->invert && !cond)) { + if (filter->hash) + apoint_delete(apt); + return NULL; } - mem_free(hash); } + if (!apt) + apt = apoint_new(buf, note, tstart, tend - tstart, state); return apt; } diff --git a/src/args.c b/src/args.c index 118ddc1..d2e4860 100644 --- a/src/args.c +++ b/src/args.c @@ -54,7 +54,8 @@ enum { /* Long options */ enum { - OPT_FILTER_TYPE = 1000, + OPT_FILTER_INVERT = 1000, + OPT_FILTER_TYPE, OPT_FILTER_HASH, OPT_FILTER_PATTERN, OPT_FILTER_START_FROM, @@ -410,7 +411,7 @@ int parse_args(int argc, char **argv) int range = 0; int limit = INT_MAX; /* Filters */ - struct item_filter filter = { 0, NULL, NULL, -1, -1, -1, -1, 0, 0, 0 }; + struct item_filter filter = { 0, 0, NULL, NULL, -1, -1, -1, -1, 0, 0, 0 }; /* Format strings */ const char *fmt_apt = NULL; const char *fmt_rapt = NULL; @@ -457,6 +458,7 @@ int parse_args(int argc, char **argv) {"quiet", no_argument, NULL, 'q'}, {"query", optional_argument, NULL, 'Q'}, + {"filter-invert", no_argument, NULL, OPT_FILTER_INVERT}, {"filter-type", required_argument, NULL, OPT_FILTER_TYPE}, {"filter-hash", required_argument, NULL, OPT_FILTER_HASH}, {"filter-pattern", required_argument, NULL, OPT_FILTER_PATTERN}, @@ -623,6 +625,10 @@ int parse_args(int argc, char **argv) case 'Q': query = 1; break; + case OPT_FILTER_INVERT: + filter.invert = !filter.invert; + filter_opt = 1; + break; case OPT_FILTER_TYPE: filter.type_mask = parse_type_mask(optarg); EXIT_IF(filter.type_mask == 0, diff --git a/src/calcurse.h b/src/calcurse.h index c6ddc8d..40e253e 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -427,6 +427,7 @@ enum item_type { /* Filter settings. */ struct item_filter { + int invert; int type_mask; char *hash; regex_t *regex; diff --git a/src/event.c b/src/event.c index fe8f883..65af662 100644 --- a/src/event.c +++ b/src/event.c @@ -152,7 +152,8 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note, { char buf[BUFSIZ], *nl; time_t tstart, tend; - struct event *ev; + struct event *ev = NULL; + int cond; EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || !check_time(start.tm_hour, start.tm_min), @@ -179,31 +180,29 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note, /* Filter item. */ if (filter) { - if (!(filter->type_mask & TYPE_MASK_EVNT)) - return NULL; - if (filter->regex && regexec(filter->regex, buf, 0, 0, 0)) - return NULL; - if (filter->start_from != -1 && tstart < filter->start_from) - return NULL; - if (filter->start_to != -1 && tstart > filter->start_to) - return NULL; - if (filter->end_from != -1 && tend < filter->end_from) - return NULL; - if (filter->end_to != -1 && tend > filter->end_to) - return NULL; - } - - ev = event_new(buf, note, tstart, id); + cond = ( + !(filter->type_mask & TYPE_MASK_EVNT) || + (filter->regex && regexec(filter->regex, buf, 0, 0, 0)) || + (filter->start_from != -1 && tstart < filter->start_from) || + (filter->start_to != -1 && tstart > filter->start_to) || + (filter->end_from != -1 && tend < filter->end_from) || + (filter->end_to != -1 && tend > filter->end_to) + ); + if (filter->hash) { + ev = event_new(buf, note, tstart, id); + char *hash = event_hash(ev); + cond = cond || !hash_matches(filter->hash, hash); + mem_free(hash); + } - /* Filter by hash. */ - if (filter && filter->hash) { - char *hash = event_hash(ev); - if (!hash_matches(filter->hash, hash)) { - event_delete(ev); - ev = NULL; + if ((!filter->invert && cond) || (filter->invert && !cond)) { + if (filter->hash) + event_delete(ev); + return NULL; } - mem_free(hash); } + if (!ev) + ev = event_new(buf, note, tstart, id); return ev; } diff --git a/src/io.c b/src/io.c index 0e7baea..27c6a31 100644 --- a/src/io.c +++ b/src/io.c @@ -707,8 +707,7 @@ void io_load_todo(struct item_filter *filter) { FILE *data_file; char *newline; - int nb_tod = 0; - int c, id, completed; + int c, id, completed, cond; char buf[BUFSIZ], e_todo[BUFSIZ], note[MAX_NOTESIZ + 1]; unsigned line = 0; @@ -760,34 +759,31 @@ void io_load_todo(struct item_filter *filter) io_extract_data(e_todo, buf, sizeof buf); /* Filter item. */ + struct todo *todo = NULL; if (filter) { - if (!(filter->type_mask & TYPE_MASK_TODO)) - continue; - if (filter->regex && - regexec(filter->regex, e_todo, 0, 0, 0)) - continue; - if (filter->priority && id != filter->priority) - continue; - if (filter->completed && !completed) - continue; - if (filter->uncompleted && completed) - continue; - } - - struct todo *todo = todo_add(e_todo, id, completed, note); + cond = ( + !(filter->type_mask & TYPE_MASK_TODO) || + (filter->regex && regexec(filter->regex, e_todo, 0, 0, 0)) || + (filter->priority && id != filter->priority) || + (filter->completed && !completed) || + (filter->uncompleted && completed) + ); + if (filter->hash) { + todo = todo_add(e_todo, id, completed, note); + char *hash = todo_hash(todo); + cond = cond || !hash_matches(filter->hash, hash); + mem_free(hash); + } - /* Filter by hash. */ - if (filter && filter->hash) { - char *hash = todo_hash(todo); - if (!hash_matches(filter->hash, hash)) { - todo_delete(todo); - todo = NULL; + if ((!filter->invert && cond) || (filter->invert && !cond)) { + if (filter->hash) + todo_delete(todo); + continue; } - mem_free(hash); } - if (todo) - ++nb_tod; + if (!todo) + todo = todo_add(e_todo, id, completed, note); } file_close(data_file, __FILE_POS__); } diff --git a/src/recur.c b/src/recur.c index ca99a21..e481c08 100644 --- a/src/recur.c +++ b/src/recur.c @@ -349,7 +349,8 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start, { char buf[BUFSIZ], *nl; time_t tstart, tend, tuntil; - struct recur_apoint *rapt; + struct recur_apoint *rapt = NULL; + int cond; EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || !check_date(end.tm_year, end.tm_mon, end.tm_mday) || @@ -393,32 +394,34 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start, /* Filter item. */ if (filter) { - if (!(filter->type_mask & TYPE_MASK_RECUR_APPT)) - return NULL; - if (filter->regex && regexec(filter->regex, buf, 0, 0, 0)) - return NULL; - if (filter->start_from != -1 && tstart < filter->start_from) - return NULL; - if (filter->start_to != -1 && tstart > filter->start_to) - return NULL; - if (filter->end_from != -1 && tend < filter->end_from) - return NULL; - if (filter->end_to != -1 && tend > filter->end_to) - return NULL; - } - - rapt = recur_apoint_new(buf, note, tstart, tend - tstart, state, - recur_char2def(type), freq, tuntil, exc); + cond = ( + !(filter->type_mask & TYPE_MASK_RECUR_APPT) || + (filter->regex && regexec(filter->regex, buf, 0, 0, 0)) || + (filter->start_from != -1 && tstart < filter->start_from) || + (filter->start_to != -1 && tstart > filter->start_to) || + (filter->end_from != -1 && tend < filter->end_from) || + (filter->end_to != -1 && tend > filter->end_to) + ); + if (filter->hash) { + rapt = recur_apoint_new(buf, note, tstart, + tend - tstart, state, + recur_char2def(type), + freq, tuntil, exc); + char *hash = recur_apoint_hash(rapt); + cond = cond || !hash_matches(filter->hash, hash); + mem_free(hash); + } - /* Filter by hash. */ - if (filter && filter->hash) { - char *hash = recur_apoint_hash(rapt); - if (!hash_matches(filter->hash, hash)) { - recur_apoint_erase(rapt); - rapt = NULL; + if ((!filter->invert && cond) || (filter->invert && !cond)) { + if (filter->hash) + recur_apoint_erase(rapt); + return NULL; } - mem_free(hash); } + if (!rapt) + rapt = recur_apoint_new(buf, note, tstart, tend - tstart, + state, recur_char2def(type), freq, + tuntil, exc); return rapt; } @@ -431,7 +434,8 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id, { char buf[BUFSIZ], *nl; time_t tstart, tend, tuntil; - struct recur_event *rev; + struct recur_event *rev = NULL; + int cond; EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || !check_time(start.tm_hour, start.tm_min) || @@ -466,32 +470,33 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id, /* Filter item. */ if (filter) { - if (!(filter->type_mask & TYPE_MASK_RECUR_EVNT)) - return NULL; - if (filter->regex && regexec(filter->regex, buf, 0, 0, 0)) - return NULL; - if (filter->start_from != -1 && tstart < filter->start_from) - return NULL; - if (filter->start_to != -1 && tstart > filter->start_to) - return NULL; - if (filter->end_from != -1 && tend < filter->end_from) - return NULL; - if (filter->end_to != -1 && tend > filter->end_to) - return NULL; - } - - rev = recur_event_new(buf, note, tstart, id, recur_char2def(type), - freq, tuntil, exc); + cond = ( + !(filter->type_mask & TYPE_MASK_RECUR_EVNT) || + (filter->regex && regexec(filter->regex, buf, 0, 0, 0)) || + (filter->start_from != -1 && tstart < filter->start_from) || + (filter->start_to != -1 && tstart > filter->start_to) || + (filter->end_from != -1 && tend < filter->end_from) || + (filter->end_to != -1 && tend > filter->end_to) + ); + if (filter->hash) { + rev = recur_event_new(buf, note, tstart, id, + recur_char2def(type), + freq, tuntil, exc); + char *hash = recur_event_hash(rev); + cond = cond || !hash_matches(filter->hash, hash); + mem_free(hash); + } - /* Filter by hash. */ - if (filter && filter->hash) { - char *hash = recur_event_hash(rev); - if (!hash_matches(filter->hash, hash)) { - recur_event_erase(rev); - rev = NULL; + if ((!filter->invert && cond) || (filter->invert && !cond)) { + if (filter->hash) + recur_event_erase(rev); + return NULL; } - mem_free(hash); } + if (!rev) + rev = recur_event_new(buf, note, tstart, id, + recur_char2def(type), + freq, tuntil, exc); return rev; } -- cgit v1.2.3-54-g00ecf