From b64f3061f5dcccc53c77fb912eaea5a6ca370cc9 Mon Sep 17 00:00:00 2001 From: Paolo Donadeo Date: Mon, 18 May 2026 10:04:07 +0200 Subject: [PATCH] Removed remind man from git --- contrib/remind/remind_manual.txt | 5302 ------------------------------ 1 file changed, 5302 deletions(-) delete mode 100644 contrib/remind/remind_manual.txt diff --git a/contrib/remind/remind_manual.txt b/contrib/remind/remind_manual.txt deleted file mode 100644 index 1373da9..0000000 --- a/contrib/remind/remind_manual.txt +++ /dev/null @@ -1,5302 +0,0 @@ -REMIND(1) VERSION 06.02.05 REMIND(1) - -NAME - remind - a sophisticated reminder service - -THE BOOK OF REMIND - This man page is a good reference for Remind. However, if you are a novice wishing to learn Remind, I suggest - downloading "The Book of Remind" from the Remind home page at https://dianne.skoll.ca/projects/remind/ - -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 re‐ - minders 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 com‐ - puter-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, ac‐ - cepting 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 re‐ - minders 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 "RE‐ - MINDER 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 num‐ - ber 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 en‐ - coding. This flag also enables the use of the UNICODE "left-to-right" mark that can fix up for‐ - matting problems with right-to-left languages in the calendar display. - - 'z' has the effect of setting the system variable $TerminalHyperlinks to 1. See the documentation of - this variable in the section "SYSTEM VARIABLES" - - '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 op‐ - tion 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 documenta‐ - tion 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 approxi‐ - mation 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 termi‐ - nal 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 back‐ - ground is dark, and Remind will brighten up dark colors to make them visible. If m=1, then Remind as‐ - sumes 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 impossi‐ - ble 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. - - -wcol[,pad[,spc[,spc2]]]] - 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 stan‐ - dard 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. spc2 may be 0 or 1 and it specifies whether or not blank lines - should be printed in between reminders on the same day. The default is 1, which causes the blank lines - to be printed. - - 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 en‐ - ables 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 out‐ - put. - - Note that to pass INFO strings to a back-end, you must use -pp or -ppp. The simpler -p format is not ca‐ - pable 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 vari‐ - able. - - -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, re‐ - gardless 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 re‐ - minders 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 re‐ - minders in the calendar if at least one -a option is used.) - - -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. - - -dchars - 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 - - p Issue warnings if a POP-OMIT-CONTEXT, POP-VARS or POP-FUNCS matches a corresponding PUSH that is - in a different file. - - 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 com‐ - mands: - - 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 %(...) substitu‐ - tion 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 char‐ - acters 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 de‐ - fault 0. A value of 0 causes times to be inserted in 12-hour (am/pm) format. 1 causes times to be in‐ - serted 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. - - -kcmd 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 -kcmd1 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. - - -uname 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, us‐ - ing -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 vari‐ - ables 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. - - -ivar=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, -ivar is exactly the same as -ivar=0. - - -ifunc(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 no‐ - tion 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 de‐ - tails. 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 run‐ - ning: - - 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.) - - --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 sensi‐ - ble 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 op‐ - tion 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 back‐ - slash 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, parame‐ - ters, invocation options, etc. - -THE REM COMMAND - The most powerful command in a Remind script is the REM command. This command is responsible for issuing re‐ - minders. 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 com‐ - mand-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 us‐ - age 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 para‐ - graph-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 con‐ - secutive 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 sys‐ - tem 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 re‐ - minder depends on the back-end. For the Rem2PS back-end, SPECIAL PostScript is equivalent to a PS-type re‐ - minder, 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 par‐ - ticular 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 TRIG‐ - GER 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 key‐ - word 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 compo‐ - nent 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 ver‐ - sions 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 PRI‐ - ORITY 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 re‐ - minder 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 spec‐ - ified 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 con‐ - sidered "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 "omit‐ - ted". 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 spe‐ - cific 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 automati‐ - cally 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 repre‐ - senting 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 reaches 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 is‐ - sued 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 al‐ - lows precise control over the advance triggering of all types of reminders. However, discussion must be de‐ - ferred until after expressions and user-defined functions are explained. See the subsection "PRECISE SCHEDUL‐ - ING" 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 syn‐ - thesized 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_strings they recognize, and must ignore info_strings 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 can‐ - not 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 stan‐ - dard 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 dig‐ - its. - - %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 ac‐ - tual number of days between these two dates; OMITs are not counted. (Strict date subtraction is per‐ - formed.) - - %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. - - % - 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 new‐ - line. - - %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:mmam" 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-nega‐ - tive. - - %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 com‐ - pared. - - %? 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 com‐ - pared. - - %@ 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 "CAL‐ - ENDAR 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 $Ad‐ - dBlankLines 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 exam‐ - ple, %*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 re‐ - minder. 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 sub‐ - stituted 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, meet‐ - ings, 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 ex‐ - ample: - - 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. The keyword COMPLETED-THROUGH may be - used as a synonym for COMPLETE-THROUGH. - -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 Re‐ - mind'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 week‐ - ends. - - 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 ad‐ - vanced 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 equiv‐ - alent: - - 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 exam‐ - ple, 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: Sup‐ - pose 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 direc‐ - tive. 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 recom‐ - mended!) 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 subdirecto‐ - ries!) 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 contain‐ - ing standard reminder scripts. For this installation of Remind, the system directory is "/usr/local/share/re‐ - mind". - -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 un‐ - desired actions. The RUN command can restrict this: If you include the command RUN OFF in your top-level re‐ - minder 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 re‐ - minder script; it will not work in any files accessed by the INCLUDE command. This is to protect you from some‐ - one 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() func‐ - tion. 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 ap‐ - propriate 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 it‐ - self 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 exe‐ - cuted. 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 im‐ - plicit 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 intro‐ - duce 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 corre‐ - sponds to the C "int" type. - - STRING The STRING data type consists of strings of characters. It is somewhat comparable to a C character ar‐ - ray, 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, and several more. - These are not safe to use on multi-byte strings; instead use mbindex, mbstrlen and mbsubstr, and the mb - variants of the others. 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. - - TIME The TIME data type is used for two different purposes: To represent a time of day with one-minute preci‐ - sion or to represent a duration with one-minute precision. The context of where a TIME is used deter‐ - mines 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 inter‐ - nally 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. - - 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", "", "π is Cool! 🙂" - - 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, op‐ - tionally 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, re‐ - turns 1. - - - Unary minus. Can be applied to an INT. Returns the negative of the operand. - - * Multiplication. Returns the product of two INTs. 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 INTs, 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 INTs. - - INT + TIME or TIME + INT - returns a TIME obtained by adding INT minutes to the original TIME. The re‐ - sult 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 STRINGs. - - 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 INTs. - - DATE - DATE - returns (as an INT) the difference in days between two DATEs. - - TIME - TIME - returns (as an INT) the difference in minutes between two TIMEs. - - DATETIME - DATETIME - returns (as an INT) the difference in minutes between two DATETIMEs. - - 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 in‐ - equality. - - 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 other‐ - wise. 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 -ivar=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 con‐ - trol 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. - - $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 $MinsFro‐ - mUTC 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 dae‐ - mon 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 consid‐ - ered 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. Con‐ - sider 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 fol‐ - lowing: - - 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 re‐ - minders 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, $De‐ - faultDelta 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 -tn 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 char‐ - acters. 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 pe‐ - riod. - - $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 out‐ - put 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 represen‐ - tation, this will be 2147483647. - - $IntMin (read-only) - The smallest representable INT. On a machine with 32-bit signed integers using twos-complement represen‐ - tation, 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" lo‐ - cale 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 nega‐ - tive 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 lat‐ - itude 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 rea‐ - sons, 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 re‐ - minder 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. The de‐ - fault value is 10,000. - - $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 un‐ - til 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 your‐ - self. 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 fol‐ - lows: 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 re‐ - minders. 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 sec‐ - tion "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 Re‐ - mind 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. - - $Shaded (read-only) - Returns the number of times a SHADE special reminder has triggered. This variable is set only in calen‐ - dar mode, not agenda mode. You can use this variable to avoid shading a calendar day that has already - been shaded. - - For example, suppose you want to shade all calendar boxes yellow if any reminders have triggered on that - day. But if a box has been explicitly shaded, you don't want to overwrite that shading. You could use - something like this: - - SET n $NumTrig - # Do all your reminders here... - - # If anything has triggered and the box is - # not already shaded, then shade it yellow - IF $NumTrig > n && !$Shaded - REM SPECIAL SHADE 255 255 128 - ENDIF - - $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 de‐ - scending 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 prior‐ - ity 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 de‐ - scending 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 $SuppressImplicit‐ - Warnings to 1 suppresses these warnings. The default is 0 and we do not recommend disabling the warn‐ - ings. - - $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 holi‐ - day files and language packs. The value of $SysInclude is "/usr/local/share/remind" on this installa‐ - tion. - - $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. - - $TerminalHyperlinks (INT type) - If your terminal supports escape sequences to allow HTML-like anchors around text (see - https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda), then you can set this variable to 1. - Remind will then make any reminder with a "Url:" info string into a hyperlink in your terminal. By de‐ - fault, $TerminalHyperlinks is set to 1 if Remind's standard output is a terminal, or to 0 if it is not. - - $WarningLevel (STRING type) - As new versions of Remind are released, new warnings may be added. If your formerly-fine scripts sud‐ - denly start issuing warnings when you upgrade Remind, then as a stopgap measure, you may set $Warn‐ - ingLevel 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 $Warn‐ - ingLevel, 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, $Don‐ - tQueue, $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) sys‐ - tem 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 vari‐ - ables 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 fol‐ - lowed 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 re‐ - turns 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 to‐ - day(). - - 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, re‐ - spectively; 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; other‐ - wise, 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 parame‐ - ters red, green and blue are integers from 0 to 255 specifying the value of the respective color compo‐ - nent. As a special case, all three values can be -1, in which case the ANSI sequence "ESC[0m" is re‐ - turned, 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 ansi‐ - color(-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-de‐ - fined function exists. Note that this function examines only user-defined functions, not built-in func‐ - tions. 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 evalu‐ - ation 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 speci‐ - fied 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) re‐ - turns "". - - 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 nth sub‐ - sequent 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: - - 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 mid‐ - night. 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 either standard output or standard error is - a TTY, returns the width of the terminal in columns. If neither standard output nor standard error is 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 with‐ - out 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 charac‐ - ters 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 gen‐ - erated 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 sec‐ - ond 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 compo‐ - nent 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, re‐ - turns 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 sub‐ - stitution 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-es‐ - caped. 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 com‐ - puted. - - 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 No‐ - vember, 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 be‐ - fore 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: - - 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() re‐ - turns the directory containing the symbolic link and not the directory containing the target of the sym‐ - bolic 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, re‐ - turns 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 environ‐ - ment variable. Returns "" if the environment variable is not defined. Note that the names of environ‐ - ment 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 in‐ - terpreted 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; re‐ - turns 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 ex‐ - pression but evaluated in a non-constant context, isconst will still return 1. For details about con‐ - stant 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 de‐ - faults 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 start‐ - ing 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 date‐ - time 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 bytes in string converted to lower-case. Note: This function works - correctly only for ASCII strings. If you are using Unicode characters outside the ASCII set, use mblower - instead. - - mblower(s_string) - Returns a STRING with all upper-case characters in string converted to lower-case. This function works - correctly on any Unicode string. - - 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 speci‐ - fied 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 start‐ - ing 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() func‐ - tions are accurate to within a couple of minutes of the times in "Old Farmer's Almanac" for Ottawa, On‐ - tario. - - 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, re‐ - spectively. The returned value is an integer from 0 to 359, representing the phase of the moon in de‐ - grees. 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 mid‐ - night 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 moon‐ - rise 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 mid‐ - night 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 earli‐ - est 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 week‐ - days 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 Wednes‐ - day, 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 plas‐ - tic 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 de‐ - tails, 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. Note that in Calendar Mode, now() always returns 00:00. - - 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 bytes, pads - to to len bytes 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" - - mbpad(x_arg, s_padstr, i_len [, i_right]) - This is the multibyte counterpart to pad. The length is specified in characters rather than bytes. Use - mbpad rather than pad if either of the strings contains non-ASCII characters. - - 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 Post‐ - Script 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 Post‐ - Script 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, or 00:00 in Calendar Mode. - - realtoday() - Returns the date as provided by the operating system. This is in contrast to Remind's concept of "to‐ - day", which may be changed if it is running in calendar mode, or if a date has been supplied on the com‐ - mand line. - - rows() If either standard output or standard error is a TTY, returns the height of the terminal in rows. If - neither standard output nor standard error is 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: - - 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 stepth 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 speci‐ - fies 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 sup‐ - plied, 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 lati‐ - tudes, 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 sup‐ - plied, 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 com‐ - mand line, or (in Calendar Mode) 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 de‐ - tails 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 com‐ - mand, 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 trigdate‐ - time(). If the REM command did not have an AT clause, returns the integer -1 (and differs from trigdate‐ - time() 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 informa‐ - tion. - - 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 trig‐ - ger 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 "re‐ - peat" 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 SCAN‐ - FROM 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 pa‐ - rameter, 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 calcu‐ - late 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 trig‐ - gered. Returns the empty string if there were no TAGs. If there are multiple tags, they are each sepa‐ - rated 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: - - 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. - - upper(s_string) - Returns a STRING with all lower-case bytes in string converted to upper-case. Note: This function works - correctly only for ASCII strings. If you are using Unicode characters outside the ASCII set, use mbupper - instead. - - mbupper(s_string) - Returns a STRING with all lower-case characters in string converted to upper-case. This function works - correctly on any Unicode string. - - 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.05, returns "06.02.05". It is - guaranteed that as new versions of Remind are released, the value returned by version() will strictly in‐ - crease, 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 (follow‐ - ing 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 can‐ - not 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 cor‐ - rects 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: - - 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: - - ["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 in‐ - voked, 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 se‐ - quentially. 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 exe‐ - cuted. - - 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; in‐ - stead, 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 de‐ - fault, 1000.) - - o If a user-defined function has the same name as a built-in function, it is ignored and the built-in func‐ - tion is used. To prevent conflicts with future versions of Remind (which may define more built-in func‐ - tions), 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 en‐ - abled. - - 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. Con‐ - sider 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 re‐ - named 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. Alterna‐ - tively, 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 in‐ - ternal 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 previ‐ - ously 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 in‐ - stead 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 OMITted 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_func‐ - tion 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 re‐ - minder. 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 re‐ - minder 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 re‐ - minder, 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 re‐ - quired. 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 com‐ - mand-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 trig‐ - date() 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 trig‐ - ger 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 pow‐ - erful. 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 re‐ - sults, as the OMIT context can change depending on the current date. For example, if you use the following com‐ - mand 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 Septem‐ - ber, 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 op‐ - tions 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 "" - - 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 pro‐ - cessing. Any queued timed reminders are discarded. If you are in calendar mode (described next), then the cal‐ - endar 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 ar‐ - ray: - - 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 de‐ - scribed 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 to‐ - day'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 calen‐ - dar. - - 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 %"...%" se‐ - quence, 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 in‐ - serted 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 com‐ - mand. 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 itera‐ - tions. - - Note that for efficiency, Remind caches the reminder script (and any INCLUDEd 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 re‐ - minders. 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 re‐ - peat 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 -ivar=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 op‐ - tions. - - 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: - - -ifunc(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 re‐ - minder 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 PS‐ - FILE-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 pri‐ - ority. 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 Post‐ - Script-type reminders are triggered for a single day, each section of PostScript is not enclosed in a save-re‐ - store 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 bot‐ - tom 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 bor‐ - der 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: - - 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 docu‐ - ment 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 file‐ - name 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 com‐ - pare 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 com‐ - ments 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 re‐ - minders 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-con‐ - stant 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 environ‐ - ment (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 as‐ - sumed to be non-constant. A non-constant context is the code in the scope of an IF statement where the IF ex‐ - pression 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-con‐ - stant. 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 imme‐ - diately, 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 speci‐ - fies 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. Re‐ - minders 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 ar‐ - gument, 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 prior‐ - ity-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 calsuf‐ - fix() can be defined. They work with all reminders that produce an entry in the calendar (i.e., CAL- and possi‐ - bly 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 mes‐ - sages. 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 lan‐ - guage. 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 lan‐ - guage. 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 lan‐ - guage. Note that $Am and $Pm should be the translations of "AM" and "PM" (morning and afternoon time in‐ - dicators) 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 unpre‐ - dictable. - - 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 Re‐ - mind'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 over‐ - rides the substitution sequence "%N". The three arguments are an integer alt which, if non-zero, indi‐ - cates 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" se‐ - quence 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 ta‐ - ble that maps one string (the original string) to a new string (the translated string.) When Remind starts exe‐ - cuting, 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 transla‐ - tion-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 encour‐ - aged 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 let‐ - ter 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. If you are in a UTF-8 locale, you can also use the - UTF-8-encoded Hebrew spellings for the month names, namely: - - תשרי, חשוון, כסלו, טבת, שבט, אדר, ניסן, אייר, סיון, תמוז, אב, אלול. - - 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, or in Hebrew, - 'אדר א and 'אדר ב. - - Remind also permits the following alternative spellings for Hebrew month names: - - Tishrey - Can also be spelled Tishri or Tishrei - - Heshvan - Can also be spelled Cheshvan or Kheshvan - - Shvat Can also be spelled Shevat - - Tamuz Can also be spelled Tammuz - - Adar A Can also be spelled Adar 1, Adar I, אדר א or אדר 1. - - Adar B Can also be spelled Adar 2, Adar II, אדר ב or אדר 2. - - Iyar Can also be spelled Iyyar. - - 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 pe‐ - riod 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 cor‐ - responds 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". - - ivritmon(d_date) - Returns the name of the Hebrew month corresponding to date, in UTF-8-encoded Hebrew script. For example, - ivritmon('1993/04/12') returns "ניסן". - - 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 ar‐ - guments. 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 parame‐ - ter 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 either the English transliteration shown previously, or the Hebrew spelling - encoded in UTF-8. 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 de‐ - scribed 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 Ashke‐ - nazim 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 excep‐ - tion; it works similarly to MSG when the -p option is not supplied.) - - The various SPECIALs recognized are particular for each backend; however, there are four SPECIALs that all back‐ - ends 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 inter‐ - preted 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 ter‐ - minal. - - 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: "(Wn)" 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 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 OMITs.) - -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 Amer‐ - ica. - - 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) - -Remind 2026-03-02 REMIND(1)