7235 lines
272 KiB
Markdown
7235 lines
272 KiB
Markdown
# NAME
|
|
|
|
remind - a sophisticated reminder service
|
|
|
|
# SYNOPSIS
|
|
|
|
**remind \[*options*\] *filename* \[*date*\] \[*\*rep*\] \[*time*\]**
|
|
|
|
# DESCRIPTION
|
|
|
|
**Remind** reads the supplied *filename* and executes the commands found
|
|
in it. The commands are used to issue reminders and alarms. Each
|
|
reminder or alarm can consist of a message sent to standard output, or a
|
|
program to be executed.
|
|
|
|
If *filename* is specified as a single dash \'-\', then **Remind** takes
|
|
its input from standard input. In this case, if **Remind** has been
|
|
compiled against the GNU Readline library, it will use Readline to give
|
|
you an interactive line-editing interface.
|
|
|
|
If *filename* happens to be a directory rather than a plain file, then
|
|
**Remind** reads all of the files (but not any subdirectories!) in that
|
|
directory that match the pattern \"\*.rem\". The files are read in
|
|
sorted order; the sort order may depend on your locale, but should match
|
|
the sort order used by the shell to expand \"\*.rem\".
|
|
|
|
**Remind** reads its files starting from the beginning to the end, or
|
|
until it encounters a line whose sole content is \"\_\_EOF\_\_\"
|
|
(without the quotes.) Anything after the \_\_EOF\_\_ marker is
|
|
completely ignored.
|
|
|
|
# MODES OF OPERATION
|
|
|
|
**Remind** has four major modes of operation:
|
|
|
|
**Agenda Mode**
|
|
|
|
: Agenda mode is the default mode. In this mode, **Remind** prints
|
|
today\'s reminders on standard output and exits. It may fork a
|
|
background process to pop up queued reminders for later in the day.
|
|
|
|
**Calendar Mode**
|
|
|
|
: In this mode, **Remind** generates a calendar either by drawing it
|
|
in the terminal or by sending data in computer-readable format to a
|
|
back-end program that actually draws the calendar.
|
|
|
|
**Daemon Mode**
|
|
|
|
: This is a special mode of operation in which **Remind** is invoked
|
|
by a front-end and runs as a daemon, accepting requests from the
|
|
front-end and sending messages back to the front-end. **TkRemind**
|
|
uses **Remind** in daemon mode.
|
|
|
|
**Purge Mode**
|
|
|
|
: In this mode, **Remind** produces no output, but creates new
|
|
versions of its input files with all expired reminders commented
|
|
out.
|
|
|
|
# OPTIONS
|
|
|
|
**Remind** has a slew of options. If you\'re new to the program, ignore
|
|
them for now and skip to the section \"REMINDER FILES\".
|
|
|
|
**-n**
|
|
|
|
: The **-n** option causes **Remind** to print the **next** occurrence
|
|
of each reminder in a simple calendar format. You can sort this by
|
|
date by piping the output through **sort(1)**. Note that the **-n**
|
|
option causes any **-g** option to be *ignored* and also implicitly
|
|
enables the **-o** option.
|
|
|
|
**-j\[*n*\]**
|
|
|
|
: Runs **Remind** in \"purge\" mode to get rid of expired reminders.
|
|
See the section PURGE MODE for details.
|
|
|
|
**-r**
|
|
|
|
: The **-r** option disables **RUN** directives and the **shell()**
|
|
function.
|
|
|
|
**-c**_\[flags\]n_
|
|
|
|
: The **-c** option causes **Remind** to produce a calendar that is
|
|
sent to standard output. If you supply a number *n*, then a calendar
|
|
will be generated for *n* months, starting with the current month.
|
|
By default, a calendar for only the current month is produced. This
|
|
option implicitly enables the **-o** option.
|
|
|
|
You can precede *n* (if any) with a set of flags. The flags are as
|
|
follows:
|
|
|
|
**\'+\'**
|
|
|
|
: causes a calendar for *n* weeks to be produced.
|
|
|
|
**\'a\'**
|
|
|
|
: causes **Remind** to display reminders on the calendar on the
|
|
day they actually occur *as well as* on any preceding days
|
|
specified by the reminder\'s *delta*. This *also* causes
|
|
**Remind** to include text outside %\"\...%\" sequences that
|
|
would otherwise be removed (though the actual %\" markers
|
|
themselves are removed.)
|
|
|
|
**\'l\'**
|
|
|
|
: causes **Remind** to use VT100 line-drawing characters to draw
|
|
the calendar. The characters are hard-coded and will only work
|
|
on terminals that emulate the VT00 line-drawing character set.
|
|
|
|
**\'u\'**
|
|
|
|
: is similar to \'l\', but causes **Remind** to use UNICODE
|
|
line-drawing characters to draw the calendar. The characters are
|
|
hard-coded and will only work on terminals that are set to UTF-8
|
|
character encoding. This flag also enables the use of the
|
|
UNICODE \"left-to-right\" mark that can fix up formatting
|
|
problems with right-to-left languages in the calendar display.
|
|
|
|
**\'z\'**
|
|
|
|
: causes **Remind** to use escape sequences to turn reminders with
|
|
a \"URL\" info string into hyperlinks. In order to work, your
|
|
terminal must support the escape sequences documented at
|
|
https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
|
|
|
|
**\'c\'**
|
|
|
|
: causes **Remind** to use VT100 escape sequences to approximate
|
|
SPECIAL COLOR reminders. Note that this flag is kept for
|
|
backwards-compatibility; you should use the
|
|
**-@**_\[n\]\[,m\]\[,b\]_ command-line option instead.
|
|
|
|
In a UTF-8 locale, **Remind** will use \"left-to-right marks\" when
|
|
creating a calendar with the **-c** option. Some terminals don\'t
|
|
handle this correctly and garble the rendering of the calendar; see
|
|
the documentation of **\$SuppressLRM** in the section \"SYSTEM
|
|
VARIABLES\" for a workaround.
|
|
|
|
**-@\[*n*\]\[,*m*\]\[,*b*\]**
|
|
|
|
: Tells **Remind** to approximate SPECIAL COLOR and SHADE reminders
|
|
using VT100 escape sequences. The approximation is (of necessity)
|
|
very coarse, because the VT100 only has eight different color
|
|
sequences, each with one of two brightnesses. A color component
|
|
greater than 64 is considered \"on\", and if any of the three color
|
|
components is greater than 128, the color is considered \"bright\".
|
|
|
|
If you supply the optional numeric parameters, the have the
|
|
following meanings: *n*=0 tells **Remind** to use the standard 16
|
|
VT100 colors. *n*=1 tells it to use an extended 256-color palette
|
|
supported by many terminal emulators such as xterm. And *n*=2 tells
|
|
it to use escape sequences that support true 24-bit colors, again
|
|
supported by many terminal emulators such as xterm.
|
|
|
|
If the optional *m* parameter is supplied following a comma, then
|
|
*m*=0 tells **Remind** that the terminal background is dark, and
|
|
**Remind** will brighten up dark colors to make them visible. If
|
|
*m*=1, then **Remind** assumes the terminal background is light and
|
|
it will darken bright colors to make them visible. If *m* is
|
|
specified as 2, then **Remind** does not perform any adjustments,
|
|
and some reminders may be hard or impossible to see if the color is
|
|
too close to the terminal background color. If you supply the letter
|
|
**t** rather than a number, then **Remind** attempts to guess the
|
|
background color of the terminal, *even if* stdout is not a
|
|
terminal.
|
|
|
|
On startup, if the standard output is a terminal, **Remind**
|
|
attempts to determine if the terminal background is dark or light by
|
|
sending a special escape sequence to determine the background color.
|
|
The *m* parameter can override this check (or force it if *m* is
|
|
given as **t**.)
|
|
|
|
If the optional *b* parameter is supplied following a comma, then
|
|
*b=0* tells **Remind** to ignore SPECIAL SHADE reminders (the
|
|
default) and *b=1* tells **Remind** to respect SPECIAL SHADE
|
|
reminders by emitting VT100 escape codes to color the background of
|
|
the calendar cell. Note that SHADE does not work well unless you are
|
|
using the extended 256-color palette (*n*=1) or the true 24-bit
|
|
colors (*n*=2). Note that for calendar cells that are shaded, the
|
|
clamping mechanism described earlier for *m=0* or *m=1* is skipped;
|
|
it is assumed that if you set *both* the foreground color of a
|
|
reminder and the background color of a cell, then you know what you
|
|
are doing.
|
|
|
|
**-w*col*\[,*pad*\[,*spc*\]\]\]**
|
|
|
|
: The **-w** option specifies the output width, padding and spacing of
|
|
the formatted calendar output. *Col* specifies the number of columns
|
|
in the output device. If *col* is not specified, or is specified as
|
|
0, it defaults to the larger of 71 or the actual width of your
|
|
terminal, or to 80 if standard output is not a terminal. If *col* is
|
|
specified as the letter **t**, then **Remind** attempts to get the
|
|
width of the **/dev/tty** terminal device. This is useful, for
|
|
example, if you pipe calendar output into **less**; even though
|
|
standard output is a pipe, you want the calendar to be sized
|
|
correctly for your terminal window:
|
|
|
|
remind -c -wt .reminders | less
|
|
|
|
> Note that the value of *col* is also used to set the system variable
|
|
> \$FormWidth, which is initialized to *col* - 8. See \"SYSTEM
|
|
> VARIABLES\" for details.
|
|
>
|
|
> *Pad* specifies how many lines to use to \"pad\" empty calendar boxes.
|
|
> This defaults to 5. If you have many reminders on certain days that
|
|
> make your calendar too large to fit on a page, you can try reducing
|
|
> *pad* to make the empty boxes smaller. *Spc* specifies how many blank
|
|
> lines to leave between the day number and the first reminder entry. It
|
|
> defaults to 1.
|
|
>
|
|
> Any of *col*, *pad* or *spc* can be omitted, providing you provide the
|
|
> correct number of commas. Don\'t use any spaces in the option.
|
|
|
|
**-s\[a\]n**
|
|
|
|
: The **-s** option is very similar to the **-c** option, except that
|
|
the output calendar is not formatted. It is listed in a \"simple
|
|
format\" that can be used as input for more sophisticated
|
|
calendar-drawing programs. If *n* starts with \"+\", then it is
|
|
interpreted as a number of weeks. This option also implicitly
|
|
enables the **-o** option.
|
|
|
|
If you immediately follow the **s** with the letter **a**, then
|
|
**Remind** displays reminders on the calendar on the day they
|
|
actually occur *as well as* on any preceding days specified by the
|
|
reminder\'s *delta*.
|
|
|
|
**-p\[a\]\[p\]\[p\]\[q\]\[+\]n**
|
|
|
|
: The **-p** option is very similar to the **-s** option, except that
|
|
the output contains additional information for use by a back-end
|
|
such as the **Rem2PS** program, which creates a PostScript calendar,
|
|
and various other back-end programs. If *n* starts with \"+\", then
|
|
it specifies a number of weeks rather than a number of months, and
|
|
back-ends are expected to produce weekly calendars. Note that not
|
|
all back-ends support weekly calendars; currently, only **rem2pdf**
|
|
and **rem2html** do. Specifying a weekly calendar implicitly enables
|
|
the pure JSON interchange format, similar to **-ppp**.
|
|
|
|
The format of the **-p** output is described in the **rem2ps(1)**
|
|
man page. If you immediately follow the **p** with the letter **a**,
|
|
then **Remind** displays reminders on the calendar on the day they
|
|
actually occur *as well as* on any preceding days specified by the
|
|
reminder\'s *delta*. If you follow the **p** with another **p**,
|
|
then **Remind** uses a more comprehensive JSON-based format rather
|
|
than the \"simple calendar\" format. This format is also documented
|
|
in the **rem2ps(1)** man page. Finally, if you use three p\'s, as in
|
|
**-ppp**, then **Remind** uses a pure JSON format, again documented
|
|
in **rem2ps(1)**. If you include a **q** letter with this option,
|
|
then the usual calendar-mode substitution filter is disabled and the
|
|
%\"\...%\" sequences are preserved in the output.
|
|
|
|
Note that to pass INFO strings to a back-end, you must use **-pp**
|
|
or **-ppp**. The simpler **-p** format is not capable of
|
|
transmitting the INFO strings to the back-end.
|
|
|
|
The **-p**, **-pp** and **-ppp** options implicitly enable the
|
|
**-o** option.
|
|
|
|
Note that the **-pp** or **-ppp** options also enable the **-l**
|
|
option.
|
|
|
|
**-l**
|
|
|
|
: If you use the -l option in conjunction with the -p option, then
|
|
**Remind** outputs additional information for back-end programs such
|
|
as **rem2ps**. This additional information lets the back-end
|
|
programs correlate a reminder with the source file and line number
|
|
that produced it.
|
|
|
|
**-m**
|
|
|
|
: The **-m** option causes the **-c** or **-p** options to produce a
|
|
calendar whose first column is Monday rather than Sunday. (This
|
|
conforms to the international standard.)
|
|
|
|
**-v**
|
|
|
|
: The **-v** option makes the output of **Remind** slightly more
|
|
verbose. Currently, this causes **Remind** to echo a bad line in
|
|
case of an error, and to print a security message if a script tests
|
|
the \$RunOff system variable.
|
|
|
|
**-o**
|
|
|
|
: The **-o** option causes **Remind** to ignore all **ONCE**
|
|
directives. Note that **ONCE** is also ignored if any of the **-c**,
|
|
**-n**, **-p**, or **-s** options is used, if a repetition factor
|
|
**\*n** is used, or if a date other than today\'s date is specified
|
|
on the command-line.
|
|
|
|
**-t**
|
|
|
|
: The **-t** option causes **Remind** to trigger all non-expired
|
|
reminders, regardless of the *delta* supplied for each reminder.
|
|
|
|
**-tn**
|
|
|
|
: If you supply a number *n* after the **-t** option, then **Remind**
|
|
pretends that every **REM** command has a delta of ++*n*, regardless
|
|
of any existing delta.
|
|
|
|
**-tz**
|
|
|
|
: If you supply the letter **z** after the **-t** option, then
|
|
**Remind** sets all REM statements\' deltas to zero, regardless of
|
|
the value supplied in the REM statement itself. In effect, this
|
|
disables all deltas of the form **+**_n_ and **++**_n_.
|
|
|
|
**-tt\[*n*\]**
|
|
|
|
: The **-tt** option causes **Remind** to assume a default delta of
|
|
*n* minutes for all timed reminders. If **-tt** is given with no
|
|
*n*, a default delta of 5 minutes is used.
|
|
|
|
**-h**
|
|
|
|
: The **-h** option (\"hush\...\") suppresses certain warning and
|
|
information messages. In particular, if no reminders are triggered,
|
|
this mode produces no output.
|
|
|
|
**-a**
|
|
|
|
: The **-a** option causes **Remind** not to immediately trigger timed
|
|
reminders that trigger on the current day. It also causes **Remind**
|
|
not to place timed reminders in a calendar. If you supply two or
|
|
more **-a** options, then **Remind** *will* trigger timed reminders
|
|
that are in the future, but will not trigger timed reminders whose
|
|
time has passed. (Regardless of how many **-a** options you supply,
|
|
**Remind** will not include timed reminders in the calendar if at
|
|
least one **-a** option is used.)
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
|
|
**-q**
|
|
|
|
: The **-q** option causes **Remind** not to queue timed reminders for
|
|
later execution.
|
|
|
|
**-f**
|
|
|
|
: The **-f** option causes **Remind** to remain in the foreground when
|
|
processing queued reminders, rather than forking off a background
|
|
process to handle them.
|
|
|
|
**-e**
|
|
|
|
: The **-e** option diverts error messages (normally sent to the
|
|
standard error stream) to the standard output stream.
|
|
|
|
**-d**_chars_
|
|
|
|
: The **-d** option enables certain debugging modes. The *chars*
|
|
specify which modes to enable:
|
|
|
|
**e**
|
|
|
|
: Echo all input lines
|
|
|
|
**x**
|
|
|
|
: Trace all expression evaluation
|
|
|
|
**t**
|
|
|
|
: Display all trigger date computation
|
|
|
|
**v**
|
|
|
|
: Dump the variable table after execution of the reminder script
|
|
|
|
**l**
|
|
|
|
: Echo lines when displaying error messages
|
|
|
|
**f**
|
|
|
|
: Trace the reading of reminder files
|
|
|
|
**s**
|
|
|
|
: Trace expression parsing and display the internal expression
|
|
node tree. This is unlikely to be useful unless you are working
|
|
on **Remind**\'s expression evaluation engine.
|
|
|
|
**h**
|
|
|
|
: Dump hash-table statistics on exit.
|
|
|
|
**u**
|
|
|
|
: When **Remind** exits, print a list of variables that were SET,
|
|
but not subsequently used.
|
|
|
|
Note that the **u** debugging flag may produce spurious
|
|
warnings. For example, this sequence of commands:
|
|
|
|
DEBUG +u
|
|
SET a 1
|
|
IFTRIG Wed
|
|
MSG a = [a]
|
|
ENDIF
|
|
|
|
will issue a warning about **a** being unused unless it is run
|
|
on a Wednesday.
|
|
|
|
**n**
|
|
|
|
: Print debugging information about why **Remind** considers an
|
|
expression to be \"non-constant\"
|
|
|
|
**q**
|
|
|
|
: Output a TRANSLATE command each time the **\_()** built-in
|
|
function is called or the **%(\...)** substitution sequence is
|
|
encountered.
|
|
|
|
**-g**\[**a\|d**\[**a\|d**\[**a\|d**\[**a\|d**\]\]\]\]
|
|
|
|
: Normally, reminders are issued in the order in which they are
|
|
encountered in the reminder script. The **-g** option cause
|
|
**Remind** to sort reminders by date and time prior to issuing them.
|
|
The optional **a** and **d** characters specify the sort order
|
|
(ascending or descending) for the date, time and priority fields.
|
|
See the section \"SORTING REMINDERS\" for more information.
|
|
|
|
Note that **-g** is *ignored* if you use the **-n** option.
|
|
|
|
**-b**\[*n*\]
|
|
|
|
: Set the time format for the calendar and simple-calendar outputs.
|
|
*N* can range from 0 to 2, with the default 0. A value of 0 causes
|
|
times to be inserted in 12-hour (am/pm) format. 1 causes times to be
|
|
inserted in 24-hour format, and 2 inhibits the automatic insertion
|
|
of times in the calendar output.
|
|
|
|
**-x**\[*n*\]
|
|
|
|
: Sets the iteration limit for the **SATISFY** clause of a **REM**
|
|
command. Defaults to 1000.
|
|
|
|
**-k**_cmd_
|
|
|
|
: Instead of simply printing **MSG**-type reminders, this causes them
|
|
to be passed to the specific *cmd*. You must use \'%s\' where you
|
|
want the body to appear, and may need to enclose this option in
|
|
quotes. Note that all shell characters in the body of the reminder
|
|
are escaped with a backslash, and the entire body of the reminder is
|
|
passed as a single argument. Note that this option **overrides** the
|
|
**-r** option and the **RUN OFF** command.
|
|
|
|
> As an example, suppose you have an X Window program called
|
|
> **xmessage** that pops up a window and displays its invocation
|
|
> arguments. You could use:
|
|
>
|
|
> remind '-kxmessage %s &' ...
|
|
>
|
|
> to have all of your **MSG**-type reminders processed using xmessage.
|
|
>
|
|
> A word of warning: It is very easy to spawn dozens of xmessage
|
|
> processes with the above technique. So be very careful. Because all
|
|
> shell and whitespace characters are escaped, the program you execute
|
|
> with the **-k** option must be prepared to handle the entire message
|
|
> as a single argument.
|
|
>
|
|
> If you follow the **-k** option with a colon, then the command is
|
|
> applied only to queued timed reminders. Normal reminders are handled
|
|
> as usual. In the above example, if you want normal reminders to simply
|
|
> be displayed as usual, but queued reminders to be sent to notify-send,
|
|
> you could use:
|
|
>
|
|
> remind '-k:notify-send %s &' ...
|
|
>
|
|
> You use both **-k**_cmd1_ and **-k:**_cmd2_ to use different commands
|
|
> for queued versus non-queued reminders.
|
|
|
|
**-z**\[*n*\] Runs **Remind** in \"daemon mode\". If *n*
|
|
|
|
: is supplied, it specifies how often (in minutes) **Remind** should
|
|
wake up to check if the reminder script has been changed. *N*
|
|
defaults to 1, and can range from 1 to 60. Note that the use of the
|
|
**-z** option also enables the **-f** option.
|
|
|
|
> If **Remind** is compiled on a system that supports **inotify**(7),
|
|
> then if the reminder script supplied on the command-line is actually a
|
|
> directory, **Remind** additionally checks if all files within that
|
|
> directory have been modified since startup.
|
|
>
|
|
> If you supply the option **-zj**, **Remind** runs in a special mode
|
|
> called **server mode**. This is documented in the tkremind man page;
|
|
> see tkremind(1). The older server mode option **-z0** still works, but
|
|
> is deprecated; it uses an ad-hoc method to communicate with the client
|
|
> rather than using JSON to communicate with the client.
|
|
|
|
**-u**_name_
|
|
|
|
: Runs **Remind** with the uid and gid of the user specified by
|
|
*name*. The option changes the uid and gid as described, and sets
|
|
the environment variables HOME, SHELL and USER to the home
|
|
directory, shell, and user name, respectively, of the specified
|
|
user. LOGNAME is also set to the specified user name. This option is
|
|
meant for use in shell scripts that mail reminders to all users.
|
|
Note that as of **Remind** 3.00.17, using **-u** implies **-r** \--
|
|
the RUN directive and shell() functions are disabled. However, if
|
|
you prefix *name* with a **+**-sign, then RUN and shell() are *not*
|
|
disabled. That is, **-uwhatever** switches the user to **whatever**
|
|
and disables RUN, whereas **-u+whatever** switches the user to
|
|
**whatever** but leaves RUN enabled.
|
|
|
|
> Non-root users can also use the **-u** option. However, in this case,
|
|
> it only changes the environment variables as described above. It does
|
|
> not change the effective uid or gid.
|
|
|
|
**-+**_username_
|
|
|
|
: Causes **Remind** to trust files owned by the user *username*.
|
|
Normally, if **Remind** reads a file that you do not own, it
|
|
disables RUN and the shell() function. This option causes it to also
|
|
trust files owned by *username*. You can supply multiple **-+**
|
|
options to trust multiple users, up to a limit of 20 trusted users.
|
|
|
|
**-y**
|
|
|
|
: Causes **Remind** to synthesize a tag for any reminder that lacks a
|
|
TAG clause.
|
|
|
|
**-i**_var=expr_
|
|
|
|
: Sets the value of the specified *var* to *expr*, and **preserves**
|
|
*var*. *Expr* can be any valid **Remind** expression. See the
|
|
section \"INITIALIZING VARIABLES ON THE COMMAND LINE\" for more
|
|
details. If you omit the **=**_expr_ part, then *var* is initialized
|
|
to 0. In other words, **-i**_var_ is exactly the same as
|
|
**-i**_var=0_.
|
|
|
|
**-i**_func(args)=definition_
|
|
|
|
: Allows you to define a function on the command line.
|
|
|
|
If you supply a *date* on the command line, it must consist of *day
|
|
month year*, where *day* is the day of the month, *month* is at least
|
|
the first three letters of the English name of the month, and *year* is
|
|
a year (all 4 digits) from 1990 to about 2075. You can leave out the
|
|
*day*, which then defaults to 1.
|
|
|
|
If you do supply a *date* on the command line, then **Remind** uses it,
|
|
rather than the actual system date, as its notion of \"today.\" This
|
|
lets you create calendars for future months, or test to see how your
|
|
reminders will be triggered in the future. Similarly, you can supply a
|
|
*time* to set **Remind**\'s notion of \"now\" to a particular time.
|
|
Supplying a *time* on the command line also implicitly enables the
|
|
**-q** option and disables the **-z** option. The *time* may be
|
|
specified in 24-hour format (e.g., 13:20) or common \"AM/PM\" format
|
|
(1:20pm).
|
|
|
|
If you would rather specify the date more succinctly, you can supply it
|
|
as YYYY-MM-DD or YYYY/MM/DD. You can even supply a date and time on the
|
|
command line as one argument: YYYY-MM-DD@HH:MM.
|
|
|
|
In addition, you can supply a *repeat* parameter, which has the form
|
|
\**rep*. This causes **Remind** to be run *rep* times, with the date
|
|
incrementing on each iteration. You may have to enclose the parameter in
|
|
quotes to avoid shell expansion. See the subsection \"Repeated
|
|
Execution\" in the section \"CALENDAR MODE\" for more information.
|
|
|
|
# LONG OPTIONS
|
|
|
|
**Remind** supports the following long options, which *are*
|
|
case-sensitive:
|
|
|
|
**\--version**
|
|
|
|
: The **\--version** option causes **Remind** to print its version
|
|
number to standard output and then exit.
|
|
|
|
**\--hide-completed-todos**
|
|
|
|
: In Calendar Mode, **Remind** normally shows all TODOs. If you supply
|
|
this option, the it will not show TODOs that have been marked as
|
|
completed.
|
|
|
|
**\--only-todos**
|
|
|
|
: Only issue TODO-type reminders.
|
|
|
|
**\--only-events**
|
|
|
|
: Do not issue TODO-type reminders.
|
|
|
|
**\--json**
|
|
|
|
: In Agenda Mode, output JSON instead of the normal text-mode output.
|
|
**\--json** also disables sorting (the **-g** option) and disables
|
|
queueing (the **-q** option). See the section \"AGENDA MODE JSON
|
|
OUTPUT\" for more details. The **\--json** option is ignored in
|
|
Calendar Mode. Note that in JSON mode, the output from any
|
|
**RUN**-type reminder that would normally appear on standard output
|
|
is redirected to standard error instead; this is so that
|
|
**RUN**-type reminders don\'t mess up the output and cause invalid
|
|
JSON to be produced on standard output.
|
|
|
|
**\--print-errs**
|
|
|
|
: The **\--print-errs** option causes **Remind** to print all possible
|
|
error messages to standard output and then exit. The messages are
|
|
printed in a format suitable for the first argument of a TRANSLATE
|
|
command. If you TRANSLATE the error messages, then **Remind** will
|
|
use the translated versions when outputting error and warning
|
|
messages. See also TRANSLATE GENERATE in the section \"THE
|
|
TRANSLATION TABLE\".
|
|
|
|
Note that if an untranslated message contains printf-style
|
|
formatting sequences like \"%s\" or \"%d\", then the translated
|
|
message *must* contain the same sequences in the same order, or
|
|
**Remind** will ignore it and use the original untranslated message.
|
|
|
|
**\--print-config-cmd**
|
|
|
|
: This option causes **Remind** to print the exact **./configure**
|
|
command that was used when **Remind** was built. You can use this to
|
|
build a new version of **Remind** using the same configuration as an
|
|
existing one by running:
|
|
|
|
eval `remind --print-config-cmd`
|
|
|
|
from the top-level **Remind** source directory. (However, it\'s
|
|
safer to simply run **remind \--print-config-cmd** and then type in
|
|
the command once you\'ve verified that it looks OK.)
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
|
|
**\--print-tokens**
|
|
|
|
: The **\--print-tokens** option causes **Remind** to print the tokens
|
|
used by the parser, built-in function names, and system variable
|
|
names to standard output and then exit. This output is designed to
|
|
make it easy to create a syntax-highlighting file for various text
|
|
editors. The output can be modified by hand or by a script into a
|
|
syntax-highlighting file with relative ease.
|
|
|
|
**\--max-execution-time**=_n_
|
|
|
|
: Limit the total execution time (as measured by the wall clock) to
|
|
*n* seconds. This is useful if **Remind** is invoked on
|
|
potentially-untrustworthy files that could attempt to use a lot of
|
|
resources. Note that the limit *n* is approximate and **Remind**
|
|
might execute for one or two more seconds before it is killed. If
|
|
*n* is specified as zero, then no limit is applied, just as if the
|
|
option had not been used at all.
|
|
|
|
If a limit is applied, it applies only to the foreground run of
|
|
**Remind**. If **Remind** finishes processing the script and then
|
|
starts handling queued reminders, the time limit is reset to no
|
|
limit.
|
|
|
|
**\--max-expr-complexity**=_n_
|
|
|
|
: Limit the total complexity of expression valuation for a given line
|
|
in a script to *n* nodes. Roughly speaking, each function call,
|
|
operator, constant, variable reference, etc corresponds to one
|
|
expression node. By default, the limit is set to 10000000 (ten
|
|
million). You can explicitly set it to zero if you don\'t want any
|
|
limit to apply. The default limit of ten million should never be
|
|
triggered by any sensible Remind script, however, and we don\'t
|
|
recommend changing the limit.
|
|
|
|
**\--test**
|
|
|
|
: The **\--test** long option is only for use by the acceptance tests
|
|
run by \"make test\". Do not use this option in production.
|
|
|
|
**\--flush**
|
|
|
|
: The **\--flush** long option makes **Remind**\'s standard output and
|
|
standard error streams unbuffered. It is mostly used for testing and
|
|
should probably not be used in production.
|
|
|
|
# REMINDER FILES
|
|
|
|
**Remind** uses scripts to control its operation. You can use any text
|
|
editor capable of creating plain-text files to create a **Remind**
|
|
script. The commands inside a script can range from the very simple and
|
|
almost immediately understandable:
|
|
|
|
REM Mar 31 MSG International Transgender Day of Visibility
|
|
|
|
to the baroque and obscure:
|
|
|
|
REM [date(thisyear, 1, 1) + 180] ++5 OMIT \
|
|
sat sun BEFORE MSG [ord(thisyear-1980)] payment due %b!
|
|
|
|
A reminder file consists of commands, with one command per line. Several
|
|
lines can be continued using the backslash character, as in the above
|
|
example. In this case, all of the concatenated lines are treated as a
|
|
single line by **Remind**. Note that if an error occurs, **Remind**
|
|
reports the line number of the last line of a continued line.
|
|
|
|
**Remind** ignores blank lines, and lines beginning with the \'#\' or
|
|
\';\' characters. You can use the semicolon as a comment character if
|
|
you wish to pass a **Remind** script through the C pre-processor, which
|
|
interprets the \'#\' character as the start of a pre-processing
|
|
directive.
|
|
|
|
Note that **Remind** processes line continuations before anything else.
|
|
For example:
|
|
|
|
# This is a comment \
|
|
This line is part of the comment because of line continuation \
|
|
and so on.
|
|
REM MSG This line is not ignored (no \ above)
|
|
|
|
**Remind** is not case sensitive; you can generally use any mixture of
|
|
upper- or lower-case for commands, parameters, invocation options, etc.
|
|
|
|
# THE REM COMMAND
|
|
|
|
The most powerful command in a **Remind** script is the **REM** command.
|
|
This command is responsible for issuing reminders. Its syntax is:
|
|
|
|
> **REM** \[**ONCE**\] \[*date_spec*\] \[*back*\] \[*delta*\]
|
|
> \[*repeat*\] \[**TODO**\] \[**MAX-OVERDUE** *n*\]
|
|
> \[**COMPLETE-THROUGH** *complete_date*\] \[**PRIORITY** *prio*\]
|
|
> \[**SKIP** \| **BEFORE** \| **AFTER**\] \[**OMIT** *omit_list*\]
|
|
> \[**ADDOMIT**\] \[**NOQUEUE**\] \[**OMITFUNC** *omit_function*\]
|
|
> \[**AT** *time* \[*tdelta*\] \[*trepeat*\]\] \[**SCHED**
|
|
> *sched_function*\] \[**WARN** *warn_function*\] \[**UNTIL**
|
|
> *expiry_date* \| **THROUGH** *last_date*\] \[**SCANFROM** *scan_date*
|
|
> \| **FROM** *start_date*\] \[**DURATION** *duration*\] \[**TAG**
|
|
> *tag*\] \[**TZ** *timezone*\] \[**INFO** \"*info_string*\"\] **MSG**
|
|
> \| **MSF** \| **RUN** \| **CAL** \| **SATISFY** \| **SPECIAL**
|
|
> *special* \| **PS** \| **PSFILE** *body*
|
|
|
|
The parts of the **REM** command can be specified in any order, except
|
|
that the *body* must come immediately after the **MSG**, **RUN**,
|
|
**CAL**, **PS**, **PSFILE** or **SATISFY** keyword. The portion of the
|
|
**REM** command before the **MSG**, **MSF** **RUN**, **CAL** or
|
|
**SATISFY** clause is called a *trigger*.
|
|
|
|
In earlier versions of **Remind**, the **REM** token was optional
|
|
providing that the remainder of the command cannot be mistaken for
|
|
another **Remind** command. However, this use is deprecated and will now
|
|
cause a warning to be issued. All of your reminder lines should be
|
|
written to start with the REM command.
|
|
|
|
**MSG, MSF, RUN, CAL, SPECIAL, PS and PSFILE**
|
|
|
|
These keywords denote the *type* of the reminder. (**SATISFY** is more
|
|
complicated and will be explained later.) A **MSG**-type reminder
|
|
normally prints a message to the standard output, after passing the
|
|
*body* through a special substitution filter, described in the section
|
|
\"THE SUBSTITUTION FILTER.\" However, if you have used the **-k**
|
|
command-line option, then **MSG**-type reminders are passed to the
|
|
appropriate program. Note that the options **-c**, **-s**, **-p** and
|
|
**-n** disable the **-k** option.
|
|
|
|
Earlier versions of **Remind** let you omit the reminder type, in which
|
|
case it defaulted to **MSG**. However, this usage is deprecated and will
|
|
cause a warning. Something like:
|
|
|
|
REM 6 January Dianne's Birthday
|
|
|
|
will issue the warning \"Missing REM type; assuming MSG\"
|
|
|
|
The **MSF** keyword is almost the same as the **MSG** keyword, except
|
|
that the reminder is formatted to fit into a paragraph-like format.
|
|
Three system variables control the formatting of **MSF**-type
|
|
reminders - they are **\$FirstIndent**, **\$SubsIndent** and
|
|
**\$FormWidth**. They are discussed in the section \"SYSTEM VARIABLES.\"
|
|
The **MSF** keyword causes the spacing of your reminder to be altered -
|
|
extra spaces are discarded, and two spaces are placed after periods and
|
|
other characters, as specified by the system variables **\$EndSent** and
|
|
**\$EndSentIg**. Note that if the body of the reminder includes newline
|
|
characters (placed there with the %\_ sequence), then the newlines are
|
|
treated as the beginnings of new paragraphs, and the **\$FirstIndent**
|
|
indentation is used for the next line. You can use two consecutive
|
|
newlines to have spaced paragraphs emitted from a single reminder body.
|
|
|
|
A **RUN**-type reminder also passes the *body* through the substitution
|
|
filter, but then executes the result as a system command. A **CAL**-type
|
|
reminder is used only to place entries in the calendar produced when
|
|
**Remind** is run with the **-c**, **-s** or **-p** options. When
|
|
**Remind** runs a command, it sets the command\'s standard input to come
|
|
from /dev/null.
|
|
|
|
A **PS** or **PSFILE**-type reminder is used to pass PostScript code
|
|
directly to the printer when producing PostScript calendars. This can be
|
|
used to shade certain calendar entries (see the psshade() function),
|
|
include graphics in the calendar, or almost any other purpose you can
|
|
think of. You should not use these types of reminders unless you are an
|
|
expert PostScript programmer. The **PS** and **PSFILE** reminders are
|
|
ignored unless **Remind** is run with the **-p** option. See the section
|
|
\"More about PostScript\" for more details.
|
|
|
|
A **SPECIAL**-type reminder is used to pass \"out-of-band\" information
|
|
from **Remind** to a calendar-producing back-end. It should be followed
|
|
by a word indicating the type of special data being passed. The type of
|
|
a special reminder depends on the back-end. For the **Rem2PS** back-end,
|
|
**SPECIAL PostScript** is equivalent to a **PS**-type reminder, and
|
|
**SPECIAL PSFile** is equivalent to a **PSFILE**-type reminder. The body
|
|
of a **SPECIAL** reminder is obviously dependent upon the back-end. A
|
|
back-end *must* ignore a **SPECIAL** that it does not recognize.
|
|
|
|
**DATE SPECIFICATIONS**
|
|
|
|
A *date_spec* consists of zero to four parts. These parts are *day* (day
|
|
of month), *month* (month name), *year* and *weekday.* *Month* and
|
|
*weekday* are the English names of months and weekdays. At least the
|
|
first three characters must be used. The following are examples of the
|
|
various parts of a *date_spec:*
|
|
|
|
*day:*
|
|
|
|
: 1, 22, 31, 14, 3
|
|
|
|
*month:*
|
|
|
|
: JANUARY, feb, March, ApR, may, Aug
|
|
|
|
*year:*
|
|
|
|
: 1990, 1993, 2030. The year can range from 1990 to 2075.
|
|
|
|
*weekday:*
|
|
|
|
: Monday, tue, Wed, THU, Friday, saturday, sundAy
|
|
|
|
Note that there can be several *weekday* components separated by spaces
|
|
in a *date_spec.*
|
|
|
|
**INTERPRETATION OF DATE SPECIFICATIONS**
|
|
|
|
The following examples show how date specifications are interpreted.
|
|
|
|
1\. Null date specification - the reminder is triggered every day. The
|
|
trigger date for a specific run is simply the current system date. For
|
|
example:
|
|
|
|
REM MSG This is triggered every time Remind runs
|
|
|
|
2\. Only *day* present. The reminder is triggered on the specified day
|
|
of each month. The trigger date for a particular run is the closest such
|
|
day to the current system date. For example:
|
|
|
|
REM 1 MSG First of every month.
|
|
REM 31 MSG 31st of every month that has 31 days.
|
|
|
|
3\. Only *month* present. The reminder is triggered every day of the
|
|
specified month. Example:
|
|
|
|
REM Feb MSG Every day in February
|
|
|
|
4\. *day* and *month* present. Examples:
|
|
|
|
REM 6 Jan MSG Every 6th of January
|
|
REM Feb 29 MSG Every 29th of February
|
|
|
|
5\. Only *year* present. Example:
|
|
|
|
REM 1991 MSG Every day in 1991
|
|
|
|
6\. *year* and *day* present. Examples:
|
|
|
|
REM 1 1990 MSG 1st of every month in 1990
|
|
REM 1992 23 MSG 23rd of every month in 1992
|
|
|
|
7\. *year* and *month* present. Examples:
|
|
|
|
REM Feb 1991 MSG Every day in Feb 1991
|
|
REM 1992 September MSG Every day in Sept 1992
|
|
|
|
8\. *year, month* and *day* present. Examples:
|
|
|
|
REM 8 Jan 1991 MSG 8th January 1991.
|
|
REM 1992 March 9 MSG 9th March 1992.
|
|
|
|
9\. *weekday* only. Examples:
|
|
|
|
REM Sat MSG Every Saturday
|
|
REM Mon Tue Wed Thu Fri MSG Every working day
|
|
REM Monday Wednesday MSG Every Monday and Wednesday
|
|
|
|
10\. *weekday* and *day* present. Examples:
|
|
|
|
REM Sat 1 MSG First Saturday of every month
|
|
REM Mon Tue Wed Thu Fri 15 \
|
|
MSG 1st working day on or after 15th of every month
|
|
|
|
11\. *weekday* and *month* present. Examples:
|
|
|
|
REM Mon March MSG Every Monday in March
|
|
REM Mon Tue Wed Thu Fri Feb MSG Every working day in February
|
|
|
|
12\. *weekday, month* and *day* present. Examples:
|
|
|
|
REM Mon 1 March MSG First Monday in March
|
|
REM Sat Sun 15 July MSG First Sat or Sun on or after 15 July
|
|
|
|
13\. *weekday* and *year* present. Example:
|
|
|
|
REM Sat Sun 1991 MSG Every Saturday and Sunday in 1991
|
|
|
|
14\. *weekday, day* and *year* present. Examples:
|
|
|
|
REM Mon 15 1990 MSG 1st Mon after 15th of every month in 1990
|
|
REM Mon Tue Wed Thu Fri 1 1990 \
|
|
MSG 1st working day of every month in 1990
|
|
|
|
15\. *weekday, month* and *year* present. Example:
|
|
|
|
REM Mon Wed 1991 Feb MSG Every Mon and Wed in Feb 1991.
|
|
|
|
16\. *weekday, day, month* and *year* present. Example:
|
|
|
|
REM Mon Tue Wed Thu Fri 28 Oct 1990 \
|
|
MSG 1st working day on or after 28 October 1990.
|
|
|
|
Note that when both *weekday* and *day* are specified, **Remind**
|
|
chooses the first date on or after the specified *day* that also
|
|
satisfies the *weekday* constraint. It does this by picking the first
|
|
date on or after the specified *day* that is listed in the list of
|
|
*weekdays.* Thus, a reminder like:
|
|
|
|
REM Mon Tue 28 Oct 1990 MSG Hi
|
|
|
|
would be issued only on Monday, 29 October, 1990. It would not be issued
|
|
on Tuesday, 30 October, 1990, since the 29th is the first date to
|
|
satisfy the *weekday* constraints.
|
|
|
|
**SHORT-HAND DATE SPECIFICATIONS**
|
|
|
|
In addition to spelling out the day, month and year separately, you can
|
|
specify YYYY-MM-DD or YYYY/MM/DD. For example, the following statements
|
|
are equivalent:
|
|
|
|
REM 5 June 2010 MSG Cool!
|
|
REM 2010-06-05 MSG Cool!
|
|
|
|
You can also specify a date and time as YYYY-MM-DD@HH:MM. These
|
|
statements are equivalent:
|
|
|
|
REM 19 Dec 2010 AT 16:45 MSG Hi
|
|
REM 2010-12-19@16:45 MSG Hi
|
|
|
|
There\'s one subtlety with short-hand date specifications: The following
|
|
statements are *not* equivalent:
|
|
|
|
REM 19 Dec 2010 AT 16:45 +60 MSG Hi
|
|
REM 2010-12-19@16:45 +60 MSG Hi
|
|
|
|
In the second statement, the \"+60\" is a *delta* that applies to the
|
|
date rather than a *tdelta* that applies to the time. We recommend
|
|
explicitly using the AT keyword with timed reminders.
|
|
|
|
**THE REMIND ALGORITHM**
|
|
|
|
**Remind** uses the following algorithm to compute a trigger date:
|
|
Starting from the current date, it examines each day, one at a time,
|
|
until it finds a date that satisfies the date specification, or proves
|
|
to itself that no such date exists. (Actually, **Remind** merely
|
|
*behaves* as if it used this algorithm; it would be much too slow in
|
|
practice. Internally, **Remind** uses much faster techniques to
|
|
calculate a trigger date.) See DETAILS ABOUT TRIGGER COMPUTATION for
|
|
more information.
|
|
|
|
**BACKWARD SCANNING**
|
|
|
|
Sometimes, it is necessary to specify a date as being a set amount of
|
|
time before another date. For example, the last Monday in a given month
|
|
is computed as the first Monday in the next month, minus 7 days. The
|
|
*back* specification in the reminder is used in this case:
|
|
|
|
REM Mon 1 -7 MSG Last Monday of every month.
|
|
|
|
A *back* is specified with one or two dashes followed by an integer.
|
|
This causes **Remind** to move \"backwards\" from what would normally be
|
|
the trigger date. The difference between \--7 and -7 will be explained
|
|
when the **OMIT** keyword is described.
|
|
|
|
**ADVANCE WARNING**
|
|
|
|
For some reminders, it is appropriate to receive advance warning of the
|
|
event. For example, you may wish to be reminded of someone\'s birthday
|
|
several days in advance. The *delta* portion of the **REM** command
|
|
achieves this. It is specified as one or two \"+\" signs followed by a
|
|
number *n*. Again, the difference between the \"+\" and \"++\" forms
|
|
will be explained under the **OMIT** keyword. **Remind** will trigger
|
|
the reminder on computed trigger date, as well as on each of the *n*
|
|
days before the event. Here are some examples:
|
|
|
|
REM 6 Jan +5 MSG Remind me of birthday 5 days in advance.
|
|
|
|
The above example would be triggered every 6th of January, as well as
|
|
the 1st through 5th of January.
|
|
|
|
**PERIODIC REMINDERS**
|
|
|
|
We have already seen some built-in mechanisms for certain types of
|
|
periodic reminders. For example, an event occurring every Wednesday
|
|
could be specified as:
|
|
|
|
REM Wed MSG Event!
|
|
|
|
However, events that do not repeat daily, weekly, monthly or yearly
|
|
require another approach. The *repeat* component of the **REM** command
|
|
fills this need. To use it, you must completely specify a date (year,
|
|
month and day, and optionally weekday); this is the start date of the
|
|
repetition period. The *repeat* component is an asterisk followed by a
|
|
number specifying the repetition period in days.
|
|
|
|
For example, suppose you get paid every second Wednesday, and your last
|
|
payday was Wednesday, 28 October, 1992. You can use:
|
|
|
|
REM 28 Oct 1992 *14 MSG Payday
|
|
|
|
This issues the reminder every 14 days, starting from 28 Oct 1992. You
|
|
can use *delta* and *back* with *repeat.* Note, however, that the *back*
|
|
is used only to compute the starting date; thereafter, the reminder
|
|
repeats with the specified period. Similarly, if you specify a weekday,
|
|
it is used only to calculate the starting date, and does not affect the
|
|
repetition period.
|
|
|
|
**SCANFROM and FROM**
|
|
|
|
The **SCANFROM** and **FROM** keywords are for advanced **Remind**
|
|
programmers only, and will be explained in the section \"DETAILS ABOUT
|
|
TRIGGER COMPUTATION\" near the end of this manual. Note that
|
|
**SCANFROM** is available only in versions of **Remind** from 03.00.04
|
|
up. **FROM** is available only from 03.01.00 and later.
|
|
|
|
**PRIORITY**
|
|
|
|
The **PRIORITY** keyword must be followed by a number from 0 to 9999. It
|
|
is used in calendar mode and when sorting reminders. If two reminders
|
|
have the same trigger date and time, then they are sorted by priority.
|
|
If the **PRIORITY** keyword is not supplied, a default priority of 5000
|
|
is used. (This default can be changed by adjusting the system variable
|
|
**\$DefaultPrio**. See the section \"SYSTEM VARIABLES\" for more
|
|
information.)
|
|
|
|
**EXPIRY DATES**
|
|
|
|
Some reminders should be issued periodically for a certain time, but
|
|
then expire. For example, suppose you have a class every Friday, and
|
|
that your last class is on 11 December 1992. You can use:
|
|
|
|
REM Fri UNTIL 11 Dec 1992 MSG Class today.
|
|
|
|
Another example: Suppose you have jury duty from 30 November 1992 until
|
|
4 December 1992. The following reminder will issue the message every day
|
|
of your jury duty, as well as 2 days ahead of time:
|
|
|
|
REM 1992-11-30 *1 +2 UNTIL 1992-12-04 MSG Jury duty
|
|
|
|
Note that the *repeat* of \*1 is necessary; without it, the reminder
|
|
would be issued only on 30 November (and the two days preceding.)
|
|
|
|
As a special case, you can use the **THROUGH** keyword instead of \*1
|
|
and **UNTIL**. The following two **REM** commands are equivalent:
|
|
|
|
REM 1992-11-30 *1 +2 UNTIL 1992-12-04 MSG Jury duty
|
|
|
|
REM 1992-11-30 +2 THROUGH 1992-12-04 MSG Jury duty
|
|
|
|
If you have an expiry date via the use of **THROUGH** or **UNTIL**, then
|
|
**Remind** will *never* trigger the reminder after the expiry date. For
|
|
example, if you have this:
|
|
|
|
OMIT 2021-01-08
|
|
REM 2021-01-01 THROUGH 2021-01-08 AFTER MSG Test
|
|
|
|
the reminder will not be triggered on 2021-01-08, and nor will it be
|
|
triggered on 2021-01-09; even though the AFTER keyword would normally
|
|
move the 8th\'s reminder to the 9th, the expiry date of 2021-01-08
|
|
overrides that.
|
|
|
|
**THE ONCE KEYWORD**
|
|
|
|
Sometimes, it is necessary to ensure that reminders are run only once on
|
|
a given day. For example, compare the following two reminders:
|
|
|
|
REM Fri RUN do_backup
|
|
REM Fri ONCE RUN do_backup
|
|
|
|
The first will be run every time you invoke **Remind** on a Friday,
|
|
whereas the second will be run only the first time you invoke **Remind**
|
|
on a given Friday.
|
|
|
|
If you run **Remind** from your .login script, for example, and log in
|
|
several times per day, the *do_backup* program in the first reminder
|
|
will be run each time you log in. If, however, you use the **ONCE**
|
|
keyword in the reminder, the **Remind** checks the last access date of
|
|
the reminder script. If it is the same as the current date, **Remind**
|
|
assumes that it has already been run, and will not issue reminders
|
|
containing the **ONCE** keyword.
|
|
|
|
Note that if you view or edit your reminder script, the last access date
|
|
will be updated, and the **ONCE** keyword will not operate properly. You
|
|
can fix this by setting a timestamp file for **Remind** to track the
|
|
last-run date; see the documentation of **\$OnceFile** in the **SYSTEM
|
|
VARIABLES** section. If you use standard input as your **Remind** input
|
|
file, then you *must* use **\$OnceFile** for the **ONCE** keyword to
|
|
work properly.
|
|
|
|
If you start **Remind** with the **-o** option, then the **ONCE**
|
|
keyword will be ignored and any **\$OnceFile** will be ignored.
|
|
|
|
**LOCALLY OMITTING WEEKDAYS**
|
|
|
|
The **OMIT** portion of the **REM** command is used to \"omit\" certain
|
|
days when counting the *delta* or *back*. It is specified using the
|
|
keyword **OMIT** followed by a list of weekdays. Its action is best
|
|
illustrated with examples:
|
|
|
|
REM 1 +1 OMIT Sat Sun MSG Important Event
|
|
|
|
This reminder is normally triggered on the first of every month, as well
|
|
as the day preceding it. However, if the first of the month falls on a
|
|
Sunday or Monday, then the reminder is triggered starting from the
|
|
previous Friday. This is because the *delta* of +1 does not count
|
|
Saturday or Sunday when it counts backwards from the trigger date to
|
|
determine how much advance warning to give.
|
|
|
|
Contrast this with the use of \"++1\" in the above command. In this
|
|
case, the reminder is triggered on the first of each month, as well as
|
|
the day preceding it. The omitted days are counted.
|
|
|
|
REM 1 -1 OMIT Sat Sun MSG Last working day of month
|
|
|
|
Again, in the above example, the *back* of -1 normally causes the
|
|
trigger date to be the last day of the month. However, because of the
|
|
**OMIT** clause, if the first of the month falls on a Sunday or Monday,
|
|
the trigger date is moved backwards past the weekend to Friday. (If you
|
|
have globally omitted holidays, the reminder will be moved back past
|
|
them, also. See \"The OMIT command\" for more details.)
|
|
|
|
By comparison, if we had used \"\--1\", the reminder would be triggered
|
|
on the last day of the month, regardless of the **OMIT**.
|
|
|
|
If you locally omit weekdays but also have globally-omitted weekdays,
|
|
then the list of omitted weekdays is the union of the two. Consider this
|
|
example:
|
|
|
|
OMIT Sat Sun
|
|
REM 15 OMIT Fri Sat MSG Whatever
|
|
|
|
In the REM command, the effective list of omitted weekdays will be
|
|
Friday, Saturday and Sunday.
|
|
|
|
**COMPUTED LOCAL OMITS**
|
|
|
|
The **OMITFUNC** phrase of the **REM** command allows you to supply a
|
|
function that determines whether or not a date is omitted. Note that
|
|
**OMITFUNC** must be given just the name of a user-defined function; it
|
|
can\'t take an arbitrary expression or the name of a built-in function.
|
|
|
|
The function is passed a single parameter of type **DATE**, and must
|
|
return a non-zero integer if the date is considered \"omitted\" and 0
|
|
otherwise. Here\'s an example:
|
|
|
|
FSET _third(x) (day(x) % 3) || \
|
|
(wkdaynum(x) == 0) || \
|
|
(wkdaynum(x) == 6)
|
|
REM OMITFUNC _third AFTER MSG Working day divisible by 3
|
|
|
|
In the example above, the reminder is triggered every Monday to Friday
|
|
whose day-of-month number is divisible by three. Here\'s how it works:
|
|
|
|
**o**
|
|
|
|
: The **OMITFUNC \_third** portion causes all days for which
|
|
**\_third(x)** returns non-zero to be considered \"omitted\". This
|
|
causes all days whose day-of-month number is *not* a multiple of
|
|
three to be omitted. Note that \_third also returns non-zero if the
|
|
weekday is Sunday or Saturday.
|
|
|
|
**o**
|
|
|
|
: The **AFTER** keyword causes the reminder to be moved after a block
|
|
of omitted days.
|
|
|
|
The combination of OMITFUNC and AFTER keyword causes the reminder to be
|
|
issued on all days whose day-of-month number is divisible by three, but
|
|
not on Saturday or Sunday.
|
|
|
|
Note that if you use **OMITFUNC**, then a local **OMIT** is *ignored* as
|
|
are *all global OMITs*. If you want to omit specific weekdays, your omit
|
|
function will need to test for them specifically. If you want to take
|
|
into account the global **OMIT** context, then your omit function will
|
|
need to test for that explicitly (using the **isomitted()** function.)
|
|
|
|
Note that an incorrect **OMITFUNC** might cause all days to be
|
|
considered omitted. For that reason, when **Remind** searches through
|
|
omitted days, it terminates the search after the **SATISFY** iteration
|
|
limit (command-line option **-x**.)
|
|
|
|
**ADDING TRIGGER DATES TO THE OMIT CONTEXT**
|
|
|
|
If the **ADDOMIT** keyword appears in a **REM** command, then the
|
|
trigger date (if one could be calculated) is automatically added to the
|
|
list of global OMITs.
|
|
|
|
The command:
|
|
|
|
REM ... whatever ... ADDOMIT MSG Foo
|
|
|
|
is identical in behavior to the sequence:
|
|
|
|
REM ... whatever ... SATISFY 1
|
|
IF trigvalid()
|
|
OMIT [trigdate()] MSG Foo
|
|
ENDIF
|
|
|
|
**TIMED REMINDERS**
|
|
|
|
Timed reminders are those that have an **AT** keyword followed by a
|
|
*time* and optional *tdelta* and *trepeat*. The *time* may be specified
|
|
in 24-hour format, with 0:00 representing midnight, 12:00 representing
|
|
noon, and 23:59 representing one minute to midnight. Alternatively, it
|
|
may be specified in common \"AM/PM\" format; in this case, the hour must
|
|
range from 1 to 12. 12:00am represents midnight, 12:00pm represents
|
|
noon, and 11:59pm represents one minute to midnight. The \"am\" and
|
|
\"pm\" portions are case-insensitive and the \"m\" is optional.
|
|
|
|
You can use either a colon or a period to separate the hours from the
|
|
minutes. That is, 13:39 and 13.39 are equivalent.
|
|
|
|
**Remind** treats timed reminders specially. If the trigger date for a
|
|
timed reminder is the same as the current system date, the reminder is
|
|
queued for later activation. When **Remind** has finished processing the
|
|
reminder file, it puts itself in the background, and activates timed
|
|
reminders when the system time reached the specified time. Note that if
|
|
you use the **NOQUEUE** modifier in the **REM** command, then this
|
|
queuing and background activation is *not* performed. **NOQUEUE** is
|
|
useful if you want a time to be associated with a reminder (e.g., in the
|
|
calendar) but are not interested in a popup reminder happening at the
|
|
specified time.
|
|
|
|
If the trigger date is *not* the same as the system date, the reminder
|
|
is not queued.
|
|
|
|
For example, the following reminder, triggered every working day, will
|
|
emit a message telling you to leave at 5:00pm:
|
|
|
|
REM Mon Tue Wed Thu Fri AT 17:00 MSG Time to leave!
|
|
|
|
The following reminder will be triggered on Thursdays and Fridays, but
|
|
will only be queued on Fridays:
|
|
|
|
REM Fri ++1 AT 1:00PM MSG Lunch at 1pm Friday.
|
|
|
|
The *tdelta* and *trepeat* have the same form as a *repeat* and *delta*,
|
|
but are specified in minutes. For example, this reminder will be
|
|
triggered at 12:00pm as well as 45 minutes before:
|
|
|
|
REM AT 12:00 +45 MSG Example
|
|
|
|
The following will be issued starting at 10:45, every half hour until
|
|
11:45, and again at noon.
|
|
|
|
REM AT 12:00 +75 *30 MSG Example2
|
|
|
|
The \"+75\" means that the reminder is issued starting 75 minutes before
|
|
noon; in other words, at 10:45. The \*30 specifies that the reminder is
|
|
subsequently to be issued every 30 minutes. Note that the reminder is
|
|
always issued at the specified time, even if the *tdelta* is not a
|
|
multiple of the *trepeat*. So the above example is issued at 10:45am,
|
|
11:15am, 11:45am, and 12:00pm. Note that in the time specification,
|
|
there is no distinction between the \"+\" and \"++\" forms of *tdelta*.
|
|
|
|
Normally, **Remind** will issue timed reminders as it processes the
|
|
reminder script, as well as queuing them for later. If you do not want
|
|
**Remind** to issue the reminders when processing the script, but only
|
|
to queue them for later, use the **-a** command-line option. If you do
|
|
not want reminders to be queued for later, use the **-q** command-line
|
|
option.
|
|
|
|
Normally, **Remind** forks a background process to handle queued
|
|
reminders. If you want **Remind** to remain in the foreground, use the
|
|
**-f** command-line option. This is useful, for example, in .xinitrc
|
|
scripts, where you can use the command:
|
|
|
|
remind -fa myreminders &
|
|
|
|
This ensures that when you exit X-Windows, the **Remind** process is
|
|
killed.
|
|
|
|
**WARNING ABOUT TIMED REMINDERS**
|
|
|
|
Note: If you use user-defined functions or variables (described later)
|
|
in the bodies of timed reminders, then when the timed reminders are
|
|
activated, the variables and functions have the definitions that were in
|
|
effect at the end of the reminder script. These definitions may *not*
|
|
necessarily be those that were in effect at the time the reminder was
|
|
queued. In addition, the OMIT context is whatever was in effect at the
|
|
end of the reminder script, which may not necessarily be the same as
|
|
when the **REM** command was first processed.
|
|
|
|
**THE SCHED AND WARN KEYWORDS**
|
|
|
|
The **SCHED** keyword allows more precise control over the triggering of
|
|
timed reminders, and the **WARN** keyword allows precise control over
|
|
the advance triggering of all types of reminders. However, discussion
|
|
must be deferred until after expressions and user-defined functions are
|
|
explained. See the subsection \"PRECISE SCHEDULING\" further on.
|
|
|
|
**TAG, INFO AND DURATION**
|
|
|
|
The **TAG** keyword lets you \"tag\" certain reminders. This facility is
|
|
used by certain back-ends or systems built around **Remind**, such as
|
|
**TkRemind**. These back-ends have specific rules about tags; see their
|
|
documentation for details.
|
|
|
|
The **TAG** keyword is followed by a tag consisting of up to 48
|
|
characters. You can have as many TAG clauses as you like in a given REM
|
|
statement. A tag can contain any character except for whitespace and a
|
|
comma.
|
|
|
|
If you supply the **-y** option to **Remind**, then any reminder that
|
|
lacks a **TAG** will have one synthesized. The synthesized tag consists
|
|
of the characters \"\_\_syn\_\_\" followed by the hexadecimal
|
|
representation of the MD5 sum of the REM command line. This lets you
|
|
give a more-or-less unique identifier to each distinct REM command.
|
|
|
|
The **INFO** keyword is similar to **TAG** but is intended to convey
|
|
metadata about an event, such as its location. Back-ends will have their
|
|
own rules about which *info_string*s they recognize, and must ignore
|
|
*info_string*s they don\'t recognize. Note that **INFO** must be
|
|
followed by a quoted string; you can include newlines in the string by
|
|
supplying them as \"\\n\".
|
|
|
|
An INFO string *must* be of the form \"Header: Value\". The header can
|
|
consist of any printable character, but cannot contain whitespace. The
|
|
value can consist of any characters you like. Space may not appear
|
|
before the colon, but can appear afterwards; such space is not
|
|
considered to be part of the value. If there is more than one INFO
|
|
string for a given reminder, there cannot be any duplicate headers. Case
|
|
is ignored when determining if a header is a duplicate of an existing
|
|
one.
|
|
|
|
For example, a hypothetical back-end might let you set the location and
|
|
description of a reminder like this:
|
|
|
|
REM 26 Feb 2025 INFO "Location: Boardroom #2" \
|
|
INFO "Description: Go over latest pull requests" \
|
|
MSG Engineering meeting
|
|
|
|
While back-ends can choose which INFO strings to support, all back-ends
|
|
should endeavor to support three standard ones: **Location:**,
|
|
**Description:** and **Url:**. TkRemind supports all three of these,
|
|
turning reminders with a **Url:** INFO string into hyper-links, and
|
|
popping up information windows for the **Location:** and
|
|
**Description:** INFO strings. **Location:** and **Url:** are
|
|
self-explanatory; **Description:** is meant for a longer, more in-depth
|
|
description of the reminder than the summary that is normally displayed.
|
|
|
|
The **DURATION** keyword makes sense only for timed reminders; it
|
|
specifies the duration of an event. For example, if you have a 90-minute
|
|
meeting starting at 1:00pm, you could use any of the following:
|
|
|
|
REM 5 March 2021 AT 13:00 DURATION 1:30 MSG Meeting
|
|
REM 5 March 2021 AT 13:00 DURATION 90 MSG Meeting
|
|
REM 5 March 2021 AT 1:00pm DURATION 1:30 MSG Meeting
|
|
REM 5 March 2021 AT 1:00pm DURATION 90 MSG Meeting
|
|
|
|
For long-duration reminders, it is convenient to use expressions to
|
|
simplify writing the DURATION. For example, if you are away from 20 Feb
|
|
2023 through 23 Feb 2023 (a total of 4 days) you could write:
|
|
|
|
REM 20 Feb AT 00:00 DURATION [4*24]:00 MSG away
|
|
REM 20 Feb AT 00:00 DURATION [4*24*60] MSG away
|
|
|
|
Note that *duration* is specified either as *hours*:*minutes* or just as
|
|
*minutes* specified as an *integer*.
|
|
|
|
If you specify a duration of 00:00 or 0, then **Remind** behaves exactly
|
|
as if no **DURATION** at all had been present. Although durations
|
|
specified as *hours*:*minutes* look superficially like a time-of-day,
|
|
they are not; the *hours* component is not limited to the range 00-23.
|
|
|
|
# SYNTACTIC SUGAR FOR REM
|
|
|
|
The REM command has syntactic sugar to let you express common reminders.
|
|
The following pairs of reminders are equivalent:
|
|
|
|
REM First Monday April MSG Foo
|
|
REM Mon 1 April MSG Foo
|
|
|
|
REM Second Monday May MSG Bar
|
|
REM Mon 8 May MSG Bar
|
|
|
|
REM Third Monday MSG Third Monday of every month
|
|
REM Mon 15 MSG Third Monday of every month
|
|
|
|
REM Fourth Sunday June 2025 MSG Fourth Sunday in June 2025
|
|
REM Sun 22 June 2025 MSG Fourth Sunday in June 2025
|
|
|
|
REM Last Monday MSG Last Monday of every month
|
|
REM Mon 1 --7 MSG Last Monday of every month
|
|
|
|
REM Last Monday April MSG Last Monday of every April
|
|
REM Mon 1 May --7 MSG Last Monday of every April
|
|
|
|
REM Last Monday December 2025 MSG Last Monday of Dec 2025
|
|
REM Monday 1 Jan 2026 --7 MSG Last Monday of Dec 2025
|
|
|
|
Note that **Last** effectively adjusts the month and year, if necessary,
|
|
to make the reminder trigger on the correct date.
|
|
|
|
The keyword **IN** is completely ignored, so you can write (for
|
|
example):
|
|
|
|
REM Second Monday in May MSG foo
|
|
REM Last Monday in December 2025 MSG Bar
|
|
|
|
An alternate form of *back* makes writing reminders easier. The
|
|
following groups of reminders are equivalent:
|
|
|
|
REM ~~1 MSG Last day of every month
|
|
REM Lastday MSG Last day of every month
|
|
REM 1 --1 MSG Last day of every month
|
|
|
|
REM May ~~1 MSG Last day of May
|
|
REM Lastday May MSG Last day of May
|
|
REM 1 June --1 MSG Last day of May
|
|
|
|
REM Dec 2025 ~~1 MSG Last day of December 2025
|
|
REM Lastday Dec 2025 MSG Last day of December 2025
|
|
REM 1 Jan 2026 --1 MSG Last day of December 2025
|
|
|
|
REM Apr ~1 OMIT SAT SUN MSG Last workday of April
|
|
REM Lastworkday April OMIT SAT SUN MSG Last workday of April
|
|
REM 1 May -1 OMIT SAT SUN MSG Last workday of April
|
|
|
|
REM Apr ~~7 MSG Seventh-last day of April
|
|
REM 1 May --7 MSG Seventh-last day of April
|
|
|
|
REM Apr ~2 OMIT SAT SUN MSG Second-last workday of April
|
|
REM 1 May -2 OMIT SAT SUN MSG Second-last workday of April
|
|
|
|
As we see, \"Lastday\" is equivalent to \~\~1 and \"Lastworkday\" to
|
|
\~1.
|
|
|
|
Note that the First/Second/Third/Fourth/Last keywords and the \~ and
|
|
\~\~ form of *back* imply a value for the day of the month; as such,
|
|
they cannot be combined with a day. Additionally,
|
|
First/Second/Third/Fourth/Last must have at least one weekday name. The
|
|
following are illegal:
|
|
|
|
REM First Monday 3 June MSG Huh?
|
|
REM April 3 ~~1 MSG What?
|
|
REM Second June MSG Where's the weekday???
|
|
|
|
# THE SUBSTITUTION FILTER
|
|
|
|
Before being processed, the body of a **REM** command is passed through
|
|
a substitution filter. The filter scans for sequences \"%x\" (where
|
|
\"x\" is any letter and certain other characters) and performs
|
|
substitutions as shown below. (All dates refer to the trigger date of
|
|
the reminder.)
|
|
|
|
**%a**
|
|
|
|
: is replaced with \"on *weekday, day month, year*\"
|
|
|
|
For example, consider the reminder:
|
|
|
|
REM 18 Oct 1990 +4 MSG Meeting with Bob %a.
|
|
|
|
On 16 October 1990, it would print \"Meeting with Bob on Thursday,
|
|
18 October, 1990.\"
|
|
|
|
On 17 October 1990, it would print \"Meeting with Bob tomorrow.\"
|
|
|
|
On 18 October 1990, it would print \"Meeting with Bob today.\"
|
|
|
|
**%b**
|
|
|
|
: is replaced with \"in *diff* day\'s time\" where *diff* is the
|
|
**actual** number of days between the current date and the trigger
|
|
date. (**OMITs** have no effect.)
|
|
|
|
For example, consider:
|
|
|
|
REM 18 Oct 1990 +4 MSG Meeting with Bob %b.
|
|
|
|
On 16 October 1990, it would print \"Meeting with Bob in 2 days\'
|
|
time.\"
|
|
|
|
On 17 October 1990, it would print \"Meeting with Bob tomorrow.\"
|
|
|
|
On 18 October 1990, it would print \"Meeting with Bob today.\"
|
|
|
|
**%c**
|
|
|
|
: is replaced with \"on *weekday*\"
|
|
|
|
Example: REM 18 Oct 1990 +4 MSG Meeting with Bob %c.
|
|
|
|
On 16 October 1990, it would print \"Meeting with Bob on Thursday.\"
|
|
|
|
On 17 October 1990, it would print \"Meeting with Bob tomorrow.\"
|
|
|
|
On 18 October 1990, it would print \"Meeting with Bob today.\"
|
|
|
|
**%d**
|
|
|
|
: is replaced with \"*day*\", the day of the month.
|
|
|
|
**%e**
|
|
|
|
: is replaced with \"on *dd-mm-yyyy*\"
|
|
|
|
**%f**
|
|
|
|
: is replaced with \"on *mm-dd-yyyy*\"
|
|
|
|
**%g**
|
|
|
|
: is replaced with \"on *weekday, day month*\"
|
|
|
|
**%h**
|
|
|
|
: is replaced with \"on *dd-mm*\"
|
|
|
|
**%i**
|
|
|
|
: is replaced with \"on *mm-dd*\"
|
|
|
|
**%j**
|
|
|
|
: is replaced with \"on *weekday, month day-th, year*\" This form
|
|
appends the characters \"st\", \"nd\", \"rd\" or \"th\" to the day
|
|
of the month, as appropriate.
|
|
|
|
**%k**
|
|
|
|
: is replaced with \"on *weekday, month day-th*\"
|
|
|
|
**%l**
|
|
|
|
: is replaced with \"on *yyyy-mm-dd*\"
|
|
|
|
**%m**
|
|
|
|
: is replaced with \"*month*\", the name of the month.
|
|
|
|
**%n**
|
|
|
|
: is replaced with the number (1 to 12) of the month.
|
|
|
|
**%o**
|
|
|
|
: is replaced with \" (today)\" if and only if the current system date
|
|
is the same as the date being used by **Remind** as the current
|
|
date. Recall that you can specify a date for **Remind** to use on
|
|
the command line. This substitution is not generally useful in a
|
|
**REM** command, but is useful in a **BANNER** command. (See \"The
|
|
BANNER Command.\")
|
|
|
|
**%p**
|
|
|
|
: is replaced with \"s\" if the *diff* between the current date and
|
|
the trigger date is not 1. You can use this to construct reminders
|
|
like:
|
|
|
|
REM 1 Jan +4 MSG %x day%p to go before New Year!
|
|
|
|
**%q**
|
|
|
|
: is replaced with \"\'s\" if the *diff* between the trigger date and
|
|
the current date is 1. Otherwise, it is replaced with \"s\'\" This
|
|
can be used as follows:
|
|
|
|
REM 1 Jan +4 MSG New Year in %x day%q time!
|
|
|
|
**%r**
|
|
|
|
: is replaced with the day of the month (01 to 31) padded with a
|
|
leading zero if needed to pad to two digits.
|
|
|
|
**%s**
|
|
|
|
: is replaced with \"st\", \"nd\", \"rd\" or \"th\" depending on the
|
|
day of the month.
|
|
|
|
**%t**
|
|
|
|
: is replaced with the number of the month (01 to 12) padded to two
|
|
digits with a leading zero.
|
|
|
|
**%u**
|
|
|
|
: is replaced with \"on *weekday, day-th month, year*\" This is
|
|
similar to **%a** except that \"st\", \"nd\", \"rd\" or \"th\" is
|
|
added to the *day* as appropriate.
|
|
|
|
**%v**
|
|
|
|
: is replaced with \"on *weekday, day-th month*\"
|
|
|
|
**%w**
|
|
|
|
: is replaced with \"*weekday*\", the name of the day of the week.
|
|
|
|
**%x**
|
|
|
|
: is replaced with the *diff* between the current date and the trigger
|
|
date. The *diff* is defined as the actual number of days between
|
|
these two dates; **OMITs** are not counted. (Strict date subtraction
|
|
is performed.)
|
|
|
|
**%y**
|
|
|
|
: is replaced with \"*year*\", the year of the trigger date.
|
|
|
|
**%z**
|
|
|
|
: is replaced with \"*yy*\", the last two digits of the year.
|
|
|
|
**%(**_any_text_**)**
|
|
|
|
: is replaced with the lookup of *any_text* in the translation table.
|
|
It is the equivalent of \[\_(\"any_text\")\] but is more convenient
|
|
to type.
|
|
|
|
**%\<**_any_text_**\>**
|
|
|
|
: is replaced with the INFO value associated with the header
|
|
*any_text* or the empty string if no such INFO value exists. It is
|
|
the equivalent of \[triginfo(\"any_text\")\] but is more convenient
|
|
to type.
|
|
|
|
**%\_**
|
|
|
|
: (percent-underscore) is replaced with a newline. You can use this to
|
|
achieve multi-line reminders. Note that calendar back-ends vary in
|
|
how they handle multi-line reminders:
|
|
|
|
**o**
|
|
|
|
: Running **remind -c** preserves newlines in the terminal
|
|
calendar output.
|
|
|
|
**o**
|
|
|
|
: **rem2pdf** preserves newlines if **remind** is invoked with the
|
|
**-pp** or **-ppp** option.
|
|
|
|
**o**
|
|
|
|
: **rem2html** preserves newlines if **remind** is invoked with
|
|
the **-pp** option.
|
|
|
|
**o**
|
|
|
|
: **tkremind** preserves newlines.
|
|
|
|
**o**
|
|
|
|
: **rem2ps** converts newlines to spaces. But **rem2ps** is
|
|
deprecated; use **rem2pdf** instead.
|
|
|
|
**o**
|
|
|
|
: The \"simple calendar\" formats (i.e., **remind**\'s **-s**,
|
|
**-n** and **-p** options) convert newlines to spaces.
|
|
|
|
All calendar back-ends collapse multiple spaces to a single space
|
|
and multiple newlines to a single newline.
|
|
|
|
**%1**
|
|
|
|
: is replaced with \"now\", \"*m* minutes from now\", \"*m* minutes
|
|
ago\", \"*h* hours from now\", \"*h* hours ago\", \"*h* hours and
|
|
*m* minutes from now\" or \"*h* hours and *m* minutes ago\", as
|
|
appropriate for a timed reminder. Note that unless you specify the
|
|
**-a** option, timed reminders will be triggered like normal
|
|
reminders, and thus a timed reminder that occurred earlier in the
|
|
day may be triggered. This causes the need for the \"\...ago\"
|
|
forms.
|
|
|
|
**%2**
|
|
|
|
: is replaced with \"at *hh*:*mm*am\" or \"..pm\" depending on the
|
|
**AT** time of the reminder.
|
|
|
|
**%3**
|
|
|
|
: is replaced with \"at *hh*:*mm*\" in 24-hour format.
|
|
|
|
**%4**
|
|
|
|
: is replaced with \"*mm*\" where *mm* is the number of minutes
|
|
between \"now\" and the time specified by **AT**. If the **AT** time
|
|
is earlier than the current time, then the result is negative.
|
|
|
|
**%5**
|
|
|
|
: is replaced with \"*ma*\" where *ma* is the absolute value of the
|
|
number produced by **%4**.
|
|
|
|
**%6**
|
|
|
|
: is replaced with \"ago\" or \"from now\", depending on the
|
|
relationship between the **AT** time and the current time.
|
|
|
|
**%7**
|
|
|
|
: is replaced with the number of hours between the **AT** time and the
|
|
current time. It is always non-negative.
|
|
|
|
**%8**
|
|
|
|
: is replaced with the number of minutes between the **AT** time and
|
|
the current time, after the hours (**%7**) have been subtracted out.
|
|
This is a number ranging from 0 to 59.
|
|
|
|
**%9**
|
|
|
|
: is replaced with \"s\" if the value produced by **%8** is not 1.
|
|
|
|
**%0**
|
|
|
|
: is replaced with \"s\" if the value produced by **%7** is not 1.
|
|
|
|
**%!**
|
|
|
|
: is replaced with \"is\" if the current date and time is before the
|
|
trigger date and the **AT** time, or \"was\" if it is after. The
|
|
**%!** sequence may be used in a non-timed reminder, in which case
|
|
only dates are compared.
|
|
|
|
**%?**
|
|
|
|
: is replaced with \"are\" if the current date and time is before the
|
|
trigger date and the **AT** time, or \"were\" if it is after. The
|
|
**%?** sequence may be used in a non-timed reminder, in which case
|
|
only dates are compared.
|
|
|
|
**%@**
|
|
|
|
: is similar to **%2** but displays the current time.
|
|
|
|
**%#**
|
|
|
|
: is similar to **%3** but displays the current time.
|
|
|
|
**%:**
|
|
|
|
: is replaced with \" (done)\" for a TODO reminder whose trigger date
|
|
is on or after its COMPLETE-THROUGH date. It is replaced with the
|
|
empty string in any other situation. Note that because **Remind**
|
|
does not display completed TODO reminders in Agenda Mode, this
|
|
escape sequence is really only useful in Calendar Mode.
|
|
|
|
**%\"**
|
|
|
|
: (percent-doublequote) is removed. This sequence is not used by the
|
|
substitution filter, but is used to tell **Remind** which text to
|
|
include in a calendar entry when the **-c**, **-s** or **-p** option
|
|
is chosen. See \"CALENDAR MODE\"
|
|
|
|
Notes:
|
|
|
|
o
|
|
|
|
: **Remind** normally prints a blank line after each reminder; if the
|
|
last character of the body is \"%\", the blank line will not be
|
|
printed. You can globally suppress the extra blank lines by setting
|
|
**\$AddBlankLines** to 0.
|
|
|
|
o
|
|
|
|
: Substitutions a, b, c, e, f, g, h, i, j, k, l, u and v all are
|
|
replaced with \"today\" if the current date equals the trigger date,
|
|
or \"tomorrow\" if the trigger date is one day after the current
|
|
date. Thus, they are **not** the same as substitutions built up from
|
|
the simpler %w, %y, etc. sequences.
|
|
|
|
o
|
|
|
|
: The a, c, e, f, g, h, i, j, k, l, u, v, 2, and 3 substitutions may
|
|
be preceded by an asterisk (for example, **%\*c**) which causes the
|
|
word \"at\" or \"on\" that would normally be included in the output
|
|
to be omitted.
|
|
|
|
o
|
|
|
|
: The ! and ? substitutions may be preceded by an asterisk (**%\*!**
|
|
or **%\*?**), in which case the comparison is made between the
|
|
trigger date and realtoday() instead of today().
|
|
|
|
o
|
|
|
|
: Any of the substitutions dealing with time (0 through 9) produce
|
|
undefined results if used in a reminder that does not have an **AT**
|
|
keyword. Also, if a reminder has a *delta* and may be triggered on
|
|
several days, the time substitutions ignore the date. Thus, the
|
|
**%1** substitution may report that a meeting is in 15 minutes, for
|
|
example, even though it may only be in 2 days time, because a
|
|
*delta* has triggered the reminder. It is recommended that you use
|
|
the time substitutions only in timed reminders with no *delta* that
|
|
are designed to be queued for timed activation.
|
|
|
|
o
|
|
|
|
: Capital letters can be used in the substitution sequence, in which
|
|
case the first character of the substituted string is capitalized
|
|
(if it is normally a lower-case letter.)
|
|
|
|
o
|
|
|
|
: All other characters following a \"%\" sign are simply copied. In
|
|
particular, to get a \"%\" sign out, use \"%%\" in the body. To
|
|
start the body of a reminder with a space, use \"% \", since
|
|
**Remind** normally scans for the first non-space character after a
|
|
**MSG,** **CAL** or **RUN** token.
|
|
|
|
# EVENTS AND TODOS
|
|
|
|
The **REM** command is normally used to create an *EVENT*. This is
|
|
something that happens at a certain time, possibly recurring, and
|
|
happens no matter what action you take. Events include things like
|
|
birthdays, holidays, meetings, etc\... pretty much everything that
|
|
occurs on a particular schedule. Once the date of an event has passed,
|
|
**Remind** will no longer remind you about the event.
|
|
|
|
A *TODO* is different; it is a task that you have to complete by a
|
|
specific date or date and time. If you don\'t explicitly mark a TODO as
|
|
done, **Remind** will keep reminding you about it *even past* the due
|
|
date..
|
|
|
|
To mark a **REM** as a TODO, simply include the TODO keyword. For
|
|
example:
|
|
|
|
REM TODO 15 August 2025 ++5 MSG Buy cat food %b.
|
|
|
|
In Agenda Mode, **Remind** will start warning you on 10 Aug 2025 that
|
|
you have to but cat food in 5 days\' time, 4 days\' time, etc\...
|
|
|
|
However, on 16 Aug 2025, **Remind** will say \"Buy cat food yesterday.\"
|
|
and it will keep reminding you of your need to buy cat food until the
|
|
end of time, or until you mark the TODO as done.
|
|
|
|
# MARKING TODOS AS DONE
|
|
|
|
There are two ways to mark a TODO as done. If the TODO is not recurring,
|
|
the simplest way is simply to remove the TODO designator from the REM
|
|
command (or indeed, to completely delete it.) The former keeps the
|
|
reminder on the calendar while the latter completely removes it.
|
|
|
|
If a TODO is recurring, use the **COMPLETE-THROUGH** clause to mark
|
|
which recurrences have been completed. For example:
|
|
|
|
REM TODO 30 April ++15 COMPLETE-THROUGH 2025-04-30 MSG File taxes
|
|
|
|
Canadian income taxes must be filed every 30 April. The above command
|
|
will remind you to pay taxes in 2026. If you don\'t update the
|
|
COMPLETE-THROUGH date, then after 30 April 2026, **Remind** will keep
|
|
reminding you until the end of time that your taxes were due on 30 April
|
|
2026. To indicate that you\'ve paid them, simply update the
|
|
COMPLETE-THROUGH date to 2026-04-30 and then **Remind** will start
|
|
reminding you of your 2027 taxes (starting 15 days before the due date.)
|
|
|
|
It is an error to specify COMPLETE-THROUGH without also specifying TODO.
|
|
|
|
# LIMITING REMINDERS ABOUT OVERDUE TODOS
|
|
|
|
Although **Remind** is happy to keep reminding you about overdue TODOs
|
|
for hundreds of years, for some things this may be pointless. If you
|
|
want **Remind** to *stop* nagging you about an overdue TODO after a
|
|
certain number of days, use the MAX-OVERDUE *n* clause. In this case,
|
|
**Remind** stops reminding you of a TODO that is overdue by more than
|
|
*n* days. Here is an example.
|
|
|
|
REM TODO 2025-08-13 ++5 MAX-OVERDUE 5 MSG Task: %b.
|
|
|
|
**Remind** *starts* reminding you of the task on 2025-08-08, because of
|
|
the ++5 back value. It keeps reminding you of the task after the due
|
|
date. However, the last time it will remind you will be on 2025-08-18,
|
|
because of the MAX-OVERDUE clause. Starting on 2025-08-19, **Remind**
|
|
will no longer remind you of the task since it\'s probably
|
|
pointless\-\--it has passed the MAX-OVERDUE period.
|
|
|
|
# MORE DETAILS ABOUT TODOS
|
|
|
|
TODOs are treated specially only in Agenda Mode. In Calendar Mode, they
|
|
appear in the calendar exactly as a normal event would.
|
|
|
|
TODOs are implemented internally by using the COMPLETE-THROUGH date plus
|
|
one day as the starting point for **Remind**\'s date-scanning algorithm.
|
|
If you have a recurring TODO without a COMPLETE-THROUGH clause, then
|
|
**Remind** starts scanning from the beginning of time, which we all know
|
|
is 1 January 1990. Consider this command:
|
|
|
|
REM TODO Wed +7 MSG Take out the trash %a (%b)
|
|
|
|
Running that command in Agenda Mode on 2025-08-13 yields the following
|
|
output:
|
|
|
|
Take out the trash on Wednesday, 3 January, 1990 (13006 days ago)
|
|
|
|
**Remind** is very persistent about reminding you of tasks! If you take
|
|
out the trash and mark it done:
|
|
|
|
REM TODO Wed +7 COMPLETE-THROUGH 2025-08-13 MSG Take out the trash %a (%b)
|
|
|
|
then you get this:
|
|
|
|
Take out the trash on Wednesday, 20 August, 2025 (in 7 days' time)
|
|
|
|
You can use **FROM** and **UNTIL** to limit the recurrence interval of
|
|
tasks just as you can with events. For example, if you are house-sitting
|
|
for the month of August and need to water plants every Wednesday:
|
|
|
|
REM TODO Wed +7 FROM 2025-08-06 UNTIL 2025-08-27 MSG Plants %b.
|
|
|
|
Running that command on 13 Aug yields: \"Plants 7 days ago.\" because
|
|
you have not told **Remind** that you completed the first watering. If
|
|
you finish your duties and add a COMPLETE-THROUGH date of 2025-08-27,
|
|
then **Remind** never reminds you of that task in the future.
|
|
|
|
In Purge Mode, **Remind** will not purge TODOs unless they have been
|
|
marked as complete. In the case of a recurring TODO, **Remind** will not
|
|
purge it until the last occurrence is marked as complete.
|
|
|
|
# THE OMIT COMMAND
|
|
|
|
In addition to being a keyword in the **REM** command, **OMIT** is a
|
|
command in its own right. Its syntax is:
|
|
|
|
> **OMIT** *weekday* \[*weekday*\...\]
|
|
>
|
|
> or:
|
|
>
|
|
> **OMIT** \[*day*\] *month* \[*year*\]
|
|
>
|
|
> or:
|
|
>
|
|
> **OMIT** \[*day1*\] *month1* \[*year1*\] **THROUGH** \[*day2*\]
|
|
> *month2* \[*year2*\]
|
|
|
|
The **OMIT** command is used to \"globally\" omit certain days (usually
|
|
holidays). These globally-omitted days are skipped by the \"-\" and
|
|
\"+\" forms of *back* and *delta*, but not by the \"\--\" and \"++\"
|
|
forms. Some examples:
|
|
|
|
OMIT Saturday Sunday
|
|
OMIT 1 Jan
|
|
OMIT 7 Sep 1992
|
|
OMIT 15 Jan THROUGH 14 Feb
|
|
OMIT May # Equivalent to OMIT May 1 THROUGH May 31
|
|
OMIT 25 Dec THROUGH 4 Jan
|
|
OMIT 2023-05-03 THROUGH 2023-05-12
|
|
OMIT Jun THROUGH July # Equivalent to OMIT Jun 1 THROUGH July 31
|
|
|
|
The first example omits every Saturday and Sunday. This is useful for
|
|
reminders that shouldn\'t trigger on weekends.
|
|
|
|
The second example specifies a holiday that occurs on the same date each
|
|
year - New Year\'s Day.
|
|
|
|
The third example specifies a holiday that changes each year - Labour
|
|
Day. For these types of holidays, you must create an **OMIT** command
|
|
for each year. (Later, in the description of expressions and some of the
|
|
more advanced features of **Remind**, you will see how to automate this
|
|
for some cases.)
|
|
|
|
As with the REM command, you can use shorthand specifiers for dates; the
|
|
following are equivalent:
|
|
|
|
OMIT 7 Sep 1992
|
|
OMIT 1992-09-07
|
|
|
|
For convenience, you can use a *delta* and **MSG** or **RUN** keyword in
|
|
the **OMIT** command. The following sequences are equivalent:
|
|
|
|
OMIT 1 Jan
|
|
REM 1 Jan +4 MSG New year's day is %b!
|
|
|
|
and
|
|
|
|
OMIT 1 Jan +4 MSG New year's day is %b!
|
|
|
|
The **THROUGH** keyword lets you conveniently OMIT a range of days. For
|
|
example, the following sequences are equivalent:
|
|
|
|
OMIT 3 Jan 2011
|
|
OMIT 4 Jan 2011
|
|
OMIT 5 Jan 2011
|
|
|
|
and
|
|
|
|
OMIT 3 Jan 2011 THROUGH 5 Jan 2011
|
|
|
|
Note that **Remind** has a compiled-in limit to the number of full
|
|
OMITs. If you omit a range of *N* fully-specified (i.e., year included)
|
|
days, then *N* full OMITs are used up. Trying to omit a very large range
|
|
may result in the error \"Too many full OMITs\"
|
|
|
|
You can make a THROUGH **OMIT** do double-duty as a **REM** command as
|
|
long as both dates are fully specified
|
|
|
|
OMIT 6 Sep 2010 THROUGH 10 Sep 2010 MSG Vacation
|
|
|
|
If you use a THROUGH clause, then either the year must be supplied
|
|
before and after the THROUGH, or it must be missing before and after the
|
|
THROUGH. The following are legal:
|
|
|
|
OMIT 25 Dec THROUGH 6 Jan
|
|
OMIT 25 Dec 2024 THROUGH 6 Jan 2025
|
|
|
|
But the following are not:
|
|
|
|
OMIT 25 Dec THROUGH 6 Jan 2025
|
|
OMIT 25 Dec 2024 THROUGH 6 Jan
|
|
|
|
You can debug your global OMITs with the following command:
|
|
|
|
OMIT DUMP
|
|
|
|
The OMIT DUMP command prints the current global omits to standard
|
|
output.
|
|
|
|
**THE BEFORE, AFTER AND SKIP KEYWORDS**
|
|
|
|
Normally, days that are omitted, whether by a global **OMIT** command or
|
|
the local **OMIT** or **OMITFUNC** keywords in a **REM** statement, only
|
|
affect the counting of the -*back* or the +*delta*. For example, suppose
|
|
you have a meeting every Wednesday. Suppose, too, that you have
|
|
indicated 11 Nov as a holiday:
|
|
|
|
OMIT 11 Nov +4 MSG Remembrance Day
|
|
REM Wed +1 MSG Code meeting %b.
|
|
|
|
The above sequence will issue a reminder about a meeting for 11 November
|
|
1992, which is a Wednesday. This is probably incorrect. There are three
|
|
options:
|
|
|
|
**BEFORE**
|
|
|
|
: This keyword moves the reminder to before any omitted days. Thus, in
|
|
the above example, use of **BEFORE** would cause the meeting
|
|
reminder to be triggered on Tuesday, 10 November 1992.
|
|
|
|
**AFTER**
|
|
|
|
: This keyword moves the reminder to after any omitted days. In the
|
|
above example, the meeting reminder would be triggered on Thursday,
|
|
12 November 1992.
|
|
|
|
**SKIP**
|
|
|
|
: This keyword causes the reminder to be skipped completely on any
|
|
omitted days. Thus, in the above example, the reminder would not be
|
|
triggered on 11 November 1992. However, it would be triggered as
|
|
usual on the following Wednesday, 18 November 1992.
|
|
|
|
The **BEFORE** and **AFTER** keywords move the trigger date of a
|
|
reminder to before or after a block of omitted days, respectively.
|
|
Suppose you normally run a backup on the first day of the month.
|
|
However, if the first day of the month is a weekend or holiday, you run
|
|
the backup on the first working day following the weekend or holiday.
|
|
You could use:
|
|
|
|
REM 1 OMIT Sat Sun AFTER RUN do_backup
|
|
|
|
Let\'s examine how the trigger date is computed. The **1** specifies the
|
|
first day of the month. The local **OMIT** keyword causes the **AFTER**
|
|
keyword to move the reminder forward past weekends. Finally, the
|
|
**AFTER** keyword will keep moving the reminder forward until it has
|
|
passed any holidays specified with global **OMIT** commands.
|
|
|
|
# TIMEZONE SUPPORT
|
|
|
|
The **REM** command supports an optional **TZ** keyword, which should be
|
|
followed by the *case-sensitive* time zone name in which the command is
|
|
to be interpreted. Note that if you use the **TZ** keyword, then you
|
|
*must also* use an **AT** clause. Here are some examples:
|
|
|
|
REM Wednesday AT 14:00 TZ America/Toronto MSG 2PM Eastern (%2).
|
|
REM Wednesday AT 23:59 TZ America/Los_Angeles SATISFY [$Td == 13] MSG Foo %b %2.
|
|
|
|
Within a **SATISFY** clause and an **OMITFUNC** function, all trigger
|
|
functions and the trigger date are interpreted _in the time zone_
|
|
_specified in the_ **REM** _command_. Outside the **REM** command,
|
|
however, trigger functions are adjusted to the local time zone. If the
|
|
local time zone is UTC and we feed **Remind** the following file on
|
|
2025-09-04 UTC:
|
|
|
|
SET $AddBlankLines 0
|
|
BANNER %
|
|
REM Wednesday AT 14:00 TZ America/Toronto MSG 2PM Eastern (%2).
|
|
set a $T
|
|
set b $Tt
|
|
REM MSG a = [a], b = [b]
|
|
REM Wednesday AT 23:59 TZ America/Los_Angeles SATISFY [$Td == 13] MSG Foo %b %2.
|
|
set c $T
|
|
set d $Tt
|
|
REM MSG c = [c], d = [d]
|
|
|
|
Then the output is as follows:
|
|
|
|
a = 2025-09-10, b = 18:00
|
|
c = 2026-05-14, d = 06:59
|
|
|
|
That is because the trigger date of the first (Wednesday, 2025-09-10 at
|
|
14:00 Eastern time) is 2025-09-10 at 18:00 UTC. In the second case,
|
|
Wednesday, 13 May 2026 is the SATISFied trigger date, which is adjusted
|
|
to Thursday, 14 May 2026 at 06:59 UTC because of the time zone
|
|
adjustment.
|
|
|
|
If you use an invalid time zone name after the **TZ** keyword, results
|
|
are undefined. As mentioned previously, time zone names *are*
|
|
case-sensitive; America/Toronto is valid, but america/toronto is not.
|
|
|
|
If you are on a system that stores time zone data in
|
|
/usr/share/zoneinfo, then **Remind** will attempt to validate the time
|
|
zone name and will warn you if it appears to be invalid. If you want to
|
|
specify a time zone that lacks a file under /usr/share/zoneinfo anyway,
|
|
and want to suppress the warning, prefix the time zone name with \"!\".
|
|
For example:
|
|
|
|
REM Thursday AT 14:45 TZ !EST+5EDT,M3.2.0/2,M11.1.0/2 MSG Old TZ format
|
|
|
|
In a reminder with the **TZ** keyword, OMIT dates are evaluated in the
|
|
specified time zone. Here\'s an example: Suppose the local time zone is
|
|
America/Toronto and you have this script:
|
|
|
|
# A Friday
|
|
OMIT 2025-09-05
|
|
|
|
# A Saturday
|
|
OMIT 2025-09-13
|
|
|
|
REM Saturday AT 01:00 TZ Europe/Amsterdam SKIP MSG Early Sat AM
|
|
|
|
On 2025-09-05 in the America/Toronto time zone, the reminder *will*
|
|
trigger. Even though 2025-09-05 has been OMITted, the SKIP keyword
|
|
evaluates the date in the Europe/Amsterdam time zone, and 2025-09-06
|
|
(the trigger date) is *not* omitted.
|
|
|
|
Conversely, on 2025-09-12 in the America/Toronto time zone, the reminder
|
|
will *not* trigger. Even though 2025-09-12 is not OMITted, 2025-09-13
|
|
is, and that is the trigger date in the Europe/Amsterdam time zone.
|
|
|
|
# THE DO, INCLUDE AND SYSINCLUDE COMMANDS
|
|
|
|
**Remind** allows you to include other files in your reminder script,
|
|
similar to the C preprocessor #include directive. For example, you might
|
|
organize different reminders into different files like this:
|
|
|
|
INCLUDE holidays.rem
|
|
INCLUDE birthdays.rem
|
|
INCLUDE "quote files with spaces.rem"
|
|
|
|
**INCLUDE** files can be nested up to a depth of 8. As shown above, if a
|
|
filename has spaces in it (not recommended!) you can use double-quotes
|
|
around the filename.
|
|
|
|
If you specify a filename of \"-\" in the **INCLUDE** command,
|
|
**Remind** will begin reading from standard input.
|
|
|
|
If you specify a *directory* as the argument to **INCLUDE**, then
|
|
**Remind** will process all files (but not subdirectories!) in that
|
|
directory that match the shell pattern \"\*.rem\". The files are
|
|
processed in sorted order; the sort order matches that used by the shell
|
|
when it expands \"\*.rem\".
|
|
|
|
Note that the file specified by an **INCLUDE** command is interpreted
|
|
relative to the _current working directory of the_ **Remind** process.
|
|
If you want to include a file relative to the directory containing the
|
|
currently-processing file, use **DO** instead. For example, if the
|
|
current file is **/home/user/.reminders/foo.rem** and Remind\'s working
|
|
directory is **/home/user**, then:
|
|
|
|
# Read /home/user/.reminders/bar.rem
|
|
DO bar.rem
|
|
|
|
# Read /usr/share/bar.rem - absolute path
|
|
DO /usr/share/bar.rem
|
|
|
|
# Read /home/user/bar.rem
|
|
INCLUDE bar.rem
|
|
|
|
# Read /usr/share/bar.rem - absolute path
|
|
INCLUDE /usr/share/bar.rem
|
|
|
|
Arguably, the **INCLUDE** command should have worked the way **DO** does
|
|
right from the start, but changing it would have broken
|
|
backward-compatibility, hence the introduction of **DO**.
|
|
|
|
Note that if the currently-processing reminders file was specified as a
|
|
symbolic link to a file that is not in the same directory as the
|
|
symbolic link itself, **DO** will fail. **Remind** does *not* resolve
|
|
the real path of symbolic links, so you should avoid using symbolic
|
|
links to files.
|
|
|
|
The **SYSINCLUDE** command is similar to **DO**, but it looks for
|
|
relative pathnames under the system directory containing standard
|
|
reminder scripts. For this installation of **Remind**, the system
|
|
directory is \"/usr/local/share/remind\".
|
|
|
|
# THE RETURN COMMAND
|
|
|
|
The **RETURN** command causes **Remind** to ignore the remaining
|
|
contents of the file currently being processed. It can be used as a
|
|
quick way to \"exit\" from an included file (though it also works at the
|
|
top-level.)
|
|
|
|
Here is an example of how **RETURN** might be used:
|
|
|
|
IF already_done
|
|
RETURN
|
|
ENDIF
|
|
set already_done 1
|
|
preserve already_done
|
|
# Do expensive processing here
|
|
|
|
# THE RUN COMMAND
|
|
|
|
If you include other files in your reminder script, you may not always
|
|
entirely trust the contents of the other files. For example, they may
|
|
contain **RUN**-type reminders that could be used to access your files
|
|
or perform undesired actions. The **RUN** command can restrict this: If
|
|
you include the command **RUN OFF** in your top-level reminder script,
|
|
any reminder or expression that would normally execute a system command
|
|
is disabled. **RUN ON** will re-enable the execution of system commands.
|
|
Note that the **RUN ON** command can *only* be used in your top-level
|
|
reminder script; it will *not* work in any files accessed by the
|
|
**INCLUDE** command. This is to protect you from someone placing a **RUN
|
|
ON** command in an included file. However, the **RUN OFF** command can
|
|
be used at top level or in an included file.
|
|
|
|
If you run **Remind** with the **-r** command-line option, **RUN**-type
|
|
reminders and the **shell()** function will be disabled, regardless of
|
|
any **RUN** commands in the reminder script. However, any command
|
|
supplied with the **-k** option will still be executed.
|
|
|
|
In addition, **Remind** contains a few other security features. It will
|
|
not read a file that is group- or world-writable. It will not run
|
|
set-uid. If it reads a file you don\'t own, it will disable RUN and the
|
|
shell() function. And if it is run as *root*, it will only read files
|
|
owned by *root*.
|
|
|
|
Note that if **Remind** reads standard input, it does *not* attempt to
|
|
check the ownership of standard input, even if it is coming from a file,
|
|
and hence does *not* disable RUN and shell() in this situation.
|
|
|
|
# THE EXPR COMMAND
|
|
|
|
**Remind** lets you completely disable expression evaluation. This could
|
|
be useful if you are running **Remind** on a somewhat-untrustworthy file
|
|
that is not expected to contain expressions. To disable expression
|
|
evaluation, use:
|
|
|
|
EXPR OFF
|
|
|
|
If **Remind** encounters an expression while EXPR OFF is in effect, it
|
|
returns an error
|
|
|
|
To re-enable expression evaluation, use:
|
|
|
|
EXPR ON
|
|
|
|
As with **RUN ON, EXPR ON** can be used only in the top-level script,
|
|
not in an included file.
|
|
|
|
# THE INCLUDECMD COMMAND
|
|
|
|
**Remind** allows you to execute a shell command and evaluate the output
|
|
of that command as if it were an included file. For example, you could
|
|
have scripts that extract reminders out of a database and print them on
|
|
stdout as REM commands. Here is an example:
|
|
|
|
INCLUDECMD extract_reminders_for dfs
|
|
|
|
We assume that the command \"extract_reminders_for\" extracts reminders
|
|
out of a central database for the named user. Another use-case of
|
|
INCLUDECMD is if you have your reminders stored in a file in some
|
|
non-Remind format; you can write a command that transforms them to
|
|
**Remind** format and then **Remind** can \"include\" the file with an
|
|
appropriate INCLUDECMD command.
|
|
|
|
Note that if RUN is disabled, then INCLUDECMD will fail with the error
|
|
message \"RUN disabled\"
|
|
|
|
**Remind** arranges so that when the command specified by INCLUDECMD is
|
|
executed, its standard input is opened to /dev/null.
|
|
|
|
INCLUDECMD passes the rest of the line to **popen**(3), meaning that the
|
|
command is executed by the shell. As such, shell meta-characters may
|
|
need escaping or arguments quoting, depending on what you\'re trying to
|
|
do. **Remind** itself does not perform any modification of the command
|
|
line (apart from the normal \[expr\] expression-pasting mechanism).
|
|
|
|
If the command passed to INCLUDECMD begins with an exclamation mark
|
|
\"!\", then **Remind** disables **RUN** for the output of the command.
|
|
If you are running a command whose output you don\'t quite trust, you
|
|
should prefix it with \"!\" so that any RUN commands it emits fail.
|
|
|
|
An **INCLUDECMD** command counts towards the INCLUDE nesting depth. For
|
|
any given **Remind** run, a given INCLUDECMD command is only executed
|
|
once and the results are cached. For example, if you generate a
|
|
calendar, each unique INCLUDECMD command is run just once, not once for
|
|
each day of the produced calendar. \"Uniqueness\" is determined by
|
|
looking at the command that will be passed to the shell, so if (for
|
|
example) your INCLUDECMD uses expression-pasting that results in
|
|
differences depending on the value of **today()**, then each *unique*
|
|
version of the command will be executed once.
|
|
|
|
If a given reminder file contains more than one identical
|
|
**INCLUDECMD**, only the first one will actually be executed. All
|
|
subsequent identical ones will use the cached output from the first one.
|
|
|
|
# THE BANNER COMMAND
|
|
|
|
When **Remind** first issues a reminder, it prints a message like this:
|
|
|
|
Reminders for Friday, 30th October, 1992 (today):
|
|
|
|
(The banner is not printed if any of the calendar-producing options is
|
|
used, or if the **-k** option is used.)
|
|
|
|
The **BANNER** command lets you change the format. It should appear
|
|
before any **REM** commands. The format is:
|
|
|
|
> **BANNER** *format*
|
|
|
|
The *format* is similar to the *body* of a **REM** command. It is passed
|
|
through the substitution filter, with an implicit trigger of the current
|
|
system date. Thus, the default banner is equivalent to:
|
|
|
|
BANNER Reminders for %w, %d%s %m, %y%o:
|
|
|
|
You can disable the banner completely with BANNER %. Or you can create a
|
|
custom banner:
|
|
|
|
BANNER Hi - here are your reminders for %y-%t-%r:
|
|
|
|
# CONTROLLING THE OMIT CONTEXT
|
|
|
|
Sometimes, it is necessary to temporarily change the global **OMITs**
|
|
that are in force for a few reminders. Three commands allow you to do
|
|
this:
|
|
|
|
**PUSH-OMIT-CONTEXT**
|
|
|
|
: This command saves the current global **OMITs** on an internal
|
|
stack.
|
|
|
|
**CLEAR-OMIT-CONTEXT**
|
|
|
|
: This command clears all of the global **OMITs**, starting you off
|
|
with a \"clean slate.\"
|
|
|
|
**POP-OMIT-CONTEXT**
|
|
|
|
: This command restores the global **OMITs** that were saved by the
|
|
most recent **PUSH-OMIT-CONTEXT**.
|
|
|
|
For example, suppose you have a block of reminders that require a clear
|
|
**OMIT** context, and that they also introduce unwanted global **OMITs**
|
|
that could interfere with later reminders. You could use the following
|
|
fragment:
|
|
|
|
PUSH-OMIT-CONTEXT # Save the current context
|
|
CLEAR-OMIT-CONTEXT # Clean the slate
|
|
# Block of reminders goes here
|
|
POP-OMIT-CONTEXT # Restore the saved omit context
|
|
|
|
# EXPRESSIONS
|
|
|
|
In certain contexts, to be described later, **Remind** will accept
|
|
expressions for evaluation. **Remind** expressions resemble C
|
|
expressions, but operate on different types of objects.
|
|
|
|
**DATA TYPES**
|
|
|
|
**Remind** expressions operate on five types of objects:
|
|
|
|
**INT**
|
|
|
|
: The **INT** data type consists of the integers representable in one
|
|
machine word. The **INT** data type corresponds to the C \"int\"
|
|
type.
|
|
|
|
**STRING**
|
|
|
|
: The **STRING** data type consists of strings of characters. It is
|
|
somewhat comparable to a C character array, but more closely
|
|
resembles the string type in BASIC.
|
|
|
|
**Remind** normally expects to be running in a UTF-8 environment. In
|
|
this environment, there is a difference between *bytes* and
|
|
*characters* since in UTF-8, a character may be represented by 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 \"één\" contains three characters but five bytes.
|
|
|
|
**Remind** has a set of functions that work on *bytes*, namely
|
|
**index**, **strlen** and **substr**. These are not safe to use on
|
|
multi-byte strings; instead use **mbindex**, **mbstrlen** and
|
|
**mbsubstr**. If you know *for sure* that a string contains only
|
|
single-byte characters, then the byte-oriented versions may be used
|
|
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
|
|
**mb**_xxx_ functions all return an error.
|
|
|
|
**TIME**
|
|
|
|
: The **TIME** data type is used for two different purposes: To
|
|
represent a time of day with one-minute precision or to represent a
|
|
duration with one-minute precision. The context of where a **TIME**
|
|
is used determines whether it is interpreted as a time of day or a
|
|
duration.
|
|
|
|
In contexts where a **TIME** represents a time of day, it may range
|
|
from 00:00 to 23:59 and is stored internally as an integer from 0 to
|
|
1439 representing the number of minutes since midnight.
|
|
|
|
In contexts where a **TIME** represents a duration, there is no
|
|
upper limit on the hour component (beyond that imposed by the
|
|
restriction that a duration expressed in minutes must fit into the
|
|
signed integer type of your CPU architecture.) Internally, a
|
|
duration is stored as an integer number of minutes.
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
|
|
**DATE**
|
|
|
|
: The **DATE** data type consists of dates (later than 1 January
|
|
1990.) Internally, **DATE** objects are stored as the number of days
|
|
since 1 January 1990.
|
|
|
|
**DATETIME**
|
|
|
|
: The **DATETIME** data type consists of a date and time together.
|
|
Internally, **DATETIME** objects are stored as the number of minutes
|
|
since midnight, 1 January 1990. You can think of a **DATETIME**
|
|
object as being the combination of **DATE** and **TIME** parts.
|
|
|
|
**CONSTANTS**
|
|
|
|
The following examples illustrate constants in **Remind** expressions:
|
|
|
|
**INT constants**
|
|
|
|
: 12, 36, -10, 0, 1209, 0x1F, 0xfe00 (the last two demonstrate the use
|
|
of hexadecimal constants)
|
|
|
|
**STRING constants**
|
|
|
|
: \"Hello there\", \"This is a test\", \"\\nHello\\tThere\", \"\"
|
|
|
|
> Note that the empty string is represented by \"\". **Remind** supports
|
|
> the escape sequences \"\\a\", \"\\b\", \"\\f\", \"\\n\", \"\\r\",
|
|
> \"\\t\" and \"\\v\" which have the same meanings as their counterparts
|
|
> in C. It also supports \"\\xAB\" where A and B are hexadecimal digits;
|
|
> this operates just as in C. The \"\\x\" must be followed by one or two
|
|
> hex digits; the escape sequence \"\\x00\" is not permitted.
|
|
>
|
|
> To include a quote in a string, use \"\\\"\". Any other character
|
|
> preceded by a backslash is inserted into the string as-is, but the
|
|
> backslash itself is removed. To include a backslash in a string, use
|
|
> \"\\\\\".
|
|
|
|
**TIME constants**
|
|
|
|
: 12:33, 0:01, 14:15, 16:42, 12.16, 13.00, 1.11, 4:30PM, 12:20am
|
|
|
|
> Note that **TIME** constants may be written in 24-hour format or in
|
|
> common \"AM/PM\" format. If you use \"AM/PM\" format, then the hour
|
|
> can range from 1 to 12. Either a period or colon can be used to
|
|
> separate the minutes from the hours. However, **Remind** will
|
|
> consistently output times in 24-hour format using only one separator
|
|
> character. (The output separator character is chosen at compile-time.)
|
|
>
|
|
> If the **TIME** is used where **Remind** expects a time-of-day (for
|
|
> example, in an **AT** clause), then it can be written in 24-hour
|
|
> format (ranging from 00:00 to 23:59) or 12-hour format (ranging from
|
|
> 12:00am to 11:59pm). If the **TIME** is used where **Remind** expects
|
|
> a duration, it must not have an *am* or *pm* suffix and the hour can
|
|
> be as large as you want, so long as the total number of minutes in the
|
|
> duration fits in a signed integer variable.
|
|
>
|
|
> For convenience, a **TIME** constant may be surrounded by single
|
|
> quotes to match **DATE** and **DATETIME** constants, but these quotes
|
|
> are optional. That is, 12:56 and \'12:56\' represent the same **TIME**
|
|
> constant.
|
|
|
|
**DATE constants**
|
|
|
|
: **DATE** constants are expressed as \'yyyy/mm/dd\' or
|
|
\'yyyy-mm-dd\', and the single quotes *must* be supplied. This
|
|
distinguishes date constants from division or subtraction of
|
|
integers. Examples:
|
|
|
|
> \'1993/02/22\', \'1992-12-25\', \'1999/01/01\'
|
|
>
|
|
> Note that **DATE** values are *printed* without the quotes. Although
|
|
> either \'-\' or \'/\' is accepted as a date separator on input, when
|
|
> dates are printed, only one will be used. The choice of whether to use
|
|
> \'-\' or \'/\' is made at compile-time. Note also that versions of
|
|
> **Remind** prior to 03.00.01 did not support date constants. In those
|
|
> versions, you must create dates using the **date()** function. Also,
|
|
> versions prior to 03.00.02 did not support the \'-\' date separator.
|
|
|
|
**DATETIME constants**
|
|
|
|
: **DATETIME** constants are expressed similarly to **DATE** constants
|
|
with the addition of an \"@HH:MM\" part, optionally followed by
|
|
\"am\" or \"pm\". For example:
|
|
|
|
> \'2008-04-05@23:11\', \'1999/02/03@14:06\', \'2001-04-07@08:30\',
|
|
> \'2020-01-01@3:20pm\'
|
|
>
|
|
> **DATETIME** values are printed without the quotes. Notes about date
|
|
> and time separator characters for **DATE** and **TIME** constants
|
|
> apply also to **DATETIME** constants.
|
|
|
|
**ZERO VALUES AND TRUE/FALSE**
|
|
|
|
All types have an associated *zero value*, which is treated as *false*
|
|
by the IF command, the IIF function, and the logical operators. The zero
|
|
values are:
|
|
|
|
> **INT** - 0
|
|
>
|
|
> **DATE** - \'1990-01-01\'
|
|
>
|
|
> **TIME** - 00:00
|
|
>
|
|
> **DATETIME** - \'1990-01-01@00:00\'
|
|
>
|
|
> **STRING** - \"\" (the empty string)
|
|
|
|
Any value other than the *zero value* is treated as *true*.
|
|
|
|
**OPERATORS**
|
|
|
|
**Remind** has the following operators. Operators on the same line have
|
|
equal precedence, while operators on lower lines have lower precedence
|
|
than those on higher lines. The operators approximately correspond to C
|
|
operators.
|
|
|
|
! - (unary logical negation and arithmetic negation)
|
|
* / % (multiplication, division, modulus)
|
|
+ - (addition/concatenation, subtraction)
|
|
< <= > >= (comparisons)
|
|
== != (equality and inequality tests)
|
|
&& (logical AND)
|
|
|| (logical OR)
|
|
|
|
**DESCRIPTION OF OPERATORS**
|
|
|
|
**!**
|
|
|
|
: Logical negation. Can be applied to any type. If the operand is
|
|
non-zero, returns 0. Otherwise, returns 1.
|
|
|
|
**-**
|
|
|
|
: Unary minus. Can be applied to an **INT**. Returns the negative of
|
|
the operand.
|
|
|
|
**\***
|
|
|
|
: Multiplication. Returns the product of two **INT**s. Alternatively,
|
|
if one argument is a **STRING** and the other an **INT**, returns a
|
|
**STRING** consisting of the INT number of repeats of the original
|
|
STRING. In this case, the INT argument cannot be negative.
|
|
|
|
**/**
|
|
|
|
: Integer division. Returns the quotient of two **INT**s, discarding
|
|
the remainder.
|
|
|
|
**%**
|
|
|
|
: Modulus. Returns the remainder upon dividing one **INT** by another.
|
|
|
|
**+**
|
|
|
|
: Has several uses. These are:
|
|
|
|
> **INT** + **INT** - returns the sum of two **INT**s.
|
|
>
|
|
> **INT** + **TIME** or **TIME** + **INT** - returns a **TIME** obtained
|
|
> by adding **INT** minutes to the original **TIME**. The result will
|
|
> always range from 00:00 through 23:59.
|
|
>
|
|
> **TIME** + **TIME** treats the second **TIME** parameter as a
|
|
> duration, converting it to an integer number of minutes past midnight,
|
|
> and then performs addition as with **TIME** + **INT**.
|
|
>
|
|
> **INT** + **DATE** or **DATE** + **INT** - returns a **DATE** obtained
|
|
> by adding **INT** days to the original **DATE**.
|
|
>
|
|
> **INT** + **DATETIME** or **DATETIME** + **INT** - returns a
|
|
> **DATETIME** obtained by adding **INT** minutes to the original
|
|
> **DATETIME**.
|
|
>
|
|
> **DATETIME** + **TIME** or **TIME** + **DATETIME** treats the **TIME**
|
|
> parameter as a duration, converting it to an integer number of minutes
|
|
> past midnight, and then performs addition as with **DATETIME** +
|
|
> **INT**.
|
|
>
|
|
> **STRING** + **STRING** - returns a **STRING** that is the
|
|
> concatenation of the two original **STRING**s.
|
|
>
|
|
> **STRING** + anything or anything + **STRING** - converts the
|
|
> non-**STRING** argument to a **STRING**, and then performs
|
|
> concatenation. See the **coerce()** function.
|
|
|
|
**-**
|
|
|
|
: Has several uses. These are:
|
|
|
|
> **INT** - **INT** - returns the difference of two **INT**s.
|
|
>
|
|
> **DATE** - **DATE** - returns (as an **INT**) the difference in days
|
|
> between two **DATE**s.
|
|
>
|
|
> **TIME** - **TIME** - returns (as an **INT**) the difference in
|
|
> minutes between two **TIME**s.
|
|
>
|
|
> **DATETIME** - **DATETIME** - returns (as an **INT**) the difference
|
|
> in minutes between two **DATETIME**s.
|
|
>
|
|
> **DATE** - **INT** - returns a **DATE** that is **INT** days earlier
|
|
> than the original **DATE**.
|
|
>
|
|
> **TIME** - **INT** - returns a **TIME** that is **INT** minutes
|
|
> earlier than the original **TIME**.
|
|
>
|
|
> **DATETIME** - **INT** - returns a **DATETIME** that is **INT**
|
|
> minutes earlier than the original **DATETIME**.
|
|
>
|
|
> **DATETIME** - **TIME** - coerces the **TIME** to an **INT** and then
|
|
> performs subtraction as above.
|
|
|
|
**\<, \<=, \>, and \>=**
|
|
|
|
: These are the comparison operators. They can take operands of any
|
|
type, but both operands must be of the same type. The comparison
|
|
operators return 1 if the comparison is true, or 0 if it is false.
|
|
Note that string comparison is done following the lexical ordering
|
|
of characters on your system, and that upper and lower case *are*
|
|
distinct for these operators.
|
|
|
|
**==, !=**
|
|
|
|
: == tests for equality, returning 1 if its operands are equal, and 0
|
|
if they are not. != tests for inequality.
|
|
|
|
> If the operands are not of the same type, == returns 0 and !=
|
|
> returns 1. Again, string comparisons are case-sensitive.
|
|
|
|
**&&**
|
|
|
|
: This is the logical AND operator. Returns the second operand if both
|
|
operands are non-zero. Otherwise, returns whichever operand is zero.
|
|
Operands can be any type and \"zero\" is interpreted as appropriate
|
|
for each operand\'s type.
|
|
|
|
**\|\|**
|
|
|
|
: This is the logical OR operator. It returns the first operand that
|
|
is non-zero; if both operands are zero, then returns the second
|
|
operand. Operands can be any type and \"zero\" is interpreted as
|
|
appropriate for each operand\'s type.
|
|
|
|
**NOTES**
|
|
|
|
If the result of an addition, subtraction or multiplication operation
|
|
would not fit in a C \"int\" type, **Remind** issues a \"Number too
|
|
high\" error. Unlike C, integer operations will not simply give the
|
|
wrong answer in case of overflow.
|
|
|
|
Operators of equal precedence are *always* evaluated from left to right,
|
|
except where parentheses dictate otherwise. This is important, because
|
|
the enhanced \"+\" operator is not necessarily associative. For example:
|
|
|
|
1 + 2 + "string" + 3 + 4 yields "3string34"
|
|
1 + (2 + "string") + (3 + 4) yields "12string7"
|
|
12:59 + 1 + "test" yields "13:00test"
|
|
12:59 + (1 + "test") yields "12:591test"
|
|
|
|
The logical operators are so-called short-circuit operators, as they are
|
|
in C. This means that if the first operand of \|\| is true, then the
|
|
second operand is *not* evaluated. Similarly, if the first operand of &&
|
|
is false, then the second operand is *not* evaluated.
|
|
|
|
**VARIABLES**
|
|
|
|
**Remind** allows you to assign values to variables. The **SET** command
|
|
is used as follows:
|
|
|
|
**SET** *var* *expr*
|
|
|
|
*Var* is the name of a variable. It must start with a letter or
|
|
underscore, and consist only of letters, digits and underscores. Only
|
|
the first 64 characters of a variable name are significant. Variable
|
|
names are *not* case sensitive; thus, \"Afoo\" and \"afOo\" are the same
|
|
variable. Examples:
|
|
|
|
SET a 10 + (9*8)
|
|
SET b "This is a test"
|
|
SET mydir getenv("HOME")
|
|
SET time 12:15
|
|
SET date today()
|
|
|
|
Note that variables themselves have no type. They take on the type of
|
|
whatever you store in them.
|
|
|
|
Variables set with SET or on the command-line with
|
|
**-i**_var=expr_ have global scope.
|
|
|
|
To delete a variable, use the **UNSET** command:
|
|
|
|
**UNSET** *var* \[*var*\...\]
|
|
|
|
For example, to delete all the variables declared above, use:
|
|
|
|
UNSET a b mydir time date
|
|
|
|
# SYSTEM VARIABLES
|
|
|
|
In addition to the regular user variables, **Remind** has several
|
|
\"system variables\" that are used to query or control the operating
|
|
state of **Remind**. System variables are available starting from
|
|
version 03.00.07 of **Remind**.
|
|
|
|
All system variables begin with a dollar sign \'\$\'. They can be used
|
|
in **SET** commands and expressions just as regular variables can. All
|
|
system variables always hold values of a specified type. In addition,
|
|
some system variables cannot be modified, and you cannot create new
|
|
system variables. System variables can be initialized on the command
|
|
line with the **-i** option, but you may need to quote them to avoid
|
|
having the shell interpret the dollar sign. System variable names are
|
|
not case-sensitive.
|
|
|
|
The following system variables are defined. Those marked \"read-only\"
|
|
cannot be changed with the **SET** command. All system variables hold
|
|
values of type **INT**, unless otherwise specified.
|
|
|
|
**\$AddBlankLines**
|
|
|
|
: If set to 1 (the default), then **Remind** normally prints a blank
|
|
line after the banner and each reminder. (This can be suppressed by
|
|
ending the reminder or banner with a single percent sign.) If
|
|
\$AddBlankLines is set to 0, then **Remind** does not print the
|
|
blank line. In this case, ending a reminder with % has no effect. If
|
|
you *do* want a blank line after a reminder, end it with **%\_** to
|
|
insert a newline.
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
|
|
**\$CalcUTC**
|
|
|
|
: If 1 (the default), then **Remind** uses C library functions to
|
|
calculate the number of minutes between local and Universal Time
|
|
Coordinated. This affects astronomical calculations (**sunrise()**
|
|
for example.) If 0, then you must supply the number of minutes
|
|
between local and Universal Time Coordinated in the
|
|
**\$MinsFromUTC** system variable.
|
|
|
|
**\$CalMode (read-only)**
|
|
|
|
: If non-zero, then the **-c** option was supplied on the command
|
|
line.
|
|
|
|
**\$CalType (read-only, STRING type)**
|
|
|
|
: If the **-c**, **-s** or **-p** command-line options were used, then
|
|
this variable has the value \"monthly\". If **-c+**, **-s+** or
|
|
**-p+** were used, then \"weekly\". Otherwise, \"none\".
|
|
|
|
**\$Daemon (read-only)**
|
|
|
|
: If \"daemon mode\" **-z** was invoked, contains the number of
|
|
minutes between wakeups. If not running in daemon mode, contains 0.
|
|
In server mode (either **-z0** or **-zj**), contains -1.
|
|
|
|
**\$DateSep (STRING type)**
|
|
|
|
: This variable can be set only to \"/\" or \"-\". It holds the
|
|
character used to separate portions of a date when **Remind** prints
|
|
a DATE or DATETIME value.
|
|
|
|
**\$DedupeReminders**
|
|
|
|
: If this variable is set to 1, then **Remind** will suppress
|
|
duplicate reminders. A given reminder is considered to be a
|
|
duplicate of a previous one if it has the *exact* same trigger date,
|
|
trigger time, and body. By default, this variable is set to 0 and
|
|
**Remind** does not suppress duplicate reminders.
|
|
|
|
As an example, consider the following reminder file:
|
|
|
|
SET $DedupeReminders 1
|
|
REM Wednesday MSG Phooey
|
|
REM 20 MSG Phooey
|
|
|
|
On Wednesday, 20 November 2024, only *one* \"Phooey\" will be
|
|
issued. In December of 2024, \"Phooey\" will be issued every
|
|
Wednesday as well as on Friday, 20 December 2024
|
|
|
|
If you set \$DedupeReminders to 0, then **Remind** does not even
|
|
track reminders to detect duplicates. Consider the following
|
|
example:
|
|
|
|
SET $DedupeReminders 0
|
|
REM Wednesday MSG Hello
|
|
SET $DedupeReminders 1
|
|
REM Wednesday MSG Hello
|
|
|
|
Every Wednesday, **Remind** will issue *two* \"Hello\" reminders.
|
|
Because \$DedupeReminders was 0 when the first \"Hello\" was issued,
|
|
it won\'t be tracked for potential duplicates.
|
|
|
|
Duplicates are detected after all variable expansion and
|
|
substitutions have been done. Consider the following:
|
|
|
|
SET $DedupeReminders 1
|
|
set a "foo"
|
|
REM MSG [a]
|
|
set a "bar"
|
|
REM MSG [a]
|
|
set a "foo"
|
|
REM MSG [a]
|
|
|
|
The first REM will trigger and print \"foo\". The second will
|
|
trigger and print \"bar\". The third will not trigger because it\'s
|
|
a duplicate of the first \"foo\".
|
|
|
|
**\$DefaultColor (STRING type)**
|
|
|
|
: This variable can be set to a string that has the form of three
|
|
space-separated numbers. Each number must be an integer from 0 to
|
|
255, or all three numbers must be -1. The default value of
|
|
**\$DefaultColor** is \"-1 -1 -1\", which suppresses default
|
|
coloring of MSG-type reminders. If you set **\$DefaultColor** to any
|
|
other value, then all MSG-, MSF- and CAL-type reminders are
|
|
effectively converted into SPECIAL COLOR reminders whose color value
|
|
is specified by **\$DefaultColor**.
|
|
|
|
Unlike other system variables, the value of **\$DefaultColor** is
|
|
*not* preserved between calendar iterations; rather, it is reset to
|
|
\"-1 -1 -1\" at the start of each iteration.
|
|
|
|
**\$DefaultPrio**
|
|
|
|
: The default priority assigned to reminders without a **PRIORITY**
|
|
clause. You can set this as required to adjust the priorities of
|
|
blocks of reminders without having to type priorities for individual
|
|
reminders. At startup, **\$DefaultPrio** is set to 5000; it can
|
|
range from 0 to 9999.
|
|
|
|
**\$DefaultDelta**
|
|
|
|
: You can set this variable to a number from 0 through 10000. If set
|
|
to a non-zero number, then **Remind** triggers any **REM** statement
|
|
that lacks a delta as if it had a delta of **++\$DefaultDelta**. By
|
|
default, **\$DefaultDelta** is zero.
|
|
|
|
**\$DefaultTDelta**
|
|
|
|
: The default time delta used if no +N is given in an AT clause. This
|
|
is normally 0, but can be set with the **-tt** option or explicitly
|
|
set in your script. If **\$DefaultDelta** is non-zero, you can use
|
|
an explicit delta of +0 in an AT clause to countermand the default
|
|
delta.
|
|
|
|
**\$DeltaOverride (read-only)**
|
|
|
|
: If non-zero, corresponds to the *n* argument given to a **-t**_n_
|
|
command-line option.
|
|
|
|
**\$DontFork (read-only)**
|
|
|
|
: If non-zero, then the **-c** option was supplied on the command
|
|
line.
|
|
|
|
**\$DontTrigAts (read-only)**
|
|
|
|
: The number of times that the **-a** option was supplied on the
|
|
command line.
|
|
|
|
**\$DontQueue (read-only)**
|
|
|
|
: If non-zero, then the **-q** option was supplied on the command
|
|
line.
|
|
|
|
**\$EndSent (STRING type)**
|
|
|
|
: Contains a list of characters that end a sentence. The **MSF**
|
|
keyword inserts two spaces after these characters. Initially,
|
|
**\$EndSent** is set to \".!?\" (period, exclamation mark, and
|
|
question mark.)
|
|
|
|
**\$EndSentIg (STRING type)**
|
|
|
|
: Contains a list of characters that should be ignored when **MSF**
|
|
decides whether or not to place two spaces after a sentence.
|
|
Initially, is set to \"\'\>)\]}\"+CHAR(34) (single-quote,
|
|
greater-than, right parenthesis, right bracket, right brace, and
|
|
double-quote.)
|
|
|
|
> For example, the default values work as follows:
|
|
>
|
|
> MSF He said, "Huh! (Two spaces will follow this.)" Yup.
|
|
>
|
|
> because the final parenthesis and quote are ignored (for the purposes
|
|
> of spacing) when they follow a period.
|
|
|
|
**\$ExpressionTimeLimit**
|
|
|
|
: If set to a non-zero value *n*, than any expression that takes
|
|
longer than *n* seconds to evaluate will be aborted and an error
|
|
returned. This is to prevent maliciously-crafted expressions for
|
|
creating a denial-of-service. In an included file,
|
|
\$ExpressionTimeLimit can only be lowered from its current value. In
|
|
the top-level file, it can be set to any value, including zero to
|
|
disable the time limit.
|
|
|
|
**\$FirstIndent**
|
|
|
|
: The number of spaces by which to indent the first line of a
|
|
**MSF**-type reminder. The default is 0.
|
|
|
|
**\$FoldYear**
|
|
|
|
: The standard Unix library functions may have difficulty dealing with
|
|
dates later than 2037. If this variable is set to 1, then the UTC
|
|
calculations \"fold back\" years later than 2037 before using the
|
|
Unix library functions. For example, to find out whether or not
|
|
daylight saving time is in effect in June, 2077, the year is
|
|
\"folded back\" to 2027, because both years begin on a Friday, and
|
|
both are non-leapyears. The rules for daylight saving time are thus
|
|
presumed to be identical for both years, and the Unix library
|
|
functions can handle 2027. By default, this variable is 0. Set it to
|
|
1 if the sun or UTC functions misbehave for years greater than 2037.
|
|
See also the section \"MACHINES WITH A 32-BIT TIME_T TYPE\"
|
|
|
|
**\$FormWidth**
|
|
|
|
: The maximum width of each line of text for formatting **MSF**-type
|
|
reminders. The default is the width of the terminal in columns,
|
|
minus 8, but clamped at a minimum of 20 and a maximum of 500. If
|
|
standard output is not a terminal, then the default is 72.If an
|
|
**MSF**-type reminder contains a word too long to fit in this width,
|
|
it will not be truncated - the width limit will be ignored.
|
|
|
|
**\$HideCompletedTodos (read-only)**
|
|
|
|
: If non-zero, then the **\--hide-completed-todos** option was
|
|
supplied on the command line.
|
|
|
|
**\$HushMode (read-only)**
|
|
|
|
: If non-zero, then the **-h** option was supplied on the command
|
|
line.
|
|
|
|
**\$IgnoreOnce (read-only)**
|
|
|
|
: If non-zero, then the **-o** option was supplied on the command
|
|
line, or implicitly enabled for some other reason. In this case,
|
|
**ONCE** directives will be ignored.
|
|
|
|
**\$InfDelta (read-only)**
|
|
|
|
: If non-zero, then the **-t** option was supplied on the command
|
|
line, with no *n* argument.
|
|
|
|
**\$IntMax (read-only)**
|
|
|
|
: The largest representable **INT**. On a machine with 32-bit signed
|
|
integers using twos-complement representation, this will be
|
|
2147483647.
|
|
|
|
**\$IntMin (read-only)**
|
|
|
|
: The smallest representable **INT**. On a machine with 32-bit signed
|
|
integers using twos-complement representation, this will be
|
|
-2147483648.
|
|
|
|
**\$Latitude (STRING type)**
|
|
|
|
: The latitude of your location, expressed as a string that is a
|
|
floating-point number. Because **Remind** does not have a native
|
|
floating-point type, we need to express it as a string. \$Latitude
|
|
can range from \"-90.0\" to \"90.0\", with positive numbers
|
|
representing points north of the equator and negative numbers
|
|
representing south. Note that regardless of your locale, \$Latitude
|
|
is always interpreted in the \"C\" locale and as such, the decimal
|
|
point must be a period (\".\").
|
|
|
|
**\$Longitude (STRING type)**
|
|
|
|
: The longitude of your location, expressed as a string that is a
|
|
floating-point number. Because **Remind** does not have a native
|
|
floating-point type, we need to express it as a string. \$Longitude
|
|
can range from \"-180.0\" to \"180.0\", with positive numbers
|
|
representing points east of the Greenwich Meridian and negative
|
|
numbers representing west. Note that regardless of your locale,
|
|
\$Longitude is always interpreted in the \"C\" locale and as such,
|
|
the decimal point must be a period (\".\").
|
|
|
|
For example, the coordinates of the Statue of Liberty in New York
|
|
City are approximately set by:
|
|
|
|
SET $Latitude "40.68933"
|
|
SET $Longitude "-74.04454"
|
|
|
|
**\$LatDeg, \$LatMin, \$LatSec (DEPRECATED)**
|
|
|
|
: These specify the latitude of your location. **\$LatDeg** can range
|
|
from -90 to 90, and the others from -59 to 59. Northern latitudes
|
|
are positive; southern ones are negative. For southern latitudes,
|
|
all three components should be negative. These three variables are
|
|
deprecated; you should use **\$Latitude** instead.
|
|
|
|
**\$Location (STRING type)**
|
|
|
|
: This is a string specifying the name of your location. It is usually
|
|
the name of your town or city. It can be set to whatever you like,
|
|
but good style indicates that it should be kept consistent with the
|
|
latitude and longitude system variables.
|
|
|
|
**\$LongDeg, \$LongMin, \$LongSec (DEPRECATED)**
|
|
|
|
: These specify the longitude of your location. **\$LongDeg** can
|
|
range from -180 to 180. Western longitudes are positive; eastern
|
|
ones are negative. Note that all three components should have the
|
|
same sign: All positive for western longitudes and all negative for
|
|
eastern longitudes. Note that for historical reasons, the sign for
|
|
longitude is *different* from the usual convention! If you find the
|
|
longitude of your location from a search engine, you will most
|
|
likely *need to invert the sign to have it work correctly with*
|
|
Remind. These three variables are deprecated; you should use
|
|
**\$Longitude** instead. Note also that **\$Longitude** uses the
|
|
standard convention of negative for western longitudes and positive
|
|
for eastern ones.
|
|
|
|
The latitude and longitude information is required for the functions
|
|
**sunrise()** and **sunset()**. Default values can be compiled into
|
|
**Remind**, or you can **SET** the correct values at the start of
|
|
your reminder scripts.
|
|
|
|
Note that setting any of **\$LongDec**, **\$LongMin** and
|
|
**\$LongSec** updates **\$Longitude** correspondingly, and setting
|
|
**\$Longitude** updates **\$LongDeg**, **\$LongMin** and
|
|
**\$LongSec**. Similar rules apply to **\$Latitude**, **\$LatDeg**,
|
|
**\$LatMin** and **\$LatSec**.
|
|
|
|
**\$JSONMode (read-only)**
|
|
|
|
: If non-zero, then the **\--json** command-line option was supplied.
|
|
|
|
**\$MaxLateMinutes**
|
|
|
|
: This variable controls how **Remind** reacts to a computer being
|
|
suspended and then woken. Normally, if a timed reminder is queued
|
|
and then the computer suspended, and then the computer is woken
|
|
*after* the timed reminder\'s trigger time, **Remind** will trigger
|
|
the timer anyway, despite the fact that the trigger time has already
|
|
passed.
|
|
|
|
If you set **\$MaxLateMinutes** to a non-zero integer between 1 and
|
|
1440, then **Remind** will *not* trigger a timed reminder whose
|
|
trigger time is more than **\$MaxLateMinutes** minutes in the past.
|
|
|
|
Note that **Remind** uses the value of **\$MaxLateMinutes** that is
|
|
in effect when it has finished reading the reminder file and puts
|
|
itself in the background. Generally, you should set
|
|
**\$MaxLateMinutes** once near the beginning of the file and not
|
|
change it after that.
|
|
|
|
**\$MaxSatIter**
|
|
|
|
: The maximum number of iterations for the **SATISFY** clause
|
|
(described later.) Must be at least 10.
|
|
|
|
**\$MaxStringLen**
|
|
|
|
: A limit on the longest string that **Remind** will allow you to
|
|
create. The default is 65535. If you set **\$MaxStringLen** to 0 or
|
|
to -1, then **remind** will allow you to create arbitrarily-long
|
|
strings, at least until it runs out of memory. We do not recommend
|
|
setting **\$MaxStringLen** to 0 or -1 because it is very easy to
|
|
write code that DOSes **Remind** in that case.
|
|
|
|
**\$MinsFromUTC**
|
|
|
|
: The number of minutes between Universal Time Coordinated and local
|
|
time. If **\$CalcUTC** is non-zero, this is calculated upon startup
|
|
of **Remind**. Otherwise, you must set it explicitly. If
|
|
**\$CalcUTC** is zero, then **\$MinsFromUTC** is used in the
|
|
astronomical calculations. You must adjust it for daylight saving
|
|
time yourself. Also, if you want to initialize **\$MinsFromUTC**
|
|
using the **-i** command-line option, you must also set
|
|
**\$CalcUTC** to 0 with the **-i** option.
|
|
|
|
**\$NextMode (read-only)**
|
|
|
|
: If non-zero, then the **-n** option was supplied on the command
|
|
line.
|
|
|
|
**\$MaxFullOmits (read-only)**
|
|
|
|
: The maximum number of full OMITs allowed (a compiled-in constant.)
|
|
|
|
**\$MaxPartialOmits (read-only)**
|
|
|
|
: The maximum number of partial OMITs allowed (a compiled-in
|
|
constant.)
|
|
|
|
**\$NumFullOmits (read-only)**
|
|
|
|
: The number of full OMITs in the current OMIT context.
|
|
|
|
**\$NumPartialOmits (read-only)**
|
|
|
|
: The number of partial OMITs in the current OMIT context.
|
|
|
|
**\$NumQueued (read-only)**
|
|
|
|
: Contains the number of reminders queued so far for background timed
|
|
triggering.
|
|
|
|
**\$NumTrig (read-only)**
|
|
|
|
: Contains the number of reminders triggered for the current date. One
|
|
use for this variable is as follows: Suppose you wish to shade in
|
|
the box of a PostScript calendar whenever a holiday is triggered.
|
|
You could save the value of **\$NumTrig** in a regular variable
|
|
prior to executing a block of holiday reminders. If the value of
|
|
**\$NumTrig** after the holiday block is greater than the saved
|
|
value, then at least one holiday was triggered, and you can execute
|
|
the command to shade in the calendar box. (See the section
|
|
\"Calendar Mode\".)
|
|
|
|
> Note that **\$NumTrig** is affected *only* by **REM** commands;
|
|
> triggers in **IFTRIG** commands do not affect it.
|
|
|
|
**\$OnceFile (STRING type)**
|
|
|
|
: If you set this variable to a non-empty string, then rather than
|
|
using the file access date to determine whether or not to run a
|
|
ONCE-type reminder, **Remind** will maintain a timestamp in the file
|
|
**\$OnceFile**. This is more reliable than using the access date of
|
|
the reminder file.
|
|
|
|
If **\$OnceFile** does not exist, then it will be created the first
|
|
time a **ONCE** keyword is processed. The file must be writable by
|
|
the current user. If you try to set **\$OnceFile** *after* a
|
|
**ONCE** reminder has already been processed, **Remind** will issue
|
|
a warning and ignore the attempt to set **\$OnceFile**.
|
|
|
|
**\$ParseUntriggered**
|
|
|
|
: A flag indicating whether or not **Remind** should fully parse
|
|
**REM** statements that are not triggered. 0 (the default) means to
|
|
skip parsing them and 1 means to parse them.
|
|
|
|
> For example, if we have the following **REM** statement:
|
|
>
|
|
> REM 2020-01-01 MSG ["bad_expression" / 2]
|
|
>
|
|
> Then if **\$ParseUntriggered** is set to 1, **Remind** will fully
|
|
> parse the line and issue a \"Type mismatch\" error even if the
|
|
> reminder is not triggered. However, if **\$ParseUntriggered** is set
|
|
> to 0, the default, then **Remind** will not issue the error except on
|
|
> 2020-01-01, when the reminder is triggered.
|
|
>
|
|
> Keeping **\$ParseUntriggered** at 0 may slightly improve performance,
|
|
> at the risk of not catching errors until a reminder is triggered. We
|
|
> recommend leaving it set to 0.
|
|
|
|
**\$PrefixLineNo (read-only)**
|
|
|
|
: If non-zero, then the **-l** option was supplied on the command
|
|
line.
|
|
|
|
**\$PSCal (read-only)**
|
|
|
|
: If non-zero, then the **-p** option was supplied on the command
|
|
line.
|
|
|
|
**\$RunOff (read-only)**
|
|
|
|
: If non-zero, the **RUN** directives are disabled.
|
|
|
|
**\$SimpleCal (read-only)**
|
|
|
|
: Set to a non-zero value if *either* of the **-p** or **-s**
|
|
command-line options was supplied.
|
|
|
|
**\$SortByDate (read-only)**
|
|
|
|
: Set to 0 if no **-g** option is used, 1 if sorting by date in
|
|
ascending order, or 2 if sorting by date in descending order.
|
|
|
|
**\$SortByPrio (read-only)**
|
|
|
|
: Set to 0 if no **-g** option is used, 1 if sorting by priority in
|
|
ascending order, or 2 if sorting by priority in descending order.
|
|
|
|
**\$SortByTime (read-only)**
|
|
|
|
: Set to 0 if no **-g** option is used, 1 if sorting by time in
|
|
ascending order, or 2 if sorting by time in descending order.
|
|
|
|
**\$SubsIndent**
|
|
|
|
: The number of spaces by which all lines (except the first) of an
|
|
**MSF**-type reminder should be indented. The default is 0.
|
|
|
|
**\$SuppressImplicitWarnings**
|
|
|
|
: Normally, **Remind** issues a warning if a line begins with an
|
|
unknown token and is treated as a **REM** command, or if a **REM**
|
|
command is missing a type and is treated as a **MSG**-type reminder.
|
|
Setting **\$SuppressImplicitWarnings** to 1 suppresses these
|
|
warnings. The default is 0 and we do not recommend disabling the
|
|
warnings.
|
|
|
|
**\$SuppressLRM**
|
|
|
|
: Normally, when **Remind** is run with the **-c** option in a UTF-8
|
|
locale, it emits a left-to-right mark sequence after printing day
|
|
names or reminders. Some terminals render this incorrectly, so you
|
|
can use:
|
|
|
|
SET $SuppressLRM 1
|
|
|
|
at the top of your reminder file to suppress the LRM sequences, or
|
|
you can invoke **Remind** with the option **\'-i\$SuppressLRM=1\'**.
|
|
|
|
**\$SysInclude (read-only, STRING type)**
|
|
|
|
: A directory path containing standard reminder scripts. Currently,
|
|
**Remind** ships with some standard holiday files and language
|
|
packs. The value of **\$SysInclude** is \"/usr/local/share/remind\"
|
|
on this installation.
|
|
|
|
**\$T (read-only, DATE or INT type)**
|
|
|
|
: Equivalent to **trigdate()**. (See BUILT-IN FUNCTIONS.)
|
|
|
|
**\$Tb (read-only, DATE or INT type)**
|
|
|
|
: Equivalent to **trigbase()**.
|
|
|
|
**\$Td (read-only)**
|
|
|
|
: Equivalent to **day(trigdate())**.
|
|
|
|
**\$Tm (read-only)**
|
|
|
|
: Equivalent to **monnum(trigdate())**.
|
|
|
|
**\$Tu (read-only, DATE or INT type)**
|
|
|
|
: Equivalent to **triguntil()**.
|
|
|
|
**\$Tw (read-only)**
|
|
|
|
: Equivalent to **wkdaynum(trigdate())**.
|
|
|
|
**\$Ty (read-only)**
|
|
|
|
: Equivalent to **year(trigdate())**.
|
|
|
|
**\$Tt (read-only, TIME or INT type)**
|
|
|
|
: Equivalent to **trigtime()**.
|
|
|
|
**\$TimeSep (STRING type)**
|
|
|
|
: This variable can be set only to \":\" or \".\". It holds the
|
|
character used to separate portions of a time when **Remind** prints
|
|
a TIME or DATETIME value.
|
|
|
|
**\$TimetIs64bit (read-only)**
|
|
|
|
: This variable returns 1 if the internal C **time_t** type is at
|
|
least 64 bits long. If it returns 0, then the internal C library is
|
|
unable to represent dates after about 2038, and **Remind** will use
|
|
a workaround to avoid problems. See also the section \"MACHINES WITH
|
|
A 32-BIT TIME_T TYPE\"
|
|
|
|
**\$TodoFilter (read-only)**
|
|
|
|
: If 0, then both events and TODOs are being output. If 1, then the
|
|
**\--only-todos** command-line option was supplied. If 2, then the
|
|
**\--only-events** command-line option was supplied.
|
|
|
|
**\$UntimedFirst (read-only)**
|
|
|
|
: Set to 1 if the **-g** option is used with a fourth sort character
|
|
of \"d\"; set to 0 otherwise.
|
|
|
|
**\$U (read-only, DATE type)**
|
|
|
|
: Exactly equivalent to **today()**. (See BUILT-IN FUNCTIONS.)
|
|
|
|
**\$Ud (read-only)**
|
|
|
|
: Equivalent to **day(today())**.
|
|
|
|
**\$Um (read-only)**
|
|
|
|
: Equivalent to **monnum(today())**.
|
|
|
|
**\$Uw (read-only)**
|
|
|
|
: Equivalent to **wkdaynum(today())**.
|
|
|
|
**\$Uy (read-only)**
|
|
|
|
: Equivalent to **year(today())**.
|
|
|
|
**\$UseVTColors (read-only)**
|
|
|
|
: Set to 1 if the **-@** or **-cc** options were used; 0 otherwise.
|
|
|
|
**\$UseBGVTColors (read-only)**
|
|
|
|
: Set to 1 if the **-@,,1** option was used; 0 otherwise.
|
|
|
|
**\$Use256Colors (read-only)**
|
|
|
|
: Set to 1 if the **-@1** option was used; 0 otherwise.
|
|
|
|
**\$UseTrueColors (read-only)**
|
|
|
|
: Set to 1 if the **-@2** option was used; 0 otherwise.
|
|
|
|
**\$TerminalBackground (read-only)**
|
|
|
|
: Returns -1 if the terminal background color could not be determined,
|
|
0 if it was found to be dark (or was specified as dark with the
|
|
**-@,0** option) or 1 if it was found to be light (or specified as
|
|
light with the **-@,1** option.) The terminal background is
|
|
considered to be \"dark\" if the average of the red, green and blue
|
|
components is at most 85 out of 255, and if the maximum of any
|
|
component is at most 128 out of 255.
|
|
|
|
**\$WarningLevel (STRING type)**
|
|
|
|
: As new versions of **Remind** are released, new warnings may be
|
|
added. If your formerly-fine scripts suddenly start issuing warnings
|
|
when you upgrade **Remind**, then as a *stopgap* measure, you may
|
|
set **\$WarningLevel** to a string of the form *AB*.*CD*.*EF* where
|
|
*AB*, *CD* and *EF* are pairs of decimal digits. This will suppress
|
|
any warnings that were introduced *after* **Remind** version
|
|
*AB*.*CD*.*EF*. If you do not set **\$WarningLevel**, then it
|
|
defaults to the current version of **Remind**, meaning all warnings
|
|
will be issued.
|
|
|
|
For example, if you want the warnings you receive limited to what
|
|
Remind 05.00.00 would have produced, use:
|
|
|
|
SET $WarningLevel "05.00.00"
|
|
|
|
We do *not* recommend setting **\$WarningLevel** as a matter of
|
|
course; you should use it to suppress warnings only for as long as
|
|
it takes for you to fix your remind scripts so they no longer cause
|
|
warnings to be emitted.
|
|
|
|
Note: If any of the calendar modes are in effect, then the values of
|
|
\$Daemon, \$DontFork, \$DontTrigAts, \$DontQueue, \$HushMode,
|
|
\$IgnoreOnce, \$InfDelta, and \$NextMode are not meaningful.
|
|
|
|
# SAVING AND RESTORING VARIABLES
|
|
|
|
Just as with the OMIT context, you can save and restore the values of
|
|
global variables and all (modifiable) system variables. For example:
|
|
|
|
SET a 1
|
|
UNSET b
|
|
|
|
# Save variables
|
|
PUSH-VARS $DefaultColor $AddBlankLines a b
|
|
|
|
SET $DefaultColor "255 0 0"
|
|
SET $AddBlankLines 0
|
|
SET a 3
|
|
SET b 4
|
|
REM MSG Hello
|
|
|
|
# Restore all the variables we pushed earlier
|
|
POP-VARS
|
|
|
|
# Now the changes to $DefaultColor and $AddBlankLines
|
|
# have been undone. Additionally, a is restored to 1
|
|
# and b is unset
|
|
|
|
As you see from the example, PUSH-VARS takes a list of global variable
|
|
names and/or system variable names. You can save the values of any
|
|
*modifiable* system variables and any global variable. You can even push
|
|
global variables that are not set.
|
|
|
|
The POP-VARS command restores the values of all system variables and
|
|
global variables that were pushed by the most recent PUSH-VARS command.
|
|
If you push an undefined global variable, then that variable is unset by
|
|
the POP-VARS command.
|
|
|
|
# BUILT-IN FUNCTIONS
|
|
|
|
**Remind** has a plethora of built-in functions. The syntax for a
|
|
function call is the same as in C - the function name, followed a
|
|
comma-separated list of arguments in parentheses. Function names are not
|
|
case-sensitive. If a function takes no arguments, it must be followed by
|
|
\"()\" in the function call. Otherwise, **Remind** will interpret it as
|
|
a variable name, and probably not work correctly.
|
|
|
|
In the descriptions below, short forms are used to denote acceptable
|
|
types for the arguments. The characters \"i\", \"s\", \"d\", \"t\" and
|
|
\"q\" denote **INT**, **STRING**, **DATE**, **TIME** and **DATETIME**
|
|
arguments, respectively. If an argument can be one of several types, the
|
|
characters are concatenated. For example, \"di_arg\" denotes an argument
|
|
that can be a **DATE** or an **INT**. \"x_arg\" denotes an argument that
|
|
can be of any type. The type of the argument is followed by an
|
|
underscore and an identifier naming the argument.
|
|
|
|
The built-in functions are:
|
|
|
|
**\_(s_message)**
|
|
|
|
: Returns the translation table entry for *message*. If there is no
|
|
such translation table entry, then returns *message* unmodified. For
|
|
example, consider this sequence:
|
|
|
|
TRANSLATE "Goodbye" "Tot ziens"
|
|
SET a _("Goodbye")
|
|
|
|
After those two lines have been executed, the variable **a** will be
|
|
set to \"Tot ziens\". See the section THE TRANSLATION TABLE for more
|
|
information.
|
|
|
|
In the body of a reminder, the substitution sequence
|
|
**%(**_text_**)** is (almost) the equivalent of
|
|
**\[\_(\"**_text_**\")\]**. Therefore, the following reminders are
|
|
almost equivalent:
|
|
|
|
|
|
REM MSG %(Goodbye)
|
|
REM MSG [_("Goodbye")]
|
|
|
|
The only difference is that if \_(\"Goodbye\") contains a **%**
|
|
sign, then that result will be run through the substitution filter,
|
|
whereas in the first reminder, it will not. That is because the
|
|
second **REM** command performs expression pasting followed by a
|
|
substitution filter pass, while the first one performs the
|
|
translation as part of the substitution filter (and does not make a
|
|
second substitution filter pass.)
|
|
|
|
**abs(i_num)**
|
|
|
|
: Returns the absolute value of *num*.
|
|
|
|
**access(s_file, si_mode)**
|
|
|
|
: Tests the access permissions for the file *file*. *Mode* can be a
|
|
string, containing a mix of the characters \"rwx\" for read, write
|
|
and execute permission testing. Alternatively, *mode* can be a
|
|
number as described in the UNIX **access**(2) system call. The
|
|
function returns 0 if the file can be accessed with the specified
|
|
*mode*, and -1 otherwise.
|
|
|
|
**adawn(\[dq_date\])**
|
|
|
|
: Returns the time of \"astronomical dawn\" on the specified *date*.
|
|
If *date* is omitted, defaults to **today()**. If a *datetime*
|
|
object is supplied, only the date component is used.
|
|
|
|
**adusk(\[dq_date\])**
|
|
|
|
: Returns the time of \"astronomical twilight\" on the specified
|
|
*date*. If *date* is omitted, defaults to **today()**.
|
|
|
|
**ampm(tq_time \[,s_am \[,s_pm \[,i_lz\]\]\])**
|
|
|
|
: Returns a **STRING** that is the result of converting *time* (which
|
|
is either a **TIME** or a **DATETIME** object) to \"AM/PM\" format.
|
|
The optional arguments *am* and *pm* are the strings to append in
|
|
the AM and PM case, respectively; they default to \"AM\" and \"PM\".
|
|
The optional argument *lz* specifies whether or not the hour should
|
|
be padded to two digits with a leading zero. If *lz* is zero, then a
|
|
leading 0 is not added; otherwise, the hour is padded out to two
|
|
digits with a leading zero. If not supplied, *lz* defaults to zero.
|
|
|
|
The function obeys the system variables \$DateSep, \$TimeSep and
|
|
\$DateTimeSep when formatting its output. Here are some examples of
|
|
its output:
|
|
|
|
ampm(0:22) returns "12:22AM"
|
|
ampm(17:45, "am", "pm") returns "5:45pm"
|
|
ampm(17:45, "am", "pm", 1) returns "05:45pm"
|
|
ampm('2020-03-14@21:34') returns "2020-03-14@9:34PM"
|
|
|
|
**ansicolor(i_red, i_green, i_blue \[,i_bg \[,i_clamp\]\])**
|
|
|
|
: Returns a **STRING** that contains an ANSI escape sequence for
|
|
changing the terminal text color. The parameters *red*, *green* and
|
|
*blue* are integers from 0 to 255 specifying the value of the
|
|
respective color component. As a special case, all three values can
|
|
be -1, in which case the ANSI sequence \"ESC\[0m\" is returned,
|
|
which resets all text attributes to normal.
|
|
|
|
The string returned by **ansicolor** depends on the color mode that
|
|
**Remind** is running in, as specified by the **-@** option. If
|
|
color mode is not enabled, then **ansicolor** always returns the
|
|
empty string. Otherwise, it returns the escape sequence that best
|
|
approximates the color according to the **-@** color mode.
|
|
|
|
The optional *bg* argument is either 0 or 1. If 0 (the default),
|
|
then the foreground color is set. If 1, then the background color is
|
|
set. Note that setting the background color only works in 256-color
|
|
or true-color mode.
|
|
|
|
The optional *clamp* argument is either 0 or 1. If 0 (the default),
|
|
then colors are not adjusted based on the terminal background color.
|
|
If 1, then **Remind** attempts to adjust dark or bright colors so
|
|
they have enough contrast to be visible in the terminal.
|
|
|
|
The first three arguments may alternatively be specified as a string
|
|
consisting of three space-separated numbers, as in this example:
|
|
\"128 128 0\"
|
|
|
|
As a special case, **ansicolor(\"\")** is equivalent to
|
|
**ansicolor(-1,-1,-1)** and returns the ANSI sequence to reset all
|
|
text attributes to normal.
|
|
|
|
Note that inserting ANSI color sequences in calendar mode *will*
|
|
produce garbled results. Therefore, we recommend defining functions
|
|
such as the ones below that return the empty string in calendar
|
|
mode:
|
|
|
|
IF $CalMode
|
|
FSET fg(r,g,b) ""
|
|
FSET bg(r,g,b) ""
|
|
ELSE
|
|
FSET fg(r,g,b) ansicolor(r,g,b)
|
|
FSET bg(r,g,b) ansicolor(r,g,b,1)
|
|
ENDIF
|
|
REM [fg(255,0,0)][bg(64,64,64)]Red on Gray[fg(-1,-1,-1)] in agenda mode
|
|
REM SPECIAL COLOR 0 255 0 Green in agenda and calendar mode
|
|
|
|
If you use the **ansicolor** function, don\'t forget to reset the
|
|
color back to normal with **ansicolor(-1,-1,-1)** or subsequent
|
|
reminders will continue to be colored.
|
|
|
|
**args(s_fname)**
|
|
|
|
: Returns the number of arguments expected by the user-defined
|
|
function *fname*, or -1 if no such user-defined function exists.
|
|
Note that this function examines only user-defined functions, not
|
|
built-in functions. Its main use is to determine whether or not a
|
|
particular user-defined function has been defined previously. The
|
|
**args()** function is available only in versions of **Remind** from
|
|
03.00.04 and up.
|
|
|
|
**asc(s_string)**
|
|
|
|
: Returns an **INT** that is the ASCII code of the first byte in
|
|
*string*. As a special case, **asc(\"\")** returns 0. For UTF-8
|
|
strings, this will return the UTF-8 byte with which the string
|
|
begins, which is not likely to be very useful.
|
|
|
|
**codepoint(s_string)**
|
|
|
|
: Returns an **INT** that is the code point of the first character in
|
|
*string*, treating multi-byte characters correctly. As a special
|
|
case, **codepoint(\"\")** returns 0.
|
|
|
|
**baseyr()**
|
|
|
|
: Returns the \"base year\" that was compiled into **Remind**
|
|
(normally 1990.) All dates are stored internally as the number of
|
|
days since 1 January of **baseyr()**.
|
|
|
|
**catch(x_arg1, x_arg2)**
|
|
|
|
: Evaluates **arg1** and if no error occurs, returns the resulting
|
|
value. If an error occurs during the evaluation of **arg1**,
|
|
evaluates and returns **arg2**. Note that **catch()** can only catch
|
|
run-time *evaluation* errors. It cannot catch *syntax* errors.
|
|
|
|
Here are some examples:
|
|
|
|
catch(4/2, 33) => 2, because 4/2 evaluates without error
|
|
catch(4/0, 33) => 33, because 4/0 gives a divide-by-zero error
|
|
catch(2, 1/0) => 2, and the second argument is not evaluated
|
|
catch(4/0, 1/0) results in a divide-by-zero error
|
|
|
|
Note in the last example that catch does *not* protect you from
|
|
errors in the evaluation of **arg2**.
|
|
|
|
**catcherr()**
|
|
|
|
: Returns a string representing the error message from the most
|
|
recently-evaluated **catch()** function whose first argument yielded
|
|
an error. Note that the error message is always in English even if
|
|
**Remind** has been localized; this lets you reliably test the
|
|
return value. Here are some examples:
|
|
|
|
# No "catch" invocations yet: sets a to "Ok"
|
|
set a catcherr()
|
|
|
|
# Sets b to "oops" and a to "Division by zero"
|
|
set b catch(1/0, "oops")
|
|
set a catcherr()
|
|
|
|
# Sets b to 1 and a to "Division by zero". The catch error
|
|
# is never cleared by a non-error catch()
|
|
set b catch(4-3, "not-evaluated")
|
|
set a catcherr()
|
|
|
|
**char(i_i1 \[,i_i2\...\])**
|
|
|
|
: This function can take any number of **INT** arguments. It returns a
|
|
**STRING** consisting of the bytes specified by the arguments. It is
|
|
easy to create invalid UTF-8 sequences; **char** does not check for
|
|
this. Note that none of the arguments can be 0, unless there is only
|
|
one argument. As a special case, **char(0)** returns \"\".
|
|
|
|
**mbchar(i_i1 \[,i_i2\...\])**
|
|
|
|
: This function can take any number of **INT** arguments. It returns a
|
|
**STRING** consisting of the characters specified by the arguments.
|
|
Any codepoint may be supplied and a correct multi-byte character
|
|
string will be returned. Note that none of the arguments can be 0,
|
|
unless there is only one argument. As a special case, **mbchar(0)**
|
|
returns \"\". Additionally, no argument may be a negative number.
|
|
|
|
**choose(i_index, x_arg1 \[,x_arg2\...\])**
|
|
|
|
: **Choose** must take at least two arguments, the first of which is
|
|
an **INT**. If *index* is *n*, then the *n*th subsequent argument is
|
|
returned. If *index* is less than 1, then *arg1* is returned. If
|
|
*index* is greater than the number of subsequent arguments, then the
|
|
last argument is returned. Examples:
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
choose(0, "foo", 1:13, 1000) returns "foo"
|
|
choose(1, "foo", 1:13, 1000) returns "foo"
|
|
choose(2, "foo", 1:13, 1000) returns 1:13
|
|
choose(3, "foo", 1:13, 1000) returns 1000
|
|
choose(4, "foo", 1:13, 1000) returns 1000
|
|
|
|
> Note that only the first argument and the chosen result are evaluated.
|
|
> Any non-chosen arguments will not be evaluated.
|
|
|
|
**coerce(s_type, x_arg)**
|
|
|
|
: This function converts *arg* to the specified *type*, if such
|
|
conversion is possible. *Type* must be one of \"INT\", \"STRING\",
|
|
\"DATE\", \"TIME\" or \"DATETIME\" (case-insensitive). The
|
|
conversion rules are as follows:
|
|
|
|
If *arg* is already of the *type* specified, it is returned
|
|
unchanged.
|
|
|
|
If *type* is \"STRING\", then *arg* is converted to a string
|
|
consisting of its printed representation.
|
|
|
|
If *type* is \"DATE\", then an **INT** *arg* is converted by
|
|
interpreting it as the number of days since 1 January **baseyr()**.
|
|
A **STRING** *arg* is converted by attempting to read it as if it
|
|
were a printed date. A **DATETIME** is converted to a date by
|
|
dropping the time component. A **TIME** *arg* cannot be converted to
|
|
a date.
|
|
|
|
If *type* is \"TIME\", then an **INT** *arg* is converted by
|
|
interpreting it as the number of minutes since midnight. A
|
|
**STRING** *arg* is converted by attempting to read it as if it were
|
|
a printed time. A **DATETIME** is converted to a time by dropping
|
|
the date component. A **DATE** *arg* cannot be converted to a time.
|
|
|
|
If *type* is \"DATETIME\", then an **INT** *arg* is converted by
|
|
interpreting it as the number of minutes since midnight, 1 January
|
|
**baseyr()**. A **STRING** is converted by attempting to read it as
|
|
if it were a printed datetime. Other types cannot be converted to a
|
|
datetime.
|
|
|
|
If *type* is \"INT\", then **DATE**, **TIME** and **DATETIME**
|
|
arguments are converted using the reverse of procedures described
|
|
above. A **STRING** *arg* is converted by parsing it as an integer.
|
|
|
|
**columns(\[s_arg\])**
|
|
|
|
: If called with no arguments, **columns()** behaves as follows: If
|
|
standard output is a TTY, returns the width of the terminal in
|
|
columns. If standard output is not a TTY, attempts to open
|
|
\"/dev/tty\" to obtain the terminal size. If this fails, returns -1.
|
|
|
|
If called with a single string argument, **columns(str)** returns
|
|
the number of columns **str** will occupy if printed to a terminal.
|
|
ANSI color-changing sequences occupy zero columns whereas some
|
|
Unicode characters occupy two columns. **columns(str)** takes all of
|
|
that into account. Note that if **Remind** was compiled without
|
|
Unicode support, **columns(str)** returns a type mismatch error.
|
|
|
|
The result of **columns(str)** may be less than, equal to, or
|
|
greater than the result of **mbstrlen(str)**. This is because some
|
|
Unicode characters are so-called combining characters that add one
|
|
to the character length, but don\'t occupy any columns on their own.
|
|
And other Unicode characters are double-width characters that add
|
|
one to the character length, but two to the number of display
|
|
columns.
|
|
|
|
**const(x_arg)**
|
|
|
|
: Evaluates *arg* and returns it, but also ensures that the result is
|
|
marked \"constant\". Use with caution; incorrect use could result in
|
|
unwanted reminders being purged in Purge Mode. See also the section
|
|
\"NON-CONSTANT EXPRESSIONS\"
|
|
|
|
**current()**
|
|
|
|
: Returns the current date and time as a DATETIME object. This may be
|
|
the actual date and time, or may be the date and time supplied on
|
|
the command line.
|
|
|
|
**date(i_y, si_m, i_d)**
|
|
|
|
: The **date()** function returns a **DATE** object with the year,
|
|
month and day components specified by *y*, *m* and *d*. The month
|
|
can be specified as an integer from 1 to 12, or a string that is the
|
|
name of a month.
|
|
|
|
**datepart(dq_datetime)**
|
|
|
|
: Returns a **DATE** object representing the date portion of
|
|
*datetime*.
|
|
|
|
**datetime(args)**
|
|
|
|
: The **datetime()** function can take anywhere from two to five
|
|
arguments. It always returns a DATETIME generated from its
|
|
arguments.
|
|
|
|
If you supply two arguments, the first must be a DATE and the second
|
|
a TIME.
|
|
|
|
If you supply three arguments, the first must be a DATE and the
|
|
second and third must be INTs. The second and third arguments are
|
|
interpreted as hours and minutes and converted to a TIME.
|
|
|
|
If you supply four arguments, they are interpreted as year, month,
|
|
day and time. Year and day must be INTs. Month may be an INT from 0
|
|
to 12 or a string naming a month. Time must be a TIME.
|
|
|
|
Finally, if you supply five arguments, they must all be INTs and are
|
|
interpreted as year, month, day, hour and minute. (Actually, month
|
|
can also be a string that is the name of a month.)
|
|
|
|
**dawn(\[dq_date\])**
|
|
|
|
: Returns the time of \"civil dawn\" on the specified *date*. If
|
|
*date* is omitted, defaults to **today()**. If a *datetime* object
|
|
is supplied, only the date component is used.
|
|
|
|
**day(dq_date)**
|
|
|
|
: This function takes a **DATE** or **DATETIME** as an argument, and
|
|
returns an **INT** that is the day-of-month component of *date*.
|
|
|
|
**daysinmon(si_m, i_y) or daysinmon(dq_date)**
|
|
|
|
: Returns the number of days in month *m* (1-12) of the year *y*. The
|
|
first argument can either be an integer from 1 to 12, or a string
|
|
that is the name of a month. If given a single DATE or DATETIME
|
|
argument, returns the number of days in the month containing the
|
|
argument.
|
|
|
|
**defined(s_var)**
|
|
|
|
: Returns 1 if the variable named by *var* is defined, or 0 if it is
|
|
not.
|
|
|
|
Note that **defined()** takes a **STRING** argument; thus, to check
|
|
if variable X is defined, use:
|
|
|
|
defined("X")
|
|
|
|
and not:
|
|
|
|
defined(X)
|
|
|
|
The second example will attempt to evaluate X, and will return an
|
|
error if it is undefined or not of type **STRING**.
|
|
|
|
**dosubst(s_str \[,d_date \[,t_time\]\]) or dosubst(s_str \[,q_datetime\])**
|
|
|
|
: Returns a **STRING** that is the result of passing *str* through the
|
|
substitution filter described earlier. The parameters *date* and
|
|
*time* (or *datetime*) establish the effective trigger date and time
|
|
used by the substitution filter. If *date* and *time* are omitted,
|
|
they default to **today()** and **now()**.
|
|
|
|
Note that if *str* does not end with \"%\", a newline character will
|
|
be added to the end of the result. Also, calling **dosubst()** with
|
|
a *date* that is in the past (i.e., if *date* \< **today()**) will
|
|
produce undefined results.
|
|
|
|
**Dosubst()** is only available starting from version 03.00.04 of
|
|
**Remind**.
|
|
|
|
**dusk(\[dq_date\])**
|
|
|
|
: Returns the time of \"civil twilight\" on the specified *date*. If
|
|
*date* is omitted, defaults to **today()**.
|
|
|
|
**easterdate(\[dqi_arg\])**
|
|
|
|
: If *arg* is an **INT**, then returns the date of Easter Sunday for
|
|
the specified year. If *arg* is a **DATE** or **DATETIME**, then
|
|
returns the date of the next Easter Sunday on or after *arg*. (The
|
|
time component of a datetime is ignored.) If *arg* is omitted, then
|
|
it defaults to **today()**.
|
|
|
|
Note that **easterdate** computes the Western Easter. For the
|
|
Orthodox Easter date, see **orthodoxeaster**.
|
|
|
|
**escape(s_string \[,i_add_quotes\])**
|
|
|
|
: Returns a **STRING** that is the same as the input string, but with
|
|
all special characters backslashed-escaped. For example, the
|
|
following command:
|
|
|
|
set a escape("foo" + char(10) + "bar")
|
|
|
|
will set a to \"foo\\nbar\" where \"\\n\" is the literal sequence
|
|
\"\\\" followed by \"n\". This is useful if you want to compute a
|
|
string in a pasted-in expression that **Remind** will then parse as
|
|
a quoted string again, such as in a TRANSLATE command or an INFO
|
|
clause.
|
|
|
|
If the optional *add_quotes* argument is supplied and is non-zero,
|
|
then the return value from **escape** will include surrounding
|
|
double-quotes.
|
|
|
|
**eval(s_arg)**
|
|
|
|
: Parses the string *arg* as an expression and evaluates it, returning
|
|
the result. Note that any variable names in the parsed expression
|
|
refer to global variables, not any local variables. For example,
|
|
consider this:
|
|
|
|
> SET x 2
|
|
> FSET f(x) x + eval("1 + x")
|
|
> REM MSG F is [f(9)]
|
|
>
|
|
> The result will be \"F is 12\" because the reference to *x* inside the
|
|
> **eval()** argument refers to the *global* variable *x* and not the
|
|
> function argument.
|
|
>
|
|
> Note that for safety, **RUN** is disabled during the evaluation of
|
|
> **eval()**, which means you can\'t use the **shell()** function from
|
|
> within an **eval()**.
|
|
|
|
**evaltrig(s_trigger \[,dq_start\])**
|
|
|
|
: Evaluates *trigger* as if it were a REM or IFTRIG trigger
|
|
specification and returns the trigger date as a **DATE** (or as a
|
|
**DATETIME** if there is an **AT** clause.) Returns a negative
|
|
**INT** if no trigger could be computed.
|
|
|
|
Normally, **evaltrig** finds a trigger date on or after today. If
|
|
you supply the *start* argument, then it scans starting from there.
|
|
|
|
For example, the expression:
|
|
|
|
evaltrig("Mon 1", '2008-10-07')
|
|
|
|
returns \'2008-11-03\', since that is the first date on or after 7
|
|
October 2008 that satisfies \"Mon 1\".
|
|
|
|
If you want to see how many days it is from the first Monday in
|
|
October, 2008 to the first Monday in November, 2008, use:
|
|
|
|
evaltrig("Mon 1", '2008-11-01') - evaltrig("Mon 1", '2008-10-01')
|
|
|
|
and the answer is 28. The trigger argument to **evaltrig** can have
|
|
all the usual trigger clauses (**OMIT**, **AT**, **SKIP**, etc.) but
|
|
*cannot* have a **SATISFY**, **MSG**, etc. reminder-type clause.
|
|
|
|
**filedate(s_filename)**
|
|
|
|
: Returns the modification date of *filename*. If *filename* does not
|
|
exist, or its modification date is before the year **baseyr()**,
|
|
then 1 January of **baseyr()** is returned.
|
|
|
|
**filedatetime(s_filename)**
|
|
|
|
: Returns the modification date and time of *filename*. If *filename*
|
|
does not exist, or its modification date is before the year
|
|
**baseyr()**, then midnight, 1 January of **baseyr()** is returned.
|
|
|
|
**filedir()**
|
|
|
|
: Returns the directory that contains the current file being
|
|
processed. It may be a relative or absolute pathname, but is
|
|
guaranteed to be correct for use in an **INCLUDE** command as
|
|
follows:
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
INCLUDE [filedir()]/stuff
|
|
|
|
> This includes the file \"stuff\" in the same directory as the current
|
|
> file being processed. Note that this workaround is no longer necessary
|
|
> because **DO stuff** will achieve the same goal.
|
|
>
|
|
> Note that if the currently-processing reminders file was specified as
|
|
> a symbolic link, then **filedir()** returns the directory containing
|
|
> the symbolic link and *not* the directory containing the target of the
|
|
> symbolic link. You should avoid using symbolic links to files unless
|
|
> both the symbolic link and its target happen to be in the same
|
|
> directory.
|
|
|
|
**filename()**
|
|
|
|
: Returns (as a **STRING**) the name of the current file being
|
|
processed by **Remind**. Inside included files, returns the name of
|
|
the included file.
|
|
|
|
**getenv(s_envvar)**
|
|
|
|
: Similar to the **getenv**(2) system call. Returns a string
|
|
representing the value of the specified environment variable.
|
|
Returns \"\" if the environment variable is not defined. Note that
|
|
the names of environment variables are generally case-sensitive;
|
|
thus, getenv(\"HOME\") is not the same as getenv(\"home\").
|
|
|
|
**hebdate(i_day, s_hebmon \[,idq_yrstart \[,i_jahr \[,i_aflag\]\]\])**
|
|
|
|
: Support for Hebrew dates - see the section \"THE HEBREW CALENDAR\"
|
|
|
|
**hebday(dq_date)**
|
|
|
|
: Support for Hebrew dates - see the section \"THE HEBREW CALENDAR\"
|
|
|
|
**hebmon(dq_date)**
|
|
|
|
: Support for Hebrew dates - see the section \"THE HEBREW CALENDAR\"
|
|
|
|
**hebyear(dq_date)**
|
|
|
|
: Support for Hebrew dates - see the section \"THE HEBREW CALENDAR\"
|
|
|
|
**hex(i_n)**
|
|
|
|
: Returns a **STRING** that is the hexadecimal representation of *n*.
|
|
There is no \"0x\" prefix and any letters in the returned value are
|
|
uppper-case.
|
|
|
|
**hour(tq_time)**
|
|
|
|
: Returns the hour component of *time*.
|
|
|
|
**htmlescape(s_str)**
|
|
|
|
: Returns a modified copy of *str* where \"\<\" is replaced with
|
|
\"<\"; \"\>\" is replaced with \">\" and \"&\" is replaced
|
|
with \"&\"
|
|
|
|
**htmlstriptags(s_str)**
|
|
|
|
: Returns a modified copy of *str* where HTML tags are stripped out.
|
|
The stripping algorithm is fairly naive; the function starts
|
|
stripping characters when it encounters a \"\<\" and it stops
|
|
stripping when it encounters a \"\>\".
|
|
|
|
**iif(x_test1, x_arg1, \[x_test2, x_arg2,\...\], x_default)**
|
|
|
|
: If *test1* is true, returns *arg1*. Otherwise, if *test2* is true,
|
|
returns *arg2*, and so on. If all of the *test* arguments are false,
|
|
returns *default*. Note that only those arguments needed to
|
|
determine the final result are evaluated. This function accepts an
|
|
odd number of arguments - note that prior to version 03.00.05 of
|
|
**Remind**, it accepted 3 arguments only. The 3-argument version of
|
|
**iif()** is compatible with previous versions of **Remind**.
|
|
|
|
**index(s_search, s_target \[,i_start)**
|
|
|
|
: Returns an **INT** that is the location of *target* in the string
|
|
*search*. Note that **index** uses *byte* positions, not character
|
|
positions, so should not be used on non-ASCII strings. Use
|
|
**mbindex** for non-ASCII strings.
|
|
|
|
The first byte of a string is numbered 1. If *target* does not exist in
|
|
*search*, then 0 is returned.
|
|
|
|
> The optional parameter *start* specifies the position in *search* at
|
|
> which to start looking for *target*.
|
|
|
|
**mbindex(s_search, s_target \[,i_start\])**
|
|
|
|
: Similar to **index()** but returns the *character* position rather
|
|
than the *byte* position. Also, *start* is interpreted as a 1-based
|
|
character index rather than a byte index.
|
|
|
|
**isany(arg1 \[,arg2, \..., argN\]);**
|
|
|
|
: Returns 1 if the first argument *arg1* is equal to any of the
|
|
subsequent arguments *arg2* through *argN*; returns 0 otherwise.
|
|
Also returns 0 if called with only one argument.
|
|
|
|
As an example, the following two expressions are equivalent:
|
|
|
|
(a == b) || (a == c) || (a == d) || (a == e)
|
|
|
|
isany(a, b, c, d, e)
|
|
|
|
**isconst(x_any)**
|
|
|
|
: Evaluates its argument and then *throws away* the value, returning 1
|
|
if the expression is constant or 0 if it is non-constant. Note that
|
|
**isconst** does not take into account the context; if *arg* is a
|
|
constant expression but evaluated in a non-constant context,
|
|
**isconst** will still return 1. For details about constant vs.
|
|
non-constant expressions, see the section \"NON-CONSTANT
|
|
EXPRESSIONS\"
|
|
|
|
**isdst(\[d_date \[,t_time\]\]) or isdst(q_datetime)**
|
|
|
|
: Returns a positive number if daylight saving time is in effect on
|
|
the specified date and time. *Date* defaults to **today()** and
|
|
*time* defaults to midnight.
|
|
|
|
Note that this function is only as reliable as the C run-time
|
|
library functions. It is available starting with version 03.00.07 of
|
|
**Remind**.
|
|
|
|
**isleap(idq_arg)**
|
|
|
|
: Returns 1 if *arg* is a leap year, and 0 otherwise. *Arg* can be an
|
|
**INT**, **DATE** or **DATETIME** object. If a **DATE** or
|
|
**DATETIME** is supplied, then the year component is used in the
|
|
test.
|
|
|
|
**isomitted(dq_date)**
|
|
|
|
: Returns 1 if *date* is omitted, given the current global **OMIT**
|
|
context. Returns 0 otherwise. (If a datetime is supplied, only the
|
|
date part is used.) Note that any local **OMIT** or **OMITFUNC**
|
|
clauses are *not* taken into account by this function.
|
|
|
|
**language()**
|
|
|
|
: Returns a **STRING** naming the compiled-in language supported by
|
|
**Remind**. **Remind** used to support compiled-in support for other
|
|
languages, but now all localization is done at run-time. As such,
|
|
this function always returns \"English\". However, the expression
|
|
**\_(\"LANGID\")** returns the two-character ISO 639 language code
|
|
of any language pack in effect, assuming the language pack author
|
|
has written the localization correctly!
|
|
|
|
**localtoutc(q_datetime)**
|
|
|
|
: Given a **DATETIME** object interpreted in the local time zone,
|
|
return a **DATETIME** object that expresses the same time in UTC.
|
|
|
|
**lower(s_string)**
|
|
|
|
: Returns a **STRING** with all upper-case characters in *string*
|
|
converted to lower-case.
|
|
|
|
**max(x_arg1 \[,x_arg2\...)**
|
|
|
|
: Can take any number of arguments, and returns the maximum. The
|
|
arguments can be of any type, but must all be of the same type. They
|
|
are compared as with the \> operator.
|
|
|
|
**min(x_arg1 \[,x_arg2\...)**
|
|
|
|
: Can take any number of arguments, and returns the minimum. The
|
|
arguments can be of any type, but must all be of the same type. They
|
|
are compared as with the \< operator.
|
|
|
|
**minsfromutc(\[d_date \[,t_time\]\]) or minsfromutc(q_datetime)**
|
|
|
|
: Returns the number of minutes from Universal Time Coordinated
|
|
(formerly GMT) to local time on the specified date and time. *Date*
|
|
defaults to **today()** and *time* defaults to midnight. If local
|
|
time is before UTC, the result is negative. Otherwise, the result is
|
|
positive.
|
|
|
|
Note that this function is only as reliable as the C run-time
|
|
library functions. It is available starting with version 03.00.07 of
|
|
**Remind**.
|
|
|
|
**minute(tq_time)**
|
|
|
|
: Returns the minute component of *time*.
|
|
|
|
**mon(dqis_arg)**
|
|
|
|
: If *arg* is of **DATE** or **DATETIME** type, returns a string that
|
|
names the month component of the date. If *arg* is an **INT** from 1
|
|
to 12, returns a string that names the month. If *arg* is a
|
|
**STRING**, returns the name of the month. This last case might
|
|
sound silly, but for example:
|
|
|
|
mon("Mar")
|
|
|
|
will return \"March\", the full name of the month.
|
|
|
|
**monnum(dq_date)** or **monnum(s_str)**
|
|
|
|
: Returns an **INT** from 1 to 12, representing the month component of
|
|
*date*. If a **STRING** is supplied rather than a **DATE** or
|
|
**DATETIME**, then if *str* is a valid month name (or minimum
|
|
3-character abbreviation of a month name) then the corresponding
|
|
month number is returned. If *str* is not a valid month name, then
|
|
an error occurs.
|
|
|
|
**moondate(i_phase \[,d_date \[,t_time\]\]) or moondate(i_phase, q_datetime)**
|
|
|
|
: This function returns the date of the first occurrence of the phase
|
|
*phase* of the moon on or after *date* and *time*. *Phase* can range
|
|
from 0 to 3, with 0 signifying new moon, 1 first quarter, 2 full
|
|
moon, and 3 third quarter. If *date* is omitted, it defaults to
|
|
**today()**. If *time* is omitted, it defaults to midnight.
|
|
|
|
For example, the following returns the date of the next full moon:
|
|
|
|
SET fullmoon moondate(2)
|
|
|
|
**moontime(i_phase \[,d_date \[,t_time\]\]) or moontime(i_phase, q_datetime)**
|
|
|
|
: This function returns the time of the first occurrence of the phase
|
|
*phase* of the moon on or after *date* and *time*. *Phase* can range
|
|
from 0 to 3, with 0 signifying new moon, 1 first quarter, 2 full
|
|
moon, and 3 third quarter. If *date* is omitted, it defaults to
|
|
**today()**. If *time* is omitted, it defaults to midnight.
|
|
**Moontime()** is intended to be used in conjunction with
|
|
**moondate()**. The **moondate()** and **moontime()** functions are
|
|
accurate to within a couple of minutes of the times in \"Old
|
|
Farmer\'s Almanac\" for Ottawa, Ontario.
|
|
|
|
For example, the following returns the date and time of the next
|
|
full moon:
|
|
|
|
MSG Next full moon at [moontime(2)] on [moondate(2)]
|
|
|
|
**moondatetime(i_phase \[,d_date \[,t_time\]\]) or moondatetime(i_phase, q_datetime)**
|
|
|
|
: This function is similar to **moondate** and **moontime**, but
|
|
returns a DATETIME result.
|
|
|
|
**moonphase(\[d_date \[,t_time\]\]) or moonphase(q_datetime)**
|
|
|
|
: This function returns the phase of the moon on *date* and *time*,
|
|
which default to **today()** and midnight, respectively. The
|
|
returned value is an integer from 0 to 359, representing the phase
|
|
of the moon in degrees. 0 is a new moon, 180 is a full moon, 90 is
|
|
first-quarter, etc.
|
|
|
|
**moonrise(\[d_date\])**
|
|
|
|
: This function returns a DATETIME result giving the date and time of
|
|
the first moonrise on or after midnight on *date*. If *date* is not
|
|
supplied, it defaults to **today()**.
|
|
|
|
Note that it is not uncommon for a day to have no moonrise, so the
|
|
date part of the return value may not be the same as the *date*
|
|
argument. So if you want a calendar of moonrise times, you could use
|
|
something like this:
|
|
|
|
SET mr moonrise()
|
|
IF datepart(mr) == today()
|
|
REM NOQUEUE [mr] MSG Moon rises at %3.
|
|
ELSE
|
|
REM MSG No moonrise today
|
|
ENDIF
|
|
|
|
**moonrisedir(\[d_date\])**
|
|
|
|
: This function returns an INT result giving the direction from which
|
|
the moon will rise on the first moonrise on or after midnight on
|
|
*date*. If *date* is not supplied, it defaults to **today()**. The
|
|
return value ranges from 0 to 359, where 0 is North, 90 is East, 180
|
|
is South and 270 is West.
|
|
|
|
**moonset(\[d_date\])**
|
|
|
|
: This function is analogous to **moonrise()** but returns the
|
|
DATETIME of the next moonset on or after midnight on *date*.
|
|
|
|
**moonsetdir(\[d_date\])**
|
|
|
|
: This function is analogous to **moonrisedir()** but returns the
|
|
direction of moonset.
|
|
|
|
**multitrig(s_trig1 \[,s_trig2, \[\... s_trigN\]\])**
|
|
|
|
: **multitrig** evaluates each string as a trigger, similar to
|
|
**evaltrig**, and returns the *earliest* trigger date that is on or
|
|
after **today()**. **multitrig** is similar to **trig** but has the
|
|
following difference:
|
|
|
|
**trig** returns the *first* trigger date that would have triggered
|
|
today, whereas **multitrig** returns the *earliest* trigger date
|
|
later than today, regardless of whether it would have triggered
|
|
today.
|
|
|
|
If no trigger can be computed that is later than **today()**, then
|
|
**multitrig** returns 1990-01-01.
|
|
|
|
Consider the following examples, assuming that today is Sunday, 24
|
|
March 2024:
|
|
|
|
# Returns 1990-01-01 because neither would trigger today
|
|
SET a trig("Mon", "Wed")
|
|
|
|
# Returns 2024-03-25 because it's the earlier trigger date
|
|
SET a multitrig("Mon", "Wed")
|
|
|
|
# Returns 2024-03-27 because it's the first that would trigger today
|
|
SET a trig("Wed +3", "Mon +3")
|
|
|
|
# Returns 2024-03-25 because it's the earlier trigger date
|
|
SET a multitrig("Wed +3", "Mon +3")
|
|
|
|
# Returns 1990-01-01 because all triggers have expired
|
|
SET a multitrig("2000", "2022", "1998", "2023")
|
|
|
|
In general, **multitrig** works better with the **Remind** algorithm
|
|
than **trig** and should be used most of the time. As an example,
|
|
this reminder is issued at the end of each quarter:
|
|
|
|
REM [multitrig("Mar 31", "Jun 30", "Sep 30", "Dec 31")] +7 MSG \
|
|
%"End of [ord($Tm/3)] quarter%" is %b.
|
|
|
|
If you want the last working day of each quarter, you could use:
|
|
|
|
PUSH-OMIT-CONTEXT
|
|
OMIT Sat Sun
|
|
REM [multitrig("Mar ~1", "Jun ~1", "Sep ~1", "Dec ~1")] +7 MSG \
|
|
%"Last working day of [ord($Tm/3)] quarter%" is %b.
|
|
POP-OMIT-CONTEXT
|
|
|
|
Note that unlike **evaltrig**, **multitrig** always returns a
|
|
**DATE** and never a **DATETIME**. Including an **AT** clause in a
|
|
trigger supplied to **multitrig** will result in an error.
|
|
|
|
**ndawn(\[dq_date\])**
|
|
|
|
: Returns the time of \"nautical dawn\" on the specified *date*. If
|
|
*date* is omitted, defaults to **today()**. If a *datetime* object
|
|
is supplied, only the date component is used.
|
|
|
|
**ndusk(\[dq_date\])**
|
|
|
|
: Returns the time of \"nautical twilight\" on the specified *date*.
|
|
If *date* is omitted, defaults to **today()**.
|
|
|
|
**nonomitted(dq_start, dq_end \[, i_step\] \[,s_wkday\...\])**
|
|
|
|
: This function returns the number of *non-*omitted days between
|
|
*start* and *end*. If *start* is non-omitted, then it is counted.
|
|
*end* is never counted.
|
|
|
|
Note that if *end* is less than *start*, the arguments are
|
|
effectively swapped, so counting always begins from the older date.
|
|
|
|
If the third argument to **nonomitted** is an **INT**, then it must
|
|
be greater than zero, and is considered to be the *step* by which
|
|
**nonomitted** counts. For example the following expression:
|
|
|
|
nonomitted('2023-07-01', '2023-07-29', 7)
|
|
|
|
returns the number of non-omitted Saturdays from 2023-07-01 up to
|
|
(but not including) 2023-07-29. (Both 2023-07-01 and 2023-07-29 are
|
|
Saturdays.)
|
|
|
|
If no *step* argument is supplied, then a step of 1 is used.
|
|
|
|
In addition to using the global OMIT context, you can supply
|
|
additional arguments that are names of weekdays to be omitted.
|
|
However, in a **REM** command, any local **OMITFUNC** clause is
|
|
*not* taken into account by this function.
|
|
|
|
For example, the following line sets a to 11 (assuming no global
|
|
OMITs):
|
|
|
|
set a nonomitted('2007-08-01', '2007-08-16', "Sat", "Sun")
|
|
|
|
because Thursday, 16 August 2007 is the 11th working day (not
|
|
counting Saturday and Sunday) after Wednesday, 1 August 2007.
|
|
|
|
**nonomitted** has various uses. For example, many schools run on a
|
|
six-day cycle and the day number is not incremented on holidays.
|
|
Suppose the school year starts with Day 1 on 4 September 2007. The
|
|
following reminder will label day numbers in a calendar:
|
|
|
|
IF today() >= '2007-09-04'
|
|
set daynum nonomitted('2007-09-04', today(), "Sat", "Sun")
|
|
REM OMIT SAT SUN SKIP CAL Day [(daynum % 6) + 1]
|
|
ENDIF
|
|
|
|
Obviously, the answer you get from **nonomitted** depends on the
|
|
global OMIT context. If you use movable OMITs, you may get
|
|
inconsistent results.
|
|
|
|
Here is a more complex use for **nonomitted**. My garbage collection
|
|
follows two interleaved 14-day cycles: One Friday, garbage and paper
|
|
recycling (\"Black Box\") are collected. The next Friday, garbage
|
|
and plastic recycling (\"Blue Box\") are collected. If any of
|
|
Monday-Friday is a holiday, collection is delayed until the
|
|
Saturday. Here\'s a way to encode these rules:
|
|
|
|
fset _garbhol(x) wkdaynum(x) == 5 && nonomitted(x-4, x+1) < 5
|
|
REM 12 November 1999 *14 AFTER OMITFUNC _garbhol MSG Black Box
|
|
REM 19 November 1999 *14 AFTER OMITFUNC _garbhol MSG Blue Box
|
|
|
|
Here\'s how it works: The \_garbhol(x) user-defined function returns
|
|
1 if and only if (1) *x* is a Friday and (2) there is at least one
|
|
OMITted day from the previous Monday up to and including the Friday.
|
|
|
|
The first REM statement sets up the 14-day black-box cycle. The
|
|
AFTER keyword makes it move collection to the Saturday if \_garbhol
|
|
returns 1. The second REM statement sets up the 14-day blue-box
|
|
cycle with a similar adjustment made by AFTER in conjunction with
|
|
\_garbhol.
|
|
|
|
**nonconst(x_arg)**
|
|
|
|
: Returns the argument *arg* unchanged, but forces the expression to
|
|
be considered *non-constant*. For details, see the section
|
|
\"NON-CONSTANT EXPRESSIONS\"
|
|
|
|
**now()**
|
|
|
|
: Returns the current system time, as a **TIME** type. This may be the
|
|
actual time, or a time supplied on the command line.
|
|
|
|
**ord(i_num)**
|
|
|
|
: Returns a string that is the ordinal number *num*. For example,
|
|
**ord(2)** returns \"2nd\", and **ord(213)** returns \"213th\".
|
|
|
|
In order to help with localization, if you define a function called
|
|
**ordx** that takes a single parameter, then calling **ord**(*n*)
|
|
invokes **ordx**(*n*) and returns whatever it does. During the
|
|
callback to **ordx**, **RUN** will be disabled.
|
|
|
|
**orthodoxeaster(\[dqi_arg\])**
|
|
|
|
: If *arg* is an **INT**, then returns the date of Orthodox Easter
|
|
Sunday for the specified year. If *arg* is a **DATE** or
|
|
**DATETIME**, then returns the date of the next Orthodox Easter
|
|
Sunday on or after *arg*. (The time component of a datetime is
|
|
ignored.) If *arg* is omitted, then it defaults to **today()**.
|
|
|
|
Note that **orthodoxeaster** computes the Orthodox Easter. For the
|
|
Western Easter date, see **easterdate**.
|
|
|
|
**ostype()**
|
|
|
|
: Returns \"UNIX\". **Remind** used to run on OS/2 and MS-DOS, but
|
|
does not any longer.
|
|
|
|
**pad(x_arg, s_padstr, i_len \[, i_right\])**
|
|
|
|
: Converts the first argument *arg* to a string if necessary, and then
|
|
if it is shorter than *len* characters, pads to to *len* characters
|
|
using as many copies (including partial copies) of *padstr* as
|
|
necessary. By default, the string is left-padded, but if *right* is
|
|
supplied and non-zero, the string will be right-padded.
|
|
|
|
Here are some examples:
|
|
|
|
pad(3, "0", 2) --> "03"
|
|
pad(465, "0", 2) --> "465"
|
|
pad("foo", " ", 5) --> " foo"
|
|
pad("foo", " ", 5, 1) --> "foo "
|
|
pad("foo", "bar", 11) --> "barbarbafoo"
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
|
|
**plural(i_num \[,s_str1 \[,s_str2\]\])**
|
|
|
|
: Can take from one to three arguments. If one argument is supplied,
|
|
returns \"s\" if *num* is not 1, and \"\" if *num* is 1.
|
|
|
|
If two arguments are supplied, returns *str1* + \"s\" if *num* is
|
|
not 1. Otherwise, returns *str1*.
|
|
|
|
If three arguments are supplied, returns *str1* if *num* is 1, and
|
|
*str2* otherwise.
|
|
|
|
**psmoon(i_phase \[,i_size \[,s_note \[,i_notesize\]\]\])**
|
|
|
|
: \[DEPRECATED\] Returns a **STRING** consisting of PostScript code to
|
|
draw a moon in the upper-left hand corner of the calendar box.
|
|
*Phase* specifies the phase of the moon, and is 0 (new moon), 1
|
|
(first quarter), 2 (full moon) or 3 (third quarter). If *size* is
|
|
specified, it controls the radius of the moon in PostScript units
|
|
(1/72 inch.) If it is not specified or is negative, the size of the
|
|
day-number font is used.
|
|
|
|
> For example, the following four lines place moon symbols on the
|
|
> PostScript calendar:
|
|
>
|
|
> REM [moondate(0)] PS [psmoon(0)]
|
|
> REM [moondate(1)] PS [psmoon(1)]
|
|
> REM [moondate(2)] PS [psmoon(2)]
|
|
> REM [moondate(3)] PS [psmoon(3)]
|
|
>
|
|
> If *note* is specified, the text is used to annotate the moon display.
|
|
> The font is the same font used for calendar entries. If *notesize* is
|
|
> given, it specifies the font size to use for the annotation, in
|
|
> PostScript units (1/72 inch.) If *notesize* is not given, it defaults
|
|
> to the size used for calendar entries. (If you annotate the display,
|
|
> be careful not to overwrite the day number \-- **Remind** does not
|
|
> check for this.) For example, if you want the time of each new moon
|
|
> displayed, you could use this in your reminder script:
|
|
>
|
|
> REM [moondate(0)] PS [psmoon(0, -1, moontime(0)+"")]
|
|
>
|
|
> Note how the time is coerced to a string by concatenating the null
|
|
> string.
|
|
|
|
**psshade(i_gray)** or **psshade(i_red, i_green, i_blue)**
|
|
|
|
: \[DEPRECATED\] Returns a **STRING** that consists of PostScript
|
|
commands to shade a calendar box. *Num* can range from 0 (completely
|
|
black) to 100 (completely white.) If three arguments are given, they
|
|
specify red, green and blue intensity from 0 to 100. Here\'s an
|
|
example of how to use this:
|
|
|
|
REM Sat Sun PS [psshade(95)]
|
|
|
|
The above command emits PostScript code to lightly shade the boxes
|
|
for Saturday and Sunday in a PostScript calendar.
|
|
|
|
Note that **psmoon** and **psshade** are deprecated; instead you
|
|
should use the SPECIAL SHADE and SPECIAL MOON reminders as described
|
|
in \"Out-of-Band Reminders.\"
|
|
|
|
**realcurrent()**
|
|
|
|
: Returns (as a DATETIME) the true date and time of day as provided by
|
|
the operating system. This is in contrast to **current()**, which
|
|
may return a time supplied on the command line.
|
|
|
|
**realnow()**
|
|
|
|
: Returns the true time of day as provided by the operating system.
|
|
This is in contrast to **now()**, which may return a time supplied
|
|
on the command line.
|
|
|
|
**realtoday()**
|
|
|
|
: Returns the date as provided by the operating system. This is in
|
|
contrast to **Remind**\'s concept of \"today\", which may be changed
|
|
if it is running in calendar mode, or if a date has been supplied on
|
|
the command line.
|
|
|
|
**rows()**
|
|
|
|
: If standard output is a TTY, returns the height of the terminal in
|
|
rows. If standard output is not a TTY, attempts to open \"/dev/tty\"
|
|
to obtain the terminal size. If this fails, returns -1.
|
|
|
|
**sgn(i_num)**
|
|
|
|
: Returns -1 if *num* is negative, 1 if *num* is positive, and 0 if
|
|
*num* is zero.
|
|
|
|
**shell(s_cmd \[,i_maxlen\])**
|
|
|
|
: Executes *cmd* as a system command, and returns the first 511
|
|
characters of output resulting from *cmd*. Any whitespace character
|
|
in the output is converted to a space. Note that if **RUN** OFF has
|
|
been executed, or the **-r** command-line option has been used,
|
|
**shell()** will result in an error, and *cmd* will not be executed.
|
|
|
|
When **shell** runs *cmd*, it arranges for *cmd*\'s standard input
|
|
file descriptor to be connected to /dev/null.
|
|
|
|
If *maxlen* is specified, then **shell()** returns the first
|
|
*maxlen* characters of output (rather than the first 511). If
|
|
*maxlen* is specified as a negative number, then it defaults to the
|
|
value of the system variable **\$MaxStringLen**.
|
|
|
|
**shellescape(s_str)**
|
|
|
|
: Returns *str* with all shell metacharacters such as \" \", \"\*\",
|
|
etc escaped with a backslash. For example:
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
SET a shellescape("a b*? c&d$e")
|
|
|
|
> will set **a** to:
|
|
|
|
"a\ b\*\?\ c\&d\$e"
|
|
|
|
**slide(d_start, i_amt \[, i_step\] \[,s_wkday\...\])**
|
|
|
|
: This function is the inverse of **nonomitted**. It adds *amt* (which
|
|
can be negative) chunks of *step* days to *start*, *not counting
|
|
omitted days*. If *step* is not supplied, then it is assumed to
|
|
be 1. Note that only every *step*th day is tested to see if it is
|
|
omitted. The optional *wkday* arguments are additional weekday names
|
|
to omit.
|
|
|
|
Consider this example:
|
|
|
|
OMIT 14 May 2009
|
|
SET a slide('2009-05-13', 5, "Sat", "Sun")
|
|
|
|
In this case, *a* is set to 2009-05-21. That\'s because we slide
|
|
forward by 5 days, not including Thursday, May 14 or Saturday and
|
|
Sunday, May 16 and 17. You can go backwards, too, so:
|
|
|
|
OMIT 14 May 2009
|
|
SET a slide('2009-05-21', -5, "Sat", "Sun")
|
|
|
|
takes *a* back to 2009-05-13.
|
|
|
|
Now consider this example:
|
|
|
|
OMIT 14 May 2009
|
|
SET a slide('2009-05-07', 2, 7)
|
|
|
|
This sets *a* to \'2009-05-28\' because we skip ahead two weeks, not
|
|
counting a week where the day we land on happens to be omitted.
|
|
Contrast with this:
|
|
|
|
OMIT 13 May 2009
|
|
SET a slide('2009-05-07', 2, 7)
|
|
|
|
which sets *a* to \'2009-05-21\'. Although 2009-05-13 is omitted, we
|
|
don\'t \"land\" on it as we step forward in chunks of 7 days, so we
|
|
never see that it is omitted.
|
|
|
|
**soleq(i_which \[, dqi_start\])**
|
|
|
|
: The **soleq** function computes solstices and equinoxes. The *which*
|
|
parameter ranges from 0 to 3, and specifies which event we are
|
|
interested in: 0 is the March equinox; 1 is the June solstice; 2 is
|
|
the September equinox and 3 is the December solstice.
|
|
|
|
The optional *start* parameter can either be an integer specifying
|
|
the year of the event we are interested in, or a **DATE** or
|
|
**DATETIME** object; if the latter, then **soleq** returns the first
|
|
event on or after the date part of the *start* parameter (it ignores
|
|
the time component if *start* is a **DATETIME**.) If *start* is not
|
|
supplied, then it defaults to **today()**.
|
|
|
|
The return value of **soleq()** is a **DATETIME** object specifying
|
|
the date and time of the solstice or equinox in the local time zone.
|
|
It should be accurate to within 3 minutes or so in the worst case.
|
|
|
|
See the included file **\$SysInclude/seasons.rem** for examples of
|
|
how to use **soleq()**.
|
|
|
|
**stdout()**
|
|
|
|
: Returns a string representing where Remind\'s standard output is
|
|
going. The return values are one of the following: \"TTY\" if
|
|
standard-output is a terminal, \"BLOCKDEV\" if it is a block device
|
|
(very unlikely), \"CHARDEV\" if it is a character device (e.g.,
|
|
/dev/null), \"DIR\" if it is a directory (very unlikely), \"PIPE\"
|
|
if it is a pipe or FIFO, \"SYMLINK\" if it is a symlink (very
|
|
unlikely), \"SOCKET\" if it is a socket, or \"UNKNOWN\" if it could
|
|
not be determined.
|
|
|
|
The purpose of **stdout()** is mostly to distinguish between TTY and
|
|
non-TTY output; you may wish to change or disable colors if the
|
|
output is not going to a TTY.
|
|
|
|
**strlen(s_str)**
|
|
|
|
: Returns the length of *str* in bytes. If the length of *str* is too
|
|
large to represent as an integer, emits a \"Number too high\" error.
|
|
Note that **strlen** returns the number of *bytes* in the string,
|
|
not the number of *characters*. These numbers are the same for ASCII
|
|
strings, but may be different for UTF-8 strings.
|
|
|
|
**mbstrlen(str)**
|
|
|
|
: Similar to **strlen**, but returns the length of the string in
|
|
*characters* rather than *bytes* and is thus safe for use on
|
|
multi-byte strings.
|
|
|
|
**substr(s_str, i_start \[,i_end\])**
|
|
|
|
: Returns a **STRING** consisting of all bytes in *str* from *start*
|
|
up to and including *end*. Bytes are numbered from 1. If *end* is
|
|
not supplied, then it defaults to the length of *str*. Because
|
|
**substr** uses *byte* indexes rather than *character* indexes, it
|
|
should not be used on multi-byte strings.
|
|
|
|
**mbsubstr(s_str, i_start \[,i_end\])**
|
|
|
|
: Similar to **substr** but uses *character* indexes rather than
|
|
*byte* indexes, and is thus safe for use on multi-byte strings.
|
|
|
|
**sunrise(\[dq_date\])**
|
|
|
|
: Returns a **TIME** indicating the time of sunrise on the specified
|
|
*date* (default **today()**.) In high latitudes, there may be no
|
|
sunrise on a particular day, in which case **sunrise()** returns the
|
|
**INT** 0 if the sun never sets, or 1440 if it never rises.
|
|
|
|
**sunset(\[dq_date\])**
|
|
|
|
: Returns a **TIME** indicating the time of sunset on the specified
|
|
*date* (default **today()**.) In high latitudes, there may be no
|
|
sunset on a particular day, in which case **sunset()** returns the
|
|
**INT** 0 if the sun never rises, or 1440 if it never sets.
|
|
|
|
The functions **sunrise()** and **sunset()** are based on an
|
|
algorithm in \"Almanac for Computers for the year 1978\" by L. E.
|
|
Doggett, Nautical Almanac Office, USNO. They require the latitude
|
|
and longitude to be specified by setting the appropriate system
|
|
variables. (See \"System Variables\".) The sun functions should be
|
|
accurate to within about 4 minutes for latitudes lower than 60
|
|
degrees. The functions are available starting from version 03.00.07
|
|
of **Remind**.
|
|
|
|
**time(i_hr, i_min)**
|
|
|
|
: Creates a **TIME** with the hour and minute components specified by
|
|
*hr* and *min*.
|
|
|
|
**timepart(tq_datetime)**
|
|
|
|
: Returns a **TIME** object representing the time portion of
|
|
*datetime*.
|
|
|
|
**timezone(\[dq_datetime\])**
|
|
|
|
: Returns a string representing the local time zone name of the given
|
|
**DATETIME**. If no argument is supplied, **Remind** uses the value
|
|
of **current()**. If a **DATE** rather than **DATETIME** is
|
|
supplied, **Remind** uses a time part of 00:00.
|
|
|
|
**today()**
|
|
|
|
: Returns **Remind**\'s notion of \"today.\" This may be the actual
|
|
system date, or a date supplied on the command line, or the date of
|
|
the calendar entry currently being computed.
|
|
|
|
**trig(s_1 \[,s_2, \...\])**
|
|
|
|
: For each string argument s\_*n*, **trig** evaluates s\_*n* as if it
|
|
were a REM or IFTRIG trigger specification. If the trigger would
|
|
trigger today, then the trigger date is returned and no further
|
|
triggers are evaluated. If none of the triggers would trigger today,
|
|
then the zero date 1990-01-01 is returned.
|
|
|
|
**trig** also has a zero-argument form; this returns the trigger
|
|
date of the *most recent* **trig** function that returned a non-zero
|
|
trigger date.
|
|
|
|
**trig** can be used to make more sophisticated versions of
|
|
**IFTRIG**. For example, if you have meetings every Monday in June
|
|
and July, and you want warnings 3 days in advance, you could use:
|
|
|
|
REM [trig("Mon Jun +3", "Mon July +3")] +3 MSG Meeting %b
|
|
|
|
NOTE: We need to repeat the +3 delta outside of the **trig**
|
|
function for advance warning to work properly. This is because
|
|
**trig** returns a date constant (the trigger date) and the REM
|
|
command does not know the details of **trig**\'s arguments.
|
|
|
|
Note that because **Remind** has short-circuit logical operators,
|
|
something like:
|
|
|
|
SET a trig("Mon +7") || trig("Fri +7")
|
|
|
|
would set the value of trig() to the date of the following Monday.
|
|
Because trig(\"Mon +7\") always returns true, the logical-OR
|
|
operator does not bother evaluating trig(\"Fri +7\") which therefore
|
|
does not set **trig()**.
|
|
|
|
**Important Note**: Because **trig()** always returns an absolute
|
|
date, it will **not** work properly with a **SATISFY** clause.
|
|
Consider this reminder:
|
|
|
|
REM [trig("Mar", "Apr")] SATISFY [$Td == 15] MSG 15 Mar or April
|
|
|
|
If we run **Remind** on 5 March 2022, we might expect the trigger
|
|
date to be calculated as 15 March 2022\... but that\'s not what
|
|
happens. Instead, the **trig** function is evaluated first, and it
|
|
returns 2022-03-05. So as far as **Remind** is concerned, the REM
|
|
statement becomes:
|
|
|
|
REM 2022-03-05 SATISFY [$Td == 15] MSG 15 Mar or April
|
|
|
|
and the SATISFY expression is never true. So: *Do not mix* trig()
|
|
and SATISFY.
|
|
|
|
**trigdate()**
|
|
|
|
: Returns the calculated trigger date of the last **REM** or
|
|
**IFTRIG** command. If used in the *body* of a **REM** command,
|
|
returns that command\'s trigger date. If the most recent **REM**
|
|
command did not yield a computable trigger date, returns the integer
|
|
0.
|
|
|
|
**trigdatetime()**
|
|
|
|
: Similar to trigdate(), but returns a **DATETIME** if the most recent
|
|
triggerable **REM** command had an **AT** clause. If there was no
|
|
**AT** clause, returns a **DATE**. If no trigger could be computed,
|
|
returns the integer 0. See \"MULTI-DAY EVENTS\" for more
|
|
information.
|
|
|
|
**trigeventstart()**
|
|
|
|
: Returns a **DATETIME** representing the start of the most recent
|
|
triggerable **REM** command that had an **AT** clause. For events
|
|
without a **DURATION** or that do not span multiple days, returns
|
|
the same as **trigdatetime()**. If the **REM** command did not have
|
|
an **AT** clause, returns the integer -1 (and differs from
|
|
**trigdatetime()** in this respect.) See \"MULTI-DAY EVENTS\" for
|
|
more information.
|
|
|
|
**trigeventstarttz()**
|
|
|
|
: Similar to **trigeventstart()** but returns the DATETIME in the time
|
|
zone specified by a TZ clause, if one was present. If no TZ clause
|
|
was present, returns the same value as **trigeventstart()**.
|
|
|
|
**trigeventduration()**
|
|
|
|
: Returns a **TIME** representing the duration of the most recent
|
|
triggerable **REM** command that had an **AT** and a **DURATION**
|
|
clause. If the event does not span multiple days, returns the same
|
|
thing as **trigduration()**. If the **REM** command lacked an **AT**
|
|
or **DURATION** clause, returns -1. See \"MULTI-DAY EVENTS\" for
|
|
more information.
|
|
|
|
**trigback()**
|
|
|
|
: Returns the \"back\" amount of the last **REM** or **IFTRIG**
|
|
command. Returns a positive integer N if the \"back\" is of the form
|
|
-N, or a negative integer if it is of the form \--N. If there is no
|
|
\"back\", then returns 0.
|
|
|
|
**trigbase()**
|
|
|
|
: Returns the \"base\" date of the last **REM** or **IFTRIG** command.
|
|
If the trigger specification includes *all three* of day, month and
|
|
year, then the base date is the date formed from those components.
|
|
If the trigger specification lacks one of those components, then 0
|
|
is returned.
|
|
|
|
Here is an example of how **trigbase()** might be used:
|
|
|
|
REM 2025-05-05 *7 UNTIL 2025-05-26 \
|
|
MSG Meeting: week #[(trigdate() - trigbase())/trigrep()+1]
|
|
|
|
On 2025-05-05, it would print: \"Meeting: week #1\". On 2025-05-12,
|
|
it would print: \"Meeting: week #2\" and so on.
|
|
|
|
**trigdelta()**
|
|
|
|
: Returns the \"delta\" amount of the last **REM** or **IFTRIG**
|
|
command. Returns a positive integer N if the \"delta\" is of the
|
|
form +N, or a negative integer if it is of the form ++N. If there is
|
|
no \"delta\", then returns 0.
|
|
|
|
**trigtimedelta()**
|
|
|
|
: Similar to **trigdelta()**, but returns the delta used in the **AT**
|
|
clause of a timed reminder.
|
|
|
|
**trigrep()**
|
|
|
|
: Returns the \"repeat\" amount of the last **REM** or **IFTRIG**
|
|
command. Returns a positive integer N if the \"repeat\" is of the
|
|
form \*N. If there is no \"repeat\", then returns 0.
|
|
|
|
**trigtimerep()**
|
|
|
|
: Similar to **trigrep()**, but returns the repeat used in the **AT**
|
|
clause of a timed reminder.
|
|
|
|
**trigtz()**
|
|
|
|
: If a **TZ** clause was used in the last **REM** or **IFTRIG**
|
|
command, returns the time zone name. Otherwise returns the empty
|
|
string.
|
|
|
|
**trigduration()**
|
|
|
|
: Returns (as a TIME type) the **DURATION** parameter of a timed
|
|
reminder. If there is no **DURATION** parameter, returns the integer
|
|
-1. See \"MULTI-DAY EVENTS\" for more information.
|
|
|
|
**trigpriority()**
|
|
|
|
: Returns the **PRIORITY** of the last **REM** or **IFTRIG** command.
|
|
|
|
**triguntil()**
|
|
|
|
: Returns (as a **DATE** type) the **UNTIL** parameter of the last
|
|
**REM** or **IFTRIG** command. If there was no **UNTIL** parameter,
|
|
returns the integer -1. If there is a **THROUGH** parameter, that
|
|
will be returned by **triguntil()** since \"THROUGH yyyy-mm-dd\" is
|
|
simply syntactic sugar for \"\*1 UNTIL yyyy-mm-dd\".
|
|
|
|
**trigscanfrom()**
|
|
|
|
: Returns (as a **DATE** type) the **SCANFROM** parameter of the last
|
|
**REM** or **IFTRIG** command. If there was no **SCANFROM**
|
|
parameter, returns the integer -1. Note that **FROM** and
|
|
**SCANFROM** interact; a reminder that has a \"FROM yyyy-mm-dd\"
|
|
parameter will act as if it has a **SCANFROM** parameter whose value
|
|
is the maximum of \"yyyy-mm-dd\" and today.
|
|
|
|
**trigfrom()**
|
|
|
|
: Returns (as a **DATE** type) the **FROM** parameter of the last
|
|
**REM** or **IFTRIG** command. If there was no **FROM** parameter,
|
|
returns the integer -1.
|
|
|
|
**triginfo(s_header)**
|
|
|
|
: Returns a **STRING** that is the INFO item associated with the
|
|
header *header*. The header should *not* contain a colon. Header
|
|
name comparisons are case-insensitive.
|
|
|
|
For example, the following will assign \"At home\" to the variable a
|
|
and the empty string to variable b:
|
|
|
|
REM INFO "Location: At home" MSG test
|
|
SET a triginfo("location")
|
|
SET b triginfo("no_such_header")
|
|
|
|
**trigistodo()**
|
|
|
|
: Returns 1 if the last REM command was a **TODO** type or 0 if not.
|
|
|
|
**trigcompletethrough()**
|
|
|
|
: Returns a **DATE** object that is the COMPLETE-THROUGH date of the
|
|
most recent **REM** command. If there was no COMPLETE-THROUGH date,
|
|
returns the **INT** 0.
|
|
|
|
**trigmaxoverdue()**
|
|
|
|
: Returns an **INT** that is the MAX-OVERDUE value of the most recent
|
|
**REM** command. If there was no MAX-OVERDUE clause, returns -1.
|
|
|
|
**trigger(d_date \[,t_time \[,i_utcflag\]\]) or trigger(q_datetime \[,i_utcflag\])**
|
|
|
|
: Returns a string suitable for use in a **REM** command or a
|
|
**SCANFROM** or UNTIL clause, allowing you to calculate trigger
|
|
dates in advance. Note that in earlier versions of **Remind**,
|
|
**trigger** was required to convert a date into something the
|
|
**REM** command could consume. However, in this version of
|
|
**Remind**, you can omit it. Normally, the *date* and *time* are the
|
|
local date and time; however, if *utcflag* is non-zero, the *date*
|
|
and *time* are interpreted as UTC times, and are converted to local
|
|
time. Examples:
|
|
|
|
trigger(\'1993/04/01\')
|
|
|
|
returns \"1 April 1993\",
|
|
|
|
trigger(\'1994/08/09\', 12:33)
|
|
|
|
returns \"9 August 1994 AT 12:33\", as does:
|
|
|
|
trigger(\'1994/08/09@12:33\').
|
|
|
|
Finally:
|
|
|
|
trigger(\'1994/12/01\', 03:00, 1)
|
|
|
|
returns \"30 November 1994 AT 22:00\" for EST, which is 5 hours
|
|
behind UTC. The value for your time zone may differ.
|
|
|
|
**trigger()** will *never* return a date earlier than \"1 January
|
|
1990\" even if the UTC flag dictates that it should. So do not use
|
|
it for reminders before about 2 January 1990 in your local time
|
|
zone. I do not anticipate this restriction being a real problem.
|
|
|
|
**trigtags()**
|
|
|
|
: Returns a comma-separated list of the TAGs associated with the most
|
|
recent **REM** command that was triggered. Returns the empty string
|
|
if there were no TAGs. If there are multiple tags, they are each
|
|
separated by a single comma, not a comma and a space.
|
|
|
|
**trigtime()**
|
|
|
|
: Returns the time of the last **REM** command with an **AT** clause
|
|
*in the system default time zone*. If the last **REM** did not have
|
|
an **AT** clause, returns the integer 0. If a **REM** command has an
|
|
**AT** clause with a **DURATION**, then you can compute the end time
|
|
as **trigtime() + trigduration()**.
|
|
|
|
**trigtimetz()**
|
|
|
|
: Similar to **trigtime()** but returns the time in the time zone
|
|
specified by a TZ clause, if one was present. If no TZ clause was
|
|
present, returns the same value as **trigtime()**.
|
|
|
|
**trigvalid()**
|
|
|
|
: Returns 1 if the value returned by **trigdate()** is valid for the
|
|
most recent **REM** command, or 0 otherwise. Sometimes **REM**
|
|
commands cannot calculate a trigger date. For example, the following
|
|
**REM** command can never be triggered:
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
REM Mon OMIT Mon SKIP MSG Impossible!
|
|
|
|
**typeof(x_arg)**
|
|
|
|
: Returns \"STRING\", \"INT\", \"DATE\", \"TIME\" or \"DATETIME\",
|
|
depending on the type of *arg*.
|
|
|
|
**tzconvert(q_datetime, s_srczone \[,s_dstzone\])**
|
|
|
|
: Converts **datetime** from the time zone named by **srczone** to the
|
|
time zone named by **dstzone**. If **srczone** is the empty string,
|
|
then the default system time zone is used as the source zone. If
|
|
**dstzone** is omitted or is the empty string, the default system
|
|
time zone is used as the destination zone. The return value is a
|
|
DATETIME. Time zone names are system-dependent; consult your
|
|
operating system for legal values. Here is an example:
|
|
|
|
tzconvert('2007-07-08@01:14', "Canada/Eastern", "Canada/Pacific")
|
|
|
|
returns
|
|
|
|
2007-07-07@22:14
|
|
|
|
If your system includes the directory /usr/share/zoneinfo,
|
|
**Remind** will warn you if you use an invalid time zone name for
|
|
**srczone** or **dstzone**. To suppress these warnings, add a \"!\"
|
|
to the beginning of the time zone name.
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
|
|
**upper(s_string)**
|
|
|
|
: Returns a **STRING** with all lower-case characters in *string*
|
|
converted to upper-case.
|
|
|
|
**utctolocal(q_datetime)**
|
|
|
|
: Given a **DATETIME** object interpreted in UTC, return a
|
|
**DATETIME** object that expresses the same time in the local time
|
|
zone.
|
|
|
|
**value(s_varname \[,x_default\])**
|
|
|
|
: Returns the value of the specified variable. For example,
|
|
value(\"X\"+\"Y\") returns the value of variable XY, if it is
|
|
defined. If XY is not defined, an error results.
|
|
|
|
However, if you supply a second argument, it is returned if the
|
|
*varname* is not defined. The expression value(\"XY\", 0) will
|
|
return 0 if XY is not defined, and the value of XY if it is defined.
|
|
Note that **value** evaluates the second argument lazily; it is
|
|
*not* evaluated if *varname* is defined.
|
|
|
|
**version()**
|
|
|
|
: Returns a string specifying the version of **Remind**. For version
|
|
06.02.01, returns \"06.02.01\". It is guaranteed that as new
|
|
versions of **Remind** are released, the value returned by
|
|
**version()** will strictly increase, according to the rules for
|
|
string ordering.
|
|
|
|
**weekno(\[dq_date, \[i_wkstart, \[i_daystart\]\]\])**
|
|
|
|
: Returns the week number of the year. If no arguments are supplied,
|
|
returns the ISO 8601 week number for **today()**. If one argument
|
|
*date* is supplied, then returns the ISO 8601 week number for that
|
|
date. If two arguments are supplied, then *wkstart* must range from
|
|
0 to 6, and represents the first day of the week (with 0 being
|
|
Sunday and 6 being Saturday.). If *wkstart* is not supplied, then it
|
|
defaults to 1. If the third argument *daystart* is supplied, then it
|
|
specifies when Week 1 starts. If *daystart* is less than or equal to
|
|
7, then Week 1 starts on the first *wkstart* on or after January
|
|
*daystart*. Otherwise, Week 1 starts on the first *wkstart* on or
|
|
after December *daystart*. If omitted, *daystart* defaults to 29
|
|
(following the ISO 8601 definition.)
|
|
|
|
**wkday(dqi_arg)**
|
|
|
|
: If *arg* is a **DATE** or **DATETIME**, returns a string
|
|
representing the day of the week of the date. If *arg* is an **INT**
|
|
from 0 to 6, returns the corresponding weekday (\"Sunday\" to
|
|
\"Saturday\").
|
|
|
|
**wkdaynum(dq_date)** or **wkdaynum(s_str)**
|
|
|
|
: Returns a number from 0 to 6 representing the day-of-week of the
|
|
specified *date*. (0 represents Sunday, and 6 represents Saturday.)
|
|
If a **STRING** is supplied, then if *str* is a valid weekday name
|
|
(or minimum 3-character abbreviation thereof) then the corresponding
|
|
weekday number is returned. If *str* is not a valid weekday name,
|
|
then an error occurs.
|
|
|
|
**year(dq_date)**
|
|
|
|
: Returns a **INT** that is the year component of *date*.
|
|
|
|
# MACHINES WITH A 32-BIT TIME_T TYPE
|
|
|
|
Internally, the standard C library represents times as a **time_t**
|
|
type. This is a signed integer type that counts seconds since midnight,
|
|
1 January 1970 UTC. If the **time_t** type is only 32 bits in size, then
|
|
the C library cannot represent times after 19 January 2038 at 03:14:07
|
|
UTC.
|
|
|
|
To work around this limitation, **Remind** will \"fold\" years greater
|
|
than 2037 to a smaller year that begins on the same day and has the same
|
|
number of days. This results in a year that\'s very likely to have the
|
|
same daylight saving rules as the original year, unless the rules have
|
|
changed in the interim (in which case the rule change could not even be
|
|
represented on a 32-bit machine, so it\'s moot.)
|
|
|
|
**Remind** then does UTC-to-local or local-to-UTC conversions with the
|
|
folded year, and then post-conversion corrects it back. This should give
|
|
correct results for astronomical functions and conversions between local
|
|
and UTC time, providing the daylight saving time rules have not changed
|
|
between the folded year and the original year.
|
|
|
|
Note that the \$FoldYear system variable is no longer that useful;
|
|
**Remind** *always* folds years if it\'s necessary on a 32-bit system.
|
|
You can set \$FoldYear to 1 to force **Remind** to fold years even on a
|
|
64-bit system, but that\'s useful only for testing and not for
|
|
production.
|
|
|
|
# MULTI-DAY EVENTS
|
|
|
|
If you specify a start time with **AT** and a duration with
|
|
**DURATION**, you can create events that span multiple days. Consider
|
|
these two REM statements:
|
|
|
|
REM 1991-02-13 AT 16:00 DURATION 72:00 MSG 72-hour event
|
|
REM 1991-02-13 THROUGH 1991-02-16 AT 16:00 MSG Four events
|
|
|
|
The first statement creates a *single* event that starts on 13 February
|
|
1991 at 16:00 and runs through 16 February 1991 at 16:00
|
|
|
|
The second statements creates *four separate* events that start at 16:00
|
|
on 13, 14, 15 and 16 February 1991 and have indefinite duration.
|
|
|
|
**Remind** handles multi-day events specially. These are the rules:
|
|
|
|
On the *first* day of a multi-day event, **trigdatetime()** will return
|
|
the starting date and time of the event, and **trigduration()** will
|
|
return the original DURATION.
|
|
|
|
On each *subsequent* day of a multi-day event, **trigdatetime()** will
|
|
return midnight on the day in question, and **trigduration()** will
|
|
return the *remaining* duration. Consider this example:
|
|
|
|
#!/bin/sh
|
|
remind - 12 feb 1991 '*6' <<'EOF'
|
|
BANNER %
|
|
REM 1991-02-13 AT 16:00 DURATION 72:00 SATISFY 1
|
|
set a trigdatetime()
|
|
set b trigduration()
|
|
set c trigeventstart()
|
|
set d trigeventduration()
|
|
MSG now=[today()] dt=[a] dur=[b] estart=[c] edur=[d]%
|
|
EOF
|
|
|
|
The output is:
|
|
|
|
now=1991-02-12 dt=1991-02-13@16:00 dur=72:00 estart=1991-02-13@16:00 edur=72:00
|
|
now=1991-02-13 dt=1991-02-13@16:00 dur=72:00 estart=1991-02-13@16:00 edur=72:00
|
|
now=1991-02-14 dt=1991-02-14@00:00 dur=64:00 estart=1991-02-13@16:00 edur=72:00
|
|
now=1991-02-15 dt=1991-02-15@00:00 dur=40:00 estart=1991-02-13@16:00 edur=72:00
|
|
now=1991-02-16 dt=1991-02-16@00:00 dur=16:00 estart=1991-02-13@16:00 edur=72:00
|
|
now=1991-02-17 dt=1991-02-13@16:00 dur=72:00 estart=-1 edur=-1
|
|
|
|
As you see, the **trigdatetime()** and **trigduration()** functions
|
|
return the start time and duration of the *remaining* portion of a
|
|
multi-day event, whereas **trigeventstart** and **trigeventduration**
|
|
always return the original start and duration of the multi-day event.
|
|
Note also that the return value for expired reminders is not reliable;
|
|
the fact that **trigeventstart** and **trigeventduration** return -1 in
|
|
that case is an implementation artifact.
|
|
|
|
**SELF-OVERLAPPING EVENTS**
|
|
|
|
A multi-day event has the possibility of \"overlapping itself\". When
|
|
this happens, **Remind** prefers the *later* event (only one copy of an
|
|
event is ever triggered for a given date.) Consider this example:
|
|
|
|
#!/bin/sh
|
|
remind - '*5' 10 Feb 1991 <<'EOF'
|
|
|
|
BANNER %
|
|
REM MON at 0:00 DURATION 192:0 MSG [today()] [trigeventstart()] [trigduration()]%
|
|
|
|
EOF
|
|
|
|
The output is:
|
|
|
|
1991-02-10 1991-02-04@00:00 48:00
|
|
1991-02-11 1991-02-11@00:00 192:00
|
|
1991-02-12 1991-02-11@00:00 168:00
|
|
1991-02-13 1991-02-11@00:00 144:00
|
|
1991-02-14 1991-02-11@00:00 120:00
|
|
|
|
Although the event from 1991-02-04 still has 24 hours left on
|
|
1991-02-11, the fresh occurrence on 1991-02-11 takes precedences and is
|
|
the one that is triggered.
|
|
|
|
I do not recommend constructing self-overlapping multi-day events.
|
|
|
|
# EXPRESSION PASTING
|
|
|
|
An extremely powerful feature of **Remind** is its macro capability, or
|
|
\"expression pasting.\"
|
|
|
|
In almost any situation where **Remind** is not expecting an expression,
|
|
you can \"paste\" an expression in. To do this, surround the expression
|
|
with square brackets. For example:
|
|
|
|
REM [mydate] MSG foo
|
|
|
|
This evaluates the expression \"mydate\", where \"mydate\" is presumably
|
|
some pre-computed variable, and then \"pastes\" the result into the
|
|
command-line for the parser to process.
|
|
|
|
If you want a literal \"\[\" character for some reason, simply use
|
|
\"\[\[\". For example:
|
|
|
|
REM MSG Here are [[square] brackets!
|
|
|
|
A formal description of this is: When **Remind** encounters a
|
|
\"pasted-in\" expression, it evaluates the expression, and coerces the
|
|
result to a **STRING**. It then substitutes the string for the pasted-in
|
|
expression, and continues parsing. Note, however, that expressions are
|
|
evaluated only once, not recursively. Thus, writing:
|
|
|
|
["[a+b]"]
|
|
|
|
causes **Remind** to read the token \"\[a+b\]\". It does not interpret
|
|
this as a pasted-in expression.
|
|
|
|
You can use expression pasting almost anywhere. However, there are a few
|
|
exceptions:
|
|
|
|
o
|
|
|
|
: If **Remind** is expecting an expression, as in the **SET** command,
|
|
or the **IF** command, you should **not** include square brackets.
|
|
For example, use:
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
SET a 4+5
|
|
|
|
and not:
|
|
|
|
SET a [4+5]
|
|
|
|
o
|
|
|
|
: You cannot use expression pasting for the first token on a line. For
|
|
example, the following will not work:
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
["SET"] a 1
|
|
|
|
> This restriction is because **Remind** must be able to unambiguously
|
|
> determine the first token of a line for the flow-control commands (to
|
|
> be discussed later.)
|
|
>
|
|
> In fact, if **Remind** cannot determine the first token on a line, it
|
|
> assumes that it is a **REM** command. If expression-pasting is used,
|
|
> **Remind** assumes it is a **REM** command. Thus, the following three
|
|
> commands are equivalent:
|
|
>
|
|
> REM 12 Nov 1993 AT 13:05 MSG BOO!
|
|
> 12 Nov 1993 AT 13:05 MSG BOO!
|
|
> [12] ["Nov " + 1993] AT [12:05+60] MSG BOO!
|
|
|
|
o
|
|
|
|
: You cannot use expression-pasting to determine the type (**MSG**,
|
|
**CAL**, etc.) of a **REM** command. You can paste expressions
|
|
before and after the **MSG**, etc. keywords, but cannot do something
|
|
like this:
|
|
|
|
REM ["12 Nov 1993 AT 13:05 " + "MSG" + " BOO!"]
|
|
|
|
However, as an escape hatch, the sequence **SPECIAL** *type* means
|
|
the same thing as just *type* where *type* is one of MSG, MSF, RUN,
|
|
CAL, PS and PSFILE. This lets you do something like this:
|
|
|
|
SET type "MSG"
|
|
REM 12 Nov 2024 SPECIAL [type] Hello
|
|
|
|
You can use this to control the types of your reminders based on
|
|
variables you set, how **Remind** is invoked, etc.
|
|
|
|
**COMMON PITFALLS WITH EXPRESSION PASTING**
|
|
|
|
Remember that extra spaces are not inserted when an expression is
|
|
pasted. Thus, something like:
|
|
|
|
REM[expr]MSG[expr]
|
|
|
|
will probably fail.
|
|
|
|
If you use an expression to calculate a *delta* or *back*, ensure that
|
|
the result is a positive number. Something like:
|
|
|
|
REM +[mydelta] Nov 12 1993 MSG foo
|
|
|
|
will fail if *mydelta* happens to be negative.
|
|
|
|
# FLOW CONTROL COMMANDS
|
|
|
|
**Remind** has commands that control the flow of a reminder script.
|
|
Normally, reminder scripts are processed sequentially. However, **IF**
|
|
and related commands allow you to process files conditionally, and skip
|
|
sections that you don\'t want interpreted.
|
|
|
|
**THE IF COMMAND**
|
|
|
|
The **IF** command has the following form:
|
|
|
|
IF expr
|
|
t-command
|
|
t-command...
|
|
ELSE
|
|
f-command
|
|
f-command...
|
|
ENDIF
|
|
|
|
Note that the commands are shown indented for clarity. Also, the
|
|
**ELSE** portion can be omitted. **IF** commands can be nested up to a
|
|
depth of 64, across *all* levels of INCLUDE.
|
|
|
|
If the *expr* evaluates to a non-zero **INT**, a **DATE** that is not
|
|
1990-01-01, a **TIME** that is not 00:00, a **DATETIME** that is not
|
|
1990-01-01@00:00, or a non-null **STRING**, then the **IF** portion is
|
|
considered true, and the *t-commands* are executed. If *expr* evaluates
|
|
to zero or null, then the *f-commands* (if the **ELSE** portion is
|
|
present) are executed.
|
|
|
|
Examples:
|
|
|
|
IF defined("want_hols")
|
|
INCLUDE /usr/share/remind/holidays
|
|
ENDIF
|
|
|
|
IF today() > '1992/2/10'
|
|
set missed_ap "You missed it!"
|
|
ELSE
|
|
set missed_ap "Still have time..."
|
|
ENDIF
|
|
|
|
**THE IFTRIG COMMAND**
|
|
|
|
The **IFTRIG** command is similar to an **IF** command, except that it
|
|
computes a trigger (as in the **REM** command), and evaluates to true if
|
|
a corresponding **REM** command would trigger. Examples:
|
|
|
|
IFTRIG 1 Nov
|
|
; Executed on 1 Nov
|
|
ELSE
|
|
; Executed except on 1 Nov
|
|
ENDIF
|
|
|
|
IFTRIG 1 -1 OMIT Sat Sun +4
|
|
; Executed on last working day of month,
|
|
; and the 4 working days preceding it
|
|
ELSE
|
|
; Executed except on above days
|
|
ENDIF
|
|
|
|
Note that the **IFTRIG** command computes a trigger date, which can be
|
|
retrieved with the **trigdate()** function. You can use all of the
|
|
normal trigger components, such as **UNTIL**, *delta*, etc. in the
|
|
**IFTRIG** command. However, you cannot use a type specifier such as
|
|
**CAL**, **MSG** or **SATISFY**; attempting to do so yields a parse
|
|
error.
|
|
|
|
# USER-DEFINED FUNCTIONS
|
|
|
|
In addition to the built-in functions, **Remind** allows you to define
|
|
your own functions. The **FSET** command does this for you:
|
|
|
|
**FSET** *fname*(*args*) *expr*
|
|
|
|
*Fname* is the name of the function, and follows the convention for
|
|
naming variables. *Args* is a comma-separated list of arguments, and
|
|
*expr* is an expression. *expr* is not evaluated at the time the
|
|
function is defined; instead, it is evaluated each time the function is
|
|
called. *Args* can be empty, in which case you define a function taking
|
|
no parameters. Here are some examples:
|
|
|
|
FSET double(x) 2*x
|
|
FSET yeardiff(date1, date2) year(date1) - year(date2)
|
|
FSET since(x) ord($Ty - x)
|
|
|
|
The last function is useful in birthday reminders. For example:
|
|
|
|
REM 1 Nov +12 MSG Dean's [since(1984)] birthday is %b.
|
|
|
|
Dean was born in 1984. The above example, on 1 November 1992, would
|
|
print:
|
|
|
|
Dean's 8th birthday is today.
|
|
|
|
Similarly, the function is useful in anniversary reminders. For example:
|
|
|
|
REM 4 June MSG [since(1989)] anniversary of the Tienanmen Square massacre
|
|
|
|
Notes:
|
|
|
|
o
|
|
|
|
: If you access a variable in *expr* that is not in the list of
|
|
arguments, the global value (if any) is used.
|
|
|
|
o
|
|
|
|
: Function and parameter names are significant to 64 characters.
|
|
|
|
o
|
|
|
|
: The **value()** function *always* accesses the global value of a
|
|
variable, even if it has the same name as an argument. For example:
|
|
|
|
fset func(x) value("x")
|
|
set x 1
|
|
set y func(5)
|
|
|
|
The above sequence sets y to 1, which is the global value of x.
|
|
|
|
o
|
|
|
|
: User-defined functions may call other functions, including other
|
|
user-defined functions. Recursive calls are allowed, but they must
|
|
terminate (for example, by using a short-circuit operator or
|
|
function that breaks the recursion) or an error will result after a
|
|
certain maximum number of recursive calls (by default, 1000.)
|
|
|
|
o
|
|
|
|
: If a user-defined function has the same name as a built-in function,
|
|
it is ignored and the built-in function is used. To prevent
|
|
conflicts with future versions of **Remind** (which may define more
|
|
built-in functions), you may wish to name all user-defined functions
|
|
beginning with an underscore.
|
|
|
|
o
|
|
|
|
: If a user-defined function is defined in a context where **RUN** is
|
|
disabled, then whenever that function is called, **RUN** will be
|
|
disabled during its evaluation, *even if* it is called from a
|
|
context where **RUN** is enabled.
|
|
|
|
To delete a user-defined function, use **FUNSET**. This takes a
|
|
space-separated list of user-defined functions to delete. For example,
|
|
after the command:
|
|
|
|
FUNSET myfunc1 otherfunc thirdfunc
|
|
|
|
it is guaranteed that no user-defined functions named myfunc1, otherfunc
|
|
or thirdfunc will exist. **Remind** does not issue an error if you try
|
|
to **FUNSET** a nonexistent user-defined function; it simply does
|
|
nothing in that case.
|
|
|
|
You can rename a user-defined function with **FRENAME**. This takes two
|
|
names: An old name and a new name. Consider this command:
|
|
|
|
FRENAME func_a func_b
|
|
|
|
If *func_a* does not exist, the command unsets *func_b* if it is
|
|
defined. However, if *func_a* exists, then it is renamed to *func_b*,
|
|
and *func_a* is no longer defined. If *func_b* was defined prior to the
|
|
**FRENAME** command, then that old definition is lost.
|
|
|
|
If either argument to the **FRENAME** command is the name of a built-in
|
|
function, the command fails with an error message and does nothing.
|
|
|
|
If you define a user-defined function and then later on redefine it,
|
|
**Remind** will issue a warning. If you do not want this warning, then
|
|
use **FUNSET** to remove the existing definition before you redefine the
|
|
function. Alternatively, you can use a \"-\" token before the function
|
|
name to suppress \"redefined function\" warnings, as in the following
|
|
example:
|
|
|
|
FSET - f(x) 2*x
|
|
# You must have space before and after the "-"
|
|
# This will NOT work:
|
|
# FSET -f(x) 2*x
|
|
|
|
# SAVING AND RESTORING FUNCTIONS
|
|
|
|
Occasionally, it is useful to redefine a function for a specific block
|
|
of reminders, but to restore its original definition at the end of that
|
|
block. Just as with variables, functions can be pushed onto and popped
|
|
off an internal stack. Here is an example:
|
|
|
|
PUSH-FUNCS msgprefix
|
|
FSET msgprefix(x) "My new prefix: "
|
|
INCLUDE block_of_reminders.rem
|
|
POP-FUNCS
|
|
|
|
The file **block_of_reminders.rem** would be executed with the
|
|
**msgprefix** function defined above. After the POP-FUNCS **msgprefix**
|
|
would be restored to its previous definition if it had one, or simply
|
|
unset if it was not previously defined.
|
|
|
|
The command PUSH-FUNCS takes a space-separated list of function names.
|
|
All of the named user-defined functions will be saved to an internal
|
|
stack. You can even push names that are not defined as any function.
|
|
|
|
After a function name has been pushed, **Remind** will not issue a
|
|
warning if you redefine it, because presumably the purpose of pushing it
|
|
in the first place is to redefine it.
|
|
|
|
The command POP-FUNCS restores the definitions of all the user-defined
|
|
functions in the corresponding PUSH-FUNCS command. If undefined
|
|
functions were pushed onto the stack, then POP-FUNCS makes those
|
|
functions undefined again. Here\'s one more example:
|
|
|
|
FUNSET a
|
|
FSET b(x) 2*x
|
|
REM MSG [b(3)] # Outputs 6
|
|
PUSH-FUNCS a b
|
|
FSET a(x) 22*x
|
|
FSET b(x) 3*x
|
|
REM MSG [a(3)] [b(3)] # Outputs 66 9
|
|
POP-FUNCS
|
|
REM MSG [a(3)] # Undefined function "a"
|
|
REM MSG [b(3)] # Outputs 6
|
|
|
|
# PRECISE SCHEDULING
|
|
|
|
The **WARN** keyword allows precise control over advance warning in a
|
|
more flexible manner than the *delta* mechanism. It should be followed
|
|
by the name of a user-defined function, *warn_function*.
|
|
|
|
If a *warn_function* is supplied, then it must take one argument of type
|
|
**INT**. **Remind** ignores any delta, and instead calls *warn_function*
|
|
successively with the arguments 1, 2, 3, \...
|
|
|
|
*Warn_function*\'s return value *n* is interpreted as follows:
|
|
|
|
o
|
|
|
|
: If *n* is positive, then the reminder is triggered exactly *n* days
|
|
before its trigger date.
|
|
|
|
o
|
|
|
|
: If *n* is negative, then it is triggered *n* days before its trigger
|
|
date, *not counting* **OMIT**ted days.
|
|
|
|
As an example, suppose you wish to be warned of American Independence
|
|
Day 5, 3, and 1 days in advance. You could use this:
|
|
|
|
FSET _wfun(x) choose(x, 5, 3, 1, 0)
|
|
REM 4 July WARN _wfun MSG American Independence Day is %b.
|
|
|
|
**NOTES**
|
|
|
|
1
|
|
|
|
: If an error occurs during the evaluation of *warn_function*, then
|
|
**Remind** stops calling it and simply issues the reminder on its
|
|
trigger date.
|
|
|
|
2
|
|
|
|
: If the absolute-values of the return values of *warn_function* are
|
|
not monotonically decreasing, **Remind** stops calling it and issues
|
|
the reminder on its trigger date.
|
|
|
|
3
|
|
|
|
: *Warn_function* should (as a matter of good style) return 0 as the
|
|
final value in its sequence of return values. However, a reminder
|
|
will *always* be triggered on its trigger date, regardless of what
|
|
*warn_function* does.
|
|
|
|
Similarly to **WARN**, the **SCHED** keyword allows precise control over
|
|
the scheduling of timed reminders. It should be followed by the name of
|
|
a user-defined function, *sched_function*.
|
|
|
|
If a scheduling function is supplied, then it must take one argument of
|
|
type **INT**. Rather than using the **AT** time, time *delta*, and time
|
|
*repeat*, **Remind** calls the scheduling function to determine when to
|
|
trigger the reminder. The first time the reminder is queued, the
|
|
scheduling function is called with an argument of 1. Each time the
|
|
reminder is triggered, it is re-scheduled by calling the scheduling
|
|
function again. On each call, the argument is incremented by one.
|
|
|
|
The return value of the scheduling function must be an **INT** or a
|
|
**TIME**. If the return value is a **TIME**, then the reminder is
|
|
re-queued to trigger at that time. If it is a positive integer *n*, then
|
|
the reminder is re-queued to trigger at the previous trigger time plus
|
|
*n* minutes. Finally, if it is a negative integer or zero, then the
|
|
reminder is re-queued to trigger *n* minutes before the **AT** time.
|
|
Note that there must be an **AT** clause for the **SCHED** clause to do
|
|
anything.
|
|
|
|
Here\'s an example:
|
|
|
|
FSET _sfun(x) choose(x, -60, 30, 15, 10, 3, 1, 1, 1, 1, 0)
|
|
REM AT 13:00 SCHED _sfun MSG foo
|
|
|
|
The reminder would first be triggered at 13:00-60 minutes, or at 12:00.
|
|
It would next be triggered 30 minutes later, at 12:30. Then, it would be
|
|
triggered at 12:45, 12:55, 12:58, 12:59, 13:00, 13:01 and 13:02.
|
|
|
|
**NOTES**
|
|
|
|
1
|
|
|
|
: If an error occurs during the evaluation of *sched_func*, then
|
|
**Remind** reverts to using the **AT** time and the *delta* and
|
|
*repeat* values, and never calls *sched_func* again.
|
|
|
|
2
|
|
|
|
: If processing *sched_func* yields a time earlier than the current
|
|
system time, it is repeatedly called with increasing argument until
|
|
it yields a value greater than or equal to the current time.
|
|
However, if the sequence of values calculated during the repetition
|
|
is not strictly increasing, then **Remind** reverts to the default
|
|
behaviour and never calls *sched_func* again.
|
|
|
|
3
|
|
|
|
: It is quite possible using *sched_func* to keep triggering a
|
|
reminder even after the **AT**-time. However, it is not possible to
|
|
reschedule a reminder past midnight - no crossing of date boundaries
|
|
is allowed. Also, it is quite possible to **not** trigger a reminder
|
|
on the **AT** time when you use a scheduling function. However, if
|
|
your scheduling function is terminated (for reasons 1 and 2) before
|
|
the **AT** time of the reminder, it *will* be triggered at the
|
|
**AT** time, because normal processing takes over.
|
|
|
|
4
|
|
|
|
: Your scheduling functions should (as a matter of good style) return
|
|
0 when no more scheduling is required. See the example.
|
|
|
|
5
|
|
|
|
: All scheduling functions are evaluated *after* the entire Remind
|
|
script has been read in. So whatever function definitions are in
|
|
effect at the end of the script are used.
|
|
|
|
# THE SATISFY CLAUSE
|
|
|
|
The form of **REM** that uses **SATISFY** is as follows:
|
|
|
|
**REM** *trigger* **SATISFY** *expr*
|
|
|
|
The way this works is as follows: **Remind** first calculates a trigger
|
|
date, in the normal fashion. Next, it sets **trigdate()** to the
|
|
calculated trigger date. It then evaluates *expr*. If the result is not
|
|
the null string or zero, processing ends. Otherwise, **Remind** computes
|
|
the next trigger date, and re-tests *expr*. This iteration continues
|
|
until *expr* evaluates to non-zero or non-null, or until the iteration
|
|
limit specified with the **-x** command-line option is reached.
|
|
|
|
If *expr* is not satisfied, then **trigvalid()** is set to 0 and the
|
|
error message \"Can\'t compute trigger\" is issued. Otherwise,
|
|
**trigvalid()** is set to 1.
|
|
|
|
This is really useful only if *expr* involves a call to the
|
|
**trigdate()** or related functions or system variables; otherwise,
|
|
*expr* will not change as **Remind** iterates. In fact, if *expr* is not
|
|
a constant and does not call **trigdate()** or related functions or
|
|
system variables, then **Remind** will issue a warning.
|
|
|
|
An example of the usefulness of **SATISFY**: Suppose you wish to be
|
|
warned of every Friday the 13th. Your first attempt may be:
|
|
|
|
# WRONG!
|
|
REM Fri 13 +2 MSG Friday the 13th is %b.
|
|
|
|
But this won\'t work. This reminder triggers on the first Friday on or
|
|
after the 13th of each month. The way to do it is with a more
|
|
complicated sequence:
|
|
|
|
REM 13 SATISFY wkdaynum(trigdate()) == 5
|
|
IF trigvalid()
|
|
REM [trigdate()] +2 MSG \
|
|
Friday the 13th is %b.
|
|
ENDIF
|
|
|
|
You can write the REM statement a little more concisely:
|
|
|
|
REM 13 SATISFY $Tw == 5
|
|
|
|
Let\'s see how this works. The **SATISFY** clause iterates through all
|
|
the 13ths of successive months, until a trigger date is found whose
|
|
day-of-week is Friday (== 5). If a valid date was found, we use the
|
|
calculated trigger date to set up the next reminder.
|
|
|
|
We could also have written:
|
|
|
|
REM Fri SATISFY day(trigdate()) == 13
|
|
|
|
but this would result in more iterations, since \"Fridays\" occur more
|
|
often than \"13ths of the month.\"
|
|
|
|
Here is another example: Suppose you want to be reminded of something on
|
|
the 15th of January, April, July, and October. You could make four
|
|
separate reminders, or you could use:
|
|
|
|
REM 15 SATISFY [isany($Tm, 1, 4, 7, 10)] MSG 15th Reminder!
|
|
|
|
This technique of using one **REM** command to calculate a trigger date
|
|
to be used by another command is quite powerful. For example, suppose
|
|
you wanted to OMIT Labour day, which is the first Monday in September.
|
|
You could use:
|
|
|
|
# Note: SATISFY 1 is an idiom for "do nothing"
|
|
REM Mon 1 Sept SATISFY 1
|
|
OMIT [trigdate()]
|
|
|
|
**CAVEAT:** This *only* omits the *next* Labour Day, not all Labour Days
|
|
in the future. This could cause strange results, as the **OMIT** context
|
|
can change depending on the current date. For example, if you use the
|
|
following command after the above commands:
|
|
|
|
REM Mon AFTER msg hello
|
|
|
|
the result will not be as you expect. Consider producing a calendar for
|
|
September, 1992. Labour Day was on Monday, 7 September, 1992. However,
|
|
when **Remind** gets around to calculating the trigger for Tuesday, 8
|
|
September, 1992, the **OMIT** command will now be omitting Labour Day
|
|
for 1993, and the \"Mon AFTER\" command will not be triggered. (But see
|
|
the description of **SCANFROM** in the section \"DETAILS ABOUT TRIGGER
|
|
COMPUTATION.\")
|
|
|
|
It is probably best to stay away from computing **OMIT** trigger dates
|
|
unless you keep these pitfalls in mind.
|
|
|
|
For versions of **Remind** starting from 03.00.07, you can include a
|
|
**MSG**, **RUN**, etc. clause in a **SATISFY** clause as follows:
|
|
|
|
REM trigger_stuff SATISFY [expr] MSG body
|
|
|
|
Note that for this case only, the *expr* after **SATISFY** *must* be
|
|
enclosed in square brackets. It must come after all the other components
|
|
of the trigger, and immediately before the **MSG**, **RUN**, etc.
|
|
keyword. If *expr* cannot be satisfied, then the reminder is not
|
|
triggered.
|
|
|
|
Thus, the \"Friday the 13th\" example can be expressed more compactly
|
|
as:
|
|
|
|
REM 13 +2 SATISFY [$Tw == 5] MSG Friday the 13th is %b.
|
|
|
|
And you can trigger a reminder on Mondays, Wednesdays and Thursdays
|
|
occurring on odd-numbered days of the month with the following:
|
|
|
|
REM Mon Wed Thu SATISFY [$Td %2 ] MSG Here it is!!!
|
|
|
|
Note that **SATISFY** and **OMITFUNC** can often be used to solve the
|
|
same problem, though in different ways. Sometimes a **SATISFY** is
|
|
cleaner and sometimes an **OMITFUNC**; experiment and use whichever
|
|
seems clearer.
|
|
|
|
# POSSIBLY-UNCOMPUTABLE TRIGGERS
|
|
|
|
Occasionally, you may wish to suppress the \"Can\'t compute trigger\"
|
|
warnings for reminders for which a trigger date cannot be computed. For
|
|
example, the following reminder is triggered on a Monday that is not a
|
|
holiday if the following Tuesday is a holiday:
|
|
|
|
REM Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
|
|
|
|
However, if there are no Mondays after today\'s date that satisfy the
|
|
condition, **Remind** will print the \"Can\'t compute trigger\" error.
|
|
To suppress this, use the **MAYBE-UNCOMPUTABLE** keyword:
|
|
|
|
REM MAYBE-UNCOMPUTABLE Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
|
|
|
|
It\'s almost never appropriate to use **MAYBE-UNCOMPUTABLE**, but it is
|
|
provided for those rare occasions when it makes sense. If you use
|
|
**MAYBE-UNCOMPUTABLE** inside the **evaltrig()** function, then
|
|
untriggerable triggers return -1. For example:
|
|
|
|
SET a evaltrig("MAYBE-UNCOMPUTABLE Mon SKIP OMIT Mon")
|
|
|
|
will set a to -1.
|
|
|
|
# DEBUGGING REMINDER SCRIPTS
|
|
|
|
Although the command-line **-d** option is useful for debugging, it is
|
|
often overkill. For example, if you turn on the **-dx** option for a
|
|
reminder file with many complex expressions, you\'ll get a huge amount
|
|
of output. The **DEBUG** command allows you to control the debugging
|
|
flags under program control. The format is:
|
|
|
|
**DEBUG** \[+*flagson*\] \[-*flagsoff*\]
|
|
|
|
*Flagson* and *flagsoff* consist of strings of the characters
|
|
\"shextvlfqnu\" that correspond to the debugging options discussed in
|
|
the command-line options section. If preceded with a \"+\", the
|
|
corresponding group of debugging options is switched on. Otherwise, they
|
|
are switched off. For example, you could use this sequence to debug a
|
|
complicated expression:
|
|
|
|
DEBUG +x
|
|
set a very_complex_expression(many_args)
|
|
DEBUG -x
|
|
|
|
**THE DUMPVARS COMMAND**
|
|
|
|
The command **DUMPVARS** displays the values of variables in memory. Its
|
|
format is:
|
|
|
|
**DUMPVARS** \[**-c**\] \[*var*\...\]
|
|
|
|
If you supply a space-separated list of variable names, the
|
|
corresponding variables are displayed. If you do not supply a list of
|
|
variables, then all variables in memory are displayed. To dump a system
|
|
variable, put its name in the list of variables to dump. If you put a
|
|
lone dollar sign in the list of variables to dump, then all system
|
|
variables will be dumped.
|
|
|
|
If you supply the **-c** flag, then any variable determined to be
|
|
constant will have its value followed by \"\<const\>\"
|
|
|
|
**THE ERRMSG COMMAND**
|
|
|
|
The **ERRMSG** command has the following format:
|
|
|
|
**ERRMSG** *body*
|
|
|
|
The *body* is passed through the substitution filter (with an implicit
|
|
trigger date of **today()**) and printed to the error output stream.
|
|
Example:
|
|
|
|
IF !defined("critical_var")
|
|
ERRMSG You must supply a value for "critical_var"
|
|
EXIT
|
|
ENDIF
|
|
|
|
**THE EXIT COMMAND**
|
|
|
|
The above example also shows the use of the **EXIT** command. This
|
|
causes an unconditional exit from script processing. Any queued timed
|
|
reminders are discarded. If you are in calendar mode (described next),
|
|
then the calendar processing is aborted.
|
|
|
|
If you supply an **INT**-type expression after the **EXIT** command, it
|
|
is returned to the calling program as the exit status. Otherwise, an
|
|
exit status of 99 is returned.
|
|
|
|
**THE FLUSH COMMAND**
|
|
|
|
This command simply consists of the word **FLUSH** on a line by itself.
|
|
The command flushes the standard output and standard error streams used
|
|
by **Remind**. This is not terribly useful to most people, but may be
|
|
useful if you run **Remind** as a subprocess of another program, and
|
|
want to use pipes for communication.
|
|
|
|
# AGENDA MODE JSON OUTPUT
|
|
|
|
If you supply the **\--json** argument, then Remind outputs JSON instead
|
|
of the normal text output. The JSON output consists of a single JSON
|
|
array of zero or more objects. There are three possible types of objects
|
|
in the array:
|
|
|
|
**banner**
|
|
|
|
: The **banner** object, if present, will be the first object in the
|
|
array. There will be at most one **banner** object. It contains a
|
|
single key, **banner**, whose value is the banner that **Remind**
|
|
would normally print in Agenda Mode.
|
|
|
|
**noreminders**
|
|
|
|
: The **noreminders** object, if present, will be the final object in
|
|
the array. There will be at most one **noreminders** object. It
|
|
contains a single keym, **noreminders**, whose value is the phrase
|
|
\"No reminders.\", possibly localized into a different language.
|
|
|
|
**event**
|
|
|
|
: All other objects in the array are **event** objects. They are JSON
|
|
objects that contain all of the keys described in the **rem2ps**(1)
|
|
man page section \"CALENDAR ENTRIES\". However, the
|
|
**calendar_body**, **plain_body** and **raw_body** keys will not be
|
|
present.
|
|
|
|
JSON output can be used by a front-end to display an attractive list of
|
|
reminders in Agenda Mode. The \"show today\'s reminders\" feature of
|
|
**tkremind** uses the JSON output.
|
|
|
|
# CALENDAR MODE
|
|
|
|
If you supply the **-c**, **-s** or **-p** command-line option, then
|
|
**Remind** runs in \"calendar mode.\" In this mode, **Remind**
|
|
interprets the script repeatedly, performing one iteration through the
|
|
whole file for each day in the calendar. Reminders that trigger are
|
|
saved in internal buffers, and then inserted into the calendar in the
|
|
appropriate places.
|
|
|
|
If you also supply the **-a** option, then **Remind** will not include
|
|
timed reminders in the calendar.
|
|
|
|
The **-p** option is used in conjunction with the **Rem2PS** program to
|
|
produce a calendar in PostScript format. For example, the following
|
|
command will send PostScript code to standard output:
|
|
|
|
remind -p .reminders | rem2ps
|
|
|
|
You can print a PostScript calendar by piping this to the **lpr**
|
|
command.
|
|
|
|
If you have a reminder script called \".reminders\", and you execute
|
|
this command:
|
|
|
|
remind -c .reminders jan 1993
|
|
|
|
then **Remind** executes the script 31 times, once for each day in
|
|
January. Each time it executes the script, it increments the value of
|
|
**today()**. Any reminders whose trigger date matches **today()** are
|
|
entered into the calendar.
|
|
|
|
**MSG** and **CAL**-type reminders, by default, have their entire body
|
|
inserted into the calendar. **RUN**-type reminders are not normally
|
|
inserted into the calendar. However, if you enclose a portion of the
|
|
body in the %\"\...%\" sequence, only that portion is inserted. For
|
|
example, consider the following:
|
|
|
|
REM 6 Jan MSG %"Dianne's birthday%" is %b
|
|
|
|
In agenda mode, **Remind** would print \"Dianne\'s birthday is today\"
|
|
on 6 January. However, in the calendar mode, only the text \"Dianne\'s
|
|
birthday\" is inserted into the box for 6 January.
|
|
|
|
If you explicitly use the %\"\...%\" sequence in a **RUN**-type
|
|
reminder, then the text between the delimiters is inserted into the
|
|
calendar. If you use the sequence %\"%\" in a **MSG** or **CAL**-type
|
|
reminder, then no calendar entry is produced for that reminder.
|
|
|
|
**PRESERVING VARIABLES**
|
|
|
|
Because **Remind** iterates through the script for each day in the
|
|
calendar, slow operations may severely reduce the speed of producing a
|
|
calendar.
|
|
|
|
For example, suppose you set the variables \"me\" and \"hostname\" as
|
|
follows:
|
|
|
|
SET me shell("whoami")
|
|
SET hostname shell("hostname")
|
|
|
|
Normally, **Remind** clears all variables between iterations in calendar
|
|
mode. However, if certain variables are slow to compute, and will not
|
|
change between iterations, you can \"preserve\" their values with the
|
|
**PRESERVE** command. Also, since function definitions are preserved
|
|
between calendar iterations, there is no need to redefine them on each
|
|
iteration. Thus, you could use the following sequence:
|
|
|
|
IF ! defined("initialized")
|
|
set initialized 1
|
|
set me shell("whoami")
|
|
set hostname shell("hostname")
|
|
fset func(x) complex_expr
|
|
preserve initialized me hostname
|
|
ENDIF
|
|
|
|
The operation is as follows: On the first iteration through the script,
|
|
\"initialized\" is not defined. Thus, the commands between **IF** and
|
|
**ENDIF** are executed. The **PRESERVE** command ensures that the values
|
|
of initialized, me and hostname are preserved for subsequent iterations.
|
|
On the next iteration, the commands are skipped, since initialized has
|
|
remained defined. Thus, time-consuming operations that do not depend on
|
|
the value of **today()** are done only once.
|
|
|
|
Most system variables (those whose names start with \'\$\') are
|
|
automatically preserved between calendar iterations.
|
|
|
|
Note that for efficiency, **Remind** caches the reminder script (and any
|
|
**INCLUDE**d files) in memory when producing a calendar.
|
|
|
|
Timed reminders are sorted and placed into the calendar in time order.
|
|
These are followed by non-timed reminders. **Remind** automatically
|
|
places the time of timed reminders in the calendar according to the
|
|
**-b** command-line option. Reminders in calendar mode are sorted as if
|
|
the **-g** option had been used; you can change the sort order in
|
|
calendar mode by explicitly using the **-g** option to specify a
|
|
different order from the default.
|
|
|
|
**REPEATED EXECUTION**
|
|
|
|
If you supply a *repeat* parameter on the command line, and do not use
|
|
the **-c**, **-p**, or **-s** options, **Remind** operates in a similar
|
|
manner to calendar mode. It repeatedly executes the reminder script,
|
|
incrementing **today()** with each iteration. The same rules about
|
|
preserving variables and function definitions apply. Note that using
|
|
*repeat* on the command line also enables the **-q** option and disables
|
|
any **-z** option. As an example, if you want to see how **Remind** will
|
|
behave for the next week, you can type:
|
|
|
|
remind .reminders '*7'
|
|
|
|
If you want to print the dates of the next 1000 days, use:
|
|
|
|
(echo 'banner %'; echo 'msg [today()]%') | remind - '*1000'
|
|
|
|
# INITIALIZING VARIABLES ON THE COMMAND LINE
|
|
|
|
The **-i** option is used to initialize variables on the **Remind**
|
|
command line. The format is **-i**_var=expr_, where *expr* is any
|
|
valid expression. Note that you may have to use quotes or escapes to
|
|
prevent the shell from interpreting special characters in *expr*. You
|
|
can have as many **-i** options as you want on the command line, and
|
|
they are processed in order. Thus, if a variable is defined in one
|
|
**-i** option, it can be referred to by subsequent **-i** options.
|
|
|
|
Note that if you supply a date on the command line, it is not parsed
|
|
until all options have been processed. Thus, if you use **today()** in
|
|
any of the **-i** expressions, it will return the same value as
|
|
**realtoday()** and not the date supplied on the command line.
|
|
|
|
Any variables defined on the command line are **preserved** as with the
|
|
**PRESERVE** command.
|
|
|
|
You should not have any spaces between the **-i** option and the equal
|
|
sign; otherwise, strange variable names are created that can only be
|
|
accessed with the **value()** or **defined()** functions.
|
|
|
|
You can also define a function on the command line by using:
|
|
|
|
**-i**_func(args)=definition_
|
|
|
|
Be sure to protect special characters from shell interpretation.
|
|
|
|
# MORE ABOUT POSTSCRIPT
|
|
|
|
The **PS** and **PSFILE** reminders pass PostScript code directly to the
|
|
printer. They differ in that the **PS**-type reminder passes its body
|
|
directly to the PostScript output (after processing by the substitution
|
|
filter) while the **PSFILE**-type\'s body should simply consist of a
|
|
filename. The **Rem2PS** program will open the file named in the
|
|
**PSFILE**-type reminder, and include its contents in the PostScript
|
|
output.
|
|
|
|
The PostScript-type reminders for a particular day are included in the
|
|
PostScript output in sorted order of priority. Note that the order of
|
|
PostScript commands has a *major* impact on the appearance of the
|
|
calendars. For example, PostScript code to shade a calendar box will
|
|
obliterate code to draw a moon symbol if the moon symbol code is placed
|
|
in the calendar first. For this reason, you should not provide **PS** or
|
|
**PSFILE**-type reminders with priorities; instead, you should ensure
|
|
that they appear in the reminder script in the correct order. PostScript
|
|
code should draw objects working from the background to the foreground,
|
|
so that foreground objects properly overlay background ones. If you
|
|
prioritize these reminders and run the script using descending sort
|
|
order for priorities, the PostScript output will not work.
|
|
|
|
All of the PostScript code for a particular date is enclosed in a
|
|
**save**-**restore** pair. However, if several PostScript-type reminders
|
|
are triggered for a single day, each section of PostScript is not
|
|
enclosed in a **save**-**restore** pair - instead, the entire body of
|
|
included PostScript is enclosed.
|
|
|
|
PostScript-type reminders are executed by the PostScript printer before
|
|
any regular calendar entries. Thus, regular calendar entries will
|
|
overlay the PostScript-type reminders, allowing you to create shaded or
|
|
graphical backgrounds for particular days.
|
|
|
|
Before executing your PostScript code, the origin of the PostScript
|
|
coordinate system is positioned to the bottom left-hand corner of the
|
|
\"box\" in the calendar representing **today()**. This location is
|
|
exactly in the middle of the intersection of the bottom and left black
|
|
lines delineating the box - you may have to account for the thickness of
|
|
these lines when calculating positions.
|
|
|
|
Several PostScript variables are available to the PostScript code you
|
|
supply. All distance and size variables are in PostScript units (1/72
|
|
inch.) The variables are:
|
|
|
|
LineWidth
|
|
|
|
: The width of the black grid lines making up the calendar.
|
|
|
|
Border
|
|
|
|
: The border between the center of the grid lines and the space used
|
|
to print calendar entries. This border is normally blank space.
|
|
|
|
BoxWidth and BoxHeight
|
|
|
|
: The width and height of the calendar box, from center-to-center of
|
|
the black gridlines.
|
|
|
|
InBoxHeight
|
|
|
|
: The height from the center of the bottom black gridline to the top
|
|
of the regular calendar entry area. The space from here to the top
|
|
of the box is used only to draw the day number.
|
|
|
|
/DayFont, /EntryFont, /SmallFont, /TitleFont and /HeadFont
|
|
|
|
: The fonts used to draw the day numbers, the calendar entries, the
|
|
small calendars, the calendar title (month, year) and the
|
|
day-of-the-week headings, respectively.
|
|
|
|
DaySize, EntrySize, TitleSize and HeadSize
|
|
|
|
: The sizes of the above fonts. (The size of the small calendar font
|
|
is *not* defined here.) For example, if you wanted to print the
|
|
Hebrew date next to the regular day number in the calendar, use:
|
|
|
|
```{=html}
|
|
<!-- -->
|
|
```
|
|
REM PS Border BoxHeight Border sub DaySize sub moveto \
|
|
/DayFont findfont DaySize scalefont setfont \
|
|
([hebday(today())] [hebmon(today())]) show
|
|
|
|
> Note how /DayFont and DaySize are used.
|
|
|
|
Note that if you supply PostScript code, it is possible to produce
|
|
invalid PostScript files. Always test your PostScript thoroughly with a
|
|
PostScript viewer before sending it to the printer. You should not use
|
|
any document structuring comments in your PostScript code.
|
|
|
|
# DAEMON MODE
|
|
|
|
If you use the **-z** command-line option, **Remind** runs in \"daemon
|
|
mode\". In this mode, no \"normal\" reminders are issued. Instead, only
|
|
timed reminders are collected and queued, and are then issued whenever
|
|
they reach their trigger time.
|
|
|
|
In addition, **Remind** wakes up every few minutes to check the
|
|
modification date on the reminder script (the filename supplied on the
|
|
command line.) If **Remind** detects that the script has changed, it
|
|
re-executes itself in daemon mode, and interprets the changed script. If
|
|
**Remind** was compiled with support for **inotify**(7), then if the
|
|
command-line reminder script is really a directory, **Remind** also
|
|
re-executes itself if any of the files in the directory is changed.
|
|
|
|
In daemon mode, **Remind** also re-reads the remind script when it
|
|
detects that the system date has changed.
|
|
|
|
In daemon mode, **Remind** acts as if the **-f** option had been used,
|
|
so to run in daemon mode in the background, use:
|
|
|
|
remind -z .reminders &
|
|
|
|
If you use **sh** or **bash**, you may have to use the \"nohup\" command
|
|
to ensure that the daemon is not killed when you log out.
|
|
|
|
# PURGE MODE
|
|
|
|
If you supply the **-j** command-line option, **Remind** runs in *purge
|
|
mode*. In this mode, it tries to purge expired reminders from your
|
|
reminder files.
|
|
|
|
In purge mode, **Remind** reads your reminder file and creates a new
|
|
file by appending \".purged\" to the original file name. Note that
|
|
**Remind** *never* edits your original file; it always creates a new
|
|
.purged file.
|
|
|
|
If you invoke **Remind** against a directory instead of a file, then a
|
|
.purged file is created for each \*.rem file in the directory.
|
|
|
|
Normally, **Remind** does not create .purged files for INCLUDed files.
|
|
However, if you supply a numeric argument after **-j**, then **Remind**
|
|
will create .purged files for the specified level of INCLUDE. For
|
|
example, if you invoke **Remind** with the argument **-j2**, then
|
|
.purged files will be created for the file (or directory) specified on
|
|
the command line, any files included by them, and any files included by
|
|
those files. However, .purged files will not be created for
|
|
third-or-higher level INCLUDE files.
|
|
|
|
Determining which reminders have expired is extremely tricky. **Remind**
|
|
does its best, but you should always compare the .purged file to the
|
|
original file and hand-merge the changes back in.
|
|
|
|
**Remind** annotates the .purged file as follows:
|
|
|
|
An expired reminder is prefixed with: #!P: Expired:
|
|
|
|
In situations where **Remind** cannot reliably determine that something
|
|
was expired, you may see the following comments inserted before the
|
|
problematic line:
|
|
|
|
#!P: Cannot purge SATISFY-type reminders
|
|
|
|
#!P: The next IF evaluated false...
|
|
#!P: REM statements in IF block not checked for purging.
|
|
|
|
#!P: The previous IF evaluated true.
|
|
#!P: REM statements in ELSE block not checked for purging
|
|
|
|
#!P: The next IFTRIG did not trigger.
|
|
#!P: REM statements in IFTRIG block not checked for purging.
|
|
|
|
#!P: Next line has expired, but contains expression... please verify
|
|
|
|
#!P: Next line may have expired, but contains non-constant expression
|
|
#!P: or a relative SCANFROM clause
|
|
|
|
#!P! Could not parse next line: Some-Error-Message-Here
|
|
|
|
#!P! Problem calculating trigger date
|
|
|
|
**Remind** always annotates .purged files with lines beginning with
|
|
\"#!P\". If such lines are encountered in the *original* file, they are
|
|
not copied to the .purged file.
|
|
|
|
If you use the \"Hush\" flag **-h** in conjunction with the \"Purge\"
|
|
flag **-j**, then **Remind** does *not* create any of the diagnostic
|
|
comments listed above. Instead, the only change it makes to the .purged
|
|
file is to mark expired reminders with \"#!P: Expired\".
|
|
|
|
# NON-CONSTANT EXPRESSIONS
|
|
|
|
In Purge Mode, **Remind** will not mark a REM statement as expired if
|
|
its trigger specification contains a non-constant expression. A
|
|
non-constant expression is defined as one whose value might differ from
|
|
run to run, usually because it depends on the current date, but also if
|
|
it depends on something from the environment (such as the output of the
|
|
**shell()** function.)
|
|
|
|
The use of any of the following in an expression causes **Remind** to
|
|
consider it non-constant:
|
|
|
|
> **o**
|
|
>
|
|
> : A global variable that has been assigned the result of a
|
|
> non-constant expression, or that has been assigned a value in a
|
|
> *non-constant* context (to be described later.)
|
|
>
|
|
> **o**
|
|
>
|
|
> : A system variable
|
|
>
|
|
> **o**
|
|
>
|
|
> : Certain built-in functions that depend on the current date (for
|
|
> example, **today()**) or the environment (for example,
|
|
> **shell()**).
|
|
|
|
In addition, for the purposes of safely expiring reminders in Purge
|
|
Mode, **Remind** considers the following to be non-constant:
|
|
|
|
> **o**
|
|
>
|
|
> : The use of an OMITFUNC
|
|
>
|
|
> **o**
|
|
>
|
|
> : The use of a relative SCANFROM
|
|
|
|
Whenever a variable is assigned a value, **Remind** tracks whether or
|
|
not the expression whose value it was assigned is constant or
|
|
non-constant. Additionally, variables that are assigned in a
|
|
non-constant context are always assumed to be non-constant. A
|
|
non-constant context is the code in the scope of an **IF** statement
|
|
where the **IF** expression is non-constant.
|
|
|
|
Here are some examples that should make things clear:
|
|
|
|
SET d '2025-06-01' # d is constant
|
|
REM [d] MSG Hello! # eligible for purging
|
|
|
|
SET d today() - 3 # d is non-constant
|
|
REM [d] MSG Hello! # not eligible for purging
|
|
|
|
IF wkdaynum(today()) == 3
|
|
set d '2025-06-01' # d is non-constant
|
|
ELSE
|
|
set d '2026-01-01' # d is non-constant
|
|
ENDIF
|
|
|
|
SET d '2025-06-01' # d is constant
|
|
IF today() > today() + 3 # This branch is never taken, but...
|
|
SET d '2029-01-01' # d is still marked non-constant
|
|
ENDIF
|
|
|
|
# Although here d is still '2025-06-01', it is marked
|
|
# non-constant because as far as Remind is concerned,
|
|
# the IF body *might* have been executed depending on today()
|
|
|
|
Note that within the **IF**\...**ENDIF** scope, any assignments are
|
|
non-constant because the code flow depends on today\'s date, which could
|
|
change in subsequent **Remind** runs. If you want to force a variable to
|
|
be treated as constant, no matter what, then use the following just
|
|
before you use the variable:
|
|
|
|
SET var const(var)
|
|
|
|
Variables initialized on the command-line with the **-i** flag are
|
|
*always* considered to be non-constant.
|
|
|
|
If you have an expired reminder that for some reason you never want
|
|
purged, simply use the built-in function **nonconst** somewhere in the
|
|
trigger. For example:
|
|
|
|
REM 1992-01-01 MSG This will be purged after Jan 1 1992
|
|
REM [nonconst('1992-01-01')] MSG This will never be purged
|
|
|
|
REM Wed UNTIL 1993-12-31 MSG This will be purged after 1993
|
|
REM Wed UNTIL [nonconst('1993-12-31')] MSG Never purged
|
|
|
|
The **n** debugging flag prints a message to standard error whenever
|
|
**Remind** decides that an expression is non-constant. This can produce
|
|
a large amount of output, so if you want to find out why **Remind**
|
|
considers a specific expression to be non-constant, it\'s best to use
|
|
**DEBUG +n** before it and **DEBUG -n** after it to limit the amount of
|
|
output.
|
|
|
|
# SORTING REMINDERS
|
|
|
|
The **-g** option causes **Remind** to sort reminders by trigger date,
|
|
time and priority before issuing them. Note that reminders are still
|
|
calculated in the order encountered in the script. However, rather than
|
|
being issued immediately, they are saved in an internal buffer. When
|
|
**Remind** has finished processing the script, it issues the saved
|
|
reminders in sorted order. The **-g** option can be followed by up to
|
|
four characters that must all be \"a\" or \"d\". The first character
|
|
specifies the sort order by trigger date (ascending or descending), the
|
|
second specifies the sort order by trigger time and the third specifies
|
|
the sort order by priority. If the fourth character is \"d\", the
|
|
untimed reminders are sorted before timed reminders. The default is to
|
|
sort all fields in ascending order and to sort untimed reminders after
|
|
timed reminders.
|
|
|
|
In ascending order, reminders are issued with the most imminent first.
|
|
Descending order is the reverse. Reminders are always sorted by trigger
|
|
date, and reminders with the same trigger date are then sorted by
|
|
trigger time. If two reminders have the same date and time, then the
|
|
priority is used to break ties. Reminders with the same date, time and
|
|
priority are issued in the order they were encountered.
|
|
|
|
You can define a user-defined function called SORTBANNER that takes one
|
|
**DATE**-type argument. In sort mode, the following sequence happens:
|
|
|
|
If **Remind** notices that the next reminder to issue has a different
|
|
trigger date from the previous one (or if it is the first one to be
|
|
issued), then SORTBANNER is called with the trigger date as its
|
|
argument. The result is coerced to a string, and passed through the
|
|
substitution filter with the appropriate trigger date. The result is
|
|
then displayed.
|
|
|
|
Here\'s an example - consider the following fragment:
|
|
|
|
# Switch off the normal banner
|
|
BANNER %
|
|
REM 11 March 1993 ++1 MSG Not so important
|
|
REM 17 March 1993 ++7 MSG Way in the future
|
|
REM 10 March 1993 MSG Important Reminder
|
|
REM 11 March 1993 ++1 MSG Not so important - B
|
|
FSET sortbanner(x) iif(x == today(), \
|
|
"***** THINGS TO DO TODAY *****", \
|
|
"----- Things to do %b -----")
|
|
|
|
Running this with the **-gaa** option on 10 March 1993 produces the
|
|
following output:
|
|
|
|
***** THINGS TO DO TODAY *****
|
|
|
|
Important Reminder
|
|
|
|
----- Things to do tomorrow -----
|
|
|
|
Not so important
|
|
|
|
Not so important - B
|
|
|
|
----- Things to do in 7 days' time -----
|
|
|
|
Way in the future
|
|
|
|
You can use the **args()** built-in function to determine whether or not
|
|
SORTBANNER has been defined. (This could be used, for example, to
|
|
provide a default definition for SORTBANNER in a system-wide file
|
|
included at the end of the user\'s file.) Here\'s an example:
|
|
|
|
# Create a default sortbanner function if it hasn't already
|
|
# been defined
|
|
if args("sortbanner") != 1
|
|
fset sortbanner(x) "--- Things to do %b ---"
|
|
endif
|
|
|
|
# MSGPREFIX() AND MSGSUFFIX()
|
|
|
|
You can define two functions in your script called **msgprefix()** and
|
|
**msgsuffix()**. They should each accept one argument, a number from 0
|
|
to 9999.
|
|
|
|
In agenda mode, for **MSG**- and **MSF**-type reminders, the following
|
|
sequence occurs when **Remind** triggers a reminder:
|
|
|
|
o
|
|
|
|
: If **msgprefix()** is defined, it is evaluated with the priority of
|
|
the reminder as its argument. The result is printed. It is *not*
|
|
passed through the substitution filter.
|
|
|
|
o
|
|
|
|
: The body of the reminder is printed.
|
|
|
|
o
|
|
|
|
: If **msgsuffix()** is defined, it is evaluated with the priority of
|
|
the reminder as its argument. The result is printed. It is *not*
|
|
passed through the substitution filter.
|
|
|
|
Here\'s an example: The following definition causes priority-0 reminders
|
|
to be preceded by \"URGENT\", and priority-6000 reminders to be preceded
|
|
by \"(not important)\".
|
|
|
|
fset msgprefix(x) iif(x==0, "URGENT: ", \
|
|
x==6000, "(not important) ", "")
|
|
|
|
In Calendar Mode (with the **-c**, **-s** or **-p** options), an
|
|
analogous pair of functions named **calprefix()** and **calsuffix()**
|
|
can be defined. They work with all reminders that produce an entry in
|
|
the calendar (i.e., **CAL**- and possibly **RUN**-type reminders as well
|
|
as **MSG**-type reminders.)
|
|
|
|
**NOTES**
|
|
|
|
Normally, the body of a reminder is followed by a carriage return. Thus,
|
|
the results of **msgsuffix()** will appear on the next line. If you
|
|
don\'t want this, make sure the output of **msgsuffix** begins with a
|
|
backspace. This places the suffix *before* rather than after the
|
|
carriage return. (The backspace character itself is stripped out.) Here
|
|
is an example:
|
|
|
|
FSET msgsuffix(x) char(8) + " - suffix on same line"
|
|
|
|
If **Remind** has problems evaluating **msgprefix()**, **msgsuffix()**
|
|
or **sortbanner()**, you will see a lot of error messages. For an
|
|
example of this, define the following:
|
|
|
|
fset msgprefix(x) x/0
|
|
|
|
# COMPILE-TIME SUPPORT FOR OTHER LANGUAGES
|
|
|
|
**Remind** used to support compile-time localization to other languages,
|
|
but no longer does. All localization is now done at run-time.
|
|
|
|
# RUN-TIME SUPPORT FOR OTHER LANGUAGES
|
|
|
|
**Remind** has run-time support for other languages, and compile-time
|
|
support has been removed in favour of run-time support.
|
|
|
|
A number of system variables let you translate various phrases to other
|
|
languages. These system variables are:
|
|
|
|
**\$Monday, \$Tuesday, \$Wednesday, \$Thursday, \$Friday, \$Saturday, \$Sunday**
|
|
|
|
: Set each of these system variables to a string representing the
|
|
corresponding day\'s name in your language. Strings must be valid
|
|
UTF-8 strings.
|
|
|
|
**\$January, \$February, \$March, \$April, \$May, \$June, \$July, \$August, \$September, \$October, \$November, \$December**
|
|
|
|
: Set each of these system variables to a string representing the
|
|
corresponding month\'s name in your language. Strings must be valid
|
|
UTF-8 strings.
|
|
|
|
**\$Ago, \$Am, \$And, \$At, \$Hour, \$Is, \$Minute, \$Now, \$On, \$Pm, \$Today, \$Tomorrow, \$Was**
|
|
|
|
: Set each of these system variables to the translation of the
|
|
corresponding English word into your language. Note that **\$Am**
|
|
and **\$Pm** should be the translations of \"AM\" and \"PM\"
|
|
(morning and afternoon time indicators) respectively.
|
|
|
|
**\$Hplu, \$Mplu**
|
|
|
|
: Set these to the suffix to add to the word for \"hour\" and
|
|
\"minute\" to make them plural. In English, both would be set to
|
|
\"s\".
|
|
|
|
**\$Fromnow**
|
|
|
|
: Set this to the translation of the English phrase \"from now\"
|
|
|
|
Note that if you set any of the language-related system variables, they
|
|
should be set in a section of your script that always is evaluated. If
|
|
you set them inside an **IF** statement, for example, results are
|
|
unpredictable.
|
|
|
|
Note also that the **Rem2PS** back-end does not support the full range
|
|
of UTF-8 characters. The **TkRemind**, **rem2html** and **rem2pdf**
|
|
back-ends all do support the full UTF-8 range.
|
|
|
|
# RUN-TIME MODIFICATION OF THE SUBSTITUTION FILTER
|
|
|
|
The system variables mentioned in the previous section are not typically
|
|
sufficient to properly translate Remind\'s output to another language.
|
|
Some languages have complicated rules for AM vs PM times and others have
|
|
complex rules for making words plural. **Remind** therefore allows you
|
|
to define a number of functions that modify the behavior of the
|
|
substitution filter at run-time. The functions are:
|
|
|
|
**subst_ampm(h)**
|
|
|
|
: This function is passed a single integer, namely an hour from 0
|
|
to 23. It should return a string that indicates \"AM\" or \"PM\" or
|
|
even finer gradations in some languages.
|
|
|
|
**subst_ordinal(d)**
|
|
|
|
: This function is passed a single integer, namely a day of the month
|
|
from 1 to 31. It should return a string that is suffixed to the day
|
|
number to turn it into an ordinal number. In English, for example,
|
|
the function might return \"st\", \"nd\", \"rd\" or \"th\",
|
|
depending on *d*.
|
|
|
|
**subst\_N(alt, date, time)**
|
|
|
|
: This is actually a *family* of functions, where *N* is a letter or
|
|
number. This function *completely overrides* the substitution
|
|
sequence \"%N\". The three arguments are an integer *alt* which, if
|
|
non-zero, indicates that the alternate-mode substitution sequence
|
|
\"%\*N\" was encountered; *date* which is the trigger date of the
|
|
reminder and *time* which is the trigger time.
|
|
|
|
**subst\_Nx(alt, date, time)**
|
|
|
|
: Again, this is a *family* of functions. It is similar to the
|
|
**subst\_N** family except it is only called if *date* is two or
|
|
more days away from *today()*. This is useful if you don\'t want to
|
|
override the \"today\" or \"tomorrow\" output for most substitution
|
|
sequences.
|
|
|
|
Here\'s an example of how you might customize your substitution filter.
|
|
Suppose you want to change the \"%b\" sequence to substitute \"the day
|
|
after tomorrow\" for an event two days from now. You could do this:
|
|
|
|
FSET subst_bx(a,d,t) iif(d==today()+2, "the day after tomorrow", \
|
|
"in " + (d-today()) + " days' time")
|
|
REM [today()+3] ++3 MSG Event 1 is %b%
|
|
REM [today()+2] ++3 MSG Event 2 is %b%
|
|
REM [today()+1] ++3 MSG Event 3 is %b%
|
|
REM [today()] ++3 MSG Event 4 is %b%
|
|
|
|
The output of this script is:
|
|
|
|
Event 1 is in 3 days' time
|
|
Event 2 is the day after tomorrow
|
|
Event 3 is tomorrow
|
|
Event 4 is today
|
|
|
|
Note how Event 2\'s wording was changed from the normal \"in 2 days\'
|
|
time\", and note also that the \"tomorrow\" and \"today\" events used
|
|
the normal substitution\-\--**subst_bx** is not called for trigger days
|
|
of today or tomorrow.
|
|
|
|
As a special case, if a **subst_Nx or subst_N** function returns the
|
|
integer zero, then the normal substitution mechanism is used. Therefore,
|
|
the previous example could have been written more simply as:
|
|
|
|
FSET subst_bx(a,d,t) iif(d==today()+2, "the day after tomorrow", 0)
|
|
|
|
You can override substitution sequences that are not alphanumeric as
|
|
follows:
|
|
|
|
> Override %: with **subst_colon**
|
|
>
|
|
> Override %! with **subst_bang**
|
|
>
|
|
> Override %? with **subst_question**
|
|
>
|
|
> Override %@ with **subst_at**
|
|
>
|
|
> Override %# with **subst_hash**
|
|
|
|
You can define your own substitution sequences in addition to the
|
|
built-in ones as follows: If you define a function named
|
|
**subst\_name(alt, date, time)**, then the sequence **%{name}**
|
|
calls the function with **alt** set to 0 and **date** and **time** to
|
|
the trigger date and time, respectively. The **%{name}** sequence is
|
|
replaced with whatever the function returns. The sequence **%\*{name}**
|
|
is similar, but calls the function with **alt** set to 1.
|
|
|
|
If you use a **%{name}** sequence and the function **subst\_name** is
|
|
not defined or returns an error, then **%{name}** is replaced with the
|
|
empty string.
|
|
|
|
Note that when **Remind** invokes any callback function for a
|
|
substitution sequence, **RUN** will be disabled.
|
|
|
|
# THE TRANSLATION TABLE
|
|
|
|
To assist with localizing reminder files, **Remind** maintains a table
|
|
of translations. This is simple a lookup table that maps one string (the
|
|
original string) to a new string (the translated string.) When
|
|
**Remind** starts executing, the translation table is empty.
|
|
|
|
To add a message to the translation table, use the **TRANSLATE** command
|
|
(which may be abbreviated to **TRANS**.) The **TRANSLATE** command must
|
|
be followed by two quoted strings, separated from each other and from
|
|
the command by whitespace. For example, a Dutch language file might
|
|
contain something like this:
|
|
|
|
TRANSLATE "New Moon" "Nieuwe maan"
|
|
TRANSLATE "First Quarter" "Eerste kwartier"
|
|
TRANSLATE "Full Moon" "Volle maan"
|
|
TRANSLATE "Last Quarter" "Laatste kwartier"
|
|
|
|
To actually use the translation table, make use of the **\_** built-in
|
|
function, as follows:
|
|
|
|
REM NOQUEUE [moondatetime(0)] MSG [_("New Moon")] (%2)
|
|
REM NOQUEUE [moondatetime(1)] MSG [_("First Quarter")] (%2)
|
|
REM NOQUEUE [moondatetime(2)] MSG [_("Full Moon")] (%2)
|
|
REM NOQUEUE [moondatetime(3)] MSG [_("Last Quarter")] (%2)
|
|
|
|
By using **TRANSLATE** and **\_** judiciously, you can make your
|
|
reminder files easy to translate.
|
|
|
|
**TRANSLATE** has four additional forms: If it is followed by *one*
|
|
quoted string instead of two, then **Remind** deletes the translation
|
|
table entry for that string. If it is followed by the keyword **DUMP**,
|
|
then **Remind** dumps all translation table entries to standard output.
|
|
And if it is followed by **CLEAR**, then **Remind** deletes all of the
|
|
translation table entries.
|
|
|
|
The fourth form, **TRANSLATE GENERATE**, dumps all of the strings that
|
|
can be localized (as a series of TRANSLATE commands) to standard output.
|
|
Strings that are already localized are output with their localization;
|
|
strings that are not localized are output as:
|
|
|
|
TRANSLATE "untranslated" ""
|
|
|
|
If you want to add a new language, you can obtain a skeleton translation
|
|
file by running:
|
|
|
|
echo "TRANSLATE GENERATE" | remind -h - > /tmp/skeleton.rem
|
|
|
|
If you have an existing language file that is missing some translations,
|
|
you can update it by running:
|
|
|
|
(echo INCLUDE mylang.rem; echo TRANSLATE GENERATE) | \
|
|
remind -h - > /tmp/mylang-update.rem
|
|
|
|
and then editing **mylang-update.rem** to add in the missing
|
|
translations.
|
|
|
|
If you have some reminder scripts that use the **\_()** built-in
|
|
function or **%(\...)** substitution sequence, you can generate a list
|
|
of needed TRANSLATE commands by running:
|
|
|
|
remind -q -n -dq myscript.rem 2>&1 | grep ^TRANSLATE | sort | uniq
|
|
|
|
Note that if you **SET** various translation-related system variables
|
|
such as **\$Monday**, **\$December**, **\$Ago**, etc, then **Remind**
|
|
*also* makes a corresponding translation table entry automatically. This
|
|
is done for all of the translation-related system variables *except for*
|
|
**\$Hplu** and **\$Mplu**.
|
|
|
|
The converse applies too; creating a translation table for \"December\"
|
|
automatically sets **\$December**. And if you invoke **TRANSLATE
|
|
CLEAR**, then all translation-related system variables are set to their
|
|
default values as well.
|
|
|
|
The translation table always contains a special entry **LANGID** whose
|
|
default value is **en**. Translators are encouraged to add a **LANGID**
|
|
entry in their language files; the value should be the two-characters
|
|
ISO 639 language code.
|
|
|
|
For example, if you write a translation file for the Dutch language, add
|
|
this line:
|
|
|
|
TRANSLATE "LANGID" "nl"
|
|
|
|
Scripts can use **\_(\"LANGID\")** to query the translation language
|
|
that is in effect.
|
|
|
|
The **\_()** function uses the following procedure to obtain the
|
|
translation for a string:
|
|
|
|
> 1
|
|
>
|
|
> : Look for an exact match. If found, return.
|
|
>
|
|
> 2
|
|
>
|
|
> : If the original string had an upper-case letter, search for the
|
|
> all-lower-case equivalent. If found, make the first letter of the
|
|
> result upper-case and return.
|
|
>
|
|
> 3
|
|
>
|
|
> : If the original string started with a lower-case letter, search
|
|
> for an equivalent whose first letter is upper-case and the rest
|
|
> lower-case. If found, make the first letter of the result
|
|
> lower-case and return.
|
|
>
|
|
> 4
|
|
>
|
|
> : No translation was found. Return the original string.
|
|
|
|
# LANGUAGE PACKS
|
|
|
|
**Remind** ships with a number of language packs, which are simply
|
|
reminder scripts located in **\[\$SysInclude\]/lang**. The
|
|
currently-shipping language packs are:
|
|
|
|
da.rem (Danish), de.rem (German), es.rem (Spanish), fr.rem (French),
|
|
is.rem (Icelandic), it.rem (Italian), nl.rem (Dutch), no.rem
|
|
(Norwegian), pl.rem (Polish), pt.rem (Portuguese) and ro.rem (Romanian).
|
|
|
|
To use a language pack (in this example, de.rem), simply place this at
|
|
the top of your reminders file:
|
|
|
|
SYSINCLUDE lang/de.rem
|
|
|
|
If you want **Remind** to try to find the language pack appropriate for
|
|
your locale settings, use:
|
|
|
|
SYSINCLUDE lang/auto.rem
|
|
|
|
You are encouraged to study the language packs to see how to translate
|
|
**Remind** into additional languages.
|
|
|
|
# THE HEBREW CALENDAR
|
|
|
|
**Remind** has support for the Hebrew calendar, which is a luni-solar
|
|
calendar. This allows you to create reminders for Jewish holidays,
|
|
jahrzeits (anniversaries of deaths) and smachot (joyous occasions.)
|
|
|
|
**THE HEBREW YEAR**
|
|
|
|
The Hebrew year has 12 months, alternately 30 and 29 days long. The
|
|
months are: Tishrey, Heshvan, Kislev, Tevet, Shvat, Adar, Nisan, Iyar,
|
|
Sivan, Tamuz, Av and Elul. In Biblical times, the year started in Nisan,
|
|
but Rosh Hashana (Jewish New Year) is now celebrated on the 1st and 2nd
|
|
of Tishrey.
|
|
|
|
In a cycle of 19 years, there are 7 leap years, being years 3, 6, 8, 11,
|
|
14, 17 and 19 of the cycle. In a leap year, an extra month of 30 days is
|
|
added before Adar. The two Adars are called Adar A and Adar B.
|
|
|
|
For certain religious reasons, the year cannot start on a Sunday,
|
|
Wednesday or Friday. To adjust for this, a day is taken off Kislev or
|
|
added to Heshvan. Thus, a regular year can have from 353 to 355 days,
|
|
and a leap year from 383 to 385.
|
|
|
|
When Kislev or Heshvan is short, it is called *chaser*, or lacking. When
|
|
it is long, it is called *shalem*, or full.
|
|
|
|
The Jewish date changes at sunset. However, **Remind** will change the
|
|
date at midnight, not sunset. So in the period between sunset and
|
|
midnight, **Remind** will be a day earlier than the true Jewish date.
|
|
This should not be much of a problem in practice.
|
|
|
|
The computations for the Jewish calendar were based on the program
|
|
\"hdate\" written by Amos Shapir of the Hebrew University of Jerusalem,
|
|
Israel. He also supplied the preceding explanation of the calendar.
|
|
|
|
**HEBREW DATE FUNCTIONS**
|
|
|
|
**hebday(d_date)**
|
|
|
|
: Returns the day of the Hebrew month corresponding to the *date*
|
|
parameter. For example, 12 April 1993 corresponds to 21 Nisan 5753.
|
|
Thus, hebday(\'1993/04/12\') returns 21.
|
|
|
|
**hebmon(d_date)**
|
|
|
|
: Returns the name of the Hebrew month corresponding to *date*. For
|
|
example, hebmon(\'1993/04/12\') returns \"Nisan\".
|
|
|
|
**hebyear(d_date)**
|
|
|
|
: Returns the Hebrew year corresponding to *date*. For example,
|
|
hebyear(\'1993/04/12\') returns 5753.
|
|
|
|
**hebdate(i_day, s_hebmon \[,id_yrstart \[,i_jahr \[,i_aflag\]\]\])**
|
|
|
|
: The **hebdate()** function is the most complex of the Hebrew support
|
|
functions. It can take from 2 to 5 arguments. It returns a **DATE**
|
|
corresponding to the Hebrew date.
|
|
|
|
> The *day* parameter can range from 1 to 30, and specifies the day of
|
|
> the Hebrew month. The *hebmon* parameter is a string that must name
|
|
> one of the Hebrew months specified above. Note that the month must be
|
|
> spelled out in full, and use the English transliteration shown
|
|
> previously. You can also specify \"Adar A\" and \"Adar B.\" Month
|
|
> names are not case-sensitive.
|
|
>
|
|
> The *yrstart* parameter can either be a **DATE** or an **INT**. If it
|
|
> is a **DATE**, then the **hebdate()** scans for the first Hebrew date
|
|
> on or after that date. For example:
|
|
>
|
|
> hebdate(15, "Nisan", '1990/01/01')
|
|
>
|
|
> returns 1990/03/30, because that is the first occurrence of 15 Nisan
|
|
> on or after 1 January 1990.
|
|
>
|
|
> If *yrstart* is an **INT**, it is interpreted as a Hebrew year. Thus:
|
|
>
|
|
> hebdate(22, "Kislev", 5756)
|
|
>
|
|
> returns 1995/12/15, because that date corresponds to 22 Kislev, 5756.
|
|
> Note that none of the Hebrew date functions will work with dates
|
|
> outside **Remind\'s** normal range for dates.
|
|
>
|
|
> If *yrstart* is not supplied, it defaults to **today()**.
|
|
>
|
|
> The *jahr* modifies the behaviour of **hebdate()** as follows:
|
|
>
|
|
> If *jahr* is 0 (the default), then **hebdate()** keeps scanning until
|
|
> it finds a date that exactly satisfies the other parameters. For
|
|
> example:
|
|
>
|
|
> hebdate(30, "Adar A", 1993/01/01)
|
|
>
|
|
> returns 1995/03/02, corresponding to 30 Adar A, 5755, because that is
|
|
> the next occurrence of 30 Adar A after 1 January, 1993. This behaviour
|
|
> is appropriate for Purim Katan, which only appears in leap years.
|
|
>
|
|
> If *jahr* is 1, then the date is modified as follows:
|
|
>
|
|
> o
|
|
>
|
|
> : 30 Heshvan is converted to 1 Kislev in years when Heshvan is
|
|
> *chaser*
|
|
>
|
|
> o
|
|
>
|
|
> : 30 Kislev is converted to 1 Tevet in years when Kislev is *chaser*
|
|
>
|
|
> o
|
|
>
|
|
> : 30 Adar A is converted to 1 Nisan in non-leapyears
|
|
>
|
|
> o
|
|
>
|
|
> : Other dates in Adar A are moved to the corresponding day in Adar
|
|
> in non-leapyears
|
|
>
|
|
> This behaviour is appropriate for smachot (joyous occasions) and for
|
|
> some jahrzeits - see \"JAHRZEITS.\"
|
|
>
|
|
> if *jahr* is 2, then the date is modified as follows:
|
|
>
|
|
> o
|
|
>
|
|
> : 30 Kislev and 30 Heshvan are converted to 29 Kislev and 29
|
|
> Heshvan, respectively, if the month is *chaser*
|
|
>
|
|
> o
|
|
>
|
|
> : 30 Adar A is converted to 30 Shvat in non-leapyears
|
|
>
|
|
> o
|
|
>
|
|
> : Other dates in Adar A are moved to the corresponding day in Adar
|
|
> in non-leapyears
|
|
>
|
|
> if *jahr* is not 0, 1, or 2, it is interpreted as a Hebrew year, and
|
|
> the behaviour is calculated as described in the next section,
|
|
> \"JAHRZEITS.\"
|
|
>
|
|
> The *aflag* parameter modifies the behaviour of the function for dates
|
|
> in Adar during leap years. The *aflag* is *only* used if *yrstart* is
|
|
> a **DATE** type.
|
|
>
|
|
> The *aflag* only affects date calculations if *hebmon* is specified as
|
|
> \"Adar\". In leap years, the following algorithm is followed:
|
|
>
|
|
> o
|
|
>
|
|
> : If *aflag* is 0, then the date is triggered in Adar B. This is the
|
|
> default.
|
|
>
|
|
> o
|
|
>
|
|
> : If *aflag* is 1, then the date is triggered in Adar A. This may be
|
|
> appropriate for jahrzeits in the Ashkenazi tradition; consult a
|
|
> rabbi.
|
|
>
|
|
> o
|
|
>
|
|
> : If *aflag* is 2, then the date is triggered in both Adar A and
|
|
> Adar B of a leap year. Some Ashkenazim perform jahrzeit in both
|
|
> Adar A and Adar B.
|
|
|
|
**JAHRZEITS**
|
|
|
|
A jahrzeit is a yearly commemoration of someone\'s death. It normally
|
|
takes place on the anniversary of the death, but may be delayed if
|
|
burial is delayed - consult a rabbi for more information.
|
|
|
|
In addition, because some months change length, it is not obvious which
|
|
day the anniversary of a death is. The following rules are used:
|
|
|
|
o
|
|
|
|
: If the death occurred on 30 Heshvan, and Heshvan in the year after
|
|
the death is *chaser*, then the jahrzeit is observed on 29 Heshvan
|
|
in years when Heshvan is *chaser*. Otherwise, the jahrzeit is
|
|
observed on 1 Kislev when Heshvan is *chaser*.
|
|
|
|
o
|
|
|
|
: If the death occurred on 30 Kislev, and Kislev in the year after the
|
|
death is *chaser*, then the jahrzeit is observed on 29 Kislev in
|
|
years when Kislev is *chaser*. Otherwise, the jahrzeit is observed
|
|
on 1 Tevet when Kislev is *chaser*.
|
|
|
|
o
|
|
|
|
: If the death occurred on 1-29 Adar A, it is observed on 1-29 Adar in
|
|
non-leapyears.
|
|
|
|
o
|
|
|
|
: If the death occurred on 30 Adar A, it is observed on 30 Shvat in a
|
|
non-leapyear.
|
|
|
|
Specifying a Hebrew year for the *jahr* parameter causes the correct
|
|
behaviour to be selected for a death in that year. You may also have to
|
|
specify *aflag*, depending on your tradition.
|
|
|
|
The jahrzeit information was supplied by Frank Yellin, who quoted \"The
|
|
Comprehensive Hebrew Calendar\" by Arthur Spier, and \"Calendrical
|
|
Calculations\" by E. M. Reingold and Nachum Dershowitz.
|
|
|
|
# OUT-OF-BAND REMINDERS
|
|
|
|
The **SPECIAL** keyword is used to transmit \"out-of-band\" information
|
|
to **Remind** backends, such as **tkremind** or **Rem2PS**. They are
|
|
used only when piping data from a **remind -p** line. (Note that the
|
|
COLOR special is an exception; it works similarly to MSG when the **-p**
|
|
option is not supplied.)
|
|
|
|
The various **SPECIAL**s recognized are particular for each backend;
|
|
however, there are four **SPECIAL**s that all backends should attempt to
|
|
support. They are currently supported by **Rem2PS**, **tkremind** and
|
|
**rem2html**.
|
|
|
|
The **SHADE** special replaces the **psshade()** function. Use it like
|
|
this:
|
|
|
|
REM Sat Sun SPECIAL SHADE 128
|
|
REM Mon SPECIAL SHADE 255 0 0
|
|
|
|
The **SHADE** keyword is followed by either one or three numbers, from 0
|
|
to 255. If one number is supplied, it is interpreted as a grey-scale
|
|
value from black (0) to white (255). If three numbers are supplied, they
|
|
are interpreted as RGB components from minimum (0) to maximum (255). The
|
|
example above shades weekends a fairly dark grey and makes Mondays a
|
|
fully-saturated red. (These shadings appear in calendars produced by
|
|
**Rem2PS**, **tkremind** and **rem2html**.)
|
|
|
|
The **MOON** special replaces the **psmoon()** function. Use it like
|
|
this:
|
|
|
|
REM [moondate(0)] SPECIAL MOON 0
|
|
REM [moondate(1)] SPECIAL MOON 1
|
|
REM [moondate(2)] SPECIAL MOON 2
|
|
REM [moondate(3)] SPECIAL MOON 3
|
|
|
|
These draw little moons on the various calendars. The complete syntax of
|
|
the **MOON** special is as follows:
|
|
|
|
... SPECIAL MOON phase moonsize fontsize msg
|
|
|
|
*Phase* is a number from 0 to 3, with 0 representing a new moon, 1 the
|
|
first quarter, 2 a full moon and 3 the last quarter.
|
|
|
|
*moonsize* is the diameter in PostScript units of the moon to draw. If
|
|
omitted or supplied as -1, the backend chooses an appropriate size.
|
|
|
|
*fontsize* is the font size in PostScript units of the *msg*
|
|
|
|
*Msg* is additional text that is placed near the moon glyph.
|
|
|
|
Note that only the **Rem2PS** backend supports *moonsize* and
|
|
*fontsize*; the other backends use fixed sizes.
|
|
|
|
The **COLOR** special lets you place colored reminders in the calendar.
|
|
Use it like this:
|
|
|
|
REM ... SPECIAL COLOR 255 0 0 This is a bright red reminder
|
|
REM ... SPECIAL COLOR 0 128 0 This is a dark green reminder
|
|
|
|
You can spell COLOR either the American way (\"COLOR\") or the British
|
|
way (\"COLOUR\"). This manual will use the American way.
|
|
|
|
Immediately following COLOR should be three decimal numbers ranging from
|
|
0 to 255 specifying red, green and blue intensities, respectively. The
|
|
rest of the line is the text to put in the calendar.
|
|
|
|
The COLOR special is \"doubly special\", because in agenda mode,
|
|
**remind** treats a COLOR special just like a MSG-type reminder. Also,
|
|
if you invoke **Remind** with **-@**\[*n*\], then it approximates
|
|
SPECIAL COLOR reminders on your terminal.
|
|
|
|
See also the documentation of the **\$DefaultColor** system variable in
|
|
the section \"SYSTEM VARIABLES\".
|
|
|
|
The **WEEK** special lets you place annotations such as the week number
|
|
in the calendar. For example, this would number each Monday with the ISO
|
|
8601 week number. The week number is shown like this: \"(W*n*)\" in this
|
|
example, but you can put whatever text you like after the WEEK keyword.
|
|
|
|
REM Monday SPECIAL WEEK (W[weekno()])
|
|
|
|
# MISCELLANEOUS
|
|
|
|
**COMMAND AND KEYWORD ABBREVIATIONS**
|
|
|
|
The following tokens can be abbreviated:
|
|
|
|
o
|
|
|
|
: **CLEAR-OMIT-CONTEXT** \--\> **CLEAR**
|
|
|
|
o
|
|
|
|
: **PUSH-OMIT-CONTEXT** \--\> **PUSH**
|
|
|
|
o
|
|
|
|
: **POP-OMIT-CONTEXT** \--\> **POP**
|
|
|
|
o
|
|
|
|
: **DUMPVARS** \--\> **DUMP**
|
|
|
|
o
|
|
|
|
: **BANNER** \--\> **BAN**
|
|
|
|
o
|
|
|
|
: **INCLUDE** \--\> **INC**
|
|
|
|
o
|
|
|
|
: **MAYBE-UNCOMPUTABLE** \--\> **MAYBE**
|
|
|
|
o
|
|
|
|
: **SCANFROM** \--\> **SCAN**
|
|
|
|
**NIFTY EXAMPLES**
|
|
|
|
This section is a sampling of what you can do with **Remind**.
|
|
|
|
REM 5 Feb 1991 AT 14:00 +45 *30 \
|
|
RUN mail -s "Meeting at %2" $LOGNAME </dev/null &
|
|
|
|
On 5 February, 1991, this reminder will mail you reminders of a 2:00pm
|
|
meeting at 1:15, 1:45 and 2:00. The subject of the mail message will be
|
|
\"Meeting at 2:00pm\" and the body of the message will be blank.
|
|
|
|
REM AT 17:00 RUN echo "5:00pm - GO HOME!" | xless -g +0+0 &
|
|
|
|
This reminder will pop up an xless window at 5:00pm every day. The xless
|
|
window will contain the line \"5:00pm - GO HOME!\"
|
|
|
|
REM AT 23:59 RUN (sleep 120; remind -a [filename()]) &
|
|
|
|
This reminder will run at one minute to midnight. It will cause a new
|
|
**Remind** process to start at one minute past midnight. This allows you
|
|
to have a continuous reminder service so you can work through the night
|
|
and still get timed reminders for early in the morning. Note that this
|
|
trick is no longer necessary, providing you run **Remind** in daemon
|
|
mode.
|
|
|
|
remind -c12 /dev/null Jan 1993
|
|
|
|
This invocation of **Remind** will cause it to print a calendar for
|
|
1993, with all entries left blank.
|
|
|
|
REM CAL [trigdate()-date(year(trigdate()), 1, 1)+1]
|
|
|
|
This example puts an entry in each box of a calendar showing the number
|
|
(1-365 or 366) of the day of the year.
|
|
|
|
REM Tue 2 Nov SATISFY (year(trigdate())%4) == 0
|
|
IF trigvalid()
|
|
REM [trigdate()] ++5 MSG \
|
|
U.S. Presidential Election!!
|
|
ENDIF
|
|
|
|
This example warns you 5 days ahead of each American presidential
|
|
election. The first **REM** command calculates the first Tuesday after
|
|
the first Monday in November. (This is equivalent to the first Tuesday
|
|
on or after 2 November.) The **SATISFY** clause ensures that the trigger
|
|
date is issued only in election years, which are multiples of 4. The
|
|
second **REM** command actually issues the reminder.
|
|
|
|
**DETAILS ABOUT TRIGGER COMPUTATION**
|
|
|
|
Here is a *conceptual* description of how triggers are calculated. Note
|
|
that **Remind** actually uses a much more efficient procedure, but the
|
|
results are the same as if the conceptual procedure had been followed.
|
|
|
|
**Remind** starts from the current date (that is, the value of
|
|
**today()**) and scans forward, examining each day one at a time until
|
|
it finds a date that satisfies the trigger, or can prove that no such
|
|
dates (on or later than **today()**) exist.
|
|
|
|
If **Remind** is executing a **SATISFY**-type reminder, it evaluates the
|
|
expression with **trigdate()** set to the date found above. If the
|
|
expression evaluates to zero or the null string, **Remind** continues
|
|
the scanning procedure described above, starting with the day after the
|
|
trigger found above.
|
|
|
|
The **SCANFROM** clause (having a syntax similar to **UNTIL**) can
|
|
modify the search strategy used. In this case, **Remind** begins the
|
|
scanning procedure at *scan_date*, which is the date specified in the
|
|
**SCANFROM** clause. For example:
|
|
|
|
REM Mon 1 SCANFROM 17 Jan 1992 MSG Foo
|
|
|
|
The example above will always have a trigger date of Monday, 3 February
|
|
1992. That is because **Remind** starts scanning from 17 January 1992,
|
|
and stops scanning as soon as it hits a date that satisfies \"Mon 1.\"
|
|
|
|
The main use of **SCANFROM** is in situations where you want to
|
|
calculate the positions of floating holidays. Consider the Labour Day
|
|
example shown much earlier. Labour Day is the first Monday in September.
|
|
It can move over a range of 7 days. Consider the following sequence:
|
|
|
|
REM Mon 1 Sept SCANFROM [today()-7] ADDOMIT MSG Labour Day
|
|
REM Mon AFTER MSG Hello
|
|
|
|
The **SCANFROM** clause makes sure that **Remind** begins scanning from
|
|
7 days before the current date. This ensures that Labour Day for the
|
|
current year will continue to be triggered until 7 days after it has
|
|
occurred. This allows you to safely use the AFTER keyword as shown.
|
|
|
|
As a special case, you can simply use a negative number after SCANFROM;
|
|
a negative number -N is interpreted as N days before today. Thus, the
|
|
previous example could also be written like this:
|
|
|
|
REM Mon 1 Sept SCANFROM -7 ADDOMIT MSG Labour Day
|
|
REM Mon AFTER MSG Hello
|
|
|
|
A SCANFROM that specifies a full date is called an *absolute SCANFROM*
|
|
and a SCANFROM that specifies a negative number is called a *relative
|
|
SCANFROM*.
|
|
|
|
In general, use **SCANFROM** as shown for safe movable **OMITs**. The
|
|
amount you should scan back by (7 days in the example above) depends on
|
|
the number of possible consecutive **OMITted** days that may occur, and
|
|
on the range of the movable holiday. Generally, a value of 7 is safe.
|
|
|
|
The **FROM** clause operates almost like the counterpoint to **UNTIL**.
|
|
It prevents the reminder from triggering before the **FROM** date. For
|
|
example, the following reminder:
|
|
|
|
REM Mon Thu FROM 23 Jul 2007 UNTIL 2 Aug 2007 MSG Test
|
|
|
|
will trigger on Mondays and Thursdays between 23 July 2007 and 2 August
|
|
2007 inclusive.
|
|
|
|
**FROM** is really just syntactic sugar; you could implement the
|
|
reminder above as follows:
|
|
|
|
REM Mon Thu SCANFROM [max(today(), '2007-07-23')] \
|
|
UNTIL 2 Aug 2007 MSG Test
|
|
|
|
but that\'s a lot harder to read. Internally, **Remind** treats **FROM**
|
|
exactly as illustrated using **SCANFROM**. For that reason, you cannot
|
|
use both **FROM** and **SCANFROM**.
|
|
|
|
Note that if you use one **REM** command to calculate a trigger date,
|
|
perform date calculations (addition or subtraction, for example) and
|
|
then use the modified date in a subsequent **REM** command, the results
|
|
*may not be what you intended.* This is because you have circumvented
|
|
the normal scanning mechanism. You should try to write **REM** commands
|
|
that compute trigger dates that can be used unmodified in subsequent
|
|
**REM** commands. The file \"defs.rem\" that comes with the **Remind**
|
|
distribution contains examples.
|
|
|
|
**DETAILS ABOUT TRIGVALID()**
|
|
|
|
The **trigvalid()** function returns 1 if **Remind** could find a
|
|
trigger date for the previous **REM** or **IFTRIG** command. More
|
|
specifically, it returns 1 if **Remind** finds a date *not before the
|
|
starting* date of the scanning that satisfies the trigger. In addition,
|
|
there is one special case in which **trigvalid()** returns 1 and
|
|
**trigdate()** returns a meaningful result:
|
|
|
|
If the **REM** or **IFTRIG** command did not contain an **UNTIL** or
|
|
**SATISFY** clause, and contained all of the *day*, *month* and *year*
|
|
components, then **Remind** will correctly compute a trigger date, even
|
|
if it happens to be before the start of scanning. Note that this
|
|
behaviour is not true for versions of **Remind** prior to 03.00.01.
|
|
|
|
# FILES
|
|
|
|
The traditional location of your reminders file or directory is:
|
|
|
|
$HOME/.reminders
|
|
|
|
where **\$HOME** is your home directory.
|
|
|
|
**Remind** ships with some preinstalled files for holidays and language
|
|
packs. These are located in the following directory:
|
|
|
|
/usr/local/share/remind/
|
|
|
|
Do not hard-code the above directory in your reminder files. Instead,
|
|
use the value of the \$SysInclude system variable.
|
|
|
|
# AUTHOR
|
|
|
|
Dianne Skoll \<dianne@skoll.ca\> wrote **Remind**. The moon phase code
|
|
was copied largely unmodified from \"moontool\" by John Walker. The
|
|
moonrise/moonset code comes from https://github.com/signetica/MoonRise
|
|
by Stephen R. Schmitt and Cyrus Rahman. The sunrise and sunset functions
|
|
use ideas from programs by Michael Schwartz and Marc T. Kaufman. The
|
|
Hebrew calendar support was taken from \"hdate\" by Amos Shapir. The
|
|
supported languages and their translators are listed below. Languages
|
|
marked \"complete\" support error messages in that language; all others
|
|
only support the substitution filter mechanism and month/day names.
|
|
|
|
**German** \-- Wolfgang Thronicke
|
|
|
|
**Dutch** \-- Willem Kasdorp and Erik-Jan Vens
|
|
|
|
**Finnish** \-- Mikko Silvonen (complete)
|
|
|
|
**French** \-- Laurent Duperval (complete)
|
|
|
|
**Norwegian** \-- Trygve Randen
|
|
|
|
**Danish** \-- Mogens Lynnerup
|
|
|
|
**Polish** \-- Jerzy Sobczyk (complete)
|
|
|
|
**Brazilian Portuguese** \-- Marco Paganini (complete)
|
|
|
|
**Italian** \-- Valerio Aimale
|
|
|
|
**Romanian** \-- Liviu Daia
|
|
|
|
**Spanish** \-- Rafa Couto
|
|
|
|
**Icelandic** \-- Björn Davíðsson
|
|
|
|
# BUGS
|
|
|
|
If you find a bug in Remind, please report it to: dianne@skoll.ca
|
|
|
|
There\'s no good reason why read-only system variables are not
|
|
implemented as functions, or why functions like **version()**, etc. are
|
|
not implemented as read-only system variables.
|
|
|
|
Hebrew dates in **Remind** change at midnight instead of sunset.
|
|
|
|
**Remind** has some built-in limits (for example, number of global
|
|
**OMIT**s.)
|
|
|
|
# BIBLIOGRAPHY
|
|
|
|
Nachum Dershowitz and Edward M. Reingold, \"Calendrical Calculations\",
|
|
*Software-Practice and Experience*, Vol. 20(9), Sept. 1990, pp 899-928.
|
|
|
|
L. E. Doggett, *Almanac for computers for the year 1978*, Nautical
|
|
Almanac Office, USNO.
|
|
|
|
Richard Siegel and Michael and Sharon Strassfeld, *The First Jewish*
|
|
Catalog, Jewish Publication Society of America.
|
|
|
|
Jean Meeus, *Astronomical Algorithms, Second Edition*, Willmann-Bell,
|
|
Inc.
|
|
|
|
# HOME PAGE
|
|
|
|
https://dianne.skoll.ca/projects/remind/
|
|
|
|
# MAILING LIST
|
|
|
|
https://dianne.skoll.ca/mailman/listinfo/remind-fans
|
|
|
|
# SEE ALSO
|
|
|
|
**rem**(1), **rem2ps**(1), **rem2pdf**(1), **tkremind**(1),
|
|
**rem2html**(1)
|