Add item filters

This adds the following filter options that allow for restricting the
set of items that are read from the appointments file:

* --filter-type
* --filter-start-from
* --filter-start-to
* --filter-start-after
* --filter-start-before
* --filter-end-from
* --filter-end-to
* --filter-end-after
* --filter-end-before

Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
This commit is contained in:
Lukas Fleischer 2014-08-06 08:53:51 +02:00
parent 4ec7fe1239
commit bfe73d0e5d
8 changed files with 207 additions and 24 deletions

View File

@ -163,7 +163,7 @@ void apoint_write(struct apoint *o, FILE * f)
} }
struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end, struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
char state, char *note) char state, char *note, struct item_filter *filter)
{ {
char buf[BUFSIZ], *newline; char buf[BUFSIZ], *newline;
time_t tstart, tend; time_t tstart, tend;
@ -193,6 +193,21 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
tend = mktime(&end); tend = mktime(&end);
EXIT_IF(tstart == -1 || tend == -1 || tstart > tend, EXIT_IF(tstart == -1 || tend == -1 || tstart > tend,
_("date error in appointment")); _("date error in appointment"));
/* Filter item. */
if (filter) {
if (!(filter->type_mask & TYPE_MASK_APPT))
return NULL;
if (filter->start_from >= 0 && tstart < filter->start_from)
return NULL;
if (filter->start_to >= 0 && tstart > filter->start_to)
return NULL;
if (filter->end_from >= 0 && tend < filter->end_from)
return NULL;
if (filter->end_to >= 0 && tend > filter->end_to)
return NULL;
}
return apoint_new(buf, note, tstart, tend - tstart, state); return apoint_new(buf, note, tstart, tend - tstart, state);
} }

View File

@ -46,7 +46,16 @@
/* Long options */ /* Long options */
enum { enum {
OPT_FMT_APT = 1000, OPT_FILTER_TYPE = 1000,
OPT_FILTER_START_FROM,
OPT_FILTER_START_TO,
OPT_FILTER_START_AFTER,
OPT_FILTER_START_BEFORE,
OPT_FILTER_END_FROM,
OPT_FILTER_END_TO,
OPT_FILTER_END_AFTER,
OPT_FILTER_END_BEFORE,
OPT_FMT_APT,
OPT_FMT_RAPT, OPT_FMT_RAPT,
OPT_FMT_EV, OPT_FMT_EV,
OPT_FMT_REV, OPT_FMT_REV,
@ -448,6 +457,52 @@ date_arg_extended(const char *startday, const char *range, int add_line,
} }
} }
static int parse_datearg(const char *str)
{
struct date day;
if (parse_date(str, DATEFMT_YYYYMMDD, (int *)&day.yyyy,
(int *)&day.mm, (int *)&day.dd, NULL))
return date2sec(day, 0, 0);
if (parse_date(str, DATEFMT_MMDDYYYY, (int *)&day.yyyy,
(int *)&day.mm, (int *)&day.dd, NULL))
return date2sec(day, 0, 0);
if (parse_date(str, DATEFMT_ISO, (int *)&day.yyyy,
(int *)&day.mm, (int *)&day.dd, NULL))
return date2sec(day, 0, 0);
return -1;
}
static int parse_type_mask(const char *str)
{
char *buf = mem_strdup(str), *p;
int mask = 0;
for (p = strtok(buf, ","); p; p = strtok(NULL, ",")) {
if (!strcmp(p, "event")) {
mask |= TYPE_MASK_EVNT;
} else if (!strcmp(p, "apt")) {
mask |= TYPE_MASK_APPT;
} else if (!strcmp(p, "recur-event")) {
mask |= TYPE_MASK_RECUR_EVNT;
} else if (!strcmp(p, "recur-apt")) {
mask |= TYPE_MASK_RECUR_APPT;
} else if (!strcmp(p, "recur")) {
mask |= TYPE_MASK_RECUR;
} else {
mask = 0;
goto cleanup;
}
}
cleanup:
mem_free(buf);
return mask;
}
/* /*
* Parse the command-line arguments and call the appropriate * Parse the command-line arguments and call the appropriate
* routines to handle those arguments. Also initialize the data paths. * routines to handle those arguments. Also initialize the data paths.
@ -469,6 +524,8 @@ int parse_args(int argc, char **argv)
int tflag = 0; /* -t: print todo list */ int tflag = 0; /* -t: print todo list */
int vflag = 0; /* -v: print version number */ int vflag = 0; /* -v: print version number */
int xflag = 0; /* -x: export data */ int xflag = 0; /* -x: export data */
/* Filters */
struct item_filter filter = { TYPE_MASK_ALL, -1, -1, -1, -1 };
/* 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";
@ -511,6 +568,15 @@ int parse_args(int argc, char **argv)
{"version", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'v'},
{"export", optional_argument, NULL, 'x'}, {"export", optional_argument, NULL, 'x'},
{"filter-type", required_argument, NULL, OPT_FILTER_TYPE},
{"filter-start-from", required_argument, NULL, OPT_FILTER_START_FROM},
{"filter-start-to", required_argument, NULL, OPT_FILTER_START_TO},
{"filter-start-after", required_argument, NULL, OPT_FILTER_START_AFTER},
{"filter-start-before", required_argument, NULL, OPT_FILTER_START_BEFORE},
{"filter-end-from", required_argument, NULL, OPT_FILTER_END_FROM},
{"filter-end-to", required_argument, NULL, OPT_FILTER_END_TO},
{"filter-end-after", required_argument, NULL, OPT_FILTER_END_AFTER},
{"filter-end-before", required_argument, NULL, OPT_FILTER_END_BEFORE},
{"format-apt", required_argument, NULL, OPT_FMT_APT}, {"format-apt", required_argument, NULL, OPT_FMT_APT},
{"format-recur-apt", required_argument, NULL, OPT_FMT_RAPT}, {"format-recur-apt", required_argument, NULL, OPT_FMT_RAPT},
{"format-event", required_argument, NULL, OPT_FMT_EV}, {"format-event", required_argument, NULL, OPT_FMT_EV},
@ -625,6 +691,51 @@ int parse_args(int argc, char **argv)
xfmt = IO_EXPORT_ICAL; xfmt = IO_EXPORT_ICAL;
} }
break; break;
case OPT_FILTER_TYPE:
filter.type_mask = parse_type_mask(optarg);
EXIT_IF(filter.type_mask == 0,
_("invalid filter mask"));
break;
case OPT_FILTER_START_FROM:
filter.start_from = parse_datearg(optarg);
EXIT_IF(filter.start_from == -1,
_("invalid filter start date"));
break;
case OPT_FILTER_START_TO:
filter.start_to = parse_datearg(optarg);
EXIT_IF(filter.start_to == -1,
_("invalid filter end date"));
break;
case OPT_FILTER_START_AFTER:
filter.start_from = parse_datearg(optarg) + 1;
EXIT_IF(filter.start_from == -1,
_("invalid filter start date"));
break;
case OPT_FILTER_START_BEFORE:
filter.start_to = parse_datearg(optarg) - 1;
EXIT_IF(filter.start_to == -1,
_("invalid filter end date"));
break;
case OPT_FILTER_END_FROM:
filter.end_from = parse_datearg(optarg);
EXIT_IF(filter.end_from == -1,
_("invalid filter start date"));
break;
case OPT_FILTER_END_TO:
filter.end_to = parse_datearg(optarg);
EXIT_IF(filter.end_to == -1,
_("invalid filter end date"));
break;
case OPT_FILTER_END_AFTER:
filter.end_from = parse_datearg(optarg) + 1;
EXIT_IF(filter.end_from == -1,
_("invalid filter start date"));
break;
case OPT_FILTER_END_BEFORE:
filter.end_to = parse_datearg(optarg) - 1;
EXIT_IF(filter.end_to == -1,
_("invalid filter end date"));
break;
case OPT_FMT_APT: case OPT_FMT_APT:
fmt_apt = optarg; fmt_apt = optarg;
break; break;
@ -689,7 +800,7 @@ int parse_args(int argc, char **argv)
io_check_dir(path_notes); io_check_dir(path_notes);
io_check_file(path_apts); io_check_file(path_apts);
io_check_file(path_todo); io_check_file(path_todo);
io_load_app(); io_load_app(&filter);
io_load_todo(); io_load_todo();
note_gc(); note_gc();
non_interactive = 1; non_interactive = 1;
@ -704,7 +815,7 @@ int parse_args(int argc, char **argv)
io_check_file(path_todo); io_check_file(path_todo);
/* Get default pager in case we need to show a log file. */ /* Get default pager in case we need to show a log file. */
vars_init(); vars_init();
io_load_app(); io_load_app(&filter);
io_load_todo(); io_load_todo();
io_import_data(IO_IMPORT_ICAL, ifile); io_import_data(IO_IMPORT_ICAL, ifile);
io_save_apts(path_apts); io_save_apts(path_apts);
@ -714,7 +825,7 @@ int parse_args(int argc, char **argv)
if (xflag) { if (xflag) {
io_check_file(path_apts); io_check_file(path_apts);
io_check_file(path_todo); io_check_file(path_todo);
io_load_app(); io_load_app(&filter);
io_load_todo(); io_load_todo();
io_export_data(xfmt); io_export_data(xfmt);
non_interactive = 1; non_interactive = 1;
@ -728,14 +839,14 @@ int parse_args(int argc, char **argv)
} }
if (nflag) { if (nflag) {
io_check_file(path_apts); io_check_file(path_apts);
io_load_app(); io_load_app(&filter);
next_arg(); next_arg();
non_interactive = 1; non_interactive = 1;
} }
if (dflag || rflag || sflag) { if (dflag || rflag || sflag) {
io_check_file(path_apts); io_check_file(path_apts);
io_check_file(path_conf); io_check_file(path_conf);
io_load_app(); io_load_app(&filter);
config_load(); /* To get output date format. */ config_load(); /* To get output date format. */
if (dflag) if (dflag)
date_arg(ddate, add_line, fmt_apt, date_arg(ddate, add_line, fmt_apt,
@ -756,7 +867,7 @@ int parse_args(int argc, char **argv)
io_check_file(path_conf); io_check_file(path_conf);
vars_init(); vars_init();
config_load(); /* To get output date format. */ config_load(); /* To get output date format. */
io_load_app(); io_load_app(&filter);
day.dd = day.mm = day.yyyy = 0; day.dd = day.mm = day.yyyy = 0;
app_arg(add_line, &day, 0, fmt_apt, fmt_rapt, app_arg(add_line, &day, 0, fmt_apt, fmt_rapt,
fmt_ev, fmt_rev, preg, &limit); fmt_ev, fmt_rev, preg, &limit);

View File

@ -333,7 +333,7 @@ static inline void key_generic_reload(void)
todo_init_list(); todo_init_list();
io_load_todo(); io_load_todo();
io_load_app(); io_load_app(NULL);
io_unset_modified(); io_unset_modified();
ui_todo_load_items(); ui_todo_load_items();
ui_todo_sel_reset(); ui_todo_sel_reset();
@ -684,7 +684,7 @@ int main(int argc, char **argv)
wins_erase_status_bar(); wins_erase_status_bar();
io_load_keys(conf.pager); io_load_keys(conf.pager);
io_load_todo(); io_load_todo();
io_load_app(); io_load_app(NULL);
io_unset_modified(); io_unset_modified();
wins_slctd_set(conf.default_panel); wins_slctd_set(conf.default_panel);
wins_resize(); wins_resize();

View File

@ -383,6 +383,23 @@ enum day_item_type {
APPT APPT
}; };
/* Available item type masks. */
#define TYPE_MASK_EVNT (1 << EVNT)
#define TYPE_MASK_APPT (1 << APPT)
#define TYPE_MASK_RECUR_EVNT (1 << RECUR_EVNT)
#define TYPE_MASK_RECUR_APPT (1 << RECUR_APPT)
#define TYPE_MASK_RECUR (TYPE_MASK_RECUR_EVNT | TYPE_MASK_RECUR_APPT)
#define TYPE_MASK_ALL (TYPE_MASK_EVNT | TYPE_MASK_APPT | TYPE_MASK_RECUR)
/* Filter settings. */
struct item_filter {
int type_mask;
long start_from;
long start_to;
long end_from;
long end_to;
};
/* Generic item description (to hold appointments, events...). */ /* Generic item description (to hold appointments, events...). */
struct day_item { struct day_item {
enum day_item_type type; enum day_item_type type;
@ -643,7 +660,8 @@ struct apoint *apoint_new(char *, char *, long, long, char);
unsigned apoint_inday(struct apoint *, long *); unsigned apoint_inday(struct apoint *, long *);
void apoint_sec2str(struct apoint *, long, char *, char *); void apoint_sec2str(struct apoint *, long, char *, char *);
void apoint_write(struct apoint *, FILE *); void apoint_write(struct apoint *, FILE *);
struct apoint *apoint_scan(FILE *, struct tm, struct tm, char, char *); struct apoint *apoint_scan(FILE *, struct tm, struct tm, char, char *,
struct item_filter *);
void apoint_delete(struct apoint *); void apoint_delete(struct apoint *);
struct notify_app *apoint_check_next(struct notify_app *, long); struct notify_app *apoint_check_next(struct notify_app *, long);
void apoint_switch_notify(struct apoint *); void apoint_switch_notify(struct apoint *);
@ -735,7 +753,7 @@ void event_llist_free(void);
struct event *event_new(char *, char *, long, int); struct event *event_new(char *, char *, long, int);
unsigned event_inday(struct event *, long *); unsigned event_inday(struct event *, long *);
void event_write(struct event *, FILE *); void event_write(struct event *, FILE *);
struct event *event_scan(FILE *, struct tm, int, char *); struct event *event_scan(FILE *, struct tm, int, char *, struct item_filter *);
void event_delete(struct event *); void event_delete(struct event *);
void event_paste_item(struct event *, long); void event_paste_item(struct event *, long);
@ -761,7 +779,7 @@ unsigned io_save_apts(const char *);
unsigned io_save_todo(const char *); unsigned io_save_todo(const char *);
unsigned io_save_keys(void); unsigned io_save_keys(void);
void io_save_cal(enum save_display); void io_save_cal(enum save_display);
void io_load_app(void); void io_load_app(struct item_filter *);
void io_load_todo(void); void io_load_todo(void);
void io_load_keys(const char *); void io_load_keys(const char *);
int io_check_dir(const char *); int io_check_dir(const char *);
@ -911,9 +929,10 @@ char recur_def2char(enum recur_type);
int recur_char2def(char); int recur_char2def(char);
struct recur_apoint *recur_apoint_scan(FILE *, struct tm, struct tm, struct recur_apoint *recur_apoint_scan(FILE *, struct tm, struct tm,
char, int, struct tm, char *, char, int, struct tm, char *,
llist_t *, char); llist_t *, char, struct item_filter *);
struct recur_event *recur_event_scan(FILE *, struct tm, int, char, struct recur_event *recur_event_scan(FILE *, struct tm, int, char,
int, struct tm, char *, llist_t *); int, struct tm, char *, llist_t *,
struct item_filter *);
void recur_apoint_write(struct recur_apoint *, FILE *); void recur_apoint_write(struct recur_apoint *, FILE *);
void recur_event_write(struct recur_event *, FILE *); void recur_event_write(struct recur_event *, FILE *);
void recur_save_data(FILE *); void recur_save_data(FILE *);

View File

@ -165,7 +165,7 @@ void dmon_start(int parent_exit_status)
event_llist_init(); event_llist_init();
recur_event_llist_init(); recur_event_llist_init();
todo_init_list(); todo_init_list();
io_load_app(); io_load_app(NULL);
data_loaded = 1; data_loaded = 1;
DMON_LOG(_("started at %s\n"), nowstr()); DMON_LOG(_("started at %s\n"), nowstr());

View File

@ -120,7 +120,8 @@ void event_write(struct event *o, FILE * f)
} }
/* Load the events from file */ /* Load the events from file */
struct event *event_scan(FILE * f, struct tm start, int id, char *note) struct event *event_scan(FILE * f, struct tm start, int id, char *note,
struct item_filter *filter)
{ {
char buf[BUFSIZ], *nl; char buf[BUFSIZ], *nl;
time_t tstart; time_t tstart;
@ -147,6 +148,16 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note)
tstart = mktime(&start); tstart = mktime(&start);
EXIT_IF(tstart == -1, _("date error in the event\n")); EXIT_IF(tstart == -1, _("date error in the event\n"));
/* Filter item. */
if (filter) {
if (!(filter->type_mask & TYPE_MASK_EVNT))
return NULL;
if (filter->start_from >= 0 && tstart < filter->start_from)
return NULL;
if (filter->start_to >= 0 && tstart > filter->start_to)
return NULL;
}
return event_new(buf, note, tstart, id); return event_new(buf, note, tstart, id);
} }

View File

@ -464,7 +464,7 @@ static void io_load_error(const char *filename, unsigned line,
* and then load either: a new appointment, a new event, or a new * and then load either: a new appointment, a new event, or a new
* recursive item (which can also be either an event or an appointment). * recursive item (which can also be either an event or an appointment).
*/ */
void io_load_app(void) void io_load_app(struct item_filter *filter)
{ {
FILE *data_file; FILE *data_file;
int c, is_appointment, is_event, is_recursive; int c, is_appointment, is_event, is_recursive;
@ -620,18 +620,19 @@ void io_load_app(void)
if (is_recursive) { if (is_recursive) {
recur_apoint_scan(data_file, start, end, recur_apoint_scan(data_file, start, end,
type, freq, until, notep, type, freq, until, notep,
&exc, state); &exc, state, filter);
} else { } else {
apoint_scan(data_file, start, end, state, apoint_scan(data_file, start, end, state,
notep); notep, filter);
} }
} else if (is_event) { } else if (is_event) {
if (is_recursive) { if (is_recursive) {
recur_event_scan(data_file, start, id, recur_event_scan(data_file, start, id,
type, freq, until, notep, type, freq, until, notep,
&exc); &exc, filter);
} else { } else {
event_scan(data_file, start, id, notep); event_scan(data_file, start, id, notep,
filter);
} }
} else { } else {
io_load_error(path_apts, line, io_load_error(path_apts, line,

View File

@ -330,7 +330,8 @@ static void recur_write_exc(llist_t * lexc, FILE * f)
struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start, struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
struct tm end, char type, int freq, struct tm end, char type, int freq,
struct tm until, char *note, struct tm until, char *note,
llist_t * exc, char state) llist_t * exc, char state,
struct item_filter *filter)
{ {
char buf[BUFSIZ], *nl; char buf[BUFSIZ], *nl;
time_t tstart, tend, tuntil; time_t tstart, tend, tuntil;
@ -375,6 +376,20 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
EXIT_IF(tstart == -1 || tend == -1 || tstart > tend EXIT_IF(tstart == -1 || tend == -1 || tstart > tend
|| tuntil == -1, _("date error in appointment")); || tuntil == -1, _("date error in appointment"));
/* Filter item. */
if (filter) {
if (!(filter->type_mask & TYPE_MASK_RECUR_APPT))
return NULL;
if (filter->start_from >= 0 && tstart < filter->start_from)
return NULL;
if (filter->start_to >= 0 && tstart > filter->start_to)
return NULL;
if (filter->end_from >= 0 && tend < filter->end_from)
return NULL;
if (filter->end_to >= 0 && tend > filter->end_to)
return NULL;
}
return recur_apoint_new(buf, note, tstart, tend - tstart, state, return recur_apoint_new(buf, note, tstart, tend - tstart, state,
recur_char2def(type), freq, tuntil, exc); recur_char2def(type), freq, tuntil, exc);
} }
@ -382,7 +397,8 @@ struct recur_apoint *recur_apoint_scan(FILE * f, struct tm start,
/* Load the recursive events from file */ /* Load the recursive events from file */
struct recur_event *recur_event_scan(FILE * f, struct tm start, int id, struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
char type, int freq, struct tm until, char type, int freq, struct tm until,
char *note, llist_t * exc) char *note, llist_t * exc,
struct item_filter *filter)
{ {
char buf[BUFSIZ], *nl; char buf[BUFSIZ], *nl;
time_t tstart, tuntil; time_t tstart, tuntil;
@ -417,6 +433,16 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
tstart = mktime(&start); tstart = mktime(&start);
EXIT_IF(tstart == -1 || tuntil == -1, _("date error in event")); EXIT_IF(tstart == -1 || tuntil == -1, _("date error in event"));
/* Filter item. */
if (filter) {
if (!(filter->type_mask & TYPE_MASK_RECUR_EVNT))
return NULL;
if (filter->start_from >= 0 && tstart < filter->start_from)
return NULL;
if (filter->start_to >= 0 && tstart > filter->start_to)
return NULL;
}
return recur_event_new(buf, note, tstart, id, recur_char2def(type), return recur_event_new(buf, note, tstart, id, recur_char2def(type),
freq, tuntil, exc); freq, tuntil, exc);
} }