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:
parent
4ec7fe1239
commit
bfe73d0e5d
17
src/apoint.c
17
src/apoint.c
@ -163,7 +163,7 @@ void apoint_write(struct apoint *o, FILE * f)
|
||||
}
|
||||
|
||||
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;
|
||||
time_t tstart, tend;
|
||||
@ -193,6 +193,21 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end,
|
||||
tend = mktime(&end);
|
||||
EXIT_IF(tstart == -1 || tend == -1 || tstart > tend,
|
||||
_("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);
|
||||
}
|
||||
|
||||
|
125
src/args.c
125
src/args.c
@ -46,7 +46,16 @@
|
||||
|
||||
/* Long options */
|
||||
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_EV,
|
||||
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
|
||||
* 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 vflag = 0; /* -v: print version number */
|
||||
int xflag = 0; /* -x: export data */
|
||||
/* Filters */
|
||||
struct item_filter filter = { TYPE_MASK_ALL, -1, -1, -1, -1 };
|
||||
/* Format strings */
|
||||
const char *fmt_apt = " - %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'},
|
||||
{"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-recur-apt", required_argument, NULL, OPT_FMT_RAPT},
|
||||
{"format-event", required_argument, NULL, OPT_FMT_EV},
|
||||
@ -625,6 +691,51 @@ int parse_args(int argc, char **argv)
|
||||
xfmt = IO_EXPORT_ICAL;
|
||||
}
|
||||
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:
|
||||
fmt_apt = optarg;
|
||||
break;
|
||||
@ -689,7 +800,7 @@ int parse_args(int argc, char **argv)
|
||||
io_check_dir(path_notes);
|
||||
io_check_file(path_apts);
|
||||
io_check_file(path_todo);
|
||||
io_load_app();
|
||||
io_load_app(&filter);
|
||||
io_load_todo();
|
||||
note_gc();
|
||||
non_interactive = 1;
|
||||
@ -704,7 +815,7 @@ int parse_args(int argc, char **argv)
|
||||
io_check_file(path_todo);
|
||||
/* Get default pager in case we need to show a log file. */
|
||||
vars_init();
|
||||
io_load_app();
|
||||
io_load_app(&filter);
|
||||
io_load_todo();
|
||||
io_import_data(IO_IMPORT_ICAL, ifile);
|
||||
io_save_apts(path_apts);
|
||||
@ -714,7 +825,7 @@ int parse_args(int argc, char **argv)
|
||||
if (xflag) {
|
||||
io_check_file(path_apts);
|
||||
io_check_file(path_todo);
|
||||
io_load_app();
|
||||
io_load_app(&filter);
|
||||
io_load_todo();
|
||||
io_export_data(xfmt);
|
||||
non_interactive = 1;
|
||||
@ -728,14 +839,14 @@ int parse_args(int argc, char **argv)
|
||||
}
|
||||
if (nflag) {
|
||||
io_check_file(path_apts);
|
||||
io_load_app();
|
||||
io_load_app(&filter);
|
||||
next_arg();
|
||||
non_interactive = 1;
|
||||
}
|
||||
if (dflag || rflag || sflag) {
|
||||
io_check_file(path_apts);
|
||||
io_check_file(path_conf);
|
||||
io_load_app();
|
||||
io_load_app(&filter);
|
||||
config_load(); /* To get output date format. */
|
||||
if (dflag)
|
||||
date_arg(ddate, add_line, fmt_apt,
|
||||
@ -756,7 +867,7 @@ int parse_args(int argc, char **argv)
|
||||
io_check_file(path_conf);
|
||||
vars_init();
|
||||
config_load(); /* To get output date format. */
|
||||
io_load_app();
|
||||
io_load_app(&filter);
|
||||
day.dd = day.mm = day.yyyy = 0;
|
||||
app_arg(add_line, &day, 0, fmt_apt, fmt_rapt,
|
||||
fmt_ev, fmt_rev, preg, &limit);
|
||||
|
@ -333,7 +333,7 @@ static inline void key_generic_reload(void)
|
||||
todo_init_list();
|
||||
|
||||
io_load_todo();
|
||||
io_load_app();
|
||||
io_load_app(NULL);
|
||||
io_unset_modified();
|
||||
ui_todo_load_items();
|
||||
ui_todo_sel_reset();
|
||||
@ -684,7 +684,7 @@ int main(int argc, char **argv)
|
||||
wins_erase_status_bar();
|
||||
io_load_keys(conf.pager);
|
||||
io_load_todo();
|
||||
io_load_app();
|
||||
io_load_app(NULL);
|
||||
io_unset_modified();
|
||||
wins_slctd_set(conf.default_panel);
|
||||
wins_resize();
|
||||
|
@ -383,6 +383,23 @@ enum day_item_type {
|
||||
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...). */
|
||||
struct day_item {
|
||||
enum day_item_type type;
|
||||
@ -643,7 +660,8 @@ struct apoint *apoint_new(char *, char *, long, long, char);
|
||||
unsigned apoint_inday(struct apoint *, long *);
|
||||
void apoint_sec2str(struct apoint *, long, char *, char *);
|
||||
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 *);
|
||||
struct notify_app *apoint_check_next(struct notify_app *, long);
|
||||
void apoint_switch_notify(struct apoint *);
|
||||
@ -735,7 +753,7 @@ void event_llist_free(void);
|
||||
struct event *event_new(char *, char *, long, int);
|
||||
unsigned event_inday(struct event *, long *);
|
||||
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_paste_item(struct event *, long);
|
||||
|
||||
@ -761,7 +779,7 @@ unsigned io_save_apts(const char *);
|
||||
unsigned io_save_todo(const char *);
|
||||
unsigned io_save_keys(void);
|
||||
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_keys(const char *);
|
||||
int io_check_dir(const char *);
|
||||
@ -911,9 +929,10 @@ char recur_def2char(enum recur_type);
|
||||
int recur_char2def(char);
|
||||
struct recur_apoint *recur_apoint_scan(FILE *, struct tm, struct tm,
|
||||
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,
|
||||
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_event_write(struct recur_event *, FILE *);
|
||||
void recur_save_data(FILE *);
|
||||
|
@ -165,7 +165,7 @@ void dmon_start(int parent_exit_status)
|
||||
event_llist_init();
|
||||
recur_event_llist_init();
|
||||
todo_init_list();
|
||||
io_load_app();
|
||||
io_load_app(NULL);
|
||||
data_loaded = 1;
|
||||
|
||||
DMON_LOG(_("started at %s\n"), nowstr());
|
||||
|
13
src/event.c
13
src/event.c
@ -120,7 +120,8 @@ void event_write(struct event *o, FILE * f)
|
||||
}
|
||||
|
||||
/* 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;
|
||||
time_t tstart;
|
||||
@ -147,6 +148,16 @@ struct event *event_scan(FILE * f, struct tm start, int id, char *note)
|
||||
tstart = mktime(&start);
|
||||
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);
|
||||
}
|
||||
|
||||
|
11
src/io.c
11
src/io.c
@ -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
|
||||
* 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;
|
||||
int c, is_appointment, is_event, is_recursive;
|
||||
@ -620,18 +620,19 @@ void io_load_app(void)
|
||||
if (is_recursive) {
|
||||
recur_apoint_scan(data_file, start, end,
|
||||
type, freq, until, notep,
|
||||
&exc, state);
|
||||
&exc, state, filter);
|
||||
} else {
|
||||
apoint_scan(data_file, start, end, state,
|
||||
notep);
|
||||
notep, filter);
|
||||
}
|
||||
} else if (is_event) {
|
||||
if (is_recursive) {
|
||||
recur_event_scan(data_file, start, id,
|
||||
type, freq, until, notep,
|
||||
&exc);
|
||||
&exc, filter);
|
||||
} else {
|
||||
event_scan(data_file, start, id, notep);
|
||||
event_scan(data_file, start, id, notep,
|
||||
filter);
|
||||
}
|
||||
} else {
|
||||
io_load_error(path_apts, line,
|
||||
|
30
src/recur.c
30
src/recur.c
@ -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 tm end, char type, int freq,
|
||||
struct tm until, char *note,
|
||||
llist_t * exc, char state)
|
||||
llist_t * exc, char state,
|
||||
struct item_filter *filter)
|
||||
{
|
||||
char buf[BUFSIZ], *nl;
|
||||
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
|
||||
|| 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,
|
||||
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 */
|
||||
struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
|
||||
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;
|
||||
time_t tstart, tuntil;
|
||||
@ -417,6 +433,16 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
|
||||
tstart = mktime(&start);
|
||||
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),
|
||||
freq, tuntil, exc);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user