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 <lfleischer@calcurse.org>
This commit is contained in:
Lukas Fleischer 2016-01-11 22:26:46 +01:00
parent dd85a73746
commit 7f8c62bf57
7 changed files with 91 additions and 8 deletions

View File

@ -190,6 +190,7 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
{ {
char buf[BUFSIZ], *newline; char buf[BUFSIZ], *newline;
time_t tstart, tend; time_t tstart, tend;
struct apoint *apt;
EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
!check_date(end.tm_year, end.tm_mon, end.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 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) void apoint_delete(struct apoint *apt)

View File

@ -47,6 +47,7 @@
/* Long options */ /* Long options */
enum { enum {
OPT_FILTER_TYPE = 1000, OPT_FILTER_TYPE = 1000,
OPT_FILTER_HASH,
OPT_FILTER_PATTERN, OPT_FILTER_PATTERN,
OPT_FILTER_START_FROM, OPT_FILTER_START_FROM,
OPT_FILTER_START_TO, OPT_FILTER_START_TO,
@ -442,7 +443,7 @@ int parse_args(int argc, char **argv)
int range = -1; int range = -1;
int limit = INT_MAX; int limit = INT_MAX;
/* Filters */ /* 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 */ /* Format strings */
const char *fmt_apt = " - %S -> %E\n\t%m\n"; const char *fmt_apt = " - %S -> %E\n\t%m\n";
const char *fmt_rapt = " - %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'}, {"query", optional_argument, NULL, 'Q'},
{"filter-type", required_argument, NULL, OPT_FILTER_TYPE}, {"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-pattern", required_argument, NULL, OPT_FILTER_PATTERN},
{"filter-start-from", required_argument, NULL, OPT_FILTER_START_FROM}, {"filter-start-from", required_argument, NULL, OPT_FILTER_START_FROM},
{"filter-start-to", required_argument, NULL, OPT_FILTER_START_TO}, {"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, EXIT_IF(filter.type_mask == 0,
_("invalid filter mask")); _("invalid filter mask"));
break; break;
case OPT_FILTER_HASH:
filter.hash = mem_strdup(optarg);
break;
case 'S': case 'S':
case OPT_FILTER_PATTERN: case OPT_FILTER_PATTERN:
EXIT_IF(filter.regex, EXIT_IF(filter.regex,

View File

@ -407,6 +407,7 @@ enum item_type {
/* Filter settings. */ /* Filter settings. */
struct item_filter { struct item_filter {
int type_mask; int type_mask;
char *hash;
regex_t *regex; regex_t *regex;
time_t start_from; time_t start_from;
time_t start_to; time_t start_to;
@ -1120,6 +1121,7 @@ int vasprintf(char **, const char *, va_list);
int asprintf(char **, const char *, ...); int asprintf(char **, const char *, ...);
int starts_with(const char *, const char *); int starts_with(const char *, const char *);
int starts_with_ci(const char *, const char *); int starts_with_ci(const char *, const char *);
int hash_matches(const char *, const char *);
/* vars.c */ /* vars.c */
extern int col, row; extern int col, row;

View File

@ -147,6 +147,7 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note,
{ {
char buf[BUFSIZ], *nl; char buf[BUFSIZ], *nl;
time_t tstart, tend; time_t tstart, tend;
struct event *ev;
EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
!check_time(start.tm_hour, start.tm_min), !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 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. */ /* Delete an event from the list. */

View File

@ -684,8 +684,20 @@ void io_load_todo(struct item_filter *filter)
continue; continue;
} }
todo_add(e_todo, id, note); struct todo *todo = todo_add(e_todo, id, note);
++nb_tod;
/* 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__); file_close(data_file, __FILE_POS__);
} }

View File

@ -336,6 +336,7 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
{ {
char buf[BUFSIZ], *nl; char buf[BUFSIZ], *nl;
time_t tstart, tend, tuntil; time_t tstart, tend, tuntil;
struct recur_apoint *rapt;
EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
!check_date(end.tm_year, end.tm_mon, end.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 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); 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 */ /* 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; char buf[BUFSIZ], *nl;
time_t tstart, tend, tuntil; time_t tstart, tend, tuntil;
struct recur_event *rev;
EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) || EXIT_IF(!check_date(start.tm_year, start.tm_mon, start.tm_mday) ||
!check_time(start.tm_hour, start.tm_min) || !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 NULL;
} }
return recur_event_new(buf, note, tstart, id, recur_char2def(type), rev = recur_event_new(buf, note, tstart, id, recur_char2def(type),
freq, tuntil, exc); 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) char *recur_apoint_tostr(struct recur_apoint *o)

View File

@ -1641,3 +1641,15 @@ int starts_with_ci(const char *s, const char *p)
for (; *p && tolower(*p) == tolower(*s); s++, p++); for (; *p && tolower(*p) == tolower(*s); s++, p++);
return (*p == '\0'); 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);
}