From 7f8c62bf57b85234c248316505a503602792839a Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Mon, 11 Jan 2016 22:26:46 +0100 Subject: Add an option to filter by object hash Implement a new --filter-hash option to filter by object identifiers. Each object having an identifier that has the specified pattern as a prefix is matched. Patterns starting with an exclamation mark (!) are interpreted as negative patterns. Signed-off-by: Lukas Fleischer --- src/apoint.c | 15 ++++++++++++++- src/args.c | 7 ++++++- src/calcurse.h | 2 ++ src/event.c | 15 ++++++++++++++- src/io.c | 16 ++++++++++++++-- src/recur.c | 32 +++++++++++++++++++++++++++++--- src/utils.c | 12 ++++++++++++ 7 files changed, 91 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/apoint.c b/src/apoint.c index 23c3163..457317d 100644 --- a/src/apoint.c +++ b/src/apoint.c @@ -190,6 +190,7 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end, { char buf[BUFSIZ], *newline; time_t tstart, tend; + struct apoint *apt; EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || !check_date(end.tm_year, end.tm_mon, end.tm_mday) || @@ -233,7 +234,19 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end, return NULL; } - return apoint_new(buf, note, tstart, tend - tstart, state); + apt = apoint_new(buf, note, tstart, tend - tstart, state); + + /* Filter by hash. */ + if (filter && filter->hash) { + char *hash = apoint_hash(apt); + if (!hash_matches(filter->hash, hash)) { + apoint_delete(apt); + apt = NULL; + } + mem_free(hash); + } + + return apt; } void apoint_delete(struct apoint *apt) diff --git a/src/args.c b/src/args.c index 60e8043..c843d69 100644 --- a/src/args.c +++ b/src/args.c @@ -47,6 +47,7 @@ /* Long options */ enum { OPT_FILTER_TYPE = 1000, + OPT_FILTER_HASH, OPT_FILTER_PATTERN, OPT_FILTER_START_FROM, OPT_FILTER_START_TO, @@ -442,7 +443,7 @@ int parse_args(int argc, char **argv) int range = -1; int limit = INT_MAX; /* Filters */ - struct item_filter filter = { 0, NULL, -1, -1, -1, -1, 0, 0, 0 }; + struct item_filter filter = { 0, NULL, NULL, -1, -1, -1, -1, 0, 0, 0 }; /* Format strings */ const char *fmt_apt = " - %S -> %E\n\t%m\n"; const char *fmt_rapt = " - %S -> %E\n\t%m\n"; @@ -481,6 +482,7 @@ int parse_args(int argc, char **argv) {"query", optional_argument, NULL, 'Q'}, {"filter-type", required_argument, NULL, OPT_FILTER_TYPE}, + {"filter-hash", required_argument, NULL, OPT_FILTER_HASH}, {"filter-pattern", required_argument, NULL, OPT_FILTER_PATTERN}, {"filter-start-from", required_argument, NULL, OPT_FILTER_START_FROM}, {"filter-start-to", required_argument, NULL, OPT_FILTER_START_TO}, @@ -604,6 +606,9 @@ int parse_args(int argc, char **argv) EXIT_IF(filter.type_mask == 0, _("invalid filter mask")); break; + case OPT_FILTER_HASH: + filter.hash = mem_strdup(optarg); + break; case 'S': case OPT_FILTER_PATTERN: EXIT_IF(filter.regex, diff --git a/src/calcurse.h b/src/calcurse.h index 5724265..41f7681 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -407,6 +407,7 @@ enum item_type { /* Filter settings. */ struct item_filter { int type_mask; + char *hash; regex_t *regex; time_t start_from; time_t start_to; @@ -1120,6 +1121,7 @@ int vasprintf(char **, const char *, va_list); int asprintf(char **, const char *, ...); int starts_with(const char *, const char *); int starts_with_ci(const char *, const char *); +int hash_matches(const char *, const char *); /* vars.c */ extern int col, row; diff --git a/src/event.c b/src/event.c index 1e9d940..e0891a2 100644 --- a/src/event.c +++ b/src/event.c @@ -147,6 +147,7 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note, { char buf[BUFSIZ], *nl; time_t tstart, tend; + struct event *ev; EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || !check_time(start.tm_hour, start.tm_min), @@ -187,7 +188,19 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note, return NULL; } - return event_new(buf, note, tstart, id); + ev = event_new(buf, note, tstart, id); + + /* Filter by hash. */ + if (filter && filter->hash) { + char *hash = event_hash(ev); + if (!hash_matches(filter->hash, hash)) { + event_delete(ev); + ev = NULL; + } + mem_free(hash); + } + + return ev; } /* Delete an event from the list. */ diff --git a/src/io.c b/src/io.c index fcb13ae..d25180a 100644 --- a/src/io.c +++ b/src/io.c @@ -684,8 +684,20 @@ void io_load_todo(struct item_filter *filter) continue; } - todo_add(e_todo, id, note); - ++nb_tod; + struct todo *todo = todo_add(e_todo, id, note); + + /* Filter by hash. */ + if (filter && filter->hash) { + char *hash = todo_hash(todo); + if (!hash_matches(filter->hash, hash)) { + todo_delete(todo); + todo = NULL; + } + mem_free(hash); + } + + if (todo) + ++nb_tod; } file_close(data_file, __FILE_POS__); } diff --git a/src/recur.c b/src/recur.c index ddfddb4..921b5c9 100644 --- a/src/recur.c +++ b/src/recur.c @@ -336,6 +336,7 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start, { char buf[BUFSIZ], *nl; time_t tstart, tend, tuntil; + struct recur_apoint *rapt; 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,8 +394,20 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start, return NULL; } - return recur_apoint_new(buf, note, tstart, tend - tstart, state, + rapt = recur_apoint_new(buf, note, tstart, tend - tstart, state, recur_char2def(type), freq, tuntil, exc); + + /* 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; + } + mem_free(hash); + } + + return rapt; } /* Load the recursive events from file */ @@ -405,6 +418,7 @@ 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; EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || !check_time(start.tm_hour, start.tm_min) || @@ -453,8 +467,20 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id, return NULL; } - return recur_event_new(buf, note, tstart, id, recur_char2def(type), - freq, tuntil, exc); + rev = recur_event_new(buf, note, tstart, id, recur_char2def(type), + freq, tuntil, exc); + + /* 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; + } + mem_free(hash); + } + + return rev; } char *recur_apoint_tostr(struct recur_apoint *o) diff --git a/src/utils.c b/src/utils.c index 58b1d44..528657e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1641,3 +1641,15 @@ int starts_with_ci(const char *s, const char *p) for (; *p && tolower(*p) == tolower(*s); s++, p++); return (*p == '\0'); } + +int hash_matches(const char *pattern, const char *hash) +{ + int invert = 0; + + if (pattern[0] == '!') { + invert = 1; + pattern++; + } + + return (starts_with(hash, pattern) != invert); +} -- cgit v1.2.3-54-g00ecf