mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-17 14:59:20 +02:00
Compare commits
25 Commits
06.00.00-B
...
06.00.00-B
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bf23912ae | ||
|
|
6ae0340137 | ||
|
|
0e48ace855 | ||
|
|
d1f1ddf5b7 | ||
|
|
5f9e227dc8 | ||
|
|
b770676cb6 | ||
|
|
5ee415c2fb | ||
|
|
6c2a4b66fd | ||
|
|
6c2d65c08e | ||
|
|
cd2dc3bea3 | ||
|
|
b1b80316ab | ||
|
|
f04835cf6f | ||
|
|
fb19ea6b7e | ||
|
|
e2d7796d4a | ||
|
|
de2ec1aa7b | ||
|
|
b9fb215d9d | ||
|
|
a62ed0e0c5 | ||
|
|
eceb5e3f82 | ||
|
|
d5aa93ae57 | ||
|
|
a66da78b4a | ||
|
|
af69f54bff | ||
|
|
a000a7f17e | ||
|
|
582f388500 | ||
|
|
7762f4f2d6 | ||
|
|
31c9b2afb7 |
@@ -114,7 +114,7 @@
|
||||
"DURATION" "ELSE" "ENDIF" "ERRMSG" "EXIT" "EXPR" "FIRST"
|
||||
"FLUSH" "FOURTH" "FRENAME" "FROM" "FSET" "FUNSET" "IF"
|
||||
"IFTRIG" "IN" "INC" "INCLUDE" "INCLUDECMD" "INFO" "LAST"
|
||||
"LASTDAY" "LASTWORKDAY" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF"
|
||||
"LASTDAY" "LASTWORKDAY" "MAX-OVERDUE" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF"
|
||||
"MSG" "NOQUEUE" "OMIT" "OMITFUNC" "ONCE" "POP"
|
||||
"POP-OMIT-CONTEXT" "POP-FUNCS" "POP-VARS" "PRESERVE" "PRIORITY" "PS"
|
||||
"PSFILE" "PUSH" "PUSH-FUNCS" "PUSH-VARS" "PUSH-OMIT-CONTEXT" "REM" "RETURN"
|
||||
@@ -137,8 +137,8 @@
|
||||
"$DefaultPrio" "$DefaultTDelta" "$DeltaOverride"
|
||||
"$DontFork" "$DontQueue" "$DontTrigAts" "$EndSent" "$EndSentIg"
|
||||
"$ExpressionTimeLimit" "$February" "$FirstIndent" "$FoldYear"
|
||||
"$FormWidth" "$Friday" "$Fromnow" "$Hour" "$Hplu" "$HushMode"
|
||||
"$IgnoreOnce" "$InfDelta" "$IntMax" "$IntMin" "$Is" "$January" "$July"
|
||||
"$FormWidth" "$Friday" "$Fromnow" "$HideCompletedTodos" "$Hour" "$Hplu" "$HushMode"
|
||||
"$IgnoreOnce" "$InfDelta" "$IntMax" "$IntMin" "$Is" "$January" "$JSONMode" "$July"
|
||||
"$June" "$LatDeg" "$Latitude" "$LatMin" "$LatSec" "$Location"
|
||||
"$LongDeg" "$Longitude" "$LongMin" "$LongSec" "$March" "$MaxFullOmits"
|
||||
"$MaxLateMinutes" "$MaxPartialOmits" "$MaxSatIter" "$MaxStringLen"
|
||||
@@ -148,7 +148,7 @@
|
||||
"$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday" "$September"
|
||||
"$SimpleCal" "$SortByDate" "$SortByPrio" "$SortByTime" "$SubsIndent"
|
||||
"$Sunday" "$SuppressImplicitWarnings" "$SuppressLRM" "$SysInclude" "$T" "$Tb" "$Td"
|
||||
"$TerminalBackground" "$Thursday" "$TimeSep" "$TimetIs64bit" "$Tm" "$Today"
|
||||
"$TerminalBackground" "$Thursday" "$TimeSep" "$TimetIs64bit" "$Tm" "$Today" "$TodoFilter"
|
||||
"$Tomorrow" "$Tt" "$Tuesday" "$Tw" "$Ty" "$U" "$Ud" "$Um"
|
||||
"$UntimedFirst" "$Use256Colors" "$UseBGVTColors" "$UseTrueColors"
|
||||
"$UseVTColors" "$Uw" "$Uy" "$Was" "$Wednesday")
|
||||
@@ -178,9 +178,9 @@
|
||||
"ostype" "pad" "plural" "psmoon" "psshade" "realcurrent" "realnow"
|
||||
"realtoday" "rows" "sgn" "shell" "shellescape" "slide" "soleq"
|
||||
"stdout" "strlen" "substr" "sunrise" "sunset" "time" "timepart"
|
||||
"timezone" "today" "trig" "trigback" "trigbase" "trigdate" "trigdatetime"
|
||||
"timezone" "today" "trig" "trigback" "trigbase" "trigcompletethrough" "trigdate" "trigdatetime"
|
||||
"trigdelta" "trigduration" "trigeventduration" "trigeventstart"
|
||||
"trigfrom" "trigger" "triginfo" "trigpriority" "trigrep"
|
||||
"trigfrom" "trigger" "triginfo" "trigistodo" "trigmaxoverdue" "trigpriority" "trigrep"
|
||||
"trigscanfrom" "trigtags" "trigtime" "trigtimedelta" "trigtimerep"
|
||||
"triguntil" "trigvalid" "typeof" "tzconvert" "upper" "utctolocal"
|
||||
"value" "version" "weekno" "wkday" "wkdaynum" "year"
|
||||
|
||||
@@ -15,6 +15,11 @@ CHANGES TO REMIND
|
||||
the rest of the current file. Useful for early exit from an
|
||||
INCLUDEd file.
|
||||
|
||||
- MINOR NEW FEATURE: remind: Allow the %:, %!, %?, %@ and %#
|
||||
substitution sequences to be overridden by defining the functions
|
||||
subst_colon, subst_bang, subst_question, subst_at and subst_hash,
|
||||
respectively.
|
||||
|
||||
- MAJOR IMPROVEMENTS: tkremind: TkRemind has been given an overhaul.
|
||||
The "Show Queue" and "Show Today's Reminders" windows now respect
|
||||
the color scheme. TkRemind lets you create TODO reminders and
|
||||
@@ -41,8 +46,11 @@ CHANGES TO REMIND
|
||||
- MINOR IMPROVEMENT: include/lang/nl.rem: Use "eergisteren" for "2
|
||||
days ago" and "overmorgen" for "in 2 days' time."
|
||||
|
||||
- MINOR IMPROVEMENT: tkremind: TkRemind now passes all command-line options
|
||||
back to Remind.
|
||||
- MINOR IMPROVEMENT: tkremind: TkRemind now passes all command-line
|
||||
options back to Remind.
|
||||
|
||||
- BUG FIX: tkremind: In a couple of places, the "eval" command was used
|
||||
where the intention was to use "catch". I blame Perl...
|
||||
|
||||
- BUG FIX: remind: SCANFROM and FROM are separated out internally, and
|
||||
in the JSON output, the original FROM or SCANFROM value is
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
if !defined("ansi_bold")
|
||||
# Disable ANSI attributes in calandar mode
|
||||
if $CalMode
|
||||
# Disable ANSI attributes in calendar mode or JSON mode
|
||||
if $CalMode || $PSCal || $JSONMode
|
||||
set ansi_normal ""
|
||||
set ansi_bold ""
|
||||
set ansi_faint ""
|
||||
|
||||
@@ -31,6 +31,7 @@ SET $Tomorrow "demà"
|
||||
TRANSLATE "yesterday" "ahir"
|
||||
TRANSLATE "are" "són"
|
||||
TRANSLATE "were" "eren"
|
||||
TRANSLATE "done" "completada"
|
||||
|
||||
FSET subst_bx(a,d,t) iif(d==today()+2, "demà passat", d >= today(), "d'aquí " + (d-today()) + " dies", "fa " + (today()-d) + " dies")
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "i morgen"
|
||||
TRANSLATE "yesterday" "i går"
|
||||
TRANSLATE "are" "er"
|
||||
TRANSLATE "were" "var"
|
||||
TRANSLATE "done" "fuldført"
|
||||
|
||||
BANNER Påmindelse for %w, %d. %m, %y%o:
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ SET $Tomorrow "morgen"
|
||||
TRANSLATE "yesterday" "gestern"
|
||||
TRANSLATE "are" "sind"
|
||||
TRANSLATE "were" "waren"
|
||||
TRANSLATE "done" "abgeschlossen"
|
||||
|
||||
# Banner
|
||||
BANNER Termine für %w, den %d. %m %y%o:
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "mañana"
|
||||
TRANSLATE "yesterday" "ayer"
|
||||
TRANSLATE "are" "son"
|
||||
TRANSLATE "were" "eran"
|
||||
TRANSLATE "done" "completada"
|
||||
|
||||
BANNER Agenda para el %w, %d%s %m, %y%o:
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "huomenna"
|
||||
TRANSLATE "yesterday" "eilen"
|
||||
TRANSLATE "are" "ovat"
|
||||
TRANSLATE "were" "olivat"
|
||||
TRANSLATE "done" "suoritettu"
|
||||
|
||||
BANNER Viestit %wna %d. %mta %y%o:
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "demain"
|
||||
TRANSLATE "yesterday" "hier"
|
||||
TRANSLATE "are" "sont"
|
||||
TRANSLATE "were" "étaient"
|
||||
TRANSLATE "done" "accomplie"
|
||||
|
||||
SET $On "le"
|
||||
SET $At "à"
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "αύριο"
|
||||
TRANSLATE "yesterday" "εχθές"
|
||||
TRANSLATE "are" "είναι"
|
||||
TRANSLATE "were" "ήταν"
|
||||
TRANSLATE "done" "ολοκληρώθηκε"
|
||||
|
||||
BANNER Υπενθυμίσεις: %w, %d %m, %y%o:
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "á morgun"
|
||||
TRANSLATE "yesterday" "í gær"
|
||||
TRANSLATE "are" "eru"
|
||||
TRANSLATE "were" "voru"
|
||||
TRANSLATE "done" "lokið"
|
||||
|
||||
BANNER Minnisatriði: %w, %d%s %m, %y%o:
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "domani"
|
||||
TRANSLATE "yesterday" "Ieri"
|
||||
TRANSLATE "are" "sono"
|
||||
TRANSLATE "were" "erano"
|
||||
TRANSLATE "done" "completato"
|
||||
|
||||
BANNER Promemoria per %w, %d %m %y%o:
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ SET $Tomorrow "morgen"
|
||||
TRANSLATE "yesterday" "gisteren"
|
||||
TRANSLATE "are" "zijn"
|
||||
TRANSLATE "were" "waren"
|
||||
TRANSLATE "done" "voltooid"
|
||||
|
||||
BANNER Herinneringen voor %w, %d %m, %y%o:
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "i morgen"
|
||||
TRANSLATE "yesterday" "i går"
|
||||
TRANSLATE "are" "er"
|
||||
TRANSLATE "were" "var"
|
||||
TRANSLATE "done" "fullført"
|
||||
|
||||
BANNER Påminnelse for %w, %d. %m, %y%o:
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "jutro"
|
||||
TRANSLATE "yesterday" "wczoraj"
|
||||
TRANSLATE "are" "są"
|
||||
TRANSLATE "were" "byli"
|
||||
TRANSLATE "done" "ukończone"
|
||||
|
||||
BANNER Terminarz na %w, %d. %m %y%o:
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ SET $Tomorrow "amanhã"
|
||||
TRANSLATE "yesterday" "ontem"
|
||||
TRANSLATE "are" "são"
|
||||
TRANSLATE "were" "eram"
|
||||
TRANSLATE "done" "concluída"
|
||||
|
||||
BANNER Avisos para %w, %d de %m de %y%o:
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ SET $Tomorrow "mâine"
|
||||
TRANSLATE "yesterday" "ieri"
|
||||
TRANSLATE "are" "sunt"
|
||||
TRANSLATE "were" "au fost"
|
||||
TRANSLATE "done" "finalizată"
|
||||
|
||||
BANNER Reamintiri pentru %w, %d %m %y%o:
|
||||
|
||||
|
||||
@@ -639,6 +639,10 @@ If the reminder is a TODO reminder, then \fIflag\fR will be the integer
|
||||
If the reminder has a COMPLETE-THROUGH date, then this key will be present
|
||||
and its value will be a string of the form YYYY-MM-DD.
|
||||
.TP
|
||||
.B max_overdue \fIn\fR
|
||||
If the reminder has a MAX-OVERDUE clause, then this key will be present and
|
||||
its value will be the integer argument to MAX-OVERDUE.
|
||||
.TP
|
||||
.B priority \fIn\fR
|
||||
The priority of the reminder. Always present; if no PRIORITY keyword
|
||||
is specified, then a reminder has a default priority of 5000.
|
||||
|
||||
@@ -551,9 +551,13 @@ Do not issue TODO-type reminders.
|
||||
.B \-\-json
|
||||
In Agenda Mode, output JSON instead of the normal text-mode output.
|
||||
\fB\-\-json\fR also disables sorting (the \fB-g\fR option) and
|
||||
disables queueing (the \fB-q\fR option). See the section
|
||||
"AGENDA MODE JSON OUTPUT" for more details. The \fB\-\-json\fR option
|
||||
is ignored in Calendar Mode.
|
||||
disables queueing (the \fB-q\fR option). See the section "AGENDA MODE
|
||||
JSON OUTPUT" for more details. The \fB\-\-json\fR option is ignored
|
||||
in Calendar Mode. Note that in JSON mode, the output from any
|
||||
\fBRUN\fR-type reminder that would normally appear on standard output
|
||||
is redirected to standard error instead; this is so that \fBRUN\fR-type
|
||||
reminders don't mess up the output and cause invalid JSON to be produced
|
||||
on standard output.
|
||||
.TP
|
||||
.B \-\-print-errs
|
||||
The \fB\-\-print-errs\fR option causes \fBRemind\fR to print all
|
||||
@@ -668,6 +672,7 @@ Its syntax is:
|
||||
[\fIdelta\fR]
|
||||
[\fIrepeat\fR]
|
||||
[\fBTODO\fR]
|
||||
[\fBMAX-OVERDUE\fR \fIn\fR]
|
||||
[\fBCOMPLETE-THROUGH\fR \fIcomplete_date\fR]
|
||||
[\fBPRIORITY\fR \fIprio\fR]
|
||||
[\fBSKIP\fR | \fBBEFORE\fR | \fBAFTER\fR]
|
||||
@@ -1821,13 +1826,13 @@ is replaced with "s" if the value produced by \fB%7\fR is not 1.
|
||||
.TP
|
||||
.B %!
|
||||
is replaced with "is" if the current date and time is before the
|
||||
trigger date and the \fBAT\fR time, or "was" if it is after. The %!
|
||||
trigger date and the \fBAT\fR time, or "was" if it is after. The \fB%!\fR
|
||||
sequence may be used in a non-timed reminder, in which case only dates
|
||||
are compared.
|
||||
.TP
|
||||
.B %?
|
||||
is replaced with "are" if the current date and time is before the
|
||||
trigger date and the \fBAT\fR time, or "were" if it is after. The %!
|
||||
trigger date and the \fBAT\fR time, or "were" if it is after. The \fB%?\fR
|
||||
sequence may be used in a non-timed reminder, in which case only dates
|
||||
are compared.
|
||||
.TP
|
||||
@@ -1837,9 +1842,17 @@ is similar to \fB%2\fR but displays the current time.
|
||||
.B %#
|
||||
is similar to \fB%3\fR but displays the current time.
|
||||
.TP
|
||||
.B %:
|
||||
is replaced with " (done)" for a TODO reminder whose trigger date
|
||||
is on or after its COMPLETE-THROUGH date. It is replaced with the empty
|
||||
string in any other situation. Note that because \fBRemind\fR does not
|
||||
display completed TODO reminders in Agenda Mode, this escape sequence
|
||||
is really only useful in Calendar Mode.
|
||||
.TP
|
||||
.B
|
||||
%"
|
||||
(percent-doublequote - ") is removed. This sequence is not
|
||||
.\" "
|
||||
(percent-doublequote) is removed. This sequence is not
|
||||
used by the substitution filter,
|
||||
but is used to tell \fBRemind\fR which text to include in a calendar
|
||||
entry when the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR option is chosen.
|
||||
@@ -1863,12 +1876,12 @@ sequences.
|
||||
.TP
|
||||
o
|
||||
The a, c, e, f, g, h, i, j, k, l, u, v, 2, and 3 substitutions may
|
||||
be preceded by an asterisk (for example, %*c) which causes the word
|
||||
be preceded by an asterisk (for example, \fB%*c\fR) which causes the word
|
||||
"at" or "on" that would normally be included in the output to be
|
||||
omitted.
|
||||
.TP
|
||||
o
|
||||
The ! and ? substitutions may be preceded by an asterisk (%*! or %*?),
|
||||
The ! and ? substitutions may be preceded by an asterisk (\fB%*!\fR or \fB%*?\fR),
|
||||
in which case the comparison is made between the trigger date and
|
||||
realtoday() instead of today().
|
||||
.TP
|
||||
@@ -1944,7 +1957,7 @@ which recurrences have been completed. For example:
|
||||
Canadian income taxes must be filed every 30 April. The above command
|
||||
will remind you to pay taxes in 2026. If you don't update the
|
||||
COMPLETE-THROUGH date, then after 30 April 2026, \fBRemind\fR will
|
||||
keep reminding you until the end of time that my taxes were due on 30
|
||||
keep reminding you until the end of time that your taxes were due on 30
|
||||
April 2026. To indicate that you've paid them, simply update the
|
||||
COMPLETE-THROUGH date to 2026-04-30 and then \fBRemind\fR will start
|
||||
reminding you of your 2027 taxes (starting 15 days before the due
|
||||
@@ -1952,6 +1965,26 @@ date.)
|
||||
.PP
|
||||
It is an error to specify COMPLETE-THROUGH without also specifying TODO.
|
||||
.PP
|
||||
.SH LIMITING REMINDERS ABOUT OVERDUE TODOS
|
||||
.PP
|
||||
Although \fBRemind\fR is happy to keep reminding you about overdue
|
||||
TODOs for hundreds of years, for some things this may be pointless.
|
||||
If you want \fBRemind\fR to \fIstop\fR nagging you about an overdue
|
||||
TODO after a certain number of days, use the MAX-OVERDUE \fIn\fR clause.
|
||||
In this case, \fBRemind\fR stops reminding you of a TODO that is overdue
|
||||
by more than \fIn\fR days. Here is an example.
|
||||
.PP
|
||||
.nf
|
||||
REM TODO 2025-08-13 ++5 MAX-OVERDUE 5 MSG Task: %b.
|
||||
.fi
|
||||
.PP
|
||||
\fBRemind\fR \fIstarts\fR reminding you of the task on 2025-08-08,
|
||||
because of the ++5 back value. It keeps reminding you of the task
|
||||
after the due date. However, the last time it will remind you
|
||||
will be on 2025-08-18, because of the MAX-OVERDUE clause. Starting
|
||||
on 2025-08-19, \fBRemind\fR will no longer remind you of the task
|
||||
since it's probably pointless---it has passed the MAX-OVERDUE period.
|
||||
.PP
|
||||
.SH MORE DETAILS ABOUT TODOS
|
||||
.PP
|
||||
TODOs are treated specially only in Agenda Mode. In Calendar Mode,
|
||||
@@ -2969,6 +3002,10 @@ output is not a terminal, then the default is 72.If an \fBMSF\fR-type
|
||||
reminder contains a word too long to fit in this width, it will not be
|
||||
truncated - the width limit will be ignored.
|
||||
.TP
|
||||
.B $HideCompletedTodos (read-only)
|
||||
If non-zero, then the \fB\-\-hide-completed-todos\fR option was supplied
|
||||
on the command line.
|
||||
.TP
|
||||
.B $HushMode (read-only)
|
||||
If non-zero, then the \fB\-h\fR option was supplied on the command line.
|
||||
.TP
|
||||
@@ -3056,6 +3093,9 @@ updates \fB$LongDeg\fR, \fB$LongMin\fR and \fB$LongSec\fR. Similar
|
||||
rules apply to \fB$Latitude\fR, \fB$LatDeg\fR, \fB$LatMin\fR and \fB$LatSec\fR.
|
||||
.RE
|
||||
.TP
|
||||
.B $JSONMode (read-only)
|
||||
If non-zero, then the \fB\-\-json\fR command-line option was supplied.
|
||||
.TP
|
||||
.B $MaxLateMinutes
|
||||
This variable controls how \fBRemind\fR reacts to a computer being suspended
|
||||
and then woken. Normally, if a timed reminder is queued and then the
|
||||
@@ -3259,6 +3299,11 @@ This variable returns 1 if the internal C \fBtime_t\fR type is at least
|
||||
to represent dates after about 2038, and \fBRemind\fR will use a workaround to avoid
|
||||
problems. See also the section "MACHINES WITH A 32-BIT TIME_T TYPE"
|
||||
.TP
|
||||
.B $TodoFilter (read-only)
|
||||
If 0, then both events and TODOs are being output. If 1, then the
|
||||
\fB\-\-only-todos\fR command-line option was supplied. If 2, then
|
||||
the \fB\-\-only-events\fR command-line option was spplied.
|
||||
.TP
|
||||
.B $UntimedFirst (read-only)
|
||||
Set to 1 if the \fB\-g\fR option is used with a fourth sort character
|
||||
of "d"; set to 0 otherwise.
|
||||
@@ -4742,6 +4787,18 @@ the empty string to variable b:
|
||||
.PP
|
||||
.RE
|
||||
.TP
|
||||
.B trigistodo()
|
||||
Returns 1 if the last \fRREM\fR command was a \fBTODO\fR type or 0 if not.
|
||||
.TP
|
||||
.B trigcompletethrough()
|
||||
Returns a \fBDATE\fR object that is the COMPLETE-THROUGH date of the most
|
||||
recent \fBREM\fR command. If there was no COMPLETE-THROUGH date,
|
||||
returns the \fBINT\fR 0.
|
||||
.TP
|
||||
.B trigmaxoverdue()
|
||||
Returns an \fBINT\fR that is the MAX-OVERDUE value of the most recent \fBREM\fR
|
||||
command. If there was no MAX-OVERDUE clause, returns -1.
|
||||
.TP
|
||||
.B trigger(d_date [,t_time [,i_utcflag]]) \fRor\fB trigger(q_datetime [,i_utcflag])
|
||||
Returns a string suitable for use in a \fBREM\fR command or a
|
||||
\fBSCANFROM\fR or UNTIL clause, allowing you to calculate trigger
|
||||
@@ -6432,6 +6489,20 @@ as:
|
||||
FSET subst_bx(a,d,t) iif(d==today()+2, "the day after tomorrow", 0)
|
||||
.fi
|
||||
.PP
|
||||
You can override substitution sequences that are not alphanumeric as follows:
|
||||
.RS
|
||||
.PP
|
||||
Override %: with \fBsubst_colon\fR
|
||||
.PP
|
||||
Override %! with \fBsubst_bang\fR
|
||||
.PP
|
||||
Override %? with \fBsubst_question\fR
|
||||
.PP
|
||||
Override %@ with \fBsubst_at\fR
|
||||
.PP
|
||||
Override %# with \fBsubst_hash\fR
|
||||
.RE
|
||||
.PP
|
||||
You can define your own substitution sequences in addition to the built-in
|
||||
ones as follows: If you define a function named \fBsubst_\fIname\fB(alt, date, time)\fR, then the sequence \fB%{name}\fR calls the function with \fBalt\fR
|
||||
set to 0 and \fBdate\fR and \fBtime\fR to the trigger date and time,
|
||||
|
||||
@@ -99,9 +99,11 @@ with the reminder. You can also specify advance notice, possibly
|
||||
repeating.
|
||||
|
||||
The sixth control allows you to specify whether the reminder is a TODO,
|
||||
and if so, its completion date. Double-clicking in the "Complete through"
|
||||
and if so, its completion date. Double-clicking in the "Complete through:"
|
||||
field automatically fills in the date of the calendar entry. Otherwise,
|
||||
enter a possible completion date in the form YYYY-MM-DD.
|
||||
enter a possible completion date in the form YYYY-MM-DD. You can also enter
|
||||
a number in the "Max overdue days:" field to limit how many days past the
|
||||
due date \fBRemind\fR will keep reminding you of the TODO.
|
||||
|
||||
The seventh control specifies what \fBRemind\fR should do if a reminder
|
||||
falls on a holiday or weekend.
|
||||
|
||||
@@ -1718,8 +1718,10 @@ proc toggle_complete_through { w } {
|
||||
global todobut
|
||||
if {$todobut} {
|
||||
$w.complete_through configure -state normal
|
||||
$w.max_overdue configure -state normal
|
||||
} else {
|
||||
$w.complete_through configure -state disabled
|
||||
$w.max_overdue configure -state disabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1962,7 +1964,7 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
pack $w.durationbut $w.durationh $w.durationcolon $w.durationm -side left -anchor w -in $w.durationbox
|
||||
|
||||
# TODO?
|
||||
checkbutton $w.todobut -text "This is a TODO " -command [list toggle_complete_through $w]
|
||||
checkbutton $w.todobut -text "This is a TODO " -command [list toggle_complete_through $w]
|
||||
|
||||
balloon_add_help $w.todobut "Select if this is a TODO-type reminder"
|
||||
$w.todobut deselect
|
||||
@@ -1970,7 +1972,10 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
entry $w.complete_through -width 20
|
||||
bind $w.complete_through <Double-Button-1> [list complete_through_today $w]
|
||||
balloon_add_help $w.complete_through "Enter the date of completed TODO in the form YYYY-MM-DD"
|
||||
pack $w.todobut $w.lcomplete $w.complete_through -side left -anchor w -in $w.todobox
|
||||
label $w.loverdue -text "Max overdue days: "
|
||||
entry $w.max_overdue -width 6
|
||||
balloon_add_help $w.max_overdue "Enter the maximum number of days Remind should nag you about an overdue TODO"
|
||||
pack $w.todobut $w.lcomplete $w.complete_through $w.loverdue $w.max_overdue -side left -anchor w -in $w.todobox
|
||||
|
||||
# SKIP TYPE
|
||||
label $w.labhol -text "On holidays or weekends:"
|
||||
@@ -2079,6 +2084,7 @@ proc OptionsToRemindDialog { w opts } {
|
||||
set hour ""
|
||||
set ampm ""
|
||||
$w.complete_through configure -state normal
|
||||
$w.max_overdue configure -state normal
|
||||
foreach {flag value} $opts {
|
||||
switch -glob -- $flag {
|
||||
"-text-*" {
|
||||
@@ -2361,6 +2367,10 @@ proc CreateReminder {w} {
|
||||
if {"$ct" != ""} {
|
||||
append rem " COMPLETE-THROUGH $ct"
|
||||
}
|
||||
set mo [string trim [$w.max_overdue get]]
|
||||
if {"$mo" != ""} {
|
||||
append rem " MAX-OVERDUE $mo"
|
||||
}
|
||||
}
|
||||
global SkipType
|
||||
if {$SkipType == 2} {
|
||||
@@ -3581,6 +3591,12 @@ proc ReadTaggedOptions { tag date } {
|
||||
lappend ans -entry-complete_through ""
|
||||
}
|
||||
|
||||
if {[dict exists $obj max_overdue]} {
|
||||
lappend ans -entry-max_overdue [dict get $obj max_overdue]
|
||||
} else {
|
||||
lappend ans -entry-max_overdue ""
|
||||
}
|
||||
|
||||
# Figure out the reminder type
|
||||
if {[dict exists $obj rep]} {
|
||||
# Repeat must be type 1
|
||||
@@ -3756,7 +3772,7 @@ proc EditableEnter { w } {
|
||||
if {"$c" != ""} {
|
||||
$w tag configure $tag -underline 1
|
||||
# underlinefg not supported on older versions of Tk
|
||||
eval { $w tag configure $tag -underlinefg $c }
|
||||
catch { $w tag configure $tag -underlinefg $c }
|
||||
} else {
|
||||
$w tag configure $tag -underline 1
|
||||
}
|
||||
@@ -4302,7 +4318,7 @@ proc DisplayTimeContinuously {} {
|
||||
DisplayTime
|
||||
|
||||
# Reap any zombies
|
||||
eval { exec true }
|
||||
catch { exec true }
|
||||
|
||||
set secs [clock format [clock seconds] -format "%S"]
|
||||
# Doh -- don't interpret as an octal number if leading zero
|
||||
@@ -4372,7 +4388,7 @@ proc ShowTodaysReminders { force date } {
|
||||
} else {
|
||||
set date [clock format [clock seconds] -format "%Y-%m-%d" -locale C]
|
||||
}
|
||||
append cmdline " 2>@1"
|
||||
append cmdline " 2>/dev/null"
|
||||
set f [open $cmdline r]
|
||||
while {[gets $f line] >= 0} {
|
||||
append stuff "$line\n"
|
||||
|
||||
@@ -2520,6 +2520,9 @@ void WriteJSONTrigger(Trigger const *t, int include_tags)
|
||||
PrintJSONKeyPairInt("scanfrom", t->scanfrom);
|
||||
}
|
||||
}
|
||||
if (t->max_overdue >= 0) {
|
||||
PrintJSONKeyPairInt("max_overdue", t->max_overdue);
|
||||
}
|
||||
PrintJSONKeyPairDate("from", t->from);
|
||||
PrintJSONKeyPairInt("priority", t->priority);
|
||||
PrintJSONKeyPairDateTime("eventstart", t->eventstart);
|
||||
|
||||
42
src/dorem.c
42
src/dorem.c
@@ -293,6 +293,12 @@ int DoRem(ParsePtr p)
|
||||
return E_COMPLETE_WITHOUT_TODO;
|
||||
}
|
||||
|
||||
if (trig.max_overdue >= 0 && !trig.is_todo) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
FreeTrig(&trig);
|
||||
return E_MAX_OVERDUE_WITHOUT_TODO;
|
||||
}
|
||||
|
||||
if (trig.typ == NO_TYPE) {
|
||||
if (!Hush) {
|
||||
PurgeEchoLine("%s\n", "#!P! Cannot parse next line");
|
||||
@@ -668,6 +674,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
tim->duration = NO_TIME;
|
||||
trig->need_wkday = 0;
|
||||
trig->is_todo = 0;
|
||||
trig->max_overdue = -1;
|
||||
trig->complete_through = NO_DATE;
|
||||
trig->adj_for_last = 0;
|
||||
trig->infos = NULL;
|
||||
@@ -758,6 +765,25 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
trig->skip = tok.val;
|
||||
break;
|
||||
|
||||
case T_MaxOverdue:
|
||||
if (trig->max_overdue >= 0) return E_MAX_OVERDUE_TWICE;
|
||||
DBufFree(&buf);
|
||||
r = ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
DBufFree(&buf);
|
||||
if (tok.type == T_Illegal) {
|
||||
return -tok.val;
|
||||
}
|
||||
if (tok.type != T_Day && tok.type != T_Year && tok.type != T_Number) {
|
||||
return E_EXPECTING_NUMBER;
|
||||
}
|
||||
if (tok.val < 0) {
|
||||
return E_2LOW;
|
||||
}
|
||||
trig->max_overdue = tok.val;
|
||||
break;
|
||||
|
||||
case T_Priority:
|
||||
DBufFree(&buf);
|
||||
r=ParsePriority(s, trig);
|
||||
@@ -1664,8 +1690,14 @@ int ShouldTriggerReminder(Trigger const *t, TimeTrig const *tim, int dse, int *e
|
||||
}
|
||||
/* DO trigger if has not been completed through trigger date */
|
||||
if (t->complete_through == NO_DATE || t->complete_through < dse) {
|
||||
/* Trigger date is in the past - overdue */
|
||||
/* Trigger date is in the past - overdue, Trigger unless we're
|
||||
more than max_overdue days late */
|
||||
if (dse < DSEToday) {
|
||||
if (t->max_overdue >= 0) {
|
||||
if (dse + t->max_overdue < DSEToday) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* Trigger date in future - use normal Remind rules */
|
||||
@@ -1961,8 +1993,14 @@ static int ShouldTriggerBasedOnWarn(Trigger const *t, int dse, int *err)
|
||||
}
|
||||
/* DO trigger if has not been completed through trigger date */
|
||||
if (t->complete_through == NO_DATE || t->complete_through < dse) {
|
||||
/* Trigger date is in the past - overdue */
|
||||
/* Trigger date is in the past - overdue, Trigger unless we're
|
||||
more than max_overdue days late */
|
||||
if (dse < DSEToday) {
|
||||
if (t->max_overdue >= 0) {
|
||||
if (dse + t->max_overdue < DSEToday) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* Trigger date in future - use normal Remind rules */
|
||||
|
||||
@@ -31,6 +31,39 @@
|
||||
|
||||
#define SHIP_OUT(s) if(DBufPuts(dbuf, s) != OK) return E_NO_MEM
|
||||
|
||||
static char const *
|
||||
get_function_override(int c, int addx)
|
||||
{
|
||||
static char func[32];
|
||||
|
||||
if (isalnum(c) || c == '_') {
|
||||
if (addx) {
|
||||
snprintf(func, sizeof(func), "subst_%cx", tolower(c));
|
||||
} else {
|
||||
snprintf(func, sizeof(func), "subst_%c", tolower(c));
|
||||
}
|
||||
return func;
|
||||
}
|
||||
if (addx) {
|
||||
switch(c) {
|
||||
case ':': return "subst_colonx";
|
||||
case '!': return "subst_bangx";
|
||||
case '?': return "subst_questionx";
|
||||
case '@': return "subst_atx";
|
||||
case '#': return "subst_hashx";
|
||||
}
|
||||
} else {
|
||||
switch(c) {
|
||||
case ':': return "subst_colon";
|
||||
case '!': return "subst_bang";
|
||||
case '?': return "subst_question";
|
||||
case '@': return "subst_at";
|
||||
case '#': return "subst_hash";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
check_subst_args(UserFunc *f, int n)
|
||||
{
|
||||
@@ -75,7 +108,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig const *tt, int
|
||||
char const *expr;
|
||||
char *os;
|
||||
char s[256];
|
||||
char uf[32];
|
||||
char const *substname;
|
||||
char mypm[64];
|
||||
char mycpm[64];
|
||||
char myplu[64];
|
||||
@@ -340,11 +373,15 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig const *tt, int
|
||||
continue;
|
||||
}
|
||||
done = 0;
|
||||
snprintf(uf, sizeof(uf), "subst_%c", tolower(c));
|
||||
func = FindUserFunc(uf);
|
||||
substname = get_function_override(c, 0);
|
||||
if (substname) {
|
||||
func = FindUserFunc(substname);
|
||||
} else {
|
||||
func = NULL;
|
||||
}
|
||||
if (func && check_subst_args(func, 3)) {
|
||||
snprintf(s, sizeof(s), "subst_%c(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
snprintf(s, sizeof(s), "%s(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
substname, altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
if (r == OK) {
|
||||
@@ -392,11 +429,15 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig const *tt, int
|
||||
|
||||
|
||||
if (!done) {
|
||||
snprintf(uf, sizeof(uf), "subst_%cx", tolower(c));
|
||||
func = FindUserFunc(uf);
|
||||
substname = get_function_override(c, 1);
|
||||
if (substname) {
|
||||
func = FindUserFunc(substname);
|
||||
} else {
|
||||
func = NULL;
|
||||
}
|
||||
if (func && check_subst_args(func, 3)) {
|
||||
snprintf(s, sizeof(s), "subst_%cx(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
snprintf(s, sizeof(s), "%s(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
substname, altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
if (r == OK) {
|
||||
@@ -617,6 +658,12 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig const *tt, int
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (t->is_todo && t->complete_through != NO_DATE && t->complete_through >= dse) {
|
||||
snprintf(s, sizeof(s), " (%s)", tr("done"));
|
||||
SHIP_OUT(s);
|
||||
}
|
||||
break;
|
||||
case '1':
|
||||
if (tdiff == 0)
|
||||
snprintf(s, sizeof(s), "%s", tr("now"));
|
||||
|
||||
@@ -130,6 +130,8 @@
|
||||
#define E_EXPR_DISABLED 106
|
||||
#define E_TIME_EXCEEDED 107
|
||||
#define E_COMPLETE_WITHOUT_TODO 108
|
||||
#define E_MAX_OVERDUE_TWICE 109
|
||||
#define E_MAX_OVERDUE_WITHOUT_TODO 110
|
||||
|
||||
#ifdef MK_GLOBALS
|
||||
#undef EXTERN
|
||||
@@ -257,6 +259,8 @@ EXTERN char *ErrMsg[]
|
||||
/* E_EXPR_DISABLED */ "Expression evaluation is disabled",
|
||||
/* E_TIME_EXCEEDED */ "Time limit for expression evaluation exceeded",
|
||||
/* E_COMPLETE_WITHOUT_TODO */ "COMPLETE-THROUGH specified without TODO",
|
||||
/* E_MAX_OVERDUE_TWICE */ "MAX-OVERDUE specified twice",
|
||||
/* E_MAX_OVERDUE_WITHOUT_TODO */ "MAX-OVERDUE specified without TODO",
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
|
||||
25
src/files.c
25
src/files.c
@@ -179,17 +179,14 @@ got_a_fresh_line(void)
|
||||
WarnedAboutImplicit = 0;
|
||||
}
|
||||
|
||||
static void set_cloexec(FILE *fp)
|
||||
void set_cloexec(int fd)
|
||||
{
|
||||
int flags;
|
||||
int fd;
|
||||
if (fp) {
|
||||
fd = fileno(fp);
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
if (flags >= 0) {
|
||||
flags |= FD_CLOEXEC;
|
||||
fcntl(fd, F_SETFD, flags);
|
||||
}
|
||||
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
if (flags >= 0) {
|
||||
flags |= FD_CLOEXEC;
|
||||
fcntl(fd, F_SETFD, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +215,7 @@ static void OpenPurgeFile(char const *fname, char const *mode)
|
||||
fprintf(ErrFp, tr("Cannot open `%s' for writing: %s"), DBufValue(&fname_buf), strerror(errno));
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
set_cloexec(PurgeFP);
|
||||
set_cloexec(fileno(PurgeFP));
|
||||
DBufFree(&fname_buf);
|
||||
}
|
||||
|
||||
@@ -427,7 +424,9 @@ static int OpenFile(char const *fname)
|
||||
}
|
||||
} else {
|
||||
fp = fopen(fname, "r");
|
||||
set_cloexec(fp);
|
||||
if (fp) {
|
||||
set_cloexec(fileno(fp));
|
||||
}
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, tr("Reading `%s': Opening file on disk"), fname);
|
||||
fprintf(ErrFp, "\n");
|
||||
@@ -449,7 +448,7 @@ static int OpenFile(char const *fname)
|
||||
if (strcmp(fname, "-")) {
|
||||
fp = fopen(fname, "r");
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
set_cloexec(fp);
|
||||
set_cloexec(fileno(fp));
|
||||
if (PurgeMode) OpenPurgeFile(fname, "w");
|
||||
} else {
|
||||
fp = stdin;
|
||||
@@ -650,7 +649,7 @@ static int PopFile(void)
|
||||
if (strcmp(i->filename, "-")) {
|
||||
fp = fopen(i->filename, "r");
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
set_cloexec(fp);
|
||||
set_cloexec(fileno(fp));
|
||||
if (PurgeMode) OpenPurgeFile(i->filename, "a");
|
||||
} else {
|
||||
fp = stdin;
|
||||
|
||||
32
src/funcs.c
32
src/funcs.c
@@ -173,6 +173,7 @@ static int FToday (func_info *);
|
||||
static int FTrig (func_info *);
|
||||
static int FTrigback (func_info *);
|
||||
static int FTrigbase (func_info *info);
|
||||
static int FTrigcompletethrough (func_info *);
|
||||
static int FTrigdate (func_info *);
|
||||
static int FTrigdatetime (func_info *);
|
||||
static int FTrigdelta (func_info *);
|
||||
@@ -182,6 +183,8 @@ static int FTrigeventduration(func_info *);
|
||||
static int FTrigeventstart (func_info *);
|
||||
static int FTrigfrom (func_info *);
|
||||
static int FTrigger (func_info *);
|
||||
static int FTrigistodo (func_info *);
|
||||
static int FTrigmaxoverdue (func_info *);
|
||||
static int FTrigpriority (func_info *);
|
||||
static int FTrigrep (func_info *);
|
||||
static int FTrigscanfrom (func_info *);
|
||||
@@ -347,6 +350,7 @@ BuiltinFunc Func[] = {
|
||||
{ "trig", 0, NO_MAX, 0, FTrig, NULL },
|
||||
{ "trigback", 0, 0, 0, FTrigback, NULL },
|
||||
{ "trigbase", 0, 0, 0, FTrigbase, NULL },
|
||||
{ "trigcompletethrough", 0, 0, 0, FTrigcompletethrough, NULL },
|
||||
{ "trigdate", 0, 0, 0, FTrigdate, NULL },
|
||||
{ "trigdatetime", 0, 0, 0, FTrigdatetime, NULL },
|
||||
{ "trigdelta", 0, 0, 0, FTrigdelta, NULL },
|
||||
@@ -356,6 +360,8 @@ BuiltinFunc Func[] = {
|
||||
{ "trigfrom", 0, 0, 0, FTrigfrom, NULL },
|
||||
{ "trigger", 1, 3, 0, FTrigger, NULL },
|
||||
{ "triginfo", 1, 1, 0, FTriginfo, NULL },
|
||||
{ "trigistodo", 0, 0, 0, FTrigistodo, NULL },
|
||||
{ "trigmaxoverdue", 0, 0, 0, FTrigmaxoverdue, NULL },
|
||||
{ "trigpriority", 0, 0, 0, FTrigpriority, NULL },
|
||||
{ "trigrep", 0, 0, 0, FTrigrep, NULL },
|
||||
{ "trigscanfrom", 0, 0, 0, FTrigscanfrom, NULL },
|
||||
@@ -1897,6 +1903,32 @@ static int FTrigback(func_info *info)
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigcompletethrough(func_info *info)
|
||||
{
|
||||
if (!LastTrigger.is_todo || LastTrigger.complete_through == NO_DATE) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = 0;
|
||||
return OK;
|
||||
}
|
||||
RetVal.type = DATE_TYPE;
|
||||
RETVAL = LastTrigger.complete_through;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigistodo(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = LastTrigger.is_todo;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigmaxoverdue(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = LastTrigger.max_overdue;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigdelta(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
|
||||
10
src/init.c
10
src/init.c
@@ -803,6 +803,8 @@ void InitRemind(int argc, char const *argv[])
|
||||
SortByTime = SORT_NONE;
|
||||
SortByDate = SORT_NONE;
|
||||
SortByPrio = SORT_NONE;
|
||||
/* Make sure we don't blat errors to stdout! */
|
||||
ErrFp = stderr;
|
||||
}
|
||||
|
||||
/* Figure out the offset from UTC */
|
||||
@@ -1149,10 +1151,18 @@ ProcessLongOption(char const *arg)
|
||||
return;
|
||||
}
|
||||
if (!strcmp(arg, "only-todos")) {
|
||||
if (TodoFilter == ONLY_EVENTS) {
|
||||
fprintf(ErrFp, "remind: Cannot combine --only-todos and --only-events\n");
|
||||
exit(1);
|
||||
}
|
||||
TodoFilter = ONLY_TODOS;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(arg, "only-events")) {
|
||||
if (TodoFilter == ONLY_TODOS) {
|
||||
fprintf(ErrFp, "remind: Cannot combine --only-todos and --only-events\n");
|
||||
exit(1);
|
||||
}
|
||||
TodoFilter = ONLY_EVENTS;
|
||||
return;
|
||||
}
|
||||
|
||||
20
src/main.c
20
src/main.c
@@ -1576,6 +1576,15 @@ void DoExit(ParsePtr p)
|
||||
|
||||
if (PurgeMode) return;
|
||||
|
||||
if (JSONMode) {
|
||||
if (JSONLinesEmitted) {
|
||||
printf("}\n");
|
||||
}
|
||||
/* Close the reminder list */
|
||||
printf("]\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
r = EvaluateExpr(p, &v);
|
||||
if (r || v.type != INT_TYPE) exit(99);
|
||||
exit(v.v.val);
|
||||
@@ -2056,11 +2065,15 @@ ClearLastTriggers(void)
|
||||
LastTrigger.warn[0] = 0;
|
||||
LastTrigger.omitfunc[0] = 0;
|
||||
LastTrigger.passthru[0] = 0;
|
||||
LastTrigger.is_todo = 0;
|
||||
LastTrigger.complete_through = NO_DATE;
|
||||
LastTrigger.max_overdue = -1;
|
||||
FreeTrig(&LastTrigger);
|
||||
LastTimeTrig.ttime = NO_TIME;
|
||||
LastTimeTrig.delta = NO_DELTA;
|
||||
LastTimeTrig.rep = NO_REP;
|
||||
LastTimeTrig.duration = NO_TIME;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2137,7 +2150,12 @@ System(char const *cmd, int is_queued)
|
||||
}
|
||||
}
|
||||
/* This is the child process or original if we never forked */
|
||||
(void) system(cmd);
|
||||
if (JSONMode) {
|
||||
|
||||
(void) system_to_stderr(cmd);
|
||||
} else {
|
||||
(void) system(cmd);
|
||||
}
|
||||
if (do_exit) {
|
||||
/* In the child process, so exit! */
|
||||
exit(0);
|
||||
|
||||
@@ -512,6 +512,14 @@ DumpOmits(void)
|
||||
{
|
||||
int i;
|
||||
int y, m, d;
|
||||
|
||||
/* Do nothing in --json mode */
|
||||
if (JSONMode) {
|
||||
return;
|
||||
}
|
||||
if (PurgeMode) {
|
||||
return;
|
||||
}
|
||||
printf("Global Full OMITs (%d of maximum allowed %d):\n", NumFullOmits, MAX_FULL_OMITS);
|
||||
if (!NumFullOmits) {
|
||||
printf("\tNone.\n");
|
||||
|
||||
@@ -292,3 +292,5 @@ void SetCurrentFilename(char const *fname);
|
||||
char const *GetCurrentFilename(void);
|
||||
int get_scanfrom(Trigger const *t);
|
||||
void remove_trailing_newlines(DynamicBuffer *buf);
|
||||
void set_cloexec(int fd);
|
||||
int system_to_stderr(char const *cmd);
|
||||
|
||||
@@ -80,6 +80,7 @@ Token TokArray[] = {
|
||||
{ "lastday", 7, T_BackAdj, -1 },
|
||||
{ "lastworkday", 11, T_BackAdj, 1 },
|
||||
{ "march", 3, T_Month, 2 },
|
||||
{ "max-overdue", 11, T_MaxOverdue, 0 },
|
||||
{ "may", 3, T_Month, 4 },
|
||||
{ "maybe-uncomputable", 5, T_MaybeUncomputable, 0},
|
||||
{ "monday", 3, T_WkDay, 0 },
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@@ -63,6 +64,9 @@ GenerateTranslationTemplate(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (JSONMode) {
|
||||
return;
|
||||
}
|
||||
printf("# Translation table template\n\n");
|
||||
|
||||
printf("TRANSLATE \"LANGID\" ");
|
||||
@@ -233,6 +237,10 @@ DumpTranslationTable(FILE *fp, int json)
|
||||
XlateItem *item;
|
||||
int done = 0;
|
||||
char const *t;
|
||||
|
||||
if (fileno(fp) == STDOUT_FILENO && JSONMode) {
|
||||
return;
|
||||
}
|
||||
if (!json) {
|
||||
fprintf(fp, "# Translation table\n");
|
||||
/* Always to LANGID first */
|
||||
|
||||
@@ -145,6 +145,7 @@ typedef struct {
|
||||
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
|
||||
int addomit; /* Add trigger date to global OMITs */
|
||||
int noqueue; /* Don't queue even if timed */
|
||||
int max_overdue; /* Stop warning if TODO is too far overdue */
|
||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||
@@ -234,7 +235,7 @@ enum TokTypes
|
||||
T_Else, T_Empty, T_EndIf, T_ErrMsg, T_Exit, T_Expr, T_Flush,
|
||||
T_Frename, T_Fset, T_Funset, T_If, T_IfTrig, T_In, T_Include,
|
||||
T_IncludeCmd, T_IncludeR, T_IncludeSys, T_Info, T_LastBack,
|
||||
T_LongTime, T_MaybeUncomputable, T_Month, T_NoQueue, T_Number,
|
||||
T_LongTime, T_MaxOverdue, T_MaybeUncomputable, T_Month, T_NoQueue, T_Number,
|
||||
T_Omit, T_OmitFunc, T_Once, T_Ordinal, T_Pop, T_PopFuncs, T_PopVars,
|
||||
T_Preserve, T_Priority, T_Push, T_PushFuncs, T_PushVars, T_Rem,
|
||||
T_RemType, T_Rep, T_Return, T_Scanfrom, T_Sched, T_Set, T_Skip, T_Tag,
|
||||
|
||||
38
src/utils.c
38
src/utils.c
@@ -17,6 +17,7 @@ static char const DontEscapeMe[] =
|
||||
#include "err.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
@@ -30,6 +31,43 @@ static char const DontEscapeMe[] =
|
||||
#include "globals.h"
|
||||
#include "protos.h"
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* system_to_stderr */
|
||||
/* */
|
||||
/* Run system(...) but with stdout redirected to stderr */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int system_to_stderr(char const *cmd)
|
||||
{
|
||||
int stdout_dup = dup(STDOUT_FILENO);
|
||||
int r;
|
||||
|
||||
if (stdout_dup < 0) {
|
||||
perror("dup");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Duplicate STDERR onto STDOUT */
|
||||
if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
|
||||
(void) close(stdout_dup);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set close-on-exec flag on stdout_dup */
|
||||
set_cloexec(stdout_dup);
|
||||
|
||||
r = system(cmd);
|
||||
|
||||
/* Restore original stdout */
|
||||
/* If this dup2 fails... there's not a whole lot we can do. */
|
||||
(void) dup2(stdout_dup, STDOUT_FILENO);
|
||||
if (STDOUT_FILENO != stdout_dup) {
|
||||
(void) close(stdout_dup);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* StrnCpy */
|
||||
|
||||
@@ -761,6 +761,7 @@ int DoDump(ParsePtr p)
|
||||
int dump_constness = 0;
|
||||
|
||||
if (PurgeMode) return OK;
|
||||
if (JSONMode) return OK;
|
||||
|
||||
DBufInit(&buf);
|
||||
r = ParseToken(p, &buf);
|
||||
@@ -992,6 +993,7 @@ static SysVar SysVarArr[] = {
|
||||
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 500 },
|
||||
{"Friday", 1, TRANS_TYPE, "Friday", 0, 0 },
|
||||
{"Fromnow", 1, TRANS_TYPE, "from now", 0, 0 },
|
||||
{"HideCompletedTodos", 0, INT_TYPE, &HideCompletedTodos, 0, 0 },
|
||||
{"Hour", 1, TRANS_TYPE, "hour", 0, 0 },
|
||||
{"Hplu", 1, STR_TYPE, &DynamicHplu, 0, 0 },
|
||||
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
|
||||
@@ -1001,6 +1003,7 @@ static SysVar SysVarArr[] = {
|
||||
{"IntMin", 0, INT_TYPE, &IntMin, 0, 0 },
|
||||
{"Is", 1, TRANS_TYPE, "is", 0, 0 },
|
||||
{"January", 1, TRANS_TYPE, "January", 0, 0 },
|
||||
{"JSONMode", 0, INT_TYPE, &JSONMode, 0, 0 },
|
||||
{"July", 1, TRANS_TYPE, "July", 0, 0 },
|
||||
{"June", 1, TRANS_TYPE, "June", 0, 0 },
|
||||
{"LatDeg", 1, SPECIAL_TYPE, latdeg_func, 0, 0 },
|
||||
@@ -1058,6 +1061,7 @@ static SysVar SysVarArr[] = {
|
||||
{"TimetIs64bit", 0, SPECIAL_TYPE, timet_is_64_func, 0, 0 },
|
||||
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0 },
|
||||
{"Today", 1, TRANS_TYPE, "today", 0, 0 },
|
||||
{"TodoFilter", 0, INT_TYPE, &TodoFilter, 0, 0 },
|
||||
{"Tomorrow", 1, TRANS_TYPE, "tomorrow", 0, 0 },
|
||||
{"Tt", 0, SPECIAL_TYPE, trig_time_func, 0, 0 },
|
||||
{"Tu", 0, SPECIAL_TYPE, trig_until_func, 0, 0 },
|
||||
|
||||
5
tests/json-redirect.rem
Normal file
5
tests/json-redirect.rem
Normal file
@@ -0,0 +1,5 @@
|
||||
BANNER %
|
||||
SET $AddBlankLines 0
|
||||
REM MSG Hello
|
||||
REM RUN echo This is executed by the shell.
|
||||
REM MSG Goodbye
|
||||
@@ -769,6 +769,24 @@ echo "Testing TODOS in calendar mode" >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out 2>&1
|
||||
echo "Testing TODOS in calendar mode with completed todos hidden" >> ../tests/test.out 2>&1
|
||||
../src/remind -s --hide-completed-todos ../tests/todos.rem 2025-08-13 >> ../tests/test.out 2>&1
|
||||
echo "Testing TODOS and JSON mode" >> ../tests/test.out 2>&1
|
||||
../src/remind --json ../tests/todos.rem 2025-08-13 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Testing proper redirection of RUN stdout in JSON mode... here's stdout" >> ../tests/test.out 2>&1
|
||||
../src/remind --json ../tests/json-redirect.rem 1 Jan 2025 >> ../tests/test.out 2>/dev/null
|
||||
|
||||
echo "... and here is stderr" >> ../tests/test.out 2>&1
|
||||
../src/remind --json ../tests/json-redirect.rem 1 Jan 2025 > /dev/null 2>> ../tests/test.out
|
||||
|
||||
# Test %: substitution sequence in all the languages
|
||||
for i in ../include/lang/??.rem ; do
|
||||
../src/remind "-ii=\"$i\"" -p - 2025-08-13 <<'EOF' 2>&1 | grep 2025/ >> ../tests/test.out
|
||||
DO [i]
|
||||
REM TODO 2025-08-13 MSG %(LANGID) Task1%:
|
||||
REM TODO 2025-08-13 COMPLETE-THROUGH 2025-08-12 MSG %(LANGID) Task2%:
|
||||
REM TODO 2025-08-13 COMPLETE-THROUGH 2025-08-13 MSG %(LANGID) Task3%:
|
||||
EOF
|
||||
done
|
||||
|
||||
cmp -s ../tests/test.out ../tests/test.cmp
|
||||
if [ "$?" = "0" ]; then
|
||||
|
||||
100
tests/test.cmp
100
tests/test.cmp
@@ -16580,12 +16580,13 @@ Entering UserFN c()
|
||||
Leaving UserFN c() => 33
|
||||
|
||||
DEBUG -xe
|
||||
Overridden: subst_colon subst_bang subst_question subst_at subst_hash
|
||||
Variable hash table statistics:
|
||||
Entries: 100144; Buckets: 87719; Non-empty Buckets: 66301
|
||||
Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510
|
||||
Growths: 13; Shrinks: 0
|
||||
Function hash table statistics:
|
||||
Entries: 100018; Buckets: 87719; Non-empty Buckets: 63574
|
||||
Entries: 100023; Buckets: 87719; Non-empty Buckets: 63576
|
||||
Maxlen: 5; Minlen: 0; Avglen: 1.140; Stddev: 0.934; Avg nonempty len: 1.573
|
||||
Growths: 13; Shrinks: 0
|
||||
Dedupe hash table statistics:
|
||||
@@ -24430,6 +24431,7 @@ info
|
||||
last
|
||||
lastday
|
||||
lastworkday
|
||||
max-overdue
|
||||
maybe
|
||||
maybe-uncomputable
|
||||
msf
|
||||
@@ -24618,6 +24620,7 @@ today
|
||||
trig
|
||||
trigback
|
||||
trigbase
|
||||
trigcompletethrough
|
||||
trigdate
|
||||
trigdatetime
|
||||
trigdelta
|
||||
@@ -24627,6 +24630,8 @@ trigeventstart
|
||||
trigfrom
|
||||
trigger
|
||||
triginfo
|
||||
trigistodo
|
||||
trigmaxoverdue
|
||||
trigpriority
|
||||
trigrep
|
||||
trigscanfrom
|
||||
@@ -24681,6 +24686,7 @@ $FoldYear
|
||||
$FormWidth
|
||||
$Friday
|
||||
$Fromnow
|
||||
$HideCompletedTodos
|
||||
$Hour
|
||||
$Hplu
|
||||
$HushMode
|
||||
@@ -24690,6 +24696,7 @@ $IntMax
|
||||
$IntMin
|
||||
$Is
|
||||
$January
|
||||
$JSONMode
|
||||
$July
|
||||
$June
|
||||
$LatDeg
|
||||
@@ -24747,6 +24754,7 @@ $TimeSep
|
||||
$TimetIs64bit
|
||||
$Tm
|
||||
$Today
|
||||
$TodoFilter
|
||||
$Tomorrow
|
||||
$Tt
|
||||
$Tu
|
||||
@@ -24962,6 +24970,8 @@ TRANSLATE "Duplicate argument name" ""
|
||||
TRANSLATE "Expression evaluation is disabled" ""
|
||||
TRANSLATE "Time limit for expression evaluation exceeded" ""
|
||||
TRANSLATE "COMPLETE-THROUGH specified without TODO" ""
|
||||
TRANSLATE "MAX-OVERDUE specified twice" ""
|
||||
TRANSLATE "MAX-OVERDUE specified without TODO" ""
|
||||
|
||||
# Other Messages
|
||||
TRANSLATE "%s function `%s' defined at %s(%s) does not use its argument" ""
|
||||
@@ -25044,6 +25054,7 @@ TRANSLATE "`%s' re-SET without being used (previous SET: %s:%d)" ""
|
||||
TRANSLATE "are" ""
|
||||
TRANSLATE "defined at" ""
|
||||
TRANSLATE "did you mean" ""
|
||||
TRANSLATE "done" ""
|
||||
TRANSLATE "here" ""
|
||||
TRANSLATE "psmoon() is deprecated; use SPECIAL MOON instead." ""
|
||||
TRANSLATE "psshade() is deprecated; use SPECIAL SHADE instead." ""
|
||||
@@ -39542,6 +39553,12 @@ On odd days
|
||||
2000/06/30 * * * * On days divisible by 5
|
||||
|
||||
Testing TODOS in agenda mode
|
||||
trigistodo() => 1
|
||||
trigcompletethrough() => 2024-12-31
|
||||
trigmaxoverdue() => 3
|
||||
trigistodo() => 0
|
||||
trigcompletethrough() => 0
|
||||
trigmaxoverdue() => -1
|
||||
First on 2025-08-01
|
||||
Second on 2022-08-01
|
||||
Third on 2023-08-01
|
||||
@@ -39550,6 +39567,10 @@ Fifth today
|
||||
Sixth on 2025-08-06
|
||||
Eighth on 2025-08-20
|
||||
Ninth today
|
||||
Yup today
|
||||
Yup2 yesterday
|
||||
Yup3 on 2025-08-11
|
||||
Yup4 on 2025-08-10
|
||||
|
||||
Testing TODOS in calendar mode
|
||||
2025/08/01 * * * * First
|
||||
@@ -39559,9 +39580,14 @@ Testing TODOS in calendar mode
|
||||
2025/08/06 * * * * Seventh
|
||||
2025/08/06 * * * * Eighth
|
||||
2025/08/06 * * * * Ninth
|
||||
2025/08/09 * * * * Nope
|
||||
2025/08/10 * * * * Yup4
|
||||
2025/08/11 * * * * Yup3
|
||||
2025/08/12 * * * * Yup2
|
||||
2025/08/13 * * * * Fifth
|
||||
2025/08/13 * * * * Eighth
|
||||
2025/08/13 * * * * Ninth
|
||||
2025/08/13 * * * * Yup
|
||||
2025/08/20 * * * * Fourth
|
||||
2025/08/20 * * * * Eighth
|
||||
2025/08/20 * * * * Ninth
|
||||
@@ -39573,10 +39599,82 @@ Testing TODOS in calendar mode with completed todos hidden
|
||||
2025/08/01 * * * * Second
|
||||
2025/08/01 * * * * Third
|
||||
2025/08/06 * * * * Sixth
|
||||
2025/08/09 * * * * Nope
|
||||
2025/08/10 * * * * Yup4
|
||||
2025/08/11 * * * * Yup3
|
||||
2025/08/12 * * * * Yup2
|
||||
2025/08/13 * * * * Fifth
|
||||
2025/08/13 * * * * Ninth
|
||||
2025/08/13 * * * * Yup
|
||||
2025/08/20 * * * * Fourth
|
||||
2025/08/20 * * * * Eighth
|
||||
2025/08/20 * * * * Ninth
|
||||
2025/08/27 * * * * Eighth
|
||||
2025/08/27 * * * * Ninth
|
||||
Testing TODOS and JSON mode
|
||||
[
|
||||
{"date":"2025-08-01","filename":"../tests/todos.rem","lineno":4,"d":1,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-1 ","priority":5000,"body":"First on 2025-08-01"},
|
||||
{"date":"2022-08-01","filename":"../tests/todos.rem","lineno":5,"d":1,"m":8,"is_todo":1,"complete_through":"2022-07-31","priority":5000,"body":"Second on 2022-08-01"},
|
||||
{"date":"2023-08-01","filename":"../tests/todos.rem","lineno":6,"d":1,"m":8,"is_todo":1,"complete_through":"2022-08-01","priority":5000,"body":"Third on 2023-08-01"},
|
||||
{"date":"2025-08-20","filename":"../tests/todos.rem","lineno":7,"d":20,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-20","priority":5000,"body":"Fourth on 2025-08-20"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":8,"d":13,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-13","priority":5000,"body":"Fifth today"},
|
||||
{"date":"2025-08-06","filename":"../tests/todos.rem","lineno":9,"d":6,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-6 ","priority":5000,"body":"Sixth on 2025-08-06"},
|
||||
{"date":"2025-08-20","filename":"../tests/todos.rem","lineno":11,"wd":["Wednesday"],"is_todo":1,"complete_through":"2025-08-13","delta":7,"priority":5000,"body":"Eighth on 2025-08-20"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":12,"wd":["Wednesday"],"is_todo":1,"complete_through":"2025-08-12","delta":7,"priority":5000,"body":"Ninth today"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":15,"d":13,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-13","max_overdue":3,"priority":5000,"body":"Yup today"},
|
||||
{"date":"2025-08-12","filename":"../tests/todos.rem","lineno":16,"d":12,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-12","max_overdue":3,"priority":5000,"body":"Yup2 yesterday"},
|
||||
{"date":"2025-08-11","filename":"../tests/todos.rem","lineno":17,"d":11,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-11","max_overdue":3,"priority":5000,"body":"Yup3 on 2025-08-11"},
|
||||
{"date":"2025-08-10","filename":"../tests/todos.rem","lineno":18,"d":10,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-10","max_overdue":3,"priority":5000,"body":"Yup4 on 2025-08-10"}
|
||||
]
|
||||
Testing proper redirection of RUN stdout in JSON mode... here's stdout
|
||||
[
|
||||
{"date":"2025-01-01","filename":"../tests/json-redirect.rem","lineno":3,"is_todo":0,"priority":5000,"body":"Hello"},
|
||||
{"date":"2025-01-01","filename":"../tests/json-redirect.rem","lineno":5,"is_todo":0,"priority":5000,"body":"Goodbye"}
|
||||
]
|
||||
... and here is stderr
|
||||
This is executed by the shell.
|
||||
2025/08/13 * * * * ca Task1
|
||||
2025/08/13 * * * * ca Task2
|
||||
2025/08/13 * * * * ca Task3 (completada)
|
||||
2025/08/13 * * * * da Task1
|
||||
2025/08/13 * * * * da Task2
|
||||
2025/08/13 * * * * da Task3 (fuldført)
|
||||
2025/08/13 * * * * de Task1
|
||||
2025/08/13 * * * * de Task2
|
||||
2025/08/13 * * * * de Task3 (abgeschlossen)
|
||||
2025/08/13 * * * * en Task1
|
||||
2025/08/13 * * * * en Task2
|
||||
2025/08/13 * * * * en Task3 (done)
|
||||
2025/08/13 * * * * es Task1
|
||||
2025/08/13 * * * * es Task2
|
||||
2025/08/13 * * * * es Task3 (completada)
|
||||
2025/08/13 * * * * fi Task1
|
||||
2025/08/13 * * * * fi Task2
|
||||
2025/08/13 * * * * fi Task3 (suoritettu)
|
||||
2025/08/13 * * * * fr Task1
|
||||
2025/08/13 * * * * fr Task2
|
||||
2025/08/13 * * * * fr Task3 (accomplie)
|
||||
2025/08/13 * * * * gr Task1
|
||||
2025/08/13 * * * * gr Task2
|
||||
2025/08/13 * * * * gr Task3 (ολοκληρώθηκε)
|
||||
2025/08/13 * * * * is Task1
|
||||
2025/08/13 * * * * is Task2
|
||||
2025/08/13 * * * * is Task3 (lokið)
|
||||
2025/08/13 * * * * it Task1
|
||||
2025/08/13 * * * * it Task2
|
||||
2025/08/13 * * * * it Task3 (completato)
|
||||
2025/08/13 * * * * nl Task1
|
||||
2025/08/13 * * * * nl Task2
|
||||
2025/08/13 * * * * nl Task3 (voltooid)
|
||||
2025/08/13 * * * * no Task1
|
||||
2025/08/13 * * * * no Task2
|
||||
2025/08/13 * * * * no Task3 (fullført)
|
||||
2025/08/13 * * * * pl Task1
|
||||
2025/08/13 * * * * pl Task2
|
||||
2025/08/13 * * * * pl Task3 (ukończone)
|
||||
2025/08/13 * * * * pt Task1
|
||||
2025/08/13 * * * * pt Task2
|
||||
2025/08/13 * * * * pt Task3 (concluída)
|
||||
2025/08/13 * * * * ro Task1
|
||||
2025/08/13 * * * * ro Task2
|
||||
2025/08/13 * * * * ro Task3 (finalizată)
|
||||
|
||||
@@ -1707,6 +1707,15 @@ set a c()
|
||||
|
||||
DEBUG -xe
|
||||
|
||||
fset subst_colon(a, b, c) "subst_colon"
|
||||
fset subst_bang(a, b, c) "subst_bang"
|
||||
fset subst_question(a, b, c) "subst_question"
|
||||
fset subst_at(a, b, c) "subst_at"
|
||||
fset subst_hash(a, b, c) "subst_hash"
|
||||
|
||||
REM MSG Overridden: %: %! %? %@ %#
|
||||
|
||||
|
||||
# Don't want Remind to queue reminders
|
||||
EXIT
|
||||
|
||||
|
||||
@@ -10,3 +10,23 @@ REM TODO 6 Aug 2025 +7 MSG %"Sixth%" %l
|
||||
REM TODO COMPLETE-THROUGH 2025-08-06 6 Aug 2025 +7 MSG %"Seventh%" %l
|
||||
REM TODO Wed +7 COMPLETE-THROUGH 2025-08-13 MSG %"Eighth%" %l
|
||||
REM TODO Wed +7 COMPLETE-THROUGH 2025-08-12 MSG %"Ninth%" %l
|
||||
|
||||
# Test MAX-OVERDUE
|
||||
REM TODO 2025-08-13 MAX-OVERDUE 3 MSG %"Yup%" %l
|
||||
REM TODO 2025-08-12 MAX-OVERDUE 3 MSG %"Yup2%" %l
|
||||
REM TODO 2025-08-11 MAX-OVERDUE 3 MSG %"Yup3%" %l
|
||||
REM TODO 2025-08-10 MAX-OVERDUE 3 MSG %"Yup4%" %l
|
||||
REM TODO 2025-08-9 MAX-OVERDUE 3 MSG %"Nope%" %l
|
||||
|
||||
IF !$JSONMode
|
||||
REM TODO 2025-09-09 COMPLETE-THROUGH 2024-12-31 MAX-OVERDUE 3 MSG %"Nope%" %l
|
||||
debug +x
|
||||
set a trigistodo()
|
||||
set a trigcompletethrough()
|
||||
set a trigmaxoverdue()
|
||||
REM 2025-09-09 MSG blork
|
||||
set a trigistodo()
|
||||
set a trigcompletethrough()
|
||||
set a trigmaxoverdue()
|
||||
debug -x
|
||||
ENDIF
|
||||
Reference in New Issue
Block a user