Add the triginfo("header") function and corresponding %<...> substitution sequence.

This commit is contained in:
Dianne Skoll
2025-02-01 14:39:06 -05:00
parent 231d9d77e7
commit 3b43222585
8 changed files with 94 additions and 7 deletions

View File

@@ -177,7 +177,7 @@
"slide" "soleq" "stdout" "strlen" "substr" "sunrise" "sunset" "time"
"timepart" "timezone" "today" "trig" "trigback" "trigdate"
"trigdatetime" "trigdelta" "trigduration" "trigeventduration"
"trigeventstart" "trigfrom" "trigger" "trigpriority" "trigrep"
"trigeventstart" "trigfrom" "trigger" "triginfo" "trigpriority" "trigrep"
"trigscanfrom" "trigtags" "trigtime" "trigtimedelta" "trigtimerep"
"triguntil" "trigvalid" "typeof" "tzconvert" "upper" "utctolocal"
"value" "version" "weekno" "wkday" "wkdaynum" "year")

View File

@@ -1661,6 +1661,11 @@ is replaced with "\fIyy\fR", the last two digits of the year.
is replaced with the lookup of \fIany_text\fR in the translation table.
It is the equivalent of [_("any_text")] but is more convenient to type.
.TP
.B %<\fIany_text\fR\fB>
is replaced with the INFO value associated with the header \fIany_text\fR
or the empty string if no such INFO value exists. It is the
equivalent of [triginfo("any_text")] but is more convenient to type.
.TP
.B %_
(percent-underscore) is replaced with a newline. You can use this to
achieve multi-line reminders. Note that calendar back-ends vary in
@@ -4292,7 +4297,23 @@ whose value is the maximum of "yyyy-mm-dd" and today.
.B trigfrom()
Returns (as a \fBDATE\fR type) the \fBFROM\fR parameter of the last \fBREM\fR or
\fBIFTRIG\fR command. If there was no \fBFROM\fR parameter, returns the integer -1.
.TP
.B triginfo(s_header)
Returns a \fBSTRING\fR that is the INFO item associated with the header
\fIheader\fR. The header should \fInot\fR contain a colon. Header name
comparisons are case-insensitive.
.RS
.PP
For example, the following will assign "At home" to the variable a and
the empty string to variable b:
.PP
.nf
REM INFO "Location: At home" MSG test
SET a triginfo("location")
SET b triginfo("no_such_header")
.fi
.PP
.RE
.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

View File

@@ -215,6 +215,33 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
if (!c) {
break;
}
if (c == '<') {
DynamicBuffer header;
char const *val;
DBufInit(&header);
while(1) {
c = ParseChar(p, &err, 0);
if (err) {
DBufFree(&header);
return err;
}
if (!c || c == '>') {
break;
}
DBufPutc(&header, c);
}
if (!c) {
Wprint(tr("Warning: Unterminated %%<...> substitution sequence"));
}
err = OK;
val = FindTrigInfo(t, DBufValue(&header));
DBufFree(&header);
if (val) {
SHIP_OUT(val);
}
continue;
}
if (c == '(') {
DynamicBuffer orig;
DynamicBuffer translated;

View File

@@ -162,6 +162,7 @@ static int FTrigdate (func_info *);
static int FTrigdatetime (func_info *);
static int FTrigdelta (func_info *);
static int FTrigduration (func_info *);
static int FTriginfo (func_info *);
static int FTrigeventduration(func_info *);
static int FTrigeventstart (func_info *);
static int FTrigfrom (func_info *);
@@ -326,6 +327,7 @@ BuiltinFunc Func[] = {
{ "trigeventstart", 0, 0, 0, FTrigeventstart, NULL },
{ "trigfrom", 0, 0, 0, FTrigfrom, NULL },
{ "trigger", 1, 3, 0, FTrigger, NULL },
{ "triginfo", 1, 1, 1, FTriginfo, NULL },
{ "trigpriority", 0, 0, 0, FTrigpriority, NULL },
{ "trigrep", 0, 0, 0, FTrigrep, NULL },
{ "trigscanfrom", 0, 0, 0, FTrigscanfrom, NULL },
@@ -1620,6 +1622,17 @@ static int FTrigeventduration(func_info *info)
return OK;
}
static int FTriginfo(func_info *info)
{
char const *s;
ASSERT_TYPE(0, STR_TYPE);
s = FindTrigInfo(&LastTrigger, ARGSTR(0));
if (!s) {
return RetStrVal("", info);
}
return RetStrVal(s, info);
}
static int FTrigeventstart(func_info *info)
{
if (LastTrigger.eventstart == NO_TIME) {

View File

@@ -282,3 +282,4 @@ void FreeTrigInfoChain(TrigInfo *ti);
int AppendTrigInfo(Trigger *t, char const *info);
int TrigInfoHeadersAreTheSame(char const *i1, char const *i2);
int TrigInfoIsValid(char const *info);
char const *FindTrigInfo(Trigger *t, char const *header);

View File

@@ -794,3 +794,26 @@ TrigInfoIsValid(char const *info)
}
return 1;
}
char const *
FindTrigInfo(Trigger *t, char const *header)
{
TrigInfo *ti;
size_t len;
char const *s;
if (!t || !header || !*header) return NULL;
ti = t->infos;
len = strlen(header);
while(ti) {
if (!strncasecmp(ti->info, header, len) &&
ti->info[len] == ':') {
s = ti->info + len + 1;
while(isspace(*s)) s++;
return s;
}
ti = ti->next;
}
return NULL;
}

View File

@@ -647,7 +647,7 @@ EOF
# The INFO keyword
../src/remind -pp - 1 Feb 2024 <<'EOF' >> ../tests/test.out 2>&1
REM Wed INFO "Location: here" INFO "Summary: Nope" MSG Meeting
REM Wed INFO "Location: here" INFO "Summary: Nope" MSG Meeting [triginfo("location")] %<summary> %<nonexist> [triginfo("cabbage")]
EOF
# Invalid info strings

View File

@@ -24164,6 +24164,7 @@ trigeventduration
trigeventstart
trigfrom
trigger
triginfo
trigpriority
trigrep
trigscanfrom
@@ -24541,6 +24542,7 @@ TRANSLATE "Warning: UNTIL/THROUGH date earlier than SCANFROM date" ""
TRANSLATE "Warning: UNTIL/THROUGH date earlier than start date" ""
TRANSLATE "Warning: Unable to save ONCE timestamp to %s: %s" ""
TRANSLATE "Warning: Unterminated %%(...) substitution sequence" ""
TRANSLATE "Warning: Unterminated %%<...> substitution sequence" ""
TRANSLATE "Warning: Unterminated %%{...} substitution sequence" ""
TRANSLATE "Warning: Useless use of UNTIL with fully-specified date and no *rep" ""
TRANSLATE "Warning: Variable name `%.*s...' truncated to `%.*s'" ""
@@ -24659,10 +24661,10 @@ February 2024 29 4 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
January 31
March 31
{"date":"2024-02-07","filename":"-","lineno":1,"info":{"location":"here","summary":"Nope"},"wd":["Wednesday"],"priority":5000,"body":"Meeting"}
{"date":"2024-02-14","filename":"-","lineno":1,"info":{"location":"here","summary":"Nope"},"wd":["Wednesday"],"priority":5000,"body":"Meeting"}
{"date":"2024-02-21","filename":"-","lineno":1,"info":{"location":"here","summary":"Nope"},"wd":["Wednesday"],"priority":5000,"body":"Meeting"}
{"date":"2024-02-28","filename":"-","lineno":1,"info":{"location":"here","summary":"Nope"},"wd":["Wednesday"],"priority":5000,"body":"Meeting"}
{"date":"2024-02-07","filename":"-","lineno":1,"info":{"location":"here","summary":"Nope"},"wd":["Wednesday"],"priority":5000,"rawbody":"Meeting [triginfo(\"location\")] %<summary> %<nonexist> [triginfo(\"cabbage\")]","body":"Meeting here Nope "}
{"date":"2024-02-14","filename":"-","lineno":1,"info":{"location":"here","summary":"Nope"},"wd":["Wednesday"],"priority":5000,"rawbody":"Meeting [triginfo(\"location\")] %<summary> %<nonexist> [triginfo(\"cabbage\")]","body":"Meeting here Nope "}
{"date":"2024-02-21","filename":"-","lineno":1,"info":{"location":"here","summary":"Nope"},"wd":["Wednesday"],"priority":5000,"rawbody":"Meeting [triginfo(\"location\")] %<summary> %<nonexist> [triginfo(\"cabbage\")]","body":"Meeting here Nope "}
{"date":"2024-02-28","filename":"-","lineno":1,"info":{"location":"here","summary":"Nope"},"wd":["Wednesday"],"priority":5000,"rawbody":"Meeting [triginfo(\"location\")] %<summary> %<nonexist> [triginfo(\"cabbage\")]","body":"Meeting here Nope "}
# rem2ps2 end
-stdin-(1): Invalid INFO string: Must be of the form "Header: Value"
-stdin-(2): Invalid INFO string: Must be of the form "Header: Value"