aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Fleischer <calcurse@cryptocrack.de>2014-08-06 08:53:51 +0200
committerLukas Fleischer <calcurse@cryptocrack.de>2014-08-06 12:08:14 +0200
commitbfe73d0e5d66c43006a8a0dd8d58e311432bcb57 (patch)
tree584c1f12effddb2501566a872f7787be65124b89
parent4ec7fe123925144506297df5eba4ed41c6f8331d (diff)
downloadcalcurse-bfe73d0e5d66c43006a8a0dd8d58e311432bcb57.tar.gz
calcurse-bfe73d0e5d66c43006a8a0dd8d58e311432bcb57.zip
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>
-rw-r--r--src/apoint.c17
-rw-r--r--src/args.c125
-rw-r--r--src/calcurse.c4
-rw-r--r--src/calcurse.h29
-rw-r--r--src/dmon.c2
-rw-r--r--src/event.c13
-rw-r--r--src/io.c11
-rw-r--r--src/recur.c30
8 files changed, 207 insertions, 24 deletions
diff --git a/src/apoint.c b/src/apoint.c
index f00dd1e..9bdd575 100644
--- a/src/apoint.c
+++ b/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);
}
diff --git a/src/args.c b/src/args.c
index 8a9aa49..e9c9ac2 100644
--- a/src/args.c
+++ b/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);
diff --git a/src/calcurse.c b/src/calcurse.c
index ffd7020..242a142 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -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();
diff --git a/src/calcurse.h b/src/calcurse.h
index 0fc3f62..4ae6c66 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -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 *);
diff --git a/src/dmon.c b/src/dmon.c
index c51ee70..546847f 100644
--- a/src/dmon.c
+++ b/src/dmon.c
@@ -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());
diff --git a/src/event.c b/src/event.c
index 38305b8..96ac41d 100644
--- a/src/event.c
+++ b/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);
}
diff --git a/src/io.c b/src/io.c
index a50991f..a6c29ac 100644
--- a/src/io.c
+++ b/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,
diff --git a/src/recur.c b/src/recur.c
index 69706b0..76585d6 100644
--- a/src/recur.c
+++ b/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);
}