Compare commits

...

35 Commits

Author SHA1 Message Date
Dianne Skoll
695a2a3c2d Add "dp" to hunspell dictionary. 2026-02-15 16:46:51 -05:00
Dianne Skoll
47aa542d4f Update WHATSNEW 2026-02-15 16:45:28 -05:00
Dianne Skoll
5b4d1ae264 Bump version to 06.02.04 2026-02-15 11:09:26 -05:00
Dianne Skoll
721ccb9af9 Add explicit dates to most Remind invocations in test-rem 2026-02-15 11:03:28 -05:00
Dianne Skoll
ab1a6c412a Add tests for push/pop in different files warnings. 2026-02-15 10:57:31 -05:00
Dianne Skoll
c3a555942b Don't warn if a POP... is in a different file from a PUSH... unless the -dp flag is used. 2026-02-15 10:53:08 -05:00
Dianne Skoll
0d15977875 Tweak man pages. 2026-02-05 22:47:28 -05:00
Dianne Skoll
0a7e6ee219 Fix wording. 2026-02-05 22:42:15 -05:00
Dianne Skoll
baf049662f Fix typo 2026-02-05 22:40:16 -05:00
Dianne Skoll
fd5d9a479d *sigh* don't put an extra period after the version in "rem2html --version" 2026-02-05 22:33:43 -05:00
Dianne Skoll
01d3081f19 Make TkRemind support --version 2026-02-05 22:29:53 -05:00
Dianne Skoll
7841077fc6 Make all programs support --version 2026-02-05 22:25:10 -05:00
Dianne Skoll
2003c7a703 Add --version option to rem2pdf. 2026-02-05 22:18:17 -05:00
Dianne Skoll
4a603ce60d Tweak the CSS. 2026-02-05 19:25:39 -05:00
Dianne Skoll
caad7f5aa3 Add the $Shaded system variable. 2026-02-05 13:14:22 -05:00
Dianne Skoll
ea2312c0b2 Add mblower and mbupper functions.
These are Unicode-safe versions of lower() and upper()
2026-02-05 12:41:36 -05:00
Dianne Skoll
c0c49be0b5 Bump to version 06.02.03 2026-02-05 10:08:21 -05:00
Dianne Skoll
c0594811bf Integrate some CSS from Robert Black. 2026-02-04 17:49:58 -05:00
Dianne Skoll
b7e13845b6 Move yaag CSS to one place 2026-02-04 17:33:53 -05:00
Dianne Skoll
94b340305c Make year-at-a-glance CSS classes all start with rem-yaag- 2026-02-02 11:12:27 -05:00
Dianne Skoll
f477757ac0 Update tests for correct trigbase output format. 2026-02-02 11:09:02 -05:00
Dianne Skoll
a8017c6fc7 Fix JSON format of trigbase
Reported by Georg Simon.
2026-02-02 11:05:29 -05:00
Dianne Skoll
aad746bca3 Improve --yaag CSS 2026-01-30 14:31:34 -05:00
Dianne Skoll
953ff8c49e Add "--yaag" option to rem2html to create a "year-at-a-glance" formatted calendar. 2026-01-30 12:00:41 -05:00
Dianne Skoll
b5258b1eb5 Refactor. 2026-01-22 18:09:09 -05:00
Dianne Skoll
82733e817b Increase default value of $MaxSatIter from 1000 to 10000. 2026-01-20 15:19:23 -05:00
Dianne Skoll
86e94009a4 Better error than "type mismatch" if we assign a bad value to a system variable. 2026-01-19 18:49:03 -05:00
Dianne Skoll
04ea056820 Add MOON, SHADE, WEEK, COLOR and COLOUR to keyword list even though they are not really keywords. 2026-01-18 14:24:40 -05:00
Dianne Skoll
d6ee16cc13 Avoid "use of uninitialized variable" 2026-01-13 17:02:43 -05:00
Dianne Skoll
ead660fe41 Document default setting of $TerminalHyperlinks. 2026-01-11 17:52:38 -05:00
Dianne Skoll
58e5ae15b0 Fix URL. 2026-01-11 15:22:07 -05:00
Dianne Skoll
85a8a4b016 Only set default for TerminalHyperlinks if it hasn't explicitly been set
(for example, with '-i$TerminalHyperlinks=n')
2026-01-11 10:58:30 -05:00
Dianne Skoll
c43eaec274 Default $TerminalHyperlinks to 1 if stdout is a TTY. 2026-01-11 10:56:19 -05:00
Dianne Skoll
13fd54b990 Add URLs for sunrise and sunset. 2026-01-11 10:54:34 -05:00
Dianne Skoll
a48b2ec02e Fix typo 2026-01-10 20:11:18 -05:00
31 changed files with 821 additions and 219 deletions

18
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.72 for remind 06.02.02. # Generated by GNU Autoconf 2.72 for remind 06.02.04.
# #
# #
# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation, # Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
@@ -601,8 +601,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='remind' PACKAGE_NAME='remind'
PACKAGE_TARNAME='remind' PACKAGE_TARNAME='remind'
PACKAGE_VERSION='06.02.02' PACKAGE_VERSION='06.02.04'
PACKAGE_STRING='remind 06.02.02' PACKAGE_STRING='remind 06.02.04'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/' PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
@@ -1258,7 +1258,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
'configure' configures remind 06.02.02 to adapt to many kinds of systems. 'configure' configures remind 06.02.04 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1320,7 +1320,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of remind 06.02.02:";; short | recursive ) echo "Configuration of remind 06.02.04:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@@ -1408,7 +1408,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
remind configure 06.02.02 remind configure 06.02.04
generated by GNU Autoconf 2.72 generated by GNU Autoconf 2.72
Copyright (C) 2023 Free Software Foundation, Inc. Copyright (C) 2023 Free Software Foundation, Inc.
@@ -1871,7 +1871,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by remind $as_me 06.02.02, which was It was created by remind $as_me 06.02.04, which was
generated by GNU Autoconf 2.72. Invocation command line was generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw $ $0$ac_configure_args_raw
@@ -4892,7 +4892,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by remind $as_me 06.02.02, which was This file was extended by remind $as_me 06.02.04, which was
generated by GNU Autoconf 2.72. Invocation command line was generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -4957,7 +4957,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped' ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\ ac_cs_version="\\
remind config.status 06.02.02 remind config.status 06.02.04
configured by $0, generated by GNU Autoconf 2.72, configured by $0, generated by GNU Autoconf 2.72,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT(remind, 06.02.02, , , https://dianne.skoll.ca/projects/remind/) AC_INIT(remind, 06.02.04, , , https://dianne.skoll.ca/projects/remind/)
AC_CONFIG_SRCDIR([src/queue.c]) AC_CONFIG_SRCDIR([src/queue.c])
cat <<'EOF' cat <<'EOF'

View File

@@ -106,7 +106,8 @@
"Syntax table for `remind-conf-mode'.") "Syntax table for `remind-conf-mode'.")
;;; keyword sets ;;; keyword sets
;;; MOON, WEEK, SHADE, COLOR and COLOUR are not really keywords,
;;; but they are widely-supported SPECIALS, so I add them here.
(defconst remind-keywords (defconst remind-keywords
(sort (sort
(list "ADDOMIT" "AFTER" "AT" "BAN" "BANNER" "BEFORE" "CAL" "CLEAR" (list "ADDOMIT" "AFTER" "AT" "BAN" "BANNER" "BEFORE" "CAL" "CLEAR"
@@ -120,7 +121,8 @@
"PSFILE" "PUSH" "PUSH-FUNCS" "PUSH-VARS" "PUSH-OMIT-CONTEXT" "REM" "RETURN" "PSFILE" "PUSH" "PUSH-FUNCS" "PUSH-VARS" "PUSH-OMIT-CONTEXT" "REM" "RETURN"
"RUN" "SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET" "RUN" "SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET"
"SKIP" "SPECIAL" "SYSINCLUDE" "TAG" "THIRD" "THROUGH" "TODO" "SKIP" "SPECIAL" "SYSINCLUDE" "TAG" "THIRD" "THROUGH" "TODO"
"TRANSLATE" "TRANS" "TZ" "UNSET" "UNTIL" "WARN") "TRANSLATE" "TRANS" "TZ" "UNSET" "UNTIL" "WARN"
"MOON" "WEEK" "SHADE" "COLOR" "COLOUR")
#'(lambda (a b) (> (length a) (length b))))) #'(lambda (a b) (> (length a) (length b)))))
@@ -145,7 +147,7 @@
"$May" "$MinsFromUTC" "$Minute" "$Monday" "$Mplu" "$NextMode" "$May" "$MinsFromUTC" "$Minute" "$Monday" "$Mplu" "$NextMode"
"$November" "$Now" "$NumFullOmits" "$NumPartialOmits" "$NumQueued" "$November" "$Now" "$NumFullOmits" "$NumPartialOmits" "$NumQueued"
"$NumTrig" "$October" "$On" "$OnceFile" "$ParseUntriggered" "$Pm" "$NumTrig" "$October" "$On" "$OnceFile" "$ParseUntriggered" "$Pm"
"$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday" "$September" "$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday" "$September" "$Shaded"
"$SimpleCal" "$SortByDate" "$SortByPrio" "$SortByTime" "$SubsIndent" "$SimpleCal" "$SortByDate" "$SortByPrio" "$SortByTime" "$SubsIndent"
"$Sunday" "$SuppressImplicitWarnings" "$SuppressLRM" "$SysInclude" "$T" "$Tb" "$Td" "$Sunday" "$SuppressImplicitWarnings" "$SuppressLRM" "$SysInclude" "$T" "$Tb" "$Td"
"$TerminalBackground" "$TerminalHyperlinks" "$Thursday" "$TimeSep" "$TimetIs64bit" "$Tm" "$Today" "$TodoFilter" "$TerminalBackground" "$TerminalHyperlinks" "$Thursday" "$TimeSep" "$TimetIs64bit" "$Tm" "$Today" "$TodoFilter"
@@ -165,26 +167,151 @@
(defconst remind-builtin-functions (defconst remind-builtin-functions
(sort (sort
(list "_" "abs" "access" "adawn" "adusk" "ampm" "ansicolor" "args" "asc" (list
"baseyr" "catch" "catcherr" "char" "choose" "codepoint" "coerce" "columns" "const" "current" "date" "_"
"datepart" "datetime" "dawn" "day" "daysinmon" "defined" "dosubst" "abs"
"dusk" "easterdate" "escape" "eval" "evaltrig" "filedate" "filedatetime" "access"
"filedir" "filename" "getenv" "hebdate" "hebday" "hebmon" "hebyear" "hex" "adawn"
"hour" "htmlescape" "htmlstriptags" "iif" "index" "isany" "isconst" "isdst" "adusk"
"isleap" "isomitted" "ivritmon" "language" "localtoutc" "lower" "max" "ampm"
"mbasc" "mbindex" "mbstrlen" "mbsubstr" "min" "ansicolor"
"minsfromutc" "minute" "mon" "monnum" "moondate" "moondatetime" "args"
"moonphase" "moonrise" "moonrisedir" "moonset" "moonsetdir" "moontime" "asc"
"multitrig" "ndawn" "ndusk" "nonconst" "nonomitted" "now" "ord" "orthodoxeaster" "baseyr"
"ostype" "pad" "plural" "psmoon" "psshade" "realcurrent" "realnow" "catch"
"realtoday" "rows" "sgn" "shell" "shellescape" "slide" "soleq" "catcherr"
"stdout" "strlen" "substr" "sunrise" "sunset" "time" "timepart" "char"
"timezone" "today" "trig" "trigback" "trigbase" "trigcompletethrough" "trigdate" "trigdatetime" "choose"
"trigdelta" "trigduration" "trigeventduration" "trigeventstart" "trigeventstarttz" "codepoint"
"trigfrom" "trigger" "triginfo" "trigistodo" "trigmaxoverdue" "trigpriority" "trigrep" "coerce"
"trigscanfrom" "trigtags" "trigtime" "trigtimedelta" "trigtimerep" "trigtimetz" "trigtz" "columns"
"triguntil" "trigvalid" "typeof" "tzconvert" "upper" "utctolocal" "const"
"value" "version" "weekno" "wkday" "wkdaynum" "year" "current"
"date"
"datepart"
"datetime"
"dawn"
"day"
"daysinmon"
"defined"
"dosubst"
"dusk"
"easterdate"
"escape"
"eval"
"evaltrig"
"filedate"
"filedatetime"
"filedir"
"filename"
"getenv"
"hebdate"
"hebday"
"hebmon"
"hebyear"
"hex"
"hour"
"htmlescape"
"htmlstriptags"
"iif"
"index"
"isany"
"isconst"
"isdst"
"isleap"
"isomitted"
"ivritmon"
"language"
"localtoutc"
"lower"
"max"
"mbasc"
"mbindex"
"mblower"
"mbstrlen"
"mbsubstr"
"mbupper"
"min"
"minsfromutc"
"minute"
"mon"
"monnum"
"moondate"
"moondatetime"
"moonphase"
"moonrise"
"moonrisedir"
"moonset"
"moonsetdir"
"moontime"
"multitrig"
"ndawn"
"ndusk"
"nonconst"
"nonomitted"
"now"
"ord"
"orthodoxeaster"
"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"
"trigcompletethrough"
"trigdate"
"trigdatetime"
"trigdelta"
"trigduration"
"trigeventduration"
"trigeventstart"
"trigeventstarttz"
"trigfrom"
"trigger"
"triginfo"
"trigistodo"
"trigmaxoverdue"
"trigpriority"
"trigrep"
"trigscanfrom"
"trigtags"
"trigtime"
"trigtimedelta"
"trigtimerep"
"trigtimetz"
"trigtz"
"triguntil"
"trigvalid"
"typeof"
"tzconvert"
"upper"
"utctolocal"
"value"
"version"
"weekno"
"wkday"
"wkdaynum"
"year"
) )
#'(lambda (a b) (> (length a) (length b))))) #'(lambda (a b) (> (length a) (length b)))))

View File

@@ -1,5 +1,58 @@
CHANGES TO REMIND CHANGES TO REMIND
* VERSION 06.02.04 - 2026-02-15
- IMPROVEMENT: remind: Add the mblower and mbupper functions, which are
multibyte counterparts to lower and upper.
- MINOR NEW FEATURE: remind: Add the $Shaded system variable that counts
how many times a "SPECIAL SHADE" reminder has triggered. See the
man page for an example of how this can be useful.
- MINOR IMPROVEMENT: Make all programs that ship with Remind (remind,
rem2ps, rem2pdf, rem2html and tkremind) accept a --version long option.
- CHANGE: remind: Remind used to warn if the POP-OMIT-CONTEXT, POP-VARS
or POP-FUNCS command corresponding to the relevant PUSH command was
in a different file than the PUSH command. But there are valid use
cases for this, so Remind no longer emits the warning unless you use
the "-dp" debugging flag.
* VERSION 06.02.03 - 2026-02-05
- NEW FEATURE: rem2html: Add a new --yaag option to produce a calendar
in the "year-at-a-glance" format. This format features a table with
an entire month in each row. Thanks to Robert Black for suggesting
this and for helping out with the CSS.
- CHANGE: remind: If standard output is a TTY, then default
$TerminalHyperlinks to 1
- CHANGE: remind: Increase the default value of $MaxSatIter from 1000
to 10000, reflecting the higher speed of the new expression
evaluation engine as well as the speed of modern CPUs.
- UPDATE: examples/remind.vim: Update the URL to point to maintained
version.
- IMPROVEMENT: include/sun.rem: Add Wikipedia links for sunrise/sunset
- IMPROVEMENT: Add MOON, SHADE, WEEK, COLOR and COLOUR to the Emacs
syntax highlighting keyword list.
- IMPROVEMENT: If an invalid value is assigned to a system variable,
issue the error "Invalid value for system variable" rather than
"Type mismatch"
- DOC FIX: Fix typo in man page
- BUG FIX: rem2html: Eliminate "use of uninitialized variable"
warning.
- BUG FIX: remind: The "trigbase" JSON key in "remind -pp" output had
an incorrectly-formatted value. This has been fixed; thanks to
Georg Simon for reporting this bug.
* VERSION 06.02.02 - 2026-01-10 * VERSION 06.02.02 - 2026-01-10
- NEW FEATURE: remind: Turn reminders with a "Url:" INFO string into - NEW FEATURE: remind: Turn reminders with a "Url:" INFO string into

View File

@@ -3,7 +3,7 @@
" Maintainer: Davide Alberani <da@erlug.linux.it> " Maintainer: Davide Alberani <da@erlug.linux.it>
" Last Change: 02 Nov 2015 + 13 Mar 2022 by Dianne Skoll <dianne@skoll.ca> " Last Change: 02 Nov 2015 + 13 Mar 2022 by Dianne Skoll <dianne@skoll.ca>
" Version: 0.7+dianne1 " Version: 0.7+dianne1
" URL: http://ismito.it/vim/syntax/remind.vim " URL: https://github.com/alberanid/vim-config/blob/master/syntax/remind.vim
" "
" remind is a sophisticated reminder service " remind is a sophisticated reminder service
" you can download remind from: " you can download remind from:

View File

@@ -7,6 +7,6 @@ IF access($SysInclude + "/translations/" + _("LANGID") + "/sun.rem", "r") >= 0
ENDIF ENDIF
IF !$CalMode && !$PsCal IF !$CalMode && !$PsCal
REM NOQUEUE AT [sunrise()] MSG %"%"%(Sunrise) %! %2. REM INFO "Url: https://en.wikipedia.org/wiki/Sunrise" NOQUEUE AT [sunrise()] MSG %"%"%(Sunrise) %! %2.
REM NOQUEUE AT [sunset()] MSG %"%"%(Sunset) %! %2. REM INFO "Url: https://en.wikipedia.org/wiki/Sunset" NOQUEUE AT [sunset()] MSG %"%"%(Sunset) %! %2.
ENDIF ENDIF

View File

@@ -21,6 +21,9 @@ render characters outside the ASCII character set, see
.SH OPTIONS .SH OPTIONS
.TP .TP
.B \-\-version
Print the version of \fBrem2ps\fR and exit.
.TP
.B \-v .B \-v
Be more verbose. This causes \fBrem2ps\fR to print progress messages Be more verbose. This causes \fBrem2ps\fR to print progress messages
to the standard error stream. Normally, it is silent. to the standard error stream. Normally, it is silent.

View File

@@ -349,6 +349,10 @@ Echo lines when displaying error messages
.B f .B f
Trace the reading of reminder files Trace the reading of reminder files
.TP .TP
.B p
Issue warnings if a POP-OMIT-CONTEXT, POP-VARS or POP-FUNCS matches
a corresponding PUSH that is in a different file.
.TP
.B s .B s
Trace expression parsing and display the internal expression node Trace expression parsing and display the internal expression node
tree. This is unlikely to be useful unless you are working on tree. This is unlikely to be useful unless you are working on
@@ -1360,7 +1364,7 @@ minutes. That is, 13:39 and 13.39 are equivalent.
for a timed reminder is the same as the current system date, the for a timed reminder is the same as the current system date, the
reminder is queued for later activation. When \fBRemind\fR has reminder is queued for later activation. When \fBRemind\fR has
finished processing the reminder file, it puts itself in the finished processing the reminder file, it puts itself in the
background, and activates timed reminders when the system time reached background, and activates timed reminders when the system time reaches
the specified time. Note that if you use the \fBNOQUEUE\fR modifier the specified time. Note that if you use the \fBNOQUEUE\fR modifier
in the \fBREM\fR command, then this queuing and background activation in the \fBREM\fR command, then this queuing and background activation
is \fInot\fR performed. \fBNOQUEUE\fR is useful if you want a time is \fInot\fR performed. \fBNOQUEUE\fR is useful if you want a time
@@ -2588,16 +2592,13 @@ a sequence of more than one byte. For example, in a UTF-8 environment,
the string "🙂" contains one character but four bytes. And the string the string "🙂" contains one character but four bytes. And the string
"één" contains three characters but five bytes. "één" contains three characters but five bytes.
.PP .PP
\fBRemind\fR has a set of functions \fBRemind\fR has a set of functions that work on \fIbytes\fR, namely
that work on \fIbytes\fR, namely \fBindex\fR, \fBstrlen\fR and \fBsubstr\fR. \fBindex\fR, \fBstrlen\fR and \fBsubstr\fR, and several more. These
These are not safe to use on multi-byte strings; instead use are not safe to use on multi-byte strings; instead use \fBmbindex\fR,
\fBmbindex\fR, \fBmbstrlen\fR and \fBmbsubstr\fR. If you know \fIfor sure\fR \fBmbstrlen\fR and \fBmbsubstr\fR, and the \fBmb\fR variants of the
that a string contains only single-byte characters, then the byte-oriented others. If you know \fIfor sure\fR that a string contains only
versions may be used and are faster than the multi-byte versions. single-byte characters, then the byte-oriented versions may be used
.PP and are faster than the multi-byte versions.
Some ancient or embedded systems may lack the C library functions needed
to deal with multi-byte strings. In that case, the \fBmb\fIxxx\fR functions
all return an error.
.RE .RE
.TP .TP
.B TIME .B TIME
@@ -2638,7 +2639,7 @@ The following examples illustrate constants in \fBRemind\fR expressions:
12, 36, \-10, 0, 1209, 0x1F, 0xfe00 (the last two demonstrate the use of hexadecimal constants) 12, 36, \-10, 0, 1209, 0x1F, 0xfe00 (the last two demonstrate the use of hexadecimal constants)
.TP .TP
.B STRING constants .B STRING constants
"Hello there", "This is a test", "\\nHello\\tThere", "" "Hello there", "This is a test", "\\nHello\\tThere", "", "π is Cool! 🙂"
.PP .PP
.RS .RS
Note that the empty string is represented by "". \fBRemind\fR supports Note that the empty string is represented by "". \fBRemind\fR supports
@@ -3259,7 +3260,7 @@ near the beginning of the file and not change it after that.
.TP .TP
.B $MaxSatIter .B $MaxSatIter
The maximum number of iterations for the \fBSATISFY\fR clause The maximum number of iterations for the \fBSATISFY\fR clause
(described later.) Must be at least 10. (described later.) Must be at least 10. The default value is 10,000.
.TP .TP
.B $MaxStringLen .B $MaxStringLen
A limit on the longest string that \fBRemind\fR will allow you A limit on the longest string that \fBRemind\fR will allow you
@@ -3361,6 +3362,30 @@ If non-zero, then the \fB\-p\fR option was supplied on the command line.
.B $RunOff (read-only) .B $RunOff (read-only)
If non-zero, the \fBRUN\fR directives are disabled. If non-zero, the \fBRUN\fR directives are disabled.
.TP .TP
.B $Shaded (read-only)
Returns the number of times a \fBSHADE\fR special reminder has triggered.
\fIThis variable is set only in calendar mode, not agenda mode\fR. You
can use this variable to avoid shading a calendar day that has already
been shaded.
.RS
.PP
For example, suppose you want to shade all calendar boxes yellow
\fIif\fR any reminders have triggered on that day. But if a box has
been explicitly shaded, you don't want to overwrite that shading.
You could use something like this:
.PP
.nf
SET n $NumTrig
# Do all your reminders here...
# If anything has triggered and the box is
# not already shaded, then shade it yellow
IF $NumTrig > n && !$Shaded
REM SPECIAL SHADE 255 255 128
ENDIF
.fi
.RE
.TP
.B $SimpleCal (read-only) .B $SimpleCal (read-only)
Set to a non-zero value if \fIeither\fR of the \fB\-p\fR or \fB\-s\fR Set to a non-zero value if \fIeither\fR of the \fB\-p\fR or \fB\-s\fR
command-line options was supplied. command-line options was supplied.
@@ -3492,8 +3517,8 @@ at most 85 out of 255, and if the maximum of any component is at most
If your terminal supports escape sequences to allow HTML-like If your terminal supports escape sequences to allow HTML-like
anchors around text (see https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda), then you can set this variable to 1. \fBRemind\fR will then anchors around text (see https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda), then you can set this variable to 1. \fBRemind\fR will then
make any reminder with a "Url:" info string into a hyperlink in your make any reminder with a "Url:" info string into a hyperlink in your
terminal. By default, \fB$TerminalHyperlinks\fR is set to zero because terminal. By default, \fB$TerminalHyperlinks\fR is set to 1 if \fBRemind\fR's
not all terminals support this feature. standard output is a terminal, or to 0 if it is not.
.TP .TP
.B $WarningLevel (STRING type) .B $WarningLevel (STRING type)
As new versions of \fBRemind\fR are released, new warnings may be added. As new versions of \fBRemind\fR are released, new warnings may be added.
@@ -4223,8 +4248,15 @@ Given a \fBDATETIME\fR object interpreted in the local time zone, return
a \fBDATETIME\fR object that expresses the same time in UTC. a \fBDATETIME\fR object that expresses the same time in UTC.
.TP .TP
.B lower(s_string) .B lower(s_string)
Returns a \fBSTRING\fR with all upper-case bytes in \fIstring\fR
converted to lower-case. \fBNote:\fR This function works correctly
only for ASCII strings. If you are using Unicode characters outside
the ASCII set, use \fBmblower\fR instead.
.TP
.B mblower(s_string)
Returns a \fBSTRING\fR with all upper-case characters in \fIstring\fR Returns a \fBSTRING\fR with all upper-case characters in \fIstring\fR
converted to lower-case. converted to lower-case. This function works correctly on any
Unicode string.
.TP .TP
.B max(x_arg1 [,x_arg2...) .B max(x_arg1 [,x_arg2...)
Can take any number of arguments, and returns the maximum. The arguments Can take any number of arguments, and returns the maximum. The arguments
@@ -5133,8 +5165,15 @@ of the time zone name.
.PP .PP
.TP .TP
.B upper(s_string) .B upper(s_string)
Returns a \fBSTRING\fR with all lower-case bytes in \fIstring\fR
converted to upper-case. \fBNote:\fR This function works correctly
only for ASCII strings. If you are using Unicode characters outside
the ASCII set, use \fBmbupper\fR instead.
.TP
.B mbupper(s_string)
Returns a \fBSTRING\fR with all lower-case characters in \fIstring\fR Returns a \fBSTRING\fR with all lower-case characters in \fIstring\fR
converted to upper-case. converted to upper-case. This function works correctly on any
Unicode string.
.TP .TP
.B utctolocal(q_datetime) .B utctolocal(q_datetime)
Given a \fBDATETIME\fR object interpreted in UTC, return a Given a \fBDATETIME\fR object interpreted in UTC, return a

View File

@@ -18,10 +18,12 @@ binary. If you are using Tcl/Tk 8.5, you may also need either the Img
or the tkpng extension to handle PNG images. or the tkpng extension to handle PNG images.
.SH COMMAND-LINE OPTIONS .SH COMMAND-LINE OPTIONS
\fBTkRemind\fR itself has no command-line options. However, it passes \fBTkRemind\fR itself has only one command-line option:
any command-line argument starting with \fB\-\fR to \fBRemind\fR as an \fB\-\-version\fR, which makes it print the version of \fBTkRemind\fR
option. In addition, \fBTkRemind\fR will respect the \fB\-m\fR and and exit. Any other command-line argument starting with \fB\-\fR to
\fB\-b1\fR options and adjust its appearance accordingly. \fBRemind\fR as an option. In addition, \fBTkRemind\fR will respect
the \fB\-m\fR and \fB\-b1\fR options and adjust its appearance
accordingly.
.PP .PP
\fIRead_file\fR is the file from which \fBTkRemind\fR reads reminders. \fIRead_file\fR is the file from which \fBTkRemind\fR reads reminders.
It is in standard \fBRemind\fR format. \fIWrite_file\fR is the file It is in standard \fBRemind\fR format. \fIWrite_file\fR is the file

View File

@@ -96,6 +96,14 @@ without any E<lt>htmlE<gt> or E<lt>bodyE<gt> tags.
Use I<title> as the content between E<lt>titleE<gt> and E<lt>/titleE<gt> Use I<title> as the content between E<lt>titleE<gt> and E<lt>/titleE<gt>
tags. tags.
=item --yaag
Instead of making 7-column tables for each month, show each month
as a I<single> table row of 38 columns. This is the so-called
"year-at-a-glance" format. You must use the "-ppp" option to
C<remind> or the --yaag option will be ignored. And this format
works best if you create a calendar for an entire year (so, starting
in January and using "-ppp12" to get 12 months' worth of reminders.)
=item --prologue I<html_text> =item --prologue I<html_text>
@@ -188,6 +196,7 @@ Options:
--title string What to put in <title>...</title> tags --title string What to put in <title>...</title> tags
--prologue html_text Text to insert at the top of the body --prologue html_text Text to insert at the top of the body
--epilogue html_text Text to insert at the end of the body --epilogue html_text Text to insert at the end of the body
--yaag Output one month per row for year-at-a-glance format
EOM EOM
exit($exit_status); exit($exit_status);
} }
@@ -218,6 +227,7 @@ sub parse_options
"man", "man",
"utf8", "utf8",
"pngs", "pngs",
"yaag",
"version", "version",
"stylesheet=s", "stylesheet=s",
"nostyle", "nostyle",
@@ -316,6 +326,10 @@ sub parse_input
if ($_ eq '[') { if ($_ eq '[') {
return parse_input_ppp(); return parse_input_ppp();
} }
if ($Options{yaag}) {
$Options{yaag} = 0;
print STDERR "Ignoring option --yaag: You must use remind -ppp for this option\n";
}
if (/# translations/) { if (/# translations/) {
slurp_translations(); slurp_translations();
next; next;
@@ -472,6 +486,10 @@ sub parse_input_ppp
} }
if (exists($array->[0]{caltype}) && if (exists($array->[0]{caltype}) &&
$array->[0]{caltype} eq 'weekly') { $array->[0]{caltype} eq 'weekly') {
if ($Options{yaag}) {
$Options{yaag} = 0;
print STDERR "Ignoring option --yaag for a weekly calendar\n";
}
emit_ppp_calendars($array, 'weekly'); emit_ppp_calendars($array, 'weekly');
} else { } else {
emit_ppp_calendars($array, 'monthly'); emit_ppp_calendars($array, 'monthly');
@@ -488,11 +506,51 @@ sub parse_input_ppp
} }
} }
sub print_yaag_weekday_row
{
my ($cal) = @_;
print "<tr class=\"rem-yaag-weekday-row\">";
print "<th class=\"rem-yaag-empty-header\">&nbsp;</th>";
my $ex;
for (my $i=0; $i<37; $i++) {
my $day;
if ($cal->{mondayfirst}) {
$day = $cal->{daynames}->[($i+1) % 7];
} else {
$day = $cal->{daynames}->[$i % 7];
}
if (($i % 7) == 6) {
$ex = " rem-yaag-end-of-week";
} else {
$ex = "";
}
print "<th class=\"rem-yaag-weekday-header$ex\">$day</th>";
}
print "</tr>\n";
}
sub emit_ppp_calendars sub emit_ppp_calendars
{ {
my ($array, $type) = @_; my ($array, $type) = @_;
my $prev_year = 0;
my $done_one = 0;
foreach my $cal (@$array) { foreach my $cal (@$array) {
if ($Options{yaag}) {
if ($cal->{year} != $prev_year) {
$prev_year = $cal->{year};
if ($done_one) {
print "</table>\n";
}
print "<span class=\"year_heading\">$prev_year</span>\n";
print "<table class=\"rem-yaag\">\n";
print_yaag_weekday_row($cal);
}
}
emit_one_ppp_calendar($cal, $type); emit_one_ppp_calendar($cal, $type);
$done_one = 1;
}
if ($done_one) {
print "</table>\n";
} }
} }
@@ -766,42 +824,79 @@ sub output_calendar
# Start the table # Start the table
my $class; my $class;
if ($Options{nostyle}) { if (!$Options{yaag}) {
print '<table width="100%" border="1" cellspacing=\"0\"><caption>' . if ($Options{nostyle}) {
$Month . ' ' . $Year . '</caption>' . "\n"; print '<table width="100%" border="1" cellspacing="0">';
print '<tr>'; if ($type eq 'monthly') {
$class = ' width="14%"'; print "<caption>$Month $Year </caption>";
} else { }
if ($type eq 'monthly') { print "\n<tr>";
print '<table class="rem-cal"><caption class="rem-cal-caption">' . $class = ' width="14%"';
$Month . ' ' . $Year . '</caption>' . "\n";
} else { } else {
print '<table class="rem-cal">' . "\n"; if ($type eq 'monthly') {
print '<table class="rem-cal"><caption class="rem-cal-caption">' .
$Month . ' ' . $Year . '</caption>' . "\n";
} else {
print '<table class="rem-cal">' . "\n";
}
print '<tr class="rem-cal-hdr-row">';
$class = ' class="rem-cal-hdr"';
} }
print '<tr class="rem-cal-hdr-row">'; if ($type eq 'monthly') {
$class = ' class="rem-cal-hdr"'; if (!$Mondayfirst) {
} print "<th$class>" . $Daynames[0] . '</th>';
if ($type eq 'monthly') { }
if (!$Mondayfirst) { for (my $i=1; $i<7; $i++) {
print "<th$class>" . $Daynames[0] . '</th>'; print "<th$class>" . $Daynames[$i] . '</th>';
}
if ($Mondayfirst) {
print "<th$class>" . $Daynames[0] . '</th>';
}
} else {
for (my $i=0; $i<7; $i++) {
my $inf = $date_info->[$i];
print "<th$class>" . $inf->{dayname} . "<br>" .
$inf->{day} . '&nbsp;' .
$inf->{month} . '&nbsp;' .
$inf->{year} . '</th>';
}
} }
for (my $i=1; $i<7; $i++) {
print "<th$class>" . $Daynames[$i] . '</th>';
}
if ($Mondayfirst) {
print "<th$class>" . $Daynames[0] . '</th>';
}
} else {
for (my $i=0; $i<7; $i++) {
my $inf = $date_info->[$i];
print "<th$class>" . $inf->{dayname} . "<br>" .
$inf->{day} . '&nbsp;' .
$inf->{month} . '&nbsp;' .
$inf->{year} . '</th>';
}
}
print "</tr>\n"; print "</tr>\n";
} else {
# For year-at-a-glance calendar, it's just a row
print '<tr class="rem-yaag-cal-row">';
print '<th class="rem-yaag-cal-hdr">' . $Month . "</th>\n";
my $cells_drawn = 0;
# Print the blank ones
for (my $i=0; $i<$first_col; $i++) {
print "<td class=\"rem-yaag-cal-blank\">&nbsp;</td>";
$cells_drawn++;
}
# All the entries
for (my $day=1; $day <= $Numdays; $day++) {
if (($cells_drawn % 7) == 6) {
draw_day_cell($day, 1, $type, ' rem-yaag-end-of-week');
} else {
draw_day_cell($day, 1, $type);
}
$cells_drawn++;
}
# And fill in the remaining ones
while ($cells_drawn < 37) {
if (($cells_drawn % 7) == 6) {
print "<td class=\"rem-yaag-cal-blank rem-yaag-end-of-week\">&nbsp;</td>";
} else {
print "<td class=\"rem-yaag-cal-blank\">&nbsp;</td>";
}
$cells_drawn++;
}
print "</tr>\n";
return;
}
# Start the calendar rows # Start the calendar rows
my $col = 0; my $col = 0;
if ($Options{nostyle}) { if ($Options{nostyle}) {
@@ -895,9 +990,10 @@ sub output_calendar
sub draw_day_cell sub draw_day_cell
{ {
my($day, $number_of_rows, $type) = @_; my($day, $number_of_rows, $type, $extra_class) = @_;
my $shade = $shades->[$day]; my $shade = $shades->[$day];
my $week = ''; my $week = '';
$extra_class = '' unless defined($extra_class);
if (exists($weeks->{$day})) { if (exists($weeks->{$day})) {
if ($weeks->{$day}->{url}) { if ($weeks->{$day}->{url}) {
$week = ' <a href="' . $weeks->{$day}->{url} . '">' . escape_html($weeks->{$day}->{body}) . '</a>'; $week = ' <a href="' . $weeks->{$day}->{url} . '">' . escape_html($weeks->{$day}->{body}) . '</a>';
@@ -905,19 +1001,22 @@ sub draw_day_cell
$week = ' ' . escape_html($weeks->{$day}->{body}); $week = ' ' . escape_html($weeks->{$day}->{body});
} }
} }
my $class; my $class = $classes->[$day] || '';
if ($Options{nostyle}) { if (!$Options{nostyle}) {
$class = $classes->[$day] || ''; $class .= ' ' if $class ne '';
} else { if ($Options{yaag}) {
$class = $classes->[$day] || "rem-cell rem-cell-$number_of_rows-rows"; $class .= "rem-yaag-cell"
} else {
$class .= "rem-cell rem-cell-$number_of_rows-rows";
}
} }
if ($shade) { if ($shade) {
$shade = " style=\"background: $shade;\""; $shade = " style=\"background: $shade;\"";
} else { } else {
$shade = ""; $shade = "";
} }
if ($class ne '') { if ($class ne '' || $extra_class ne '') {
print "<td class=\"$class\"$shade>\n"; print "<td class=\"$class$extra_class\"$shade>\n";
} else { } else {
print "<td valign=\"top\" $shade>\n"; print "<td valign=\"top\" $shade>\n";
} }
@@ -982,7 +1081,11 @@ sub draw_day_cell
print "<div style=\"float: right\">$day$week</div>\n"; print "<div style=\"float: right\">$day$week</div>\n";
print "<p>&nbsp;</p>\n"; print "<p>&nbsp;</p>\n";
} else { } else {
print "<div class=\"rem-daynumber\">$day$week</div>\n"; if ($Options{yaag}) {
print "<div class=\"rem-yaag-daynumber\">$day$week</div>\n";
} else {
print "<div class=\"rem-daynumber\">$day$week</div>\n";
}
} }
} else { } else {
if ($Options{nostyle}) { if ($Options{nostyle}) {
@@ -1016,7 +1119,7 @@ if ($Options{help}) {
system("perldoc $0"); system("perldoc $0");
exit(0); exit(0);
} elsif ($Options{version}) { } elsif ($Options{version}) {
print "rem2html version $rem2html_version.\n"; print "rem2html version $rem2html_version\n";
exit(0); exit(0);
} }
@@ -1048,6 +1151,11 @@ table.rem-cal {
font-size: 12pt; font-size: 12pt;
} }
span.year_heading {
font-family: helvetica, arial, sans-serif;
font-size: 28pt;
}
table.rem-sc-table { table.rem-sc-table {
font-family: helvetica, arial, sans-serif; font-family: helvetica, arial, sans-serif;
font-size: 10pt; font-size: 10pt;
@@ -1073,14 +1181,6 @@ td.rem-empty, td.rem-cell, td.rem-small-calendar {
border-width: 1px; border-width: 1px;
vertical-align: top; vertical-align: top;
} }
td.rem-today {
width: 14%;
height: 7em;
border-style: solid;
border-width: 2px;
border-color: #EE3333;
vertical-align: top;
}
table.rem-cal { table.rem-cal {
width: 100%; width: 100%;
@@ -1116,5 +1216,84 @@ td.rem-sc-empty-cell, td.rem-sc-cell {
caption.rem-sc-caption { caption.rem-sc-caption {
font-size: 12pt; font-size: 12pt;
} }
table.rem-yaag {
font-family: helvetica, arial, sans-serif;
font-size: 8pt;
table-layout: fixed;
cellspacing: 0;
border-collapse: collapse;
}
td.rem-yaag-cell {
height: 7em;
border-style: solid;
border-color: #adadad;
border-width: 1px;
vertical-align: top;
}
th.rem-yaag-weekday-header {
font-weight: 100;
font-size: 9pt;
padding: 6px 0 0 6px;
text-align:left;
border-style: solid;
border-color: #adadad;
border-width: 1px;
vertical-align: top;
}
td.rem-yaag-cal-blank {
height: 7em;
border-style: solid;
border-width: 1px;
border-color: #adadad;
background-color: #d5d6d5;
vertical-align: top;
}
td.rem-yaag-end-of-week {
border-right-width: 3;
}
th.rem-yaag-end-of-week {
border-right-width: 3;
}
th.rem-yaag-cal-hdr {
text-align: right;
padding-top: 8px;
padding-right: 5px;
font-weight: 100;
font-size: 9pt;
border-style: solid;
border-color: #adadad;
border-width: 1px;
vertical-align: top;
}
div.rem-yaag-daynumber {
float: right;
text-align: right;
vertical-align: top;
font-size: 10pt;
}
tr.rem-yaag-cal-row:nth-child(3n+1) {
border-bottom: 3px solid #000;
}
.rem-yaag-weekday-row .rem-yaag-empty-header {
height: 20pt;
width: 70px !important;
}
td.rem-today {
border-style: solid;
border-width: 2px;
border-color: #EE3333;
}
EOF EOF
} }

View File

@@ -31,6 +31,7 @@ my $media_to_size = {
}; };
my $help = 0; my $help = 0;
my $version = 0;
my $settings = { my $settings = {
landscape => 0, landscape => 0,
@@ -126,6 +127,7 @@ Options:
--title-url=URL Link calendar title to URL --title-url=URL Link calendar title to URL
--verbose, -v Print progress messages --verbose, -v Print progress messages
--help Display this help --help Display this help
--version Print version and exit
EOF EOF
} }
@@ -166,6 +168,7 @@ my $ret = GetOptions('landscape|l' => \$settings->{landscape},
'header-color=s' => \$settings->{header_color}, 'header-color=s' => \$settings->{header_color},
'daynum-color=s' => \$settings->{daynum_color}, 'daynum-color=s' => \$settings->{daynum_color},
'smallcal-color=s' => \$settings->{smallcal_color}, 'smallcal-color=s' => \$settings->{smallcal_color},
'version' => \$version,
'help' => \$help 'help' => \$help
); );
if (!$ret) { if (!$ret) {
@@ -178,6 +181,11 @@ if ($help) {
exit(0); exit(0);
} }
if ($version) {
print "rem2pdf version $VERSION\n";
exit(0);
}
my $bad = 0; my $bad = 0;
foreach my $setting (qw(bg_color line_color title_color header_color daynum_color smallcal_color)) { foreach my $setting (qw(bg_color line_color title_color header_color daynum_color smallcal_color)) {
my $c = $settings->{$setting}; my $c = $settings->{$setting};
@@ -620,6 +628,14 @@ to print per page; it is an integer that can range from 1 to 4.
Print (on STDERR) the name of the month and year for each month that Print (on STDERR) the name of the month and year for each month that
is rendered. is rendered.
=item --version
Print the version of rem2pdf and exit.
=item --help
Print a brief summary of rem2pdf usage.
=back =back
=head1 USAGE =head1 USAGE

View File

@@ -442,6 +442,10 @@ proc Initialize {} {
set PSCmd "$Remind -itkremind=1 -itkprint=1 -pp%WEEKS% -l %EXTRA%" set PSCmd "$Remind -itkremind=1 -itkprint=1 -pp%WEEKS% -l %EXTRA%"
set i 0 set i 0
while {$i < $argc} { while {$i < $argc} {
if {"[lindex $argv $i]" == "--version"} {
puts "tkremind version @VERSION@"
exit 0
}
if {[regexp -- {-[bgxim].*} [lindex $argv $i]]} { if {[regexp -- {-[bgxim].*} [lindex $argv $i]]} {
append CommandLine " [lindex $argv $i]" append CommandLine " [lindex $argv $i]"
append PSCmd " [lindex $argv $i]" append PSCmd " [lindex $argv $i]"
@@ -3602,11 +3606,11 @@ proc main {} {
font create BoldFont {*}[font actual TkDefaultFont] -weight bold font create BoldFont {*}[font actual TkDefaultFont] -weight bold
global AppendFile HighestTagSoFar DayNames global AppendFile HighestTagSoFar DayNames
catch { SetFonts }
Initialize
catch { catch {
puts "\nTkRemind Copyright (C) 1996-2026 Dianne Skoll" puts "\nTkRemind Copyright (C) 1996-2026 Dianne Skoll"
} }
catch { SetFonts }
Initialize
# If no $ConfigFile file, create an empty one # If no $ConfigFile file, create an empty one
if {![file exists $ConfigFile]} { if {![file exists $ConfigFile]} {

View File

@@ -2123,8 +2123,9 @@ static int DoCalRem(ParsePtr p, int col)
} }
} }
if (trig.typ == PASSTHRU_TYPE) { if (trig.typ == PASSTHRU_TYPE) {
if (!PsCal && !strcasecmp(trig.passthru, "SHADE")) { if (!strcasecmp(trig.passthru, "SHADE") && dse == DSEToday) {
if (dse == DSEToday) { Shaded++;
if (!PsCal) {
DBufInit(&obuf); DBufInit(&obuf);
r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE); r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE);
if (r) { if (r) {
@@ -2549,7 +2550,7 @@ void WriteJSONTrigger(Trigger const *t, int include_tags)
PrintJSONKeyPairInt("rep", t->rep); PrintJSONKeyPairInt("rep", t->rep);
} }
if (t->d != NO_DAY && t->m != NO_MON && t->y != NO_YR) { if (t->d != NO_DAY && t->m != NO_MON && t->y != NO_YR) {
printf("\"trigbase\":\"%04d-%02d-%-2d\",", printf("\"trigbase\":\"%04d-%02d-%02d\",",
t->y, t->m+1, t->d); t->y, t->m+1, t->d);
} }
/* Local omit is an array of days from 0=monday to 6=sunday. /* Local omit is an array of days from 0=monday to 6=sunday.

View File

@@ -138,6 +138,7 @@
#define E_EXPR_NODES_EXCEEDED 114 #define E_EXPR_NODES_EXCEEDED 114
#define E_EXPECTING_EOXPR 115 #define E_EXPECTING_EOXPR 115
#define E_EXPECTING_ATOM 116 #define E_EXPECTING_ATOM 116
#define E_BAD_VAL_FOR_SYSVAR 117
#ifdef MK_GLOBALS #ifdef MK_GLOBALS
#undef EXTERN #undef EXTERN
@@ -272,6 +273,7 @@ EXTERN char *ErrMsg[]
/* E_EXPR_NODES_EXCEEDED */ "Maximum expression complexity exceeded", /* E_EXPR_NODES_EXCEEDED */ "Maximum expression complexity exceeded",
/* E_EXPECTING_EOXPR */ "Expecting operator or end-of-expression", /* E_EXPECTING_EOXPR */ "Expecting operator or end-of-expression",
/* E_EXPECTING_ATOM */ "Expecting constant, variable, function call or (expression)", /* E_EXPECTING_ATOM */ "Expecting constant, variable, function call or (expression)",
/* E_BAD_VAL_FOR_SYSVAR */ "Invalid value for system variable",
} }
#endif /* MK_GLOBALS */ #endif /* MK_GLOBALS */
; ;

View File

@@ -242,6 +242,31 @@ find_end_of_expr(char const *s)
return e; return e;
} }
/***************************************************************/
/* */
/* node_str - get string associated with a node */
/* */
/***************************************************************/
static char const *
node_str(expr_node const *node)
{
switch(node->type) {
case N_VARIABLE:
case N_SYSVAR:
case N_USER_FUNC:
return node->u.value.v.str;
case N_SHORT_VAR:
case N_SHORT_SYSVAR:
case N_SHORT_USER_FUNC:
case N_SHORT_STR:
return node->u.name;
default:
return NULL;
}
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* alloc_expr_node - allocate an expr_node object */ /* alloc_expr_node - allocate an expr_node object */
@@ -418,11 +443,7 @@ get_var(expr_node *node, Value *ans, int *nonconst)
Var *v; Var *v;
char const *str; char const *str;
if (node->type == N_SHORT_VAR) { str = node_str(node);
str = node->u.name;
} else {
str = node->u.value.v.str;
}
v = FindVar(str, 0); v = FindVar(str, 0);
if (!v) { if (!v) {
Eprint("%s: `%s'", GetErr(E_NOSUCH_VAR), str); Eprint("%s: `%s'", GetErr(E_NOSUCH_VAR), str);
@@ -448,11 +469,7 @@ get_var(expr_node *node, Value *ans, int *nonconst)
static int static int
get_sysvar(expr_node const *node, Value *ans) get_sysvar(expr_node const *node, Value *ans)
{ {
if (node->type == N_SHORT_SYSVAR) { return GetSysVar(node_str(node), ans);
return GetSysVar(node->u.name, ans);
} else {
return GetSysVar(node->u.value.v.str, ans);
}
} }
/***************************************************************/ /***************************************************************/
@@ -619,13 +636,9 @@ eval_builtin(expr_node *node, Value *locals, Value *ans, int *nonconst)
static void static void
debug_enter_userfunc(expr_node *node, Value *locals, int nargs) debug_enter_userfunc(expr_node *node, Value *locals, int nargs)
{ {
char const *fname;
int i; int i;
if (node->type == N_SHORT_USER_FUNC) { char const *fname = node_str(node);
fname = node->u.name;
} else {
fname = node->u.value.v.str;
}
fprintf(ErrFp, "%s %s(", GetErr(E_ENTER_FUN), fname); fprintf(ErrFp, "%s %s(", GetErr(E_ENTER_FUN), fname);
for (i=0; i<nargs; i++) { for (i=0; i<nargs; i++) {
if (i) fprintf(ErrFp, ", "); if (i) fprintf(ErrFp, ", ");
@@ -645,13 +658,9 @@ debug_enter_userfunc(expr_node *node, Value *locals, int nargs)
static void static void
debug_exit_userfunc(expr_node *node, Value const *ans, int r, Value *locals, int nargs) debug_exit_userfunc(expr_node *node, Value const *ans, int r, Value *locals, int nargs)
{ {
char const *fname; char const *fname = node_str(node);
int i; int i;
if (node->type == N_SHORT_USER_FUNC) {
fname = node->u.name;
} else {
fname = node->u.value.v.str;
}
fprintf(ErrFp, "%s %s(", GetErr(E_LEAVE_FUN), fname); fprintf(ErrFp, "%s %s(", GetErr(E_LEAVE_FUN), fname);
for (i=0; i<nargs; i++) { for (i=0; i<nargs; i++) {
if (i) fprintf(ErrFp, ", "); if (i) fprintf(ErrFp, ", ");
@@ -702,12 +711,7 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst)
Value stack_locals[STACK_ARGS_MAX]; Value stack_locals[STACK_ARGS_MAX];
/* Get the function name */ /* Get the function name */
char const *fname; char const *fname = node_str(node);
if (node->type == N_SHORT_USER_FUNC) {
fname = node->u.name;
} else {
fname = node->u.value.v.str;
}
/* Find the function */ /* Find the function */
f = FindUserFunc(fname); f = FindUserFunc(fname);
@@ -913,13 +917,9 @@ evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst)
return CopyValue(ans, &(node->u.value)); return CopyValue(ans, &(node->u.value));
case N_SHORT_VAR: case N_SHORT_VAR:
r = get_var(node, ans, nonconst);
DBG(debug_evaluation(ans, r, "%s", node->u.name));
return r;
case N_VARIABLE: case N_VARIABLE:
r = get_var(node, ans, nonconst); r = get_var(node, ans, nonconst);
DBG(debug_evaluation(ans, r, "%s", node->u.value.v.str)); DBG(debug_evaluation(ans, r, "%s", node_str(node)));
return r; return r;
case N_LOCAL_VAR: case N_LOCAL_VAR:
@@ -929,19 +929,12 @@ evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst)
return r; return r;
case N_SHORT_SYSVAR: case N_SHORT_SYSVAR:
/* System var? Return it and note non-constant expression */
nonconst_debug(*nonconst, tr("System variable `$%s' makes expression non-constant"), node->u.name);
*nonconst = 1;
r = get_sysvar(node, ans);
DBG(debug_evaluation(ans, r, "$%s", node->u.name));
return r;
case N_SYSVAR: case N_SYSVAR:
/* System var? Return it and note non-constant expression */ /* System var? Return it and note non-constant expression */
nonconst_debug(*nonconst, tr("System variable `$%s' makes expression non-constant"), node->u.value.v.str); nonconst_debug(*nonconst, tr("System variable `$%s' makes expression non-constant"), node_str(node));
*nonconst = 1; *nonconst = 1;
r = get_sysvar(node, ans); r = get_sysvar(node, ans);
DBG(debug_evaluation(ans, r, "$%s", node->u.value.v.str)); DBG(debug_evaluation(ans, r, "$%s", node_str(node)));
return r; return r;
case N_BUILTIN_FUNC: case N_BUILTIN_FUNC:
@@ -952,8 +945,8 @@ evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst)
} }
return eval_builtin(node, locals, ans, nonconst); return eval_builtin(node, locals, ans, nonconst);
case N_USER_FUNC:
case N_SHORT_USER_FUNC: case N_SHORT_USER_FUNC:
case N_USER_FUNC:
/* User-defined function? Evaluate it */ /* User-defined function? Evaluate it */
return eval_userfunc(node, locals, ans, nonconst); return eval_userfunc(node, locals, ans, nonconst);
@@ -2869,16 +2862,12 @@ static void print_expr_tree(expr_node *node, FILE *fp)
fprintf(fp, "\"%s\"", node->u.name); fprintf(fp, "\"%s\"", node->u.name);
return; return;
case N_SHORT_VAR: case N_SHORT_VAR:
fprintf(fp, "%s", node->u.name);
return;
case N_VARIABLE: case N_VARIABLE:
fprintf(fp, "%s", node->u.value.v.str); fprintf(fp, "%s", node_str(node));
return; return;
case N_SHORT_SYSVAR: case N_SHORT_SYSVAR:
fprintf(fp, "$%s", node->u.name);
return;
case N_SYSVAR: case N_SYSVAR:
fprintf(fp, "$%s", node->u.value.v.str); fprintf(fp, "$%s", node_str(node));
return; return;
case N_LOCAL_VAR: case N_LOCAL_VAR:
fprintf(fp, "arg[%d]", node->u.arg); fprintf(fp, "arg[%d]", node->u.arg);
@@ -2892,13 +2881,8 @@ static void print_expr_tree(expr_node *node, FILE *fp)
fprintf(fp, ")"); fprintf(fp, ")");
return; return;
case N_SHORT_USER_FUNC: case N_SHORT_USER_FUNC:
fprintf(fp, "(%s", node->u.name);
if (node->child) fprintf(fp, " ");
print_kids(node, fp);
fprintf(fp, ")");
return;
case N_USER_FUNC: case N_USER_FUNC:
fprintf(fp, "(%s", node->u.value.v.str); fprintf(fp, "(%s", node_str(node));
if (node->child) fprintf(fp, " "); if (node->child) fprintf(fp, " ");
print_kids(node, fp); print_kids(node, fp);
fprintf(fp, ")"); fprintf(fp, ")");

View File

@@ -140,9 +140,11 @@ static int FLower (func_info *);
static int FMax (func_info *); static int FMax (func_info *);
static int FMbchar (func_info *); static int FMbchar (func_info *);
static int FMbindex (func_info *); static int FMbindex (func_info *);
static int FMblower (func_info *);
static int FMbpad (func_info *); static int FMbpad (func_info *);
static int FMbstrlen (func_info *); static int FMbstrlen (func_info *);
static int FMbsubstr (func_info *); static int FMbsubstr (func_info *);
static int FMbupper (func_info *);
static int FMin (func_info *); static int FMin (func_info *);
static int FMinsfromutc (func_info *); static int FMinsfromutc (func_info *);
static int FMinute (func_info *); static int FMinute (func_info *);
@@ -327,9 +329,11 @@ BuiltinFunc Func[] = {
{ "max", 1, NO_MAX, 1, FMax, NULL }, { "max", 1, NO_MAX, 1, FMax, NULL },
{ "mbchar", 1, NO_MAX, 1, FMbchar, NULL }, { "mbchar", 1, NO_MAX, 1, FMbchar, NULL },
{ "mbindex", 2, 3, 1, FMbindex, NULL }, { "mbindex", 2, 3, 1, FMbindex, NULL },
{ "mblower", 1, 1, 1, FMblower, NULL },
{ "mbpad", 3, 4, 1, FMbpad, NULL }, { "mbpad", 3, 4, 1, FMbpad, NULL },
{ "mbstrlen", 1, 1, 1, FMbstrlen, NULL }, { "mbstrlen", 1, 1, 1, FMbstrlen, NULL },
{ "mbsubstr", 2, 3, 1, FMbsubstr, NULL }, { "mbsubstr", 2, 3, 1, FMbsubstr, NULL },
{ "mbupper", 1, 1, 1, FMbupper, NULL },
{ "min", 1, NO_MAX, 1, FMin, NULL }, { "min", 1, NO_MAX, 1, FMin, NULL },
{ "minsfromutc", 0, 2, 0, FMinsfromutc, NULL }, { "minsfromutc", 0, 2, 0, FMinsfromutc, NULL },
{ "minute", 1, 1, 1, FMinute, NULL }, { "minute", 1, 1, 1, FMinute, NULL },
@@ -5173,3 +5177,50 @@ print_builtinfunc_tokens(void)
printf("%s\n", Func[i].name); printf("%s\n", Func[i].name);
} }
} }
static int mbupper_lower(func_info *info, int upper)
{
wchar_t *ws;
char *s;
size_t i, len;
int r;
ASSERT_TYPE(0, STR_TYPE);
len = mbstowcs(NULL, ARGSTR(0), 0);
if (len == (size_t) -1) {
return E_BAD_MB_SEQ;
}
ws = calloc(len+1, sizeof(wchar_t));
if (!ws) {
return E_NO_MEM;
}
(void) mbstowcs(ws, ARGSTR(0), len+1);
for (i=0; i<len; i++) {
if (upper) {
ws[i] = towupper(ws[i]);
} else {
ws[i] = towlower(ws[i]);
}
}
len = wcstombs(NULL, ws, 0);
s = calloc(len+1, 1);
if (!s) {
free(ws);
return E_NO_MEM;
}
(void) wcstombs(s, ws, len+1);
r = RetStrVal(s, info);
free(s);
free(ws);
return r;
}
static int FMblower(func_info *info)
{
return mbupper_lower(info, 0);
}
static int FMbupper(func_info *info)
{
return mbupper_lower(info, 1);
}

View File

@@ -106,6 +106,7 @@ EXTERN INIT( int DefaultPrio, NO_PRIORITY);
EXTERN INIT( int SysTime, -1); EXTERN INIT( int SysTime, -1);
EXTERN INIT( int LocalSysTime, -1); EXTERN INIT( int LocalSysTime, -1);
EXTERN INIT( int ParseUntriggered, 0); EXTERN INIT( int ParseUntriggered, 0);
EXTERN INIT( int Shaded, 0);
EXTERN char const *InitialFile; EXTERN char const *InitialFile;
EXTERN char const *LocalTimeZone; EXTERN char const *LocalTimeZone;
@@ -127,7 +128,7 @@ EXTERN INIT( int DefaultColorB, -1);
EXTERN INIT( int DefaultColorG, -1); EXTERN INIT( int DefaultColorG, -1);
EXTERN INIT( int SynthesizeTags, 0); EXTERN INIT( int SynthesizeTags, 0);
EXTERN INIT( int ScFormat, SC_AMPM); EXTERN INIT( int ScFormat, SC_AMPM);
EXTERN INIT( int MaxSatIter, 1000); EXTERN INIT( int MaxSatIter, 10000);
EXTERN INIT( int MaxStringLen, MAX_STR_LEN); EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
EXTERN INIT( int UseStdin, 0); EXTERN INIT( int UseStdin, 0);
EXTERN INIT( int PurgeMode, 0); EXTERN INIT( int PurgeMode, 0);
@@ -174,7 +175,7 @@ EXTERN INIT( char *Location, LOCATION);
/* Support hyperlinks in terminal emulators? /* Support hyperlinks in terminal emulators?
https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
*/ */
EXTERN INIT( int TerminalHyperlinks, 0); EXTERN INIT( int TerminalHyperlinks, -1);
/* UTC calculation stuff */ /* UTC calculation stuff */
EXTERN INIT( int MinsFromUTC, 0); EXTERN INIT( int MinsFromUTC, 0);
EXTERN INIT( int CalculateUTC, 1); EXTERN INIT( int CalculateUTC, 1);

View File

@@ -668,6 +668,7 @@ void InitRemind(int argc, char const *argv[])
case 'D': case 'D':
while (*arg) { while (*arg) {
switch(*arg++) { switch(*arg++) {
case 'p': case 'P': DebugFlag |= DB_PUSHPOP; break;
case 's': case 'S': DebugFlag |= DB_PARSE_EXPR; break; case 's': case 'S': DebugFlag |= DB_PARSE_EXPR; break;
case 'h': case 'H': DebugFlag |= DB_HASHSTATS; break; case 'h': case 'H': DebugFlag |= DB_HASHSTATS; break;
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break; case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
@@ -849,6 +850,15 @@ void InitRemind(int argc, char const *argv[])
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0), (void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
&MinsFromUTC, NULL); &MinsFromUTC, NULL);
} }
/* If stdout is a tty, enable terminal hyperlinks by default */
if (TerminalHyperlinks == -1) {
if (isatty(STDOUT_FILENO)) {
TerminalHyperlinks = 1;
} else {
TerminalHyperlinks = 0;
}
}
} }
/***************************************************************/ /***************************************************************/

View File

@@ -295,6 +295,7 @@ PerIterationInit(void)
DefaultColorG = -1; DefaultColorG = -1;
DefaultColorB = -1; DefaultColorB = -1;
NumTriggered = 0; NumTriggered = 0;
Shaded = 0;
JSONLinesEmitted = 0; JSONLinesEmitted = 0;
ClearLastTriggers(); ClearLastTriggers();
ClearDedupeTable(); ClearDedupeTable();
@@ -1388,6 +1389,12 @@ static int DoDebug(ParsePtr p)
val = 0; val = 0;
break; break;
case 'p':
case 'P':
if (val) DebugFlag |= DB_PUSHPOP;
else DebugFlag &= ~DB_PUSHPOP;
break;
case 'e': case 'e':
case 'E': case 'E':
if (val) DebugFlag |= DB_ECHO_LINE; if (val) DebugFlag |= DB_ECHO_LINE;

View File

@@ -176,8 +176,10 @@ int PopOmitContext(ParsePtr p)
/* Remove the context from the stack */ /* Remove the context from the stack */
SavedOmitContexts = c->next; SavedOmitContexts = c->next;
if (c->filename && fname && strcmp(c->filename, fname)) { if (DebugFlag & DB_PUSHPOP) {
Wprint(tr("POP-OMIT-CONTEXT at %s:%d matches PUSH-OMIT-CONTEXT in different file: %s:%d"), fname, LineNo, c->filename, c->lineno); if (c->filename && fname && strcmp(c->filename, fname)) {
Wprint(tr("POP-OMIT-CONTEXT at %s:%d matches PUSH-OMIT-CONTEXT in different file: %s:%d"), fname, LineNo, c->filename, c->lineno);
}
} }
/* Free memory used by the saved context */ /* Free memory used by the saved context */
if (c->partsave) free(c->partsave); if (c->partsave) free(c->partsave);

View File

@@ -985,6 +985,14 @@ static void Init(int argc, char const *argv[])
case 'e': FillPage = 1; break; case 'e': FillPage = 1; break;
case '-':
if (!strcmp(s, "version")) {
printf("rem2ps version %s\n", VERSION);
exit(0);
}
Usage("Unrecognized option");
break;
default: Usage("Unrecognized option"); default: Usage("Unrecognized option");
} }
} }
@@ -1016,6 +1024,7 @@ void Usage(char const *s)
fprintf(stderr, "-e Make calendar fill entire page\n"); fprintf(stderr, "-e Make calendar fill entire page\n");
fprintf(stderr, "-x Put day numbers on left instead of right\n"); fprintf(stderr, "-x Put day numbers on left instead of right\n");
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n"); fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
fprintf(stderr, "--version Print the version of rem2ps and exit\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@@ -221,18 +221,19 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
#define NO_MAX 127 #define NO_MAX 127
/* DEFINES for debugging flags */ /* DEFINES for debugging flags */
#define DB_PRTLINE 0x001 #define DB_PRTLINE 0x0001
#define DB_PRTEXPR 0x002 #define DB_PRTEXPR 0x0002
#define DB_PRTTRIG 0x004 #define DB_PRTTRIG 0x0004
#define DB_DUMP_VARS 0x008 #define DB_DUMP_VARS 0x0008
#define DB_ECHO_LINE 0x010 #define DB_ECHO_LINE 0x0010
#define DB_TRACE_FILES 0x020 #define DB_TRACE_FILES 0x0020
#define DB_PARSE_EXPR 0x040 #define DB_PARSE_EXPR 0x0040
#define DB_HASHSTATS 0x080 #define DB_HASHSTATS 0x0080
#define DB_TRANSLATE 0x100 #define DB_TRANSLATE 0x0100
#define DB_NONCONST 0x200 #define DB_NONCONST 0x0200
#define DB_UNUSED_VARS 0x400 #define DB_UNUSED_VARS 0x0400
#define DB_SWITCH_ZONE 0x800 #define DB_SWITCH_ZONE 0x0800
#define DB_PUSHPOP 0x1000
/* Enumeration of the tokens */ /* Enumeration of the tokens */
enum TokTypes enum TokTypes

View File

@@ -744,8 +744,10 @@ int PopUserFuncs(ParsePtr p)
return E_POPF_NO_PUSH; return E_POPF_NO_PUSH;
} }
UserFuncStack = UserFuncStack->next; UserFuncStack = UserFuncStack->next;
if (strcmp(pf->filename, GetCurrentFilename())) { if (DebugFlag & DB_PUSHPOP) {
Wprint(tr("POP-FUNCS at %s:%d matches PUSH-FUNCS in different file: %s:%d"), GetCurrentFilename(), LineNo, pf->filename, pf->lineno); if (strcmp(pf->filename, GetCurrentFilename())) {
Wprint(tr("POP-FUNCS at %s:%d matches PUSH-FUNCS in different file: %s:%d"), GetCurrentFilename(), LineNo, pf->filename, pf->lineno);
}
} }
for (i=0; i<pf->num_funcs; i++) { for (i=0; i<pf->num_funcs; i++) {
UserFunc *clone = pf->funcs[i]; UserFunc *clone = pf->funcs[i];

View File

@@ -172,7 +172,7 @@ static int latitude_longitude_func(int do_set, Value *val, double *var, double m
} else { } else {
if (val->type != STR_TYPE) return E_BAD_TYPE; if (val->type != STR_TYPE) return E_BAD_TYPE;
x = strtod_in_c_locale(val->v.str, &endptr); x = strtod_in_c_locale(val->v.str, &endptr);
if (*endptr) return E_BAD_TYPE; if (*endptr) return E_BAD_VAL_FOR_SYSVAR;
} }
if (x < min) return E_2LOW; if (x < min) return E_2LOW;
if (x > max) return E_2HIGH; if (x > max) return E_2HIGH;
@@ -466,7 +466,7 @@ static int datetime_sep_func(int do_set, Value *val)
if (val->type != STR_TYPE) return E_BAD_TYPE; if (val->type != STR_TYPE) return E_BAD_TYPE;
if (strcmp(val->v.str, "T") && if (strcmp(val->v.str, "T") &&
strcmp(val->v.str, "@")) { strcmp(val->v.str, "@")) {
return E_BAD_TYPE; return E_BAD_VAL_FOR_SYSVAR;
} }
DateTimeSep = val->v.str[0]; DateTimeSep = val->v.str[0];
return OK; return OK;
@@ -512,7 +512,7 @@ static int default_color_func(int do_set, Value *val)
} }
if (val->type != STR_TYPE) return E_BAD_TYPE; if (val->type != STR_TYPE) return E_BAD_TYPE;
if (sscanf(val->v.str, "%d %d %d", &col_r, &col_g, &col_b) != 3) { if (sscanf(val->v.str, "%d %d %d", &col_r, &col_g, &col_b) != 3) {
return E_BAD_TYPE; return E_BAD_VAL_FOR_SYSVAR;
} }
/* They either all have to be -1, or all between 0 and 255 */ /* They either all have to be -1, or all between 0 and 255 */
if (col_r == -1 && col_g == -1 && col_b == -1) { if (col_r == -1 && col_g == -1 && col_b == -1) {
@@ -547,7 +547,7 @@ static int date_sep_func(int do_set, Value *val)
if (val->type != STR_TYPE) return E_BAD_TYPE; if (val->type != STR_TYPE) return E_BAD_TYPE;
if (strcmp(val->v.str, "/") && if (strcmp(val->v.str, "/") &&
strcmp(val->v.str, "-")) { strcmp(val->v.str, "-")) {
return E_BAD_TYPE; return E_BAD_VAL_FOR_SYSVAR;
} }
DateSep = val->v.str[0]; DateSep = val->v.str[0];
return OK; return OK;
@@ -566,7 +566,7 @@ static int time_sep_func(int do_set, Value *val)
if (val->type != STR_TYPE) return E_BAD_TYPE; if (val->type != STR_TYPE) return E_BAD_TYPE;
if (strcmp(val->v.str, ":") && if (strcmp(val->v.str, ":") &&
strcmp(val->v.str, ".")) { strcmp(val->v.str, ".")) {
return E_BAD_TYPE; return E_BAD_VAL_FOR_SYSVAR;
} }
TimeSep = val->v.str[0]; TimeSep = val->v.str[0];
return OK; return OK;
@@ -1101,6 +1101,7 @@ static SysVar SysVarArr[] = {
{"RunOff", 0, INT_TYPE, &RunDisabled, 0, 0 }, {"RunOff", 0, INT_TYPE, &RunDisabled, 0, 0 },
{"Saturday", 1, TRANS_TYPE, "Saturday", 0, 0 }, {"Saturday", 1, TRANS_TYPE, "Saturday", 0, 0 },
{"September", 1, TRANS_TYPE, "September", 0, 0 }, {"September", 1, TRANS_TYPE, "September", 0, 0 },
{"Shaded" , 0, INT_TYPE, &Shaded, 0, 0 },
{"SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0 }, {"SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0 },
{"SortByDate", 0, INT_TYPE, &SortByDate, 0, 0 }, {"SortByDate", 0, INT_TYPE, &SortByDate, 0, 0 },
{"SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0 }, {"SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0 },
@@ -1343,8 +1344,10 @@ PopVars(ParsePtr p)
return E_POPV_NO_PUSH; return E_POPV_NO_PUSH;
} }
VarStack = VarStack->next; VarStack = VarStack->next;
if (strcmp(pv->filename, GetCurrentFilename())) { if (DebugFlag & DB_PUSHPOP) {
Wprint(tr("POP-VARS at %s:%d matches PUSH-VARS in different file: %s:%d"), GetCurrentFilename(), LineNo, pv->filename, pv->lineno); if (strcmp(pv->filename, GetCurrentFilename())) {
Wprint(tr("POP-VARS at %s:%d matches PUSH-VARS in different file: %s:%d"), GetCurrentFilename(), LineNo, pv->filename, pv->lineno);
}
} }
/* Pop the sysvars */ /* Pop the sysvars */

View File

@@ -76,6 +76,7 @@ COLOUR
CONTEXTs CONTEXTs
CPAN CPAN
CPP's CPP's
CPUs
CalMode CalMode
CalType CalType
CalcMinsFromUTC CalcMinsFromUTC
@@ -160,6 +161,7 @@ FreeBSD
Fromnow Fromnow
GPL GPL
Gedalia Gedalia
Georg
Getopt Getopt
GhostView GhostView
Gurman Gurman
@@ -541,6 +543,7 @@ difftime
doesn doesn
dosubst dosubst
doublequote doublequote
dp
dq dq
dqi dqi
dqis dqis
@@ -685,10 +688,12 @@ maxlen
maybexs maybexs
mbchar mbchar
mbindex mbindex
mblower
mbpad mbpad
mbstowcs mbstowcs
mbstrlen mbstrlen
mbsubstr mbsubstr
mbupper
md md
memcpy memcpy
messageBox messageBox
@@ -780,6 +785,7 @@ popen
pp12 pp12
pp3 pp3
ppp ppp
ppp12
pre pre
preprocessor preprocessor
prev prev
@@ -977,6 +983,7 @@ xsiz
xsiz1 xsiz1
y1 y1
y2 y2
yaag
year1 year1
year2 year2
yeardiff yeardiff
@@ -991,6 +998,7 @@ ziens
zj zj
zn zn
één één
π
א א
אב אב
אדר אדר

15
tests/shaded.rem Normal file
View File

@@ -0,0 +1,15 @@
REM Wed SPECIAL SHADE 255 0 0
IF !$Shaded
REM 15 SPECIAL SHADE 0 255 0
ENDIF
IF !$Shaded
REM SATISFY [$Td % 4 == 0] SPECIAL SHADE 0 0 255
ENDIF
IF !$Shaded
REM Sunday SPECIAL SHADE 0 255 255
ENDIF
IF !$Shaded
REM SPECIAL SHADE 255 255 0
ENDIF

4
tests/test-pushpop1.rem Normal file
View File

@@ -0,0 +1,4 @@
PUSH-OMIT-CONTEXT
PUSH-FUNCS a b c
PUSH-VARS a b c
DO test-pushpop2.rem

4
tests/test-pushpop2.rem Normal file
View File

@@ -0,0 +1,4 @@
POP-VARS
POP-FUNCS
POP-OMIT-CONTEXT

View File

@@ -455,8 +455,8 @@ $REMIND -c ../tests/test-addomit.rem 1 Sep 2021 >> $OUT
$REMIND -cu ../tests/utf-8.rem 1 Nov 2019 >> $OUT $REMIND -cu ../tests/utf-8.rem 1 Nov 2019 >> $OUT
$REMIND -cu '-i$SuppressLRM=1' ../tests/utf-8.rem 1 Nov 2019 >> $OUT $REMIND -cu '-i$SuppressLRM=1' ../tests/utf-8.rem 1 Nov 2019 >> $OUT
TZ=America/Toronto $REMIND -dxe ../tests/tz.rem >> $OUT 2>&1 TZ=America/Toronto $REMIND -dxe ../tests/tz.rem 2026-02-01 >> $OUT 2>&1
TZ=Europe/Berlin $REMIND -dxe ../tests/tz.rem >> $OUT 2>&1 TZ=Europe/Berlin $REMIND -dxe ../tests/tz.rem 2026-02-01 >> $OUT 2>&1
$REMIND ../tests/soleq.rem 1 April 2044 >> $OUT 2>&1 $REMIND ../tests/soleq.rem 1 April 2044 >> $OUT 2>&1
@@ -479,18 +479,18 @@ echo "REM May 22 +10 MSG Bar %b" | $REMIND -tz - 2023-05-21 >> $OUT 2>&1
rm -rf include_dir/ww rm -rf include_dir/ww
touch include_dir/ww touch include_dir/ww
chmod 0666 include_dir/ww chmod 0666 include_dir/ww
$REMIND include_dir/ww >> $OUT 2>&1 $REMIND include_dir/ww 2026-02-01 >> $OUT 2>&1
rm -rf include_dir/ww rm -rf include_dir/ww
# World-writable directory # World-writable directory
mkdir -p include_dir/ww mkdir -p include_dir/ww
touch include_dir/ww/0.rem touch include_dir/ww/0.rem
chmod 0777 include_dir/ww chmod 0777 include_dir/ww
$REMIND include_dir/ww >> $OUT 2>&1 $REMIND include_dir/ww 2026-02-01 >> $OUT 2>&1
rm -rf include_dir/ww rm -rf include_dir/ww
# This segfaulted in 04.02.03 # This segfaulted in 04.02.03
$REMIND -h '-imsgprefix(x)="foo"' /dev/null >> $OUT 2>&1 $REMIND -h '-imsgprefix(x)="foo"' /dev/null 2026-02-01 >> $OUT 2>&1
# Test --version long option # Test --version long option
$REMIND --version >> $OUT 2>&1 $REMIND --version >> $OUT 2>&1
@@ -585,19 +585,19 @@ EOF
(echo 'BANNER %'; echo 'REM 29 MSG No bug') | $REMIND -dt - 29 Feb 2024 >> $OUT 2>&1 (echo 'BANNER %'; echo 'REM 29 MSG No bug') | $REMIND -dt - 29 Feb 2024 >> $OUT 2>&1
$REMIND -ifoo - <<'EOF' >> $OUT 2>&1 $REMIND -ifoo - 2026-02-01 <<'EOF' >> $OUT 2>&1
BANNER % BANNER %
DUMP DUMP
EOF EOF
$REMIND '-i$AddBlankLines' - <<'EOF' >> $OUT 2>&1 $REMIND '-i$AddBlankLines' - 2026-02-01 <<'EOF' >> $OUT 2>&1
BANNER % BANNER %
DUMP $AddBlankLines DUMP $AddBlankLines
EOF EOF
$REMIND ../tests/expr.rem >> $OUT 2>&1 $REMIND ../tests/expr.rem 2026-02-01 >> $OUT 2>&1
$REMIND - <<'EOF' >> $OUT 2>&1 $REMIND - 2026-02-01 <<'EOF' >> $OUT 2>&1
PUSH PUSH
POP POP
PUSH PUSH
@@ -709,7 +709,7 @@ echo "" >> $OUT
$REMIND --print-tokens < /dev/null >> $OUT 2>&1 $REMIND --print-tokens < /dev/null >> $OUT 2>&1
# Torture test #2 # Torture test #2
$REMIND ../tests/torture2.rem >> $OUT 2>&1 $REMIND ../tests/torture2.rem 2026-02-01 >> $OUT 2>&1
# Expression error-reporting # Expression error-reporting
$REMIND -de - 1 Feb 2024 <<'EOF' >> $OUT 2>&1 $REMIND -de - 1 Feb 2024 <<'EOF' >> $OUT 2>&1
@@ -810,10 +810,10 @@ REM Wed MSG Wookie
EOF EOF
# Test year-folding # Test year-folding
TZ=America/Toronto $REMIND -dx ../tests/yearfold.rem >> $OUT 2>&1 TZ=America/Toronto $REMIND -dx ../tests/yearfold.rem 2026-02-01 >> $OUT 2>&1
# Test unused-variable debugging # Test unused-variable debugging
$REMIND -du - <<'EOF' >> $OUT 2>&1 $REMIND -du - 2026-02-01 <<'EOF' >> $OUT 2>&1
set a 1 set a 1
set b a*2 set b a*2
set c "What" set c "What"
@@ -987,6 +987,13 @@ REM 15 INFO "Url: https://dianne.skoll.ca" CAL Hello, linky 3!
REM 15 INFO "Url: https://dianne.skoll.ca" SPECIAL COLOR 255 0 0 Hello, linky 4! REM 15 INFO "Url: https://dianne.skoll.ca" SPECIAL COLOR 255 0 0 Hello, linky 4!
EOF EOF
# Test the $Shaded system variable
$REMIND -pp ../tests/shaded.rem 2026-02-01 >> $OUT 2>&1
# Test the push/pop warnings
$REMIND ../tests/test-pushpop1.rem 2026-01-01 >> $OUT 2>&1
$REMIND -dp ../tests/test-pushpop1.rem 2026-01-01 >> $OUT 2>&1
cmp -s $OUT $CMP cmp -s $OUT $CMP
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
echo "Remind: Acceptance tests ${GRN}PASSED${NRM}" echo "Remind: Acceptance tests ${GRN}PASSED${NRM}"

View File

@@ -1046,7 +1046,7 @@ set a057 value("a05"+"6")
"a05" + "6" => "a056" "a05" + "6" => "a056"
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH" value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a058 version() set a058 version()
version() => "06.02.02" version() => "06.02.04"
set a059 wkday(today()) set a059 wkday(today())
today() => 1991-02-16 today() => 1991-02-16
wkday(1991-02-16) => "Saturday" wkday(1991-02-16) => "Saturday"
@@ -2609,7 +2609,7 @@ a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a007 "1991-02-16" a007 "1991-02-16"
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH" a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a008 "11:44" a008 "11:44"
a058 "06.02.02" a058 "06.02.04"
a059 "Saturday" a059 "Saturday"
a010 12 a010 12
a060 6 a060 6
@@ -5563,8 +5563,8 @@ REM SATISFY ""
REM SATISFY [version() > "01.00.00"] REM SATISFY [version() > "01.00.00"]
../tests/test.rem(1074): SATISFY: expression has no reference to trigdate() or $T... ../tests/test.rem(1074): SATISFY: expression has no reference to trigdate() or $T...
../tests/test.rem(1074): Trig = Saturday, 16 February, 1991 ../tests/test.rem(1074): Trig = Saturday, 16 February, 1991
version() => "06.02.02" version() => "06.02.04"
"06.02.02" > "01.00.00" => 1 "06.02.04" > "01.00.00" => 1
../tests/test.rem(1074): Trig(satisfied) = Saturday, 16 February, 1991 ../tests/test.rem(1074): Trig(satisfied) = Saturday, 16 February, 1991
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5] REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5]
../tests/test.rem(1075): SATISFY: expression has no reference to trigdate() or $T... ../tests/test.rem(1075): SATISFY: expression has no reference to trigdate() or $T...
@@ -16762,7 +16762,16 @@ mbpad("
]8;;https://dianne.skoll.ca\Hello, linky! ]8;;https://dianne.skoll.ca\Hello, linky!
]8;;\]8;;https://dianne.skoll.ca\Hello, linky! ]8;;\]8;;https://dianne.skoll.ca\Hello, linky!
]8;;\]8;;https://dianne.skoll.ca\Hello, linky! ]8;;\]8;;https://dianne.skoll.ca\Hello, linky!
]8;;\DynBuf Mallocs: 1120 mallocs; 31872640 bytes ]8;;\../tests/test.rem(1900): Invalid value for system variable
../tests/test.rem(1901): Invalid value for system variable
../tests/test.rem(1902): Invalid value for system variable
../tests/test.rem(1903): Invalid value for system variable
../tests/test.rem(1904): Invalid value for system variable
mbupper("öÖçÇéôñÑÉÊ") => "ÖÖÇÇÉÔÑÑÉÊ"
mblower("öÖçÇéôñÑÉÊ") => "ööççéôññéê"
upper("öÖçÇéôñÑÉÊ") => "öÖçÇéôñÑÉÊ"
lower("öÖçÇéôñÑÉÊ") => "öÖçÇéôñÑÉÊ"
DynBuf Mallocs: 1132 mallocs; 31873408 bytes
Variable hash table statistics: Variable hash table statistics:
Entries: 100146; Buckets: 87719; Non-empty Buckets: 66303 Entries: 100146; Buckets: 87719; Non-empty Buckets: 66303
Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510 Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510
@@ -16784,7 +16793,7 @@ Expression nodes high-water: 302076
Expression nodes leaked: 0 Expression nodes leaked: 0
Parse level high-water: 34 Parse level high-water: 34
Max expr node evaluations per line: 2001 Max expr node evaluations per line: 2001
Total expression node evaluations: 106733 Total expression node evaluations: 106746
Test 2 Test 2
@@ -23822,7 +23831,7 @@ SECURITY: Won't read world-writable file or directory!
Error reading include_dir/ww: Can't open file Error reading include_dir/ww: Can't open file
SECURITY: Won't read world-writable file or directory! SECURITY: Won't read world-writable file or directory!
Error reading include_dir/ww: No files matching *.rem Error reading include_dir/ww: No files matching *.rem
06.02.02 06.02.04
Enabling test mode: This is meant for the acceptance test. Enabling test mode: This is meant for the acceptance test.
Do not use --test in production. Do not use --test in production.
In test mode, the system time is fixed at 2025-01-06@19:00 In test mode, the system time is fixed at 2025-01-06@19:00
@@ -24771,9 +24780,11 @@ lower
max max
mbchar mbchar
mbindex mbindex
mblower
mbpad mbpad
mbstrlen mbstrlen
mbsubstr mbsubstr
mbupper
min min
minsfromutc minsfromutc
minute minute
@@ -24940,6 +24951,7 @@ $PSCal
$RunOff $RunOff
$Saturday $Saturday
$September $September
$Shaded
$SimpleCal $SimpleCal
$SortByDate $SortByDate
$SortByPrio $SortByPrio
@@ -25187,6 +25199,7 @@ TRANSLATE "Invalid multibyte sequence" ""
TRANSLATE "Maximum expression complexity exceeded" "" TRANSLATE "Maximum expression complexity exceeded" ""
TRANSLATE "Expecting operator or end-of-expression" "" TRANSLATE "Expecting operator or end-of-expression" ""
TRANSLATE "Expecting constant, variable, function call or (expression)" "" TRANSLATE "Expecting constant, variable, function call or (expression)" ""
TRANSLATE "Invalid value for system variable" ""
# Other Messages # Other Messages
TRANSLATE "%s function `%s' defined at %s(%s) does not use its argument" "" TRANSLATE "%s function `%s' defined at %s(%s) does not use its argument" ""
@@ -39867,20 +39880,20 @@ Testing TODOS in calendar mode with completed todos hidden
2025/08/27 * * * * Ninth 2025/08/27 * * * * Ninth
Testing TODOS and JSON mode 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":"2025-08-01","filename":"../tests/todos.rem","lineno":4,"d":1,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-01","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":"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":"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-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-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-06","filename":"../tests/todos.rem","lineno":9,"d":6,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-06","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-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":12,"wd":["Wednesday"],"is_todo":1,"complete_through":"2025-08-12","delta":7,"priority":5000,"body":"Ninth today"},
{"date":"2025-08-01","filename":"../tests/todos.rem","lineno":14,"d":1,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-1 ","priority":5000,"body":"First on 2025-08-01"}, {"date":"2025-08-01","filename":"../tests/todos.rem","lineno":14,"d":1,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-01","priority":5000,"body":"First on 2025-08-01"},
{"date":"2022-08-01","filename":"../tests/todos.rem","lineno":15,"d":1,"m":8,"is_todo":1,"complete_through":"2022-07-31","priority":5000,"body":"Second on 2022-08-01"}, {"date":"2022-08-01","filename":"../tests/todos.rem","lineno":15,"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":16,"d":1,"m":8,"is_todo":1,"complete_through":"2022-08-01","priority":5000,"body":"Third on 2023-08-01"}, {"date":"2023-08-01","filename":"../tests/todos.rem","lineno":16,"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":17,"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-20","filename":"../tests/todos.rem","lineno":17,"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":18,"d":13,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-13","priority":5000,"body":"Fifth today"}, {"date":"2025-08-13","filename":"../tests/todos.rem","lineno":18,"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":19,"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-06","filename":"../tests/todos.rem","lineno":19,"d":6,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-06","priority":5000,"body":"Sixth on 2025-08-06"},
{"date":"2025-08-20","filename":"../tests/todos.rem","lineno":21,"wd":["Wednesday"],"is_todo":1,"complete_through":"2025-08-13","delta":7,"priority":5000,"body":"Eighth on 2025-08-20"}, {"date":"2025-08-20","filename":"../tests/todos.rem","lineno":21,"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":22,"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":22,"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":25,"d":13,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-13","max_overdue":3,"priority":5000,"body":"Yup today"}, {"date":"2025-08-13","filename":"../tests/todos.rem","lineno":25,"d":13,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-13","max_overdue":3,"priority":5000,"body":"Yup today"},
@@ -40094,9 +40107,9 @@ devnull test b
No reminders. No reminders.
[ [
{"banner":"Reminders for Wednesday, 1st October, 2025:"}, {"banner":"Reminders for Wednesday, 1st October, 2025:"},
{"date":"2025-10-01","filename":"-stdin-","lineno":3,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-1 ","priority":5000,"body":"Nonconst NOT set 2025-10-01"}, {"date":"2025-10-01","filename":"-stdin-","lineno":3,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-01","priority":5000,"body":"Nonconst NOT set 2025-10-01"},
{"date":"2025-10-01","filename":"-stdin-","lineno":4,"nonconst_expr":1,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-1 ","priority":5000,"body":"Nonconst IS set 2025-10-01"}, {"date":"2025-10-01","filename":"-stdin-","lineno":4,"nonconst_expr":1,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-01","priority":5000,"body":"Nonconst IS set 2025-10-01"},
{"date":"2025-10-01","filename":"-stdin-","lineno":5,"nonconst_expr":1,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-1 ","priority":5000,"body":"Nonconst IS set"} {"date":"2025-10-01","filename":"-stdin-","lineno":5,"nonconst_expr":1,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-01","priority":5000,"body":"Nonconst IS set"}
] ]
# Nonconst-expr in trigger # Nonconst-expr in trigger
set $ParseUntriggered 1 set $ParseUntriggered 1
@@ -40224,4 +40237,44 @@ February 28
+----------+----------+----------+----------+----------+----------+----------+ +----------+----------+----------+----------+----------+----------+----------+
|26 |27 |28 |29 |30 |31 | | |26 |27 |28 |29 |30 |31 | |
+----------+----------+----------+----------+----------+----------+----------+ +----------+----------+----------+----------+----------+----------+----------+
# translations
{"LANGID":"en"}
# rem2ps2 begin
February 2026 28 0 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
January 31
March 31
{"date":"2026-02-01","filename":"../tests/shaded.rem","lineno":10,"passthru":"SHADE","wd":["Sunday"],"is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":255,"b":255,"body":"0 255 255"}
{"date":"2026-02-02","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-03","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-04","filename":"../tests/shaded.rem","lineno":1,"passthru":"SHADE","wd":["Wednesday"],"is_todo":0,"priority":5000,"r":255,"g":0,"b":0,"body":"255 0 0"}
{"date":"2026-02-05","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-06","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-07","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-08","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
{"date":"2026-02-09","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-10","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-11","filename":"../tests/shaded.rem","lineno":1,"passthru":"SHADE","wd":["Wednesday"],"is_todo":0,"priority":5000,"r":255,"g":0,"b":0,"body":"255 0 0"}
{"date":"2026-02-12","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
{"date":"2026-02-13","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-14","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-15","filename":"../tests/shaded.rem","lineno":3,"passthru":"SHADE","d":15,"is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":255,"b":0,"body":"0 255 0"}
{"date":"2026-02-16","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
{"date":"2026-02-17","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-18","filename":"../tests/shaded.rem","lineno":1,"passthru":"SHADE","wd":["Wednesday"],"is_todo":0,"priority":5000,"r":255,"g":0,"b":0,"body":"255 0 0"}
{"date":"2026-02-19","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-20","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
{"date":"2026-02-21","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-22","filename":"../tests/shaded.rem","lineno":10,"passthru":"SHADE","wd":["Sunday"],"is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":255,"b":255,"body":"0 255 255"}
{"date":"2026-02-23","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-24","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
{"date":"2026-02-25","filename":"../tests/shaded.rem","lineno":1,"passthru":"SHADE","wd":["Wednesday"],"is_todo":0,"priority":5000,"r":255,"g":0,"b":0,"body":"255 0 0"}
{"date":"2026-02-26","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-27","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
{"date":"2026-02-28","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
# rem2ps2 end
No reminders.
../tests/test-pushpop2.rem(1): POP-VARS at ../tests/test-pushpop2.rem:1 matches PUSH-VARS in different file: ../tests/test-pushpop1.rem:3
../tests/test-pushpop2.rem(2): POP-FUNCS at ../tests/test-pushpop2.rem:2 matches PUSH-FUNCS in different file: ../tests/test-pushpop1.rem:2
../tests/test-pushpop2.rem(3): POP-OMIT-CONTEXT at ../tests/test-pushpop2.rem:3 matches PUSH-OMIT-CONTEXT in different file: ../tests/test-pushpop1.rem:1
No reminders.

View File

@@ -1896,6 +1896,21 @@ REM INFO "Url: https://dianne.skoll.ca" MSG Hello, linky!
REM INFO "Url: https://dianne.skoll.ca" MSF Hello, linky! REM INFO "Url: https://dianne.skoll.ca" MSF Hello, linky!
REM INFO "Url: https://dianne.skoll.ca" SPECIAL COLOR 255 0 0 Hello, linky! REM INFO "Url: https://dianne.skoll.ca" SPECIAL COLOR 255 0 0 Hello, linky!
# Bad values for system variables
SET $Latitude "Cabbage"
SET $Longitude "Carrots"
SET $TimeSep "FOO"
SET $DateSep "BAR"
SET $DefaultColor "My oh my, what lovely eyes!"
# mbupper and mblower
DEBUG +x
SET a mbupper("öÖçÇéôñÑÉÊ")
SET a mblower("öÖçÇéôñÑÉÊ")
SET a upper("öÖçÇéôñÑÉÊ")
SET a lower("öÖçÇéôñÑÉÊ")
DEBUG -x
# Don't want Remind to queue reminders # Don't want Remind to queue reminders
EXIT EXIT