diff options
author | Lars Henriksen <LarsHenriksen@get2net.dk> | 2020-02-10 10:33:51 +0100 |
---|---|---|
committer | Lukas Fleischer <lfleischer@calcurse.org> | 2020-04-28 07:32:44 -0400 |
commit | f3779d59459ee1222d8cc53ce4e4aa009b9c3851 (patch) | |
tree | 4430652deb38d912d2259b40b6335cdc1111abca | |
parent | 36f98382e708d64e41d97be330b7c012f68cf9b6 (diff) | |
download | calcurse-f3779d59459ee1222d8cc53ce4e4aa009b9c3851.tar.gz calcurse-f3779d59459ee1222d8cc53ce4e4aa009b9c3851.zip |
Help for recurrence rule extensions
The help command has been updated for "repeat".
Context dependent, very terse information is built into the repeat
command (edit command) for display in the status bar when editing the
Weekdays, Months and Monthdays lists.
Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
-rw-r--r-- | doc/repeat.txt | 170 | ||||
-rw-r--r-- | src/ui-day.c | 155 |
2 files changed, 267 insertions, 58 deletions
diff --git a/doc/repeat.txt b/doc/repeat.txt index 16a71da..7b8679b 100644 --- a/doc/repeat.txt +++ b/doc/repeat.txt @@ -4,32 +4,144 @@ Repeat Repeat an event or an appointment. You must first select the item to be repeated by moving inside the appointment -panel. Then running the repeat command will lead you to a set of three -questions, with which you will be able to specify the repetition -characteristics: - - o type: you can choose between a daily, weekly, monthly or - yearly repetition by pressing 'D', 'W', 'M' or 'Y' - respectively. - - o frequency: this indicates how often the item shall be repeated. - For example, if you want to remember an anniversary, - choose a 'yearly' repetition with a frequency of '1', - which means it must be repeated every year. Another - example: if you go to the restaurant every two days, - choose a 'daily' repetition with a frequency of '2'. - - o ending date: this specifies when to stop repeating the selected - event or appointment. To indicate an endless - repetition, enter '0' and the item will be repeated - forever. - -Notes ------ - -* Repeated items are marked with an '*' inside the appointment panel, to be - easily recognizable from non-repeated ones. - -* The 'Repeat' and 'Delete' command can be mixed to create complicated - configurations, as it is possible to delete only one occurrence of a repeated - item. +panel. Then invoke the repeat command, and you will be asked you to select a +simple or advanced repetition. A simple repetition will lead you to a set of +three questions with which you specify the basic repetition characteristics: + + o type: choose between a daily, weekly, monthly or yearly base period + + o frequency: choose the interval between base periods. '1' means every day + (week, month or year), '2' means every other day (week, ...). + For example, if you want to remember an anniversary, choose a + yearly type with a frequency of 1, which means it will be + repeated every year. Another example: if you go to a restaurant + every second day, choose a daily type with a frequency of 2. + + o until date: specifies a day after which the repetitions do not occur. To + indicate an endless repetition, enter 0 (zero) or RETURN, and + the item will be repeated forever. + +For an advanced repetition you may, in addition to the basic characteristics, +specify three lists of either days of the week, months of the year or days of +the month. The three lists modify the simple repetition in some way by either +limiting or expanding the basic pattern. + + o Weekdays: abbriviated names of days of the week (as they appear above + the calendar). For monthly or yearly repetitions the name may + have a numerical prefix (1, 2, ... or -1, -2, ...) to specify + a particular weekday of the month or year, counted from either + the start or the end of the month or year. + + o Months: the numerical name of a month (1, 2,..., 12). + + o Monthdays: the numerical name of a day of the month (1, 2,..., 31) or the + opposites (-1, -2,..., -31) which count from the end of the + month. + +For each list you may enter one or several values separated by spaces. The +prompt for the list gives a hint as to the format. If you enter '?' only, you +get very terse, context dependent information as to the effect on the +repetition. Note that both format and effect depend on the basic type. The +combined effect on the basic type of the listed days and months is derived +from the iCalendar specification (RFC5545). + +Briefly, a weekday or monthday limits the repetitions of type daily, but +expands those of type weekly, monthly and yearly. For example, with 'Weekdays' +set to 'Sat Sun' a daily type (with frequency one) is only repeated on +Saturdays and Sundays (two instead of seven repetitions per week), while a +weekly type is also repeated on the extra day (two instead of one repetition +per week). + +Similarly, a month limits the repetitions of type daily, weekly and monthly, +but expands those of type yearly. For example, with 'Months' set to '3 10', a +weekly type is only repeated in March and October, while a yearly type is also +repeated in the extra month (two instead of one yearly repetition). + +Mnemonic. If the list type (day or month) is shorter than the basic type (day, +week, month, year), it expands the repetitions of the basic type, if not, it +limits them. + +There are a some important exceptions, though, for 'Weekdays': + + o For a monthly type, the expanded repetitions are special: a weekday with a + prefix expands to that particular weekday of the month ('3Mon' = third + Monday), while a weekday without prefix expands to all weekdays of the + month ('Wed' = all Wednesdays). Furthermore, repetitions are limited if + 'Monthdays' is also set (for example, if 'Weekdays' is set to 'Fri' with + 'Monthdays' set to '13', the monthly repetition occurs only on Friday 13th). + + o For a yearly type, the expanded repetitions are special and depend also on + the setting of 'Months'. A weekday with a prefix expands to that particular + weekday of the year ('-1Sun' = last Sunday of the year), or, if 'Months' is + also set, to that weekday of the listed months. A weekday without prefix + expands to all weekdays ('Thu' = all Thurdays in either the year or listed + months). Furthermore, repetitions are limited if 'Monthdays' is also set + as for monthly type. + +When you are finished setting up the repeating item, you may test it +interactively with the 'next' command, a subcommand of the generic command +(default ': n'). Invoked with a repeating item selected in the appointments +panel, it will go to the next repetition. By doing this repeatedly, you may +step through the repetitions one by one. + +If you edit an item that is already repeating, you will be led through all six +characteristics and can modify any of them. + +Here are some typical examples. It is assumed that you have invoked the repeat +command on what will become the first repetition and have selected an advanced +repetition, that your date input format is dd/mm/yyyy, and that your language +is english. + + o an event that occurs every Tuesday and Thursday forever + type: weekly + frequency: 1 + until: 0 + weekdays: Tue Thu + months: (empty) + monthdays: (not possible) + + o an event that occurs on workdays except in July forever (holidays are not + taken into account) + type: daily + frequency: 1 + until: 0 + weekdays: Mon Tue Wed Thu Fri + months: 1 2 3 4 5 6 8 9 10 11 12 + monthdays: (empty) + + o an appointment that occurs on the first and last Monday of the month forever + type: monthly + frequency: 1 + until: 0 + weekdays: 1Mon -1Mon + months: (empty) + monthdays: (empty) + + o an appointment that occurs on all Wednesdays in June and July until the + end of June 2022 + type: monthly + frequency: 1 + until: 30/6/2022 + weekdays: Wed + months: 6 7 + monthdays: (empty) + + o an event that occurs when Daylight Saving Time begins in the EU (last + Sunday in March) + type: yearly + frequency: 1 + until: 0 + weekdays: -1Sun + months: 3 + monthdays: (empty) + + o an event that occurs on the penultimate day of February forever + type: monthly + frequency: 1 + until: 0 + weekdays: (empty) + months: 2 + monthdays: -2 + +For an example that is not possible to specify consider an event that occurs +on the last workday of each month. diff --git a/src/ui-day.c b/src/ui-day.c index e359c82..5a8d960 100644 --- a/src/ui-day.c +++ b/src/ui-day.c @@ -486,73 +486,170 @@ cleanup: return updated; } +static void help_ilist(int_list_t list, int rule) +{ + char *msg1 = ""; + char *msg2 = ""; + char *byday_w_d = _("only on these weekdays"); + char *byday_w_w = _("also on these weekdays"); + char *byday_m_m_1 = + _("also on these weekdays of month - or only on given monthdays"); + char *byday_m_m_2 = + _("either all weekdays or 1st, 2nd, ... weekday or 1st, 2nd, ... from the end"); + char *byday_y_y_1 = + _("also on these weekdays of year or given months - or only on given monthdays"); + char *byday_y_y_2 = + _("positive: 1st, 2nd,... weekday of month or year, negative: 1st, 2nd,... from end"); + char *bymonth_dwm = + _("only in these months"); + char *bymonth_y = + _("also in these months"); + char *bymonthday_d = _("only on these days of the month"); + char *bymonthday_my = _("also on these days of the month"); + + + switch (list) { + case BYDAY_W: + switch (rule) { + case RECUR_DAILY: + msg1 = byday_w_d; + msg2 = ""; + break; + case RECUR_WEEKLY: + msg1 = byday_w_w; + msg2 = ""; + break; + default: + EXIT("internal inconsistency"); + } + break; + case BYDAY_M: + switch (rule) { + case RECUR_MONTHLY: + msg1 = byday_m_m_1; + msg2 = byday_m_m_2; + break; + default: + EXIT("internal inconsistency"); + } + break; + case BYDAY_Y: + switch (rule) { + case RECUR_YEARLY: + msg1 = byday_y_y_1; + msg2 = byday_y_y_2; + break; + default: + EXIT("internal inconsistency"); + } + break; + case BYMONTH: + switch (rule) { + case RECUR_DAILY: + case RECUR_WEEKLY: + case RECUR_MONTHLY: + msg1 = bymonth_dwm; + msg2 = ""; + break; + case RECUR_YEARLY: + msg1 = bymonth_y; + msg2 = ""; + break; + default: + break; + } + break; + case BYMONTHDAY: + switch (rule) { + case RECUR_DAILY: + msg1 = bymonthday_d; + msg2 = ""; + break; + case RECUR_MONTHLY: + case RECUR_YEARLY: + msg1 = bymonthday_my; + msg2 = ""; + break; + default: + break; + } + break; + default: + break; + } + status_mesg(msg1, msg2); + keys_wgetch(win[KEY].p); +} + /* Edit an rrule (linked) list of integers. */ -static int edit_ilist(llist_t *ilist, int_list_t type) +static int edit_ilist(llist_t *ilist, int_list_t list_type, int rule_type) { char *msg; - char *msg_wday = NULL; - char *msg_format_w = _("Weekdays (%s|..|%s):"); - char *msg_format_m = - _("Weekdays (%s|..|%s, optional prefix 1..5 or -1..-5)):"); - char *msg_format_y = - _("Weekdays (%s|..|%s, optional prefix 1..53 or -1..-53):"); - char *msg_month = _("Months (1..12):"); - char *msg_mday = _("Monthdays (1..31 or -1..-31):"); - char *msg_invalid = _("Invalid format - try again."); - char *msg_cont = _("Press any key to continue."); + char *wday = NULL; + char *wday_w = _("Weekdays (%s|..|%s), '?' for help:"); + char *wday_m = + _("Weekdays (%1$s|..|%2$s or 1%1$s|..|5%2$s or -1%1$s|..|-5%2$s), '?' for help:"); + char *wday_y = + _("Weekdays (%1$s|..|%2$s or 1%1$s|..|53%2$s or -1%1$s|..|-53%2$s), '?' for help:"); + char *month = _("Months (1..12), '?' for help:"); + char *mday = _("Monthdays (1..31 or -1..-31), '?' for help:"); + char *invalid = _("Invalid format - try again."); + char *cont = _("Press any key to continue."); int updated = 0; - if (type == NOLL) + if (list_type == NOLL) return !updated; char *istr; enum getstr ret; - switch (type) { + switch (list_type) { case BYDAY_W: - asprintf(&msg_wday, msg_format_w, + asprintf(&wday, wday_w, nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1)); - msg = msg_wday; + msg = wday; break; case BYDAY_M: - asprintf(&msg_wday, msg_format_m, + asprintf(&wday, wday_m, nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1)); - msg = msg_wday; + msg = wday; break; case BYDAY_Y: - asprintf(&msg_wday, msg_format_y, + asprintf(&wday, wday_y, nl_langinfo(ABDAY_2), nl_langinfo(ABDAY_1)); - msg = msg_wday; + msg = wday; break; case BYMONTH: - msg = msg_month; + msg = month; break; case BYMONTHDAY: - msg = msg_mday; + msg = mday; break; default: msg = NULL; break; } status_mesg(msg, ""); - istr = int2str(ilist, type); + istr = int2str(ilist, list_type); while (1) { ret = updatestring(win[STA].p, &istr, 0, 1); if (ret == GETSTRING_VALID || ret == GETSTRING_RET) { - if (str2int(ilist, istr, type)) { + if (*(istr + strlen(istr) - 1) == '?') + help_ilist(list_type, rule_type); + else if (str2int(ilist, istr, list_type)) { updated = 1; break; } else { - status_mesg(msg_invalid, msg_cont); + status_mesg(invalid, cont); keys_wgetch(win[KEY].p); } mem_free(istr); status_mesg(msg, ""); - istr = int2str(ilist, type); + istr = int2str(ilist, list_type); } else if (ret == GETSTRING_ESC) break; } mem_free(istr); - mem_free(msg_wday); + mem_free(wday); return updated; } @@ -740,18 +837,18 @@ static int update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc, break; } recur_int_list_dup(&nrpt.bywday, &(*rpt)->bywday); - if (!edit_ilist(&nrpt.bywday, byday_type)) + if (!edit_ilist(&nrpt.bywday, byday_type, nrpt.type)) goto cleanup; /* Edit BYMONTH list. */ recur_int_list_dup(&nrpt.bymonth, &(*rpt)->bymonth); - if (!edit_ilist(&nrpt.bymonth, BYMONTH)) + if (!edit_ilist(&nrpt.bymonth, BYMONTH, nrpt.type)) goto cleanup; /* Edit BYMONTHDAY list. */ if (nrpt.type != RECUR_WEEKLY) { recur_int_list_dup(&nrpt.bymonthday, &(*rpt)->bymonthday); - if (!edit_ilist(&nrpt.bymonthday, BYMONTHDAY)) + if (!edit_ilist(&nrpt.bymonthday, BYMONTHDAY, nrpt.type)) goto cleanup; } |