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 <filter options>" is the (set) complement of "calcurse -G <filter options> --filter-invert". Here <filter options> may be any combination of filter options. Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
parent
9300e9154c
commit
42abbf5346
48
src/apoint.c
48
src/apoint.c
@ -200,7 +200,8 @@ 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;
|
struct apoint *apt = NULL;
|
||||||
|
int cond;
|
||||||
|
|
||||||
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) ||
|
||||||
@ -230,31 +231,30 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
|
|||||||
|
|
||||||
/* Filter item. */
|
/* Filter item. */
|
||||||
if (filter) {
|
if (filter) {
|
||||||
if (!(filter->type_mask & TYPE_MASK_APPT))
|
cond = (
|
||||||
return NULL;
|
!(filter->type_mask & TYPE_MASK_APPT) ||
|
||||||
if (filter->regex && regexec(filter->regex, buf, 0, 0, 0))
|
(filter->regex && regexec(filter->regex, buf, 0, 0, 0)) ||
|
||||||
return NULL;
|
(filter->start_from != -1 && tstart < filter->start_from) ||
|
||||||
if (filter->start_from != -1 && tstart < filter->start_from)
|
(filter->start_to != -1 && tstart > filter->start_to) ||
|
||||||
return NULL;
|
(filter->end_from != -1 && tend < filter->end_from) ||
|
||||||
if (filter->start_to != -1 && tstart > filter->start_to)
|
(filter->end_to != -1 && tend > filter->end_to)
|
||||||
return NULL;
|
);
|
||||||
if (filter->end_from != -1 && tend < filter->end_from)
|
if (filter->hash) {
|
||||||
return NULL;
|
apt = apoint_new(
|
||||||
if (filter->end_to != -1 && tend > filter->end_to)
|
buf, note, tstart, tend - tstart, state);
|
||||||
return NULL;
|
char *hash = apoint_hash(apt);
|
||||||
}
|
cond = cond || !hash_matches(filter->hash, hash);
|
||||||
|
mem_free(hash);
|
||||||
apt = apoint_new(buf, note, tstart, tend - tstart, state);
|
}
|
||||||
|
|
||||||
/* Filter by hash. */
|
if ((!filter->invert && cond) || (filter->invert && !cond)) {
|
||||||
if (filter && filter->hash) {
|
if (filter->hash)
|
||||||
char *hash = apoint_hash(apt);
|
apoint_delete(apt);
|
||||||
if (!hash_matches(filter->hash, hash)) {
|
return NULL;
|
||||||
apoint_delete(apt);
|
|
||||||
apt = NULL;
|
|
||||||
}
|
}
|
||||||
mem_free(hash);
|
|
||||||
}
|
}
|
||||||
|
if (!apt)
|
||||||
|
apt = apoint_new(buf, note, tstart, tend - tstart, state);
|
||||||
|
|
||||||
return apt;
|
return apt;
|
||||||
}
|
}
|
||||||
|
10
src/args.c
10
src/args.c
@ -54,7 +54,8 @@ enum {
|
|||||||
|
|
||||||
/* Long options */
|
/* Long options */
|
||||||
enum {
|
enum {
|
||||||
OPT_FILTER_TYPE = 1000,
|
OPT_FILTER_INVERT = 1000,
|
||||||
|
OPT_FILTER_TYPE,
|
||||||
OPT_FILTER_HASH,
|
OPT_FILTER_HASH,
|
||||||
OPT_FILTER_PATTERN,
|
OPT_FILTER_PATTERN,
|
||||||
OPT_FILTER_START_FROM,
|
OPT_FILTER_START_FROM,
|
||||||
@ -410,7 +411,7 @@ int parse_args(int argc, char **argv)
|
|||||||
int range = 0;
|
int range = 0;
|
||||||
int limit = INT_MAX;
|
int limit = INT_MAX;
|
||||||
/* Filters */
|
/* 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 */
|
/* Format strings */
|
||||||
const char *fmt_apt = NULL;
|
const char *fmt_apt = NULL;
|
||||||
const char *fmt_rapt = NULL;
|
const char *fmt_rapt = NULL;
|
||||||
@ -457,6 +458,7 @@ int parse_args(int argc, char **argv)
|
|||||||
{"quiet", no_argument, NULL, 'q'},
|
{"quiet", no_argument, NULL, 'q'},
|
||||||
{"query", optional_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-type", required_argument, NULL, OPT_FILTER_TYPE},
|
||||||
{"filter-hash", required_argument, NULL, OPT_FILTER_HASH},
|
{"filter-hash", required_argument, NULL, OPT_FILTER_HASH},
|
||||||
{"filter-pattern", required_argument, NULL, OPT_FILTER_PATTERN},
|
{"filter-pattern", required_argument, NULL, OPT_FILTER_PATTERN},
|
||||||
@ -623,6 +625,10 @@ int parse_args(int argc, char **argv)
|
|||||||
case 'Q':
|
case 'Q':
|
||||||
query = 1;
|
query = 1;
|
||||||
break;
|
break;
|
||||||
|
case OPT_FILTER_INVERT:
|
||||||
|
filter.invert = !filter.invert;
|
||||||
|
filter_opt = 1;
|
||||||
|
break;
|
||||||
case OPT_FILTER_TYPE:
|
case OPT_FILTER_TYPE:
|
||||||
filter.type_mask = parse_type_mask(optarg);
|
filter.type_mask = parse_type_mask(optarg);
|
||||||
EXIT_IF(filter.type_mask == 0,
|
EXIT_IF(filter.type_mask == 0,
|
||||||
|
@ -427,6 +427,7 @@ enum item_type {
|
|||||||
|
|
||||||
/* Filter settings. */
|
/* Filter settings. */
|
||||||
struct item_filter {
|
struct item_filter {
|
||||||
|
int invert;
|
||||||
int type_mask;
|
int type_mask;
|
||||||
char *hash;
|
char *hash;
|
||||||
regex_t *regex;
|
regex_t *regex;
|
||||||
|
47
src/event.c
47
src/event.c
@ -152,7 +152,8 @@ 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;
|
struct event *ev = NULL;
|
||||||
|
int cond;
|
||||||
|
|
||||||
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),
|
||||||
@ -179,31 +180,29 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note,
|
|||||||
|
|
||||||
/* Filter item. */
|
/* Filter item. */
|
||||||
if (filter) {
|
if (filter) {
|
||||||
if (!(filter->type_mask & TYPE_MASK_EVNT))
|
cond = (
|
||||||
return NULL;
|
!(filter->type_mask & TYPE_MASK_EVNT) ||
|
||||||
if (filter->regex && regexec(filter->regex, buf, 0, 0, 0))
|
(filter->regex && regexec(filter->regex, buf, 0, 0, 0)) ||
|
||||||
return NULL;
|
(filter->start_from != -1 && tstart < filter->start_from) ||
|
||||||
if (filter->start_from != -1 && tstart < filter->start_from)
|
(filter->start_to != -1 && tstart > filter->start_to) ||
|
||||||
return NULL;
|
(filter->end_from != -1 && tend < filter->end_from) ||
|
||||||
if (filter->start_to != -1 && tstart > filter->start_to)
|
(filter->end_to != -1 && tend > filter->end_to)
|
||||||
return NULL;
|
);
|
||||||
if (filter->end_from != -1 && tend < filter->end_from)
|
if (filter->hash) {
|
||||||
return NULL;
|
ev = event_new(buf, note, tstart, id);
|
||||||
if (filter->end_to != -1 && tend > filter->end_to)
|
char *hash = event_hash(ev);
|
||||||
return NULL;
|
cond = cond || !hash_matches(filter->hash, hash);
|
||||||
}
|
mem_free(hash);
|
||||||
|
}
|
||||||
ev = event_new(buf, note, tstart, id);
|
|
||||||
|
if ((!filter->invert && cond) || (filter->invert && !cond)) {
|
||||||
/* Filter by hash. */
|
if (filter->hash)
|
||||||
if (filter && filter->hash) {
|
event_delete(ev);
|
||||||
char *hash = event_hash(ev);
|
return NULL;
|
||||||
if (!hash_matches(filter->hash, hash)) {
|
|
||||||
event_delete(ev);
|
|
||||||
ev = NULL;
|
|
||||||
}
|
}
|
||||||
mem_free(hash);
|
|
||||||
}
|
}
|
||||||
|
if (!ev)
|
||||||
|
ev = event_new(buf, note, tstart, id);
|
||||||
|
|
||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
|
48
src/io.c
48
src/io.c
@ -707,8 +707,7 @@ void io_load_todo(struct item_filter *filter)
|
|||||||
{
|
{
|
||||||
FILE *data_file;
|
FILE *data_file;
|
||||||
char *newline;
|
char *newline;
|
||||||
int nb_tod = 0;
|
int c, id, completed, cond;
|
||||||
int c, id, completed;
|
|
||||||
char buf[BUFSIZ], e_todo[BUFSIZ], note[MAX_NOTESIZ + 1];
|
char buf[BUFSIZ], e_todo[BUFSIZ], note[MAX_NOTESIZ + 1];
|
||||||
unsigned line = 0;
|
unsigned line = 0;
|
||||||
|
|
||||||
@ -760,34 +759,31 @@ void io_load_todo(struct item_filter *filter)
|
|||||||
io_extract_data(e_todo, buf, sizeof buf);
|
io_extract_data(e_todo, buf, sizeof buf);
|
||||||
|
|
||||||
/* Filter item. */
|
/* Filter item. */
|
||||||
|
struct todo *todo = NULL;
|
||||||
if (filter) {
|
if (filter) {
|
||||||
if (!(filter->type_mask & TYPE_MASK_TODO))
|
cond = (
|
||||||
continue;
|
!(filter->type_mask & TYPE_MASK_TODO) ||
|
||||||
if (filter->regex &&
|
(filter->regex && regexec(filter->regex, e_todo, 0, 0, 0)) ||
|
||||||
regexec(filter->regex, e_todo, 0, 0, 0))
|
(filter->priority && id != filter->priority) ||
|
||||||
continue;
|
(filter->completed && !completed) ||
|
||||||
if (filter->priority && id != filter->priority)
|
(filter->uncompleted && completed)
|
||||||
continue;
|
);
|
||||||
if (filter->completed && !completed)
|
if (filter->hash) {
|
||||||
continue;
|
todo = todo_add(e_todo, id, completed, note);
|
||||||
if (filter->uncompleted && completed)
|
char *hash = todo_hash(todo);
|
||||||
continue;
|
cond = cond || !hash_matches(filter->hash, hash);
|
||||||
}
|
mem_free(hash);
|
||||||
|
}
|
||||||
struct todo *todo = todo_add(e_todo, id, completed, note);
|
|
||||||
|
if ((!filter->invert && cond) || (filter->invert && !cond)) {
|
||||||
/* Filter by hash. */
|
if (filter->hash)
|
||||||
if (filter && filter->hash) {
|
todo_delete(todo);
|
||||||
char *hash = todo_hash(todo);
|
continue;
|
||||||
if (!hash_matches(filter->hash, hash)) {
|
|
||||||
todo_delete(todo);
|
|
||||||
todo = NULL;
|
|
||||||
}
|
}
|
||||||
mem_free(hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (todo)
|
if (!todo)
|
||||||
++nb_tod;
|
todo = todo_add(e_todo, id, completed, note);
|
||||||
}
|
}
|
||||||
file_close(data_file, __FILE_POS__);
|
file_close(data_file, __FILE_POS__);
|
||||||
}
|
}
|
||||||
|
105
src/recur.c
105
src/recur.c
@ -349,7 +349,8 @@ 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;
|
struct recur_apoint *rapt = NULL;
|
||||||
|
int cond;
|
||||||
|
|
||||||
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,32 +394,34 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
|
|||||||
|
|
||||||
/* Filter item. */
|
/* Filter item. */
|
||||||
if (filter) {
|
if (filter) {
|
||||||
if (!(filter->type_mask & TYPE_MASK_RECUR_APPT))
|
cond = (
|
||||||
return NULL;
|
!(filter->type_mask & TYPE_MASK_RECUR_APPT) ||
|
||||||
if (filter->regex && regexec(filter->regex, buf, 0, 0, 0))
|
(filter->regex && regexec(filter->regex, buf, 0, 0, 0)) ||
|
||||||
return NULL;
|
(filter->start_from != -1 && tstart < filter->start_from) ||
|
||||||
if (filter->start_from != -1 && tstart < filter->start_from)
|
(filter->start_to != -1 && tstart > filter->start_to) ||
|
||||||
return NULL;
|
(filter->end_from != -1 && tend < filter->end_from) ||
|
||||||
if (filter->start_to != -1 && tstart > filter->start_to)
|
(filter->end_to != -1 && tend > filter->end_to)
|
||||||
return NULL;
|
);
|
||||||
if (filter->end_from != -1 && tend < filter->end_from)
|
if (filter->hash) {
|
||||||
return NULL;
|
rapt = recur_apoint_new(buf, note, tstart,
|
||||||
if (filter->end_to != -1 && tend > filter->end_to)
|
tend - tstart, state,
|
||||||
return NULL;
|
recur_char2def(type),
|
||||||
}
|
freq, tuntil, exc);
|
||||||
|
char *hash = recur_apoint_hash(rapt);
|
||||||
rapt = recur_apoint_new(buf, note, tstart, tend - tstart, state,
|
cond = cond || !hash_matches(filter->hash, hash);
|
||||||
recur_char2def(type), freq, tuntil, exc);
|
mem_free(hash);
|
||||||
|
}
|
||||||
/* Filter by hash. */
|
|
||||||
if (filter && filter->hash) {
|
if ((!filter->invert && cond) || (filter->invert && !cond)) {
|
||||||
char *hash = recur_apoint_hash(rapt);
|
if (filter->hash)
|
||||||
if (!hash_matches(filter->hash, hash)) {
|
recur_apoint_erase(rapt);
|
||||||
recur_apoint_erase(rapt);
|
return NULL;
|
||||||
rapt = NULL;
|
|
||||||
}
|
}
|
||||||
mem_free(hash);
|
|
||||||
}
|
}
|
||||||
|
if (!rapt)
|
||||||
|
rapt = recur_apoint_new(buf, note, tstart, tend - tstart,
|
||||||
|
state, recur_char2def(type), freq,
|
||||||
|
tuntil, exc);
|
||||||
|
|
||||||
return rapt;
|
return rapt;
|
||||||
}
|
}
|
||||||
@ -431,7 +434,8 @@ 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;
|
struct recur_event *rev = NULL;
|
||||||
|
int cond;
|
||||||
|
|
||||||
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) ||
|
||||||
@ -466,32 +470,33 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
|
|||||||
|
|
||||||
/* Filter item. */
|
/* Filter item. */
|
||||||
if (filter) {
|
if (filter) {
|
||||||
if (!(filter->type_mask & TYPE_MASK_RECUR_EVNT))
|
cond = (
|
||||||
return NULL;
|
!(filter->type_mask & TYPE_MASK_RECUR_EVNT) ||
|
||||||
if (filter->regex && regexec(filter->regex, buf, 0, 0, 0))
|
(filter->regex && regexec(filter->regex, buf, 0, 0, 0)) ||
|
||||||
return NULL;
|
(filter->start_from != -1 && tstart < filter->start_from) ||
|
||||||
if (filter->start_from != -1 && tstart < filter->start_from)
|
(filter->start_to != -1 && tstart > filter->start_to) ||
|
||||||
return NULL;
|
(filter->end_from != -1 && tend < filter->end_from) ||
|
||||||
if (filter->start_to != -1 && tstart > filter->start_to)
|
(filter->end_to != -1 && tend > filter->end_to)
|
||||||
return NULL;
|
);
|
||||||
if (filter->end_from != -1 && tend < filter->end_from)
|
if (filter->hash) {
|
||||||
return NULL;
|
rev = recur_event_new(buf, note, tstart, id,
|
||||||
if (filter->end_to != -1 && tend > filter->end_to)
|
recur_char2def(type),
|
||||||
return NULL;
|
freq, tuntil, exc);
|
||||||
}
|
char *hash = recur_event_hash(rev);
|
||||||
|
cond = cond || !hash_matches(filter->hash, hash);
|
||||||
rev = recur_event_new(buf, note, tstart, id, recur_char2def(type),
|
mem_free(hash);
|
||||||
freq, tuntil, exc);
|
}
|
||||||
|
|
||||||
/* Filter by hash. */
|
if ((!filter->invert && cond) || (filter->invert && !cond)) {
|
||||||
if (filter && filter->hash) {
|
if (filter->hash)
|
||||||
char *hash = recur_event_hash(rev);
|
recur_event_erase(rev);
|
||||||
if (!hash_matches(filter->hash, hash)) {
|
return NULL;
|
||||||
recur_event_erase(rev);
|
|
||||||
rev = NULL;
|
|
||||||
}
|
}
|
||||||
mem_free(hash);
|
|
||||||
}
|
}
|
||||||
|
if (!rev)
|
||||||
|
rev = recur_event_new(buf, note, tstart, id,
|
||||||
|
recur_char2def(type),
|
||||||
|
freq, tuntil, exc);
|
||||||
|
|
||||||
return rev;
|
return rev;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user