CLI: Revert to and update of parse_datetimearg()
An earlier commit ("CLI: take input date format from configuration file, do not accept time") replaced parse_datetimearg() with parse_datearg() and eliminated time-of-day from command line date arguments. This made the full use of filter options impossible. That earlier commit is reverted and updated. The parse_datearg() function is replaced by an updated parse_datetimearg() function that - takes the date format from the configuration file - accepts date, date-time or time The updated parse_datetimearg() function has been extended to report back the type of the date string received in order to set (filter) options correctly. Input dates for query ranges (--from, --to, --days) are still limited to dates only. Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
parent
bcfc71f4fe
commit
620c4eeca5
149
src/args.c
149
src/args.c
@ -44,6 +44,14 @@
|
|||||||
|
|
||||||
#include "calcurse.h"
|
#include "calcurse.h"
|
||||||
|
|
||||||
|
/* Input types for parse_datetimearg() */
|
||||||
|
enum {
|
||||||
|
ARG_DATE,
|
||||||
|
ARG_DATE_TIME,
|
||||||
|
ARG_TIME,
|
||||||
|
ARG_ERR
|
||||||
|
};
|
||||||
|
|
||||||
/* Long options */
|
/* Long options */
|
||||||
enum {
|
enum {
|
||||||
OPT_FILTER_TYPE = 1000,
|
OPT_FILTER_TYPE = 1000,
|
||||||
@ -277,23 +285,53 @@ date_arg_from_to(long from, long to, int add_line, const char *fmt_apt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a string with a date into the Unix time for midnight of that day.
|
* Convert a string with a (local time) date, date-time or time into
|
||||||
|
* the Unix time for that point in time as follows:
|
||||||
|
* - a date only is converted to midnight (beginning) of that day
|
||||||
|
* - a date-time is converted to that day and time
|
||||||
|
* - a time only is converted to that time of the current day
|
||||||
* The date format is taken from the user configuration.
|
* The date format is taken from the user configuration.
|
||||||
|
* The type of the input string is returned in the type argument.
|
||||||
*/
|
*/
|
||||||
static time_t parse_datearg(const char *str)
|
|
||||||
{
|
|
||||||
struct date day;
|
|
||||||
|
|
||||||
if (parse_date(str, conf.input_datefmt,
|
static time_t parse_datetimearg(const char *str, int *type)
|
||||||
(int *)&day.yyyy, (int *)&day.mm, (int *)&day.dd, NULL))
|
{
|
||||||
return date2sec(day, 0, 0);
|
char *date = mem_strdup(str);
|
||||||
else
|
*type = ARG_ERR;
|
||||||
|
char *time;
|
||||||
|
struct date day;
|
||||||
|
unsigned hour, min;
|
||||||
|
time_t ret;
|
||||||
|
|
||||||
|
time = strchr(date, ' ');
|
||||||
|
if (time) { /* Date and time? */
|
||||||
|
*time++ = '\0';
|
||||||
|
if (!parse_time(time, &hour, &min))
|
||||||
return -1;
|
return -1;
|
||||||
|
if (!parse_date(date, conf.input_datefmt,
|
||||||
|
(int *)&day.yyyy, (int *)&day.mm, (int *)&day.dd, NULL))
|
||||||
|
return -1;
|
||||||
|
ret = date2sec(day, hour, min);
|
||||||
|
*type = ARG_DATE_TIME;
|
||||||
|
} else /* Date?*/ if (parse_date(date, conf.input_datefmt,
|
||||||
|
(int *)&day.yyyy, (int *)&day.mm, (int *)&day.dd, NULL)) {
|
||||||
|
ret = date2sec(day, 0, 0);
|
||||||
|
*type = ARG_DATE;
|
||||||
|
} else /* Time? */ if (parse_time(date, &hour, &min)) {
|
||||||
|
ret = date2sec(*ui_calendar_get_today(), hour, min);
|
||||||
|
*type = ARG_TIME;
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a "from,to" date range.
|
||||||
|
* For an open-end range no change occurs at the open end.
|
||||||
|
*/
|
||||||
static int parse_daterange(const char *str, time_t *date_from, time_t *date_to)
|
static int parse_daterange(const char *str, time_t *date_from, time_t *date_to)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int type, ret = 0;
|
||||||
char *s = mem_strdup(str);
|
char *s = mem_strdup(str);
|
||||||
char *p = strchr(s, ',');
|
char *p = strchr(s, ',');
|
||||||
|
|
||||||
@ -304,21 +342,17 @@ static int parse_daterange(const char *str, time_t *date_from, time_t *date_to)
|
|||||||
p++;
|
p++;
|
||||||
|
|
||||||
if (*s != '\0') {
|
if (*s != '\0') {
|
||||||
*date_from = parse_datearg(s);
|
*date_from = parse_datetimearg(s, &type);
|
||||||
if (*date_from == -1)
|
if (*date_from == -1)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
|
||||||
*date_from = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p != '\0') {
|
if (*p != '\0') {
|
||||||
*date_to = parse_datearg(p);
|
*date_to = parse_datetimearg(p, &type);
|
||||||
if (*date_to == -1)
|
if (*date_to == -1)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
/* One second before next midnight. */
|
if (type == ARG_DATE)
|
||||||
*date_to = date_sec_change(*date_to, 0, 1) - 1;
|
*date_to = ENDOFDAY(*date_to);
|
||||||
} else {
|
|
||||||
*date_to = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -390,7 +424,7 @@ int parse_args(int argc, char **argv)
|
|||||||
const char *cfile = NULL, *ifile = NULL, *confdir = NULL;
|
const char *cfile = NULL, *ifile = NULL, *confdir = NULL;
|
||||||
|
|
||||||
int non_interactive = 1;
|
int non_interactive = 1;
|
||||||
int ch, cpid;
|
int ch, cpid, type;
|
||||||
regex_t reg;
|
regex_t reg;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
@ -497,9 +531,9 @@ int parse_args(int argc, char **argv)
|
|||||||
EXIT_IF(range == 0, _("invalid range: %s"),
|
EXIT_IF(range == 0, _("invalid range: %s"),
|
||||||
optarg);
|
optarg);
|
||||||
} else {
|
} else {
|
||||||
from = parse_datearg(optarg);
|
from = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(from == -1, _("invalid date: %s"),
|
EXIT_IF(from == -1 || type != ARG_DATE,
|
||||||
optarg);
|
_("invalid date: %s"), optarg);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter.type_mask |= TYPE_MASK_CAL;
|
filter.type_mask |= TYPE_MASK_CAL;
|
||||||
@ -544,8 +578,9 @@ int parse_args(int argc, char **argv)
|
|||||||
case 's':
|
case 's':
|
||||||
if (!optarg)
|
if (!optarg)
|
||||||
optarg = "today";
|
optarg = "today";
|
||||||
from = parse_datearg(optarg);
|
from = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(from == -1, _("invalid date: %s"), optarg);
|
EXIT_IF(from == -1 || type != ARG_DATE,
|
||||||
|
_("invalid date: %s"), optarg);
|
||||||
filter.type_mask |= TYPE_MASK_CAL;
|
filter.type_mask |= TYPE_MASK_CAL;
|
||||||
query = 1;
|
query = 1;
|
||||||
break;
|
break;
|
||||||
@ -606,78 +641,84 @@ int parse_args(int argc, char **argv)
|
|||||||
filter.regex = ®
|
filter.regex = ®
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
/* Assume that the date argument is midnight of the given day. */
|
/*
|
||||||
|
* A date only is a time span (a day) and interpreted thus:
|
||||||
|
* "to" means "to end of day"
|
||||||
|
* "after" means "from start of next day"
|
||||||
|
*/
|
||||||
case OPT_FILTER_START_FROM:
|
case OPT_FILTER_START_FROM:
|
||||||
/* Midnight. */
|
filter.start_from = parse_datetimearg(optarg, &type);
|
||||||
filter.start_from = parse_datearg(optarg);
|
|
||||||
EXIT_IF(filter.start_from == -1,
|
EXIT_IF(filter.start_from == -1,
|
||||||
_("invalid date: %s"), optarg);
|
_("invalid date: %s"), optarg);
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_START_TO:
|
case OPT_FILTER_START_TO:
|
||||||
filter.start_to = parse_datearg(optarg);
|
filter.start_to = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(filter.start_to == -1,
|
EXIT_IF(filter.start_to == -1,
|
||||||
_("invalid date: %s"), optarg);
|
_("invalid date: %s"), optarg);
|
||||||
/* Next midnight less one second. */
|
if (type == ARG_DATE)
|
||||||
filter.start_to = date_sec_change(filter.start_to, 0, 1) - 1;
|
filter.start_to = ENDOFDAY(filter.start_to);
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_START_AFTER:
|
case OPT_FILTER_START_AFTER:
|
||||||
filter.start_from = parse_datearg(optarg);
|
filter.start_from = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(filter.start_from == -1,
|
EXIT_IF(filter.start_from == -1,
|
||||||
_("invalid date: %s"), optarg);
|
_("invalid date: %s"), optarg);
|
||||||
/* Next midnight (belongs to the next day). */
|
if (type == ARG_DATE)
|
||||||
filter.start_from = date_sec_change(filter.start_from, 0, 1);
|
filter.start_from = NEXTDAY(filter.start_from);
|
||||||
|
else
|
||||||
|
filter.start_from++;
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_START_BEFORE:
|
case OPT_FILTER_START_BEFORE:
|
||||||
filter.start_to = parse_datearg(optarg);
|
filter.start_to = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(filter.start_to == -1,
|
EXIT_IF(filter.start_to == -1,
|
||||||
_("invalid date: %s"), optarg);
|
_("invalid date: %s"), optarg);
|
||||||
/* One second before midnight. */
|
|
||||||
filter.start_to--;
|
filter.start_to--;
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_START_RANGE:
|
case OPT_FILTER_START_RANGE:
|
||||||
EXIT_IF(!parse_daterange(optarg, &filter.start_from,
|
/* Set initialization values in case of open-end range. */
|
||||||
&filter.start_to),
|
filter.start_from = filter.start_to = -1;
|
||||||
|
EXIT_IF(!parse_daterange(optarg, &filter.start_from, &filter.start_to),
|
||||||
_("invalid date range: %s"), optarg);
|
_("invalid date range: %s"), optarg);
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_END_FROM:
|
case OPT_FILTER_END_FROM:
|
||||||
/* Midnight. */
|
filter.end_from = parse_datetimearg(optarg, &type);
|
||||||
filter.end_from = parse_datearg(optarg);
|
|
||||||
EXIT_IF(filter.end_from == -1,
|
EXIT_IF(filter.end_from == -1,
|
||||||
_("invalid date: %s"), optarg);
|
_("invalid date: %s"), optarg);
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_END_TO:
|
case OPT_FILTER_END_TO:
|
||||||
filter.end_to = parse_datearg(optarg);
|
filter.end_to = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(filter.end_to == -1,
|
EXIT_IF(filter.end_to == -1,
|
||||||
_("invalid date: %s"), optarg);
|
_("invalid date: %s"), optarg);
|
||||||
/* Next midnight less one second. */
|
if (type == ARG_DATE)
|
||||||
filter.end_to = date_sec_change(filter.end_to, 0, 1) - 1;
|
filter.end_to = ENDOFDAY(filter.end_to);
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_END_AFTER:
|
case OPT_FILTER_END_AFTER:
|
||||||
filter.end_from = parse_datearg(optarg);
|
filter.end_from = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(filter.end_from == -1,
|
EXIT_IF(filter.end_from == -1,
|
||||||
_("invalid date: %s"), optarg);
|
_("invalid date: %s"), optarg);
|
||||||
/* Next midnight (belongs to the next day). */
|
if (type == ARG_DATE)
|
||||||
filter.end_from = date_sec_change(filter.end_from, 0, 1);
|
filter.end_from = NEXTDAY(filter.end_from);
|
||||||
|
else
|
||||||
|
filter.end_from++;
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_END_BEFORE:
|
case OPT_FILTER_END_BEFORE:
|
||||||
filter.end_to = parse_datearg(optarg);
|
filter.end_to = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(filter.end_to == -1,
|
EXIT_IF(filter.end_to == -1,
|
||||||
_("invalid date: %s"), optarg);
|
_("invalid date: %s"), optarg);
|
||||||
/* One second before midnight. */
|
|
||||||
filter.end_to--;
|
filter.end_to--;
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FILTER_END_RANGE:
|
case OPT_FILTER_END_RANGE:
|
||||||
EXIT_IF(!parse_daterange(optarg, &filter.end_from,
|
/* Set default values in case of open-ended range. */
|
||||||
&filter.end_to),
|
filter.start_from = filter.start_to = -1;
|
||||||
|
EXIT_IF(!parse_daterange(optarg, &filter.end_from, &filter.end_to),
|
||||||
_("invalid date range: %s"), optarg);
|
_("invalid date range: %s"), optarg);
|
||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
@ -696,13 +737,15 @@ int parse_args(int argc, char **argv)
|
|||||||
filter_opt = 1;
|
filter_opt = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_FROM:
|
case OPT_FROM:
|
||||||
from = parse_datearg(optarg);
|
from = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(from == -1, _("invalid date: %s"), optarg);
|
EXIT_IF(from == -1 || type != ARG_DATE,
|
||||||
|
_("invalid date: %s"), optarg);
|
||||||
query_range = 1;
|
query_range = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_TO:
|
case OPT_TO:
|
||||||
to = parse_datearg(optarg);
|
to = parse_datetimearg(optarg, &type);
|
||||||
EXIT_IF(to == -1, _("invalid date: %s"), optarg);
|
EXIT_IF(to == -1 || type != ARG_DATE,
|
||||||
|
_("invalid date: %s"), optarg);
|
||||||
query_range = 1;
|
query_range = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_DAYS:
|
case OPT_DAYS:
|
||||||
@ -790,7 +833,7 @@ int parse_args(int argc, char **argv)
|
|||||||
if (from == -1)
|
if (from == -1)
|
||||||
from = get_today();
|
from = get_today();
|
||||||
if (to == -1)
|
if (to == -1)
|
||||||
to = from;
|
to = ENDOFDAY(from);
|
||||||
EXIT_IF(to < from, _("end date cannot come before start date"));
|
EXIT_IF(to < from, _("end date cannot come before start date"));
|
||||||
if (range > 0)
|
if (range > 0)
|
||||||
to = date_sec_change(from, 0, range - 1);
|
to = date_sec_change(from, 0, range - 1);
|
||||||
|
@ -137,10 +137,12 @@
|
|||||||
/*
|
/*
|
||||||
* Note the difference between the number of seconds in a day and daylength
|
* Note the difference between the number of seconds in a day and daylength
|
||||||
* in seconds. The two may differ when DST is in effect (daylength is either
|
* in seconds. The two may differ when DST is in effect (daylength is either
|
||||||
* 23, 24 or 25 hours. The argument to DAYLEN is of type time_t.
|
* 23, 24 or 25 hours. The argument "date" is assumed to be of type time_t.
|
||||||
*/
|
*/
|
||||||
#define DAYINSEC (DAYINMIN * MININSEC)
|
#define DAYINSEC (DAYINMIN * MININSEC)
|
||||||
#define DAYLEN(date) (date_sec_change((date), 0, 1) - (date))
|
#define NEXTDAY(date) date_sec_change((date), 0, 1)
|
||||||
|
#define DAYLEN(date) (NEXTDAY(date) - (date))
|
||||||
|
#define ENDOFDAY(date) (NEXTDAY(date) - 1)
|
||||||
#define HOURINSEC (HOURINMIN * MININSEC)
|
#define HOURINSEC (HOURINMIN * MININSEC)
|
||||||
|
|
||||||
#define MAXDAYSPERMONTH 31
|
#define MAXDAYSPERMONTH 31
|
||||||
@ -760,6 +762,7 @@ int ui_calendar_get_view(void);
|
|||||||
void ui_calendar_start_date_thread(void);
|
void ui_calendar_start_date_thread(void);
|
||||||
void ui_calendar_stop_date_thread(void);
|
void ui_calendar_stop_date_thread(void);
|
||||||
void ui_calendar_set_current_date(void);
|
void ui_calendar_set_current_date(void);
|
||||||
|
struct date *ui_calendar_get_today(void);
|
||||||
void ui_calendar_set_first_day_of_week(enum wday);
|
void ui_calendar_set_first_day_of_week(enum wday);
|
||||||
void ui_calendar_change_first_day_of_week(void);
|
void ui_calendar_change_first_day_of_week(void);
|
||||||
unsigned ui_calendar_week_begins_on_monday(void);
|
unsigned ui_calendar_week_begins_on_monday(void);
|
||||||
|
@ -144,6 +144,12 @@ void ui_calendar_set_current_date(void)
|
|||||||
pthread_mutex_unlock(&date_thread_mutex);
|
pthread_mutex_unlock(&date_thread_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the current date. */
|
||||||
|
struct date *ui_calendar_get_today(void)
|
||||||
|
{
|
||||||
|
return &today;
|
||||||
|
}
|
||||||
|
|
||||||
/* Needed to display sunday or monday as the first day of week in calendar. */
|
/* Needed to display sunday or monday as the first day of week in calendar. */
|
||||||
void ui_calendar_set_first_day_of_week(enum wday first_day)
|
void ui_calendar_set_first_day_of_week(enum wday first_day)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user