mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 22:38:37 +02:00
Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e18b4ed119 | ||
|
|
51f6ffc093 | ||
|
|
72de7c6b14 | ||
|
|
bd4785d631 | ||
|
|
cb08f12470 | ||
|
|
04146db69b | ||
|
|
d3fe045a39 | ||
|
|
2be1e16087 | ||
|
|
051e44ae3e | ||
|
|
6d5ae7a258 | ||
|
|
2e69e140eb | ||
|
|
516c4e2c39 | ||
|
|
b58ed62000 | ||
|
|
c685818783 | ||
|
|
3e20ce56c9 | ||
|
|
dd8d67f659 | ||
|
|
5ef4061819 | ||
|
|
a146a0c819 | ||
|
|
0f5a93cdf1 | ||
|
|
7db51e913e | ||
|
|
93ac1aebf7 | ||
|
|
56ebedb9de | ||
|
|
e87d33de50 | ||
|
|
a5774fd793 | ||
|
|
adb60f3400 | ||
|
|
47a0f63caa | ||
|
|
30a385a7bb | ||
|
|
9f2ae1773c | ||
|
|
f470297958 | ||
|
|
93dfc7995c | ||
|
|
c96869817f | ||
|
|
1bffa0e00b | ||
|
|
36035dda01 | ||
|
|
50a15cf089 | ||
|
|
b59d4ed4a4 | ||
|
|
4c53710279 | ||
|
|
2274e88485 | ||
|
|
984a4677f2 | ||
|
|
5e3dc54725 | ||
|
|
53a7bf9773 | ||
|
|
1dcc3897d6 | ||
|
|
fbc0375739 | ||
|
|
4a74c03fa4 | ||
|
|
d8833e6ce2 | ||
|
|
2b8b9a56aa | ||
|
|
85a8ebb357 | ||
|
|
a67d9e2524 | ||
|
|
6845e72fd5 | ||
|
|
0ab977fa05 | ||
|
|
ad64a12b2a | ||
|
|
cfde4b50bb | ||
|
|
f302c8eb95 | ||
|
|
7ecc355358 | ||
|
|
a52216d7e7 | ||
|
|
8d8d4b667d | ||
|
|
670369121e | ||
|
|
4365e580ee | ||
|
|
a8a09a905e | ||
|
|
dbb7381eb1 | ||
|
|
aa3531a6bf | ||
|
|
2848203d75 |
2
configure
vendored
2
configure
vendored
@@ -5284,7 +5284,7 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION=03.01.05
|
||||
VERSION=03.01.07
|
||||
|
||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
||||
|
||||
|
||||
@@ -45,6 +45,6 @@ if test "$GCC" = yes; then
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob)
|
||||
VERSION=03.01.05
|
||||
VERSION=03.01.07
|
||||
AC_SUBST(VERSION)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* Version 3.1 Patch 7 - 2009-05-31
|
||||
|
||||
- ENHANCEMENT: Wherever you could write "day Mon year", the parser now
|
||||
accepts "YYYY-MM-DD". This applies on the command-line and to the
|
||||
REM and OMIT keywords. You can avoid wrapping date calculations in
|
||||
the trigger() function in many cases.
|
||||
|
||||
- ENHANCEMENT: New slide() built-in function eases some complicated reminders.
|
||||
|
||||
* Version 3.1 Patch 6 - 2008-11-16
|
||||
|
||||
- MAJOR ENHANCEMENT: A new OMITFUNC clause gives you additional
|
||||
control and flexibility over "omitted days" calculations. This is
|
||||
useful when holidays influence the timing of events several days
|
||||
later. See "COMPUTED LOCAL OMITS" in the man page.
|
||||
|
||||
- ENHANCEMENT: The new evaltrig() built-in function lets you evaluate triggers
|
||||
from within an expression.
|
||||
|
||||
- ENHANCEMENT: The new weekno() built-in function returns the ISO 8601
|
||||
week number of a date.
|
||||
|
||||
- ENHANCEMENT: The "WEEK" special lets you annotate calendar output with the
|
||||
week number. The TkRemind, rem2ps and rem2html back-ends support WEEK.
|
||||
|
||||
- MINOR ENHANCEMENT: You can control whether timed reminders come before or
|
||||
after non-timed reminders with the "-g" flag.
|
||||
|
||||
- BUG FIX: TkRemind did not work correctly if ~/.reminders was a directory.
|
||||
|
||||
- BUG FIX: TkRemind incorrectly invoked Remind with the "-a" flag when
|
||||
showing today's reminders.
|
||||
|
||||
- BUG FIX: In certain cases, a trigger containing a day, month and
|
||||
weekday would fail if it needed to cross a year boundary. This has
|
||||
been fixed.
|
||||
|
||||
* Version 3.1 Patch 5 - 2008-04-15
|
||||
|
||||
- MAJOR ENHANCEMENT: If you supply a directory name on the command line
|
||||
|
||||
@@ -27,8 +27,8 @@ RUN OFF
|
||||
################################################
|
||||
# Ensure required version of remind is used... #
|
||||
################################################
|
||||
IF version() < "03.01.02"
|
||||
ERRMSG This file requires at least version 03.01.02 of Remind.%
|
||||
IF version() < "03.01.07"
|
||||
ERRMSG This file requires at least version 03.01.07 of Remind.%
|
||||
ERRMSG This version is version [version()].
|
||||
EXIT
|
||||
ENDIF
|
||||
@@ -95,11 +95,8 @@ SET Week_3 15
|
||||
SET Week_4 22
|
||||
FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
|
||||
|
||||
# Shorthand for commonly used expression...
|
||||
FSET _trig() TRIGGER(TRIGDATE())
|
||||
|
||||
# Handy function to provide SCANFROM dates...
|
||||
FSET _back(days) TRIGGER(TODAY()-days)
|
||||
FSET _back(days) TODAY()-days
|
||||
|
||||
###########################################################
|
||||
# Function which returns a string in "am/pm" format based #
|
||||
@@ -169,14 +166,14 @@ FSET _mail(from, subj) "fastmail -f " + \
|
||||
REM 4 July SCANFROM [_back(7)] SATISFY 1
|
||||
|
||||
IF WKDAYNUM(TRIGDATE()) == Sat
|
||||
REM [TRIGGER(TRIGDATE())] MSG Independence day (actual)
|
||||
OMIT [TRIGGER(TRIGDATE()-1)] MSG Independence day (observed)
|
||||
REM [TRIGDATE()] MSG Independence day (actual)
|
||||
OMIT [TRIGDATE()-1] MSG Independence day (observed)
|
||||
ELSE
|
||||
IF WKDAYNUM(TRIGDATE()) == Sun
|
||||
REM [TRIGGER(TRIGDATE())] MSG Independence day (actual)
|
||||
OMIT [TRIGGER(TRIGDATE()+1)] MSG Independence day (observed)
|
||||
REM [TRIGDATE()] MSG Independence day (actual)
|
||||
OMIT [TRIGDATE()+1] MSG Independence day (observed)
|
||||
ELSE
|
||||
OMIT [TRIGGER(TRIGDATE())] MSG Independence day
|
||||
OMIT [TRIGDATE()] MSG Independence day
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
@@ -197,7 +194,7 @@ REM Mon 8 SATISFY 1
|
||||
# But only actually trigger the delayed meeting if the previous
|
||||
# Monday was a holiday
|
||||
IF ISOMITTED(TRIGDATE()-7)
|
||||
REM [TRIGGER(TRIGDATE())] MSG Delayed meeting
|
||||
REM [TRIGDATE()] MSG Delayed meeting
|
||||
ENDIF
|
||||
|
||||
############################################################################
|
||||
@@ -288,12 +285,12 @@ REM Sat Sun SPECIAL SHADE 220
|
||||
|
||||
SET SaveTrig $NumTrig
|
||||
SET easter EASTERDATE(YEAR(TODAY()))
|
||||
REM [TRIGGER(easter-46)] MSG %"Ash Wednesday%"
|
||||
REM [TRIGGER(easter-7)] MSG %"Palm Sunday%"
|
||||
OMIT [TRIGGER(easter-2)] MSG %"Good Friday%"
|
||||
OMIT [TRIGGER(easter)] MSG %"Easter%" Sunday
|
||||
REM [TRIGGER(easter+39)] MSG %"Ascension Day%"
|
||||
REM [TRIGGER(easter+49)] MSG %"Pentecost%"
|
||||
REM [easter-46] MSG %"Ash Wednesday%"
|
||||
REM [easter-7] MSG %"Palm Sunday%"
|
||||
OMIT [easter-2] MSG %"Good Friday%"
|
||||
OMIT [easter] MSG %"Easter%" Sunday
|
||||
REM [easter+39] MSG %"Ascension Day%"
|
||||
REM [easter+49] MSG %"Pentecost%"
|
||||
|
||||
# Some holidays are omitted, some are not. You may want to change
|
||||
# which ones are omitted - use the general forms shown below.
|
||||
@@ -305,7 +302,7 @@ REM Mon Jan [Week_3] MSG Martin Luther King - %"MLK Day%"
|
||||
REM Feb 2 MSG %"Ground Hog Day%"
|
||||
REM Feb 14 MSG %"Valentine's%" Day
|
||||
REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"President's Day%"
|
||||
OMIT [trigdate()] MSG %"President's Day%"
|
||||
REM Mar 17 MSG %"St. Patrick's%" Day
|
||||
|
||||
# The DST rules are accurate for most locations in
|
||||
@@ -320,11 +317,11 @@ REM Sat May [Week_1] MSG %"Kentucky Derby%"
|
||||
REM Sun May [Week_2] MSG %"Mother's Day%"
|
||||
REM Sat May [Week_3] MSG %"Armed Forces Day%"
|
||||
REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"Memorial Day%"
|
||||
OMIT [trigdate()] MSG %"Memorial Day%"
|
||||
REM Jun 14 MSG %"Flag Day%"
|
||||
REM Sun Jun [Week_3] MSG %"Father's Day%"
|
||||
REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"Labor Day%"
|
||||
OMIT [trigdate()] MSG %"Labor Day%"
|
||||
REM Mon Oct [Week_2] MSG %"Columbus Day%"
|
||||
REM Nov 11 MSG %"Veterans Day%"
|
||||
|
||||
@@ -339,9 +336,9 @@ REM Tue Nov 2 SCANFROM [_back(7)] \
|
||||
SATISFY [(YEAR(TRIGDATE()) % 4) == 0] \
|
||||
MSG %"Election%" Day
|
||||
REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"Thanksgiving%" Day
|
||||
OMIT [trigdate()] MSG %"Thanksgiving%" Day
|
||||
REM Fri Nov [Week_4+1] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"Thanksgiving%" (cont.)
|
||||
OMIT [trigdate()] MSG %"Thanksgiving%" (cont.)
|
||||
OMIT Dec 24 MSG %"Christmas Eve%"
|
||||
OMIT Dec 25 MSG %"Christmas%" Day
|
||||
|
||||
@@ -379,10 +376,10 @@ REM PS Border Border moveto \
|
||||
([hebday(today())] [hebmon(today())]) show
|
||||
|
||||
# Fill in the phases of the moon on the PostScript calendar
|
||||
[trigger(moondate(0))] SPECIAL MOON 0
|
||||
[trigger(moondate(1))] SPECIAL MOON 1
|
||||
[trigger(moondate(2))] SPECIAL MOON 2
|
||||
[trigger(moondate(3))] SPECIAL MOON 3
|
||||
[moondate(0)] SPECIAL MOON 0
|
||||
[moondate(1)] SPECIAL MOON 1
|
||||
[moondate(2)] SPECIAL MOON 2
|
||||
[moondate(3)] SPECIAL MOON 3
|
||||
|
||||
# The following example puts sunrise and sunset times in PostScript in the
|
||||
# calendar - the sizes are hard-coded, however, and work best in landscape.
|
||||
@@ -435,11 +432,11 @@ SET InIsrael 0
|
||||
SET Reform 0
|
||||
|
||||
# Convenient function definition to save typing
|
||||
FSET _h(x, y) TRIGGER(HEBDATE(x,y))
|
||||
FSET _h(x, y) HEBDATE(x,y)
|
||||
FSET _h2(x, y) HEBDATE(x, y, TODAY()-7)
|
||||
FSET _PastSat(x, y) TRIGGER(IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1))
|
||||
FSET _PastSun(x, y) TRIGGER(IIF(WKDAYNUM(_h2(x,y))!=0, _h2(x,y), _h2(x,y)+1))
|
||||
FSET _PastMon(x, y) TRIGGER(IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1))
|
||||
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1)
|
||||
FSET _PastSun(x, y) IIF(WKDAYNUM(_h2(x,y))!=0, _h2(x,y), _h2(x,y)+1)
|
||||
FSET _PastMon(x, y) IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1)
|
||||
|
||||
# Default values in case InIsrael and Reform are not set
|
||||
SET InIsrael VALUE("InIsrael", 0)
|
||||
@@ -470,7 +467,7 @@ ELSE
|
||||
ENDIF
|
||||
|
||||
# Because Kislev can change length, we must be more careful about Chanukah
|
||||
FSET _chan(x) TRIGGER(HEBDATE(24, "Kislev", today()-9)+x)
|
||||
FSET _chan(x) HEBDATE(24, "Kislev", today()-9)+x
|
||||
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
||||
[_chan(2)] MSG %"Chanukah 2%"
|
||||
[_chan(3)] MSG %"Chanukah 3%"
|
||||
@@ -493,9 +490,9 @@ ENDIF
|
||||
|
||||
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
||||
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||
REM [TRIGGER(_h2(13, "Adar"))] ++4 MSG %"Fast of Esther%" is %b.
|
||||
REM [_h2(13, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||
ELSE
|
||||
REM [TRIGGER(_h2(11, "Adar"))] ++4 MSG %"Fast of Esther%" is %b.
|
||||
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||
ENDIF
|
||||
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
||||
[_h(15, "Adar")] ++4 MSG %"Shushan Purim%" is %b.
|
||||
@@ -521,7 +518,7 @@ IF WKDAYNUM(_h2(4, "Iyar")) == 5
|
||||
[_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
[_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
ELSE
|
||||
IF WKDAYNUM(_h2, 4, "Iyar") == 0
|
||||
IF WKDAYNUM(_h2(4, "Iyar")) == 0
|
||||
[_h(5, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
[_h(6, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
ELSE
|
||||
|
||||
377
man/remind.1
377
man/remind.1
@@ -1,4 +1,4 @@
|
||||
.TH REMIND 1 "1 July 2007"
|
||||
.TH REMIND 1 "31 August 2008"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
remind \- a sophisticated reminder service
|
||||
@@ -182,13 +182,14 @@ Echo lines when displaying error messages
|
||||
Trace the reading of reminder files
|
||||
.RE
|
||||
.TP
|
||||
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]
|
||||
Normally, reminders are issued in the order in which they are encountered
|
||||
in the reminder script. The \fB\-g\fR option cause \fBRemind\fR to
|
||||
sort reminders by date and time prior to issuing them. The optional
|
||||
\fBa\fR and \fBd\fR characters specify the sort order (ascending or
|
||||
descending) for the date, time and priority fields. See the section "Sorting
|
||||
Reminders" for more information.
|
||||
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]]
|
||||
Normally, reminders are issued in the order in which they are
|
||||
encountered in the reminder script. The \fB\-g\fR option cause
|
||||
\fBRemind\fR to sort reminders by date and time prior to issuing them.
|
||||
The optional \fBa\fR and \fBd\fR characters specify the sort order
|
||||
(ascending or descending) for the date, time and priority fields. See
|
||||
the section "Sorting Reminders" for more information.
|
||||
|
||||
.TP
|
||||
\fB\-b\fR[\fIn\fR]
|
||||
Set the time format for the calendar and simple-calendar outputs. \fIN\fR
|
||||
@@ -285,6 +286,10 @@ set \fBRemind\fR's notion of "now" to a particular time. Supplying
|
||||
a \fItime\fR on the command line also implicitly enables the \fB\-q\fR
|
||||
option and disables the \fB\-z\fR option.
|
||||
.PP
|
||||
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.
|
||||
.PP
|
||||
In addition, you can supply a \fIrepeat\fR parameter, which has the
|
||||
form *\fInum\fR. This causes \fBRemind\fR to be run \fInum\fR times,
|
||||
with the date incrementing on each iteration. You may have to enclose
|
||||
@@ -305,7 +310,7 @@ very simple and almost immediately understandable:
|
||||
to the baroque and obscure:
|
||||
.PP
|
||||
.nf
|
||||
REM [trigger(date(thisyear, 1, 1) + 180)] ++5 OMIT \\
|
||||
REM [date(thisyear, 1, 1) + 180] ++5 OMIT \\
|
||||
sat sun BEFORE MSG [ord(thisyear-1980)] payment due %b!
|
||||
.fi
|
||||
.PP
|
||||
@@ -337,6 +342,7 @@ Its syntax is:
|
||||
[\fBPRIORITY\fR \fIprio\fR]
|
||||
[\fBSKIP\fR | \fBBEFORE\fR | \fBAFTER\fR]
|
||||
[\fBOMIT\fR \fIomit_list\fR]
|
||||
[\fBOMITFUNC\fR \fIomit_function\fR]
|
||||
[\fBAT\fR \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
|
||||
[\fBSCHED\fR \fIsched_function\fR]
|
||||
[\fBWARN\fR \fIwarn_function\fR]
|
||||
@@ -631,6 +637,37 @@ the
|
||||
.I weekday
|
||||
constraints.
|
||||
.PP
|
||||
.B SHORT-HAND DATE SPECIFICATIONS
|
||||
.PP
|
||||
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:
|
||||
.PP
|
||||
.nf
|
||||
REM 5 June 2010 MSG Cool!
|
||||
REM 2010-06-05 MSG Cool!
|
||||
.fi
|
||||
.PP
|
||||
You can also specify a date and time as YYYY-MM-DD@HH:MM. These
|
||||
statements are equivalent:
|
||||
.PP
|
||||
.nf
|
||||
REM 19 Dec 2010 AT 16:45 MSG Hi
|
||||
REM 2010-12-19@16:45 MSG Hi
|
||||
.fi
|
||||
.PP
|
||||
There's one subtlety with short-hand date specifications: The following
|
||||
statements are \fInot\fR equivalent:
|
||||
.PP
|
||||
.nf
|
||||
REM 19 Dec 2010 AT 16:45 +60 MSG Hi
|
||||
REM 2010-12-19@16:45 +60 MSG Hi
|
||||
.fi
|
||||
.PP
|
||||
In the second statement, the "+60" is a \fIdelta\fR that applies to the
|
||||
date rather than a \fItdelta\fR that applies to the time. We recommend
|
||||
explicitly using the AT keyword with timed reminders.
|
||||
.PP
|
||||
.B BACKWARD SCANNING
|
||||
.PP
|
||||
Sometimes, it is necessary to specify a date as being a set amount of
|
||||
@@ -728,7 +765,7 @@ Another example: Suppose you have jury duty from 30 November 1992 until
|
||||
of your jury duty, as well as 2 days ahead of time:
|
||||
.PP
|
||||
.nf
|
||||
REM 30 Nov 1992 *1 +2 UNTIL 4 Dec 1992 MSG Jury duty
|
||||
REM 1992-11-30 *1 +2 UNTIL 1992-12-04 MSG Jury duty
|
||||
.fi
|
||||
.PP
|
||||
Note that the \fIrepeat\fR of *1 is necessary; without it, the reminder
|
||||
@@ -794,6 +831,50 @@ 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 \fBOMIT\fR.
|
||||
.PP
|
||||
.B COMPUTED LOCAL OMITS
|
||||
.PP
|
||||
The \fBOMITFUNC\fR phrase of the \fBREM\fR command allows you to
|
||||
supply a function that determines whether or not a date is omitted.
|
||||
The function is passed a single parameter of type \fBDATE\fR, and must
|
||||
return a non-zero integer if the date is considered "omitted" and 0
|
||||
otherwise. Here's an example:
|
||||
.PP
|
||||
.nf
|
||||
FSET _third(x) (day(x) % 3) || \\
|
||||
(wkdaynum(x) == 0) || \\
|
||||
(wkdaynum(x) == 6)
|
||||
REM OMITFUNC _third AFTER MSG Working day divisible by 3
|
||||
.fi
|
||||
.PP
|
||||
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:
|
||||
.TP
|
||||
.B o
|
||||
The \fBOMITFUNC _third\fR portion causes all days for which \fB_third(x)\fR
|
||||
returns non-zero to be considered "omitted". This causes all days whose
|
||||
day-of-month number is \fInot\fR a multiple of three to be omitted. Note
|
||||
that _third also returns non-zero if the weekday is Sunday or Saturday.
|
||||
.TP
|
||||
.B o
|
||||
The \fBAFTER\fR keyword causes the reminder to be moved after a block of
|
||||
omitted days.
|
||||
.PP
|
||||
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.
|
||||
.PP
|
||||
Note that if you use \fBOMITFUNC\fR, then a local \fBOMIT\fR is
|
||||
\fIignored\fR as are \fIall global OMITs\fR. If you want to omit specific
|
||||
weekdays, your omit function will need to test for them specifically. If
|
||||
you want to take into account the global \fBOMIT\fR context, then your omit
|
||||
function will need to test for that explicitly (using the \fBisomitted()\fR
|
||||
function.)
|
||||
.PP
|
||||
Note that an incorrect \fBOMITFUNC\fR might cause all days to be considered
|
||||
omitted. For that reason, when \fBRemind\fR searches through omitted days,
|
||||
it terminates the search after the \fBSATISFY\fR iteration limit
|
||||
(command-line option \fB\-x\fR.)
|
||||
.PP
|
||||
.B TIMED REMINDERS
|
||||
.PP
|
||||
Timed reminders are those that have an \fBAT\fR keyword followed
|
||||
@@ -1211,6 +1292,14 @@ must create an \fBOMIT\fR command for each year. (Later, in the
|
||||
description of expressions and some of the more advanced features of
|
||||
\fBRemind\fR, you will see how to automate this for some cases.)
|
||||
.PP
|
||||
As with the REM command, you can use shorthand specifiers for dates;
|
||||
the following are equivalent:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 7 Sep 1992
|
||||
OMIT 1992-09-07
|
||||
.fi
|
||||
.PP
|
||||
For convenience, you can use a \fIdelta\fR and \fBMSG\fR or \fBRUN\fR
|
||||
keyword in the \fBOMIT\fR command. The following sequences are exactly
|
||||
equivalent:
|
||||
@@ -1226,11 +1315,11 @@ equivalent:
|
||||
.PP
|
||||
.B THE BEFORE, AFTER AND SKIP KEYWORDS
|
||||
.PP
|
||||
Normally, days that are omitted, whether by a global \fBOMIT\fR command
|
||||
or the local \fBOMIT\fR keyword in a \fBREM\fR statement, only affect the
|
||||
counting of the \-\fIback\fR or the +\fIdelta\fR. For example, suppose
|
||||
you have a meeting every Wednesday. Suppose, too, that you have indicated
|
||||
11 Nov as a holiday:
|
||||
Normally, days that are omitted, whether by a global \fBOMIT\fR
|
||||
command or the local \fBOMIT\fR or \fBOMITFUNC\fR keywords in a
|
||||
\fBREM\fR statement, only affect the counting of the \-\fIback\fR or
|
||||
the +\fIdelta\fR. For example, suppose you have a meeting every
|
||||
Wednesday. Suppose, too, that you have indicated 11 Nov as a holiday:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 11 Nov +4 MSG Remembrance Day
|
||||
@@ -1888,6 +1977,10 @@ $IgnoreOnce, $InfDelta, and $NextMode are not meaningful.
|
||||
This variable can be set only to ":" or ".". It holds the character
|
||||
used to separate portions of a time when \fBRemind\fR prints a TIME or
|
||||
DATETIME value.
|
||||
.TP
|
||||
.B $UntimedFirst (read-only)
|
||||
Set to 1 if the \fB\-g\fR option is used with a fourth sort character
|
||||
of "d"; set to 0 otherwise.
|
||||
.PP
|
||||
.B BUILT-IN FUNCTIONS
|
||||
.PP
|
||||
@@ -2093,6 +2186,37 @@ for the specified year. If \fIarg\fR is a \fBDATE\fR or
|
||||
\fBDATETIME\fR, then returns the date of the next Easter Sunday on or
|
||||
after \fIarg\fR. (The time component of a datetime is ignored.)
|
||||
.TP
|
||||
.B evaltrig(s_trigger [,dq_start])
|
||||
Evaluates \fItrigger\fR as if it were a REM or IFTRIG trigger specification
|
||||
and returns the trigger date as a \fBDATE\fR (or as a \fBDATETIME\fR if
|
||||
there is an \fBAT\fR clause.) Returns a negative \fBINT\fR if no trigger
|
||||
could be computed.
|
||||
.RS
|
||||
.PP
|
||||
Normally, \fBevaltrig\fR finds a trigger date on or after today. If
|
||||
you supply the \fIstart\fR argument, then it scans starting from there.
|
||||
.PP
|
||||
For example, the expression:
|
||||
.PP
|
||||
.nf
|
||||
evaltrig("Mon 1", '2008-10-07')
|
||||
.fi
|
||||
.PP
|
||||
returns '2008-11-03', since that is the first date on or after
|
||||
7 October 2008 that satisfies "Mon 1".
|
||||
.PP
|
||||
If you want to see how many days it is from the first Monday in October, 2008
|
||||
to the first Monday in November, 2008, use:
|
||||
.PP
|
||||
.nf
|
||||
evaltrig("Mon 1", '2008-11-01') - evaltrig("Mon 1", '2008-10-01')
|
||||
.fi
|
||||
.PP
|
||||
and the answer is 28. The trigger argument to \fBevaltrig\fR can have
|
||||
all the usual trigger clauses (\fBOMIT\fR, \fBAT\fR, \fBSKIP\fR, etc.) but
|
||||
\fIcannot\fR have a \fBSATISFY\fR, \fBMSG\fR, etc. reminder-type clause.
|
||||
.RE
|
||||
.TP
|
||||
.B filedate(s_filename)
|
||||
Returns the modification date of \fIfilename\fR. If \fIfilename\fR
|
||||
does not exist, or its modification date is before the year
|
||||
@@ -2170,7 +2294,8 @@ or \fBDATETIME\fR is supplied, then the year component is used in the test.
|
||||
.B isomitted(dq_date)
|
||||
Returns 1 if \fIdate\fR is omitted, given the current global \fBOMIT\fR
|
||||
context. Returns 0 otherwise. (If a datetime is supplied, only the
|
||||
date part is used.)
|
||||
date part is used.) Note that any local \fBOMIT\fR or \fBOMITFUNC\fR
|
||||
clauses are \fInot\fR taken into account by this function.
|
||||
.TP
|
||||
.B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]])
|
||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
||||
@@ -2284,10 +2409,11 @@ This function returns the number of \fInon-\fRomitted days between
|
||||
counted. \fIend\fR is never counted.
|
||||
.RS
|
||||
.PP
|
||||
Note that \fIend\fR must be greater than or
|
||||
equal to \fIstart\fR or an error is reported. In addition to using
|
||||
the global OMIT context, you can supply additional arguments that are
|
||||
names of weekdays to be omitted.
|
||||
Note that \fIend\fR must be greater than or equal to \fIstart\fR or an
|
||||
error is reported. In addition to using the global OMIT context, you
|
||||
can supply additional arguments that are names of weekdays to be
|
||||
omitted. However, in a \fBREM\fR command, any local \fBOMITFUNC\fR
|
||||
clause is \fInot\fR taken into account by this function.
|
||||
.PP
|
||||
For example, the following line sets a to 11 (assuming no global OMITs):
|
||||
.PP
|
||||
@@ -2310,36 +2436,30 @@ reminder will label day numbers in a calendar:
|
||||
ENDIF
|
||||
.fi
|
||||
.PP
|
||||
Here's a more complex example: Suppose your normal garbage-collection
|
||||
day is Thursday, but if any of Monday through Thursday of a week is a holiday,
|
||||
the collection day moves to Friday. Here's one way to solve it:
|
||||
.PP
|
||||
.nf
|
||||
FSET prev_monday(x) x - wkdaynum(x-1)
|
||||
|
||||
REM Thu Fri SATISFY [wkdaynum(trigdate()) == 4 && \\
|
||||
nonomitted(prev_monday(today()), today()+1) == 4 || \\
|
||||
wkdaynum(trigdate()) == 5 && \\
|
||||
nonomitted(prev_monday(today()), today()+1) <= 4] \\
|
||||
MSG Garbage Day
|
||||
.fi
|
||||
.PP
|
||||
Whew! (You'll need to see "THE SATISFY CLAUSE" later on.) We'd
|
||||
better explain that one: The prev_monday helper function takes a date
|
||||
and returns the date of the previous Monday. The REM command will
|
||||
trigger on the first Thursday or Friday that satisfies one of the
|
||||
following conditions:
|
||||
.PP
|
||||
1) Either it's a Thursday and there are exactly four non-omitted days between
|
||||
the previous Monday and tomorrow, or
|
||||
.PP
|
||||
2) It's a Friday and there are four or fewer non-omitted days between the
|
||||
previous Monday and tomorrow. We need the "or fewer" condition to handle
|
||||
the case of more than one holiday in a given week. If that happens,
|
||||
garbage day still only moves by one day.
|
||||
.PP
|
||||
Obviously, the answer you get from \fBnonomitted\fR depends on the global
|
||||
OMIT context. If you use moveable OMITs, you may get inconsistent results.
|
||||
.PP
|
||||
Here is a more complex use for \fBnonomitted\fR. My garbage collection
|
||||
follows two interleaved 14-day cycles: One Friday, garbage and paper
|
||||
recycling ("Black Box") are collected. The next Friday, garbage and
|
||||
plastic recycling ("Blue Box") are collected. If any of Monday-Friday
|
||||
is a holiday, collection is delayed until the Saturday. Here's a way
|
||||
to encode these rules:
|
||||
.PP
|
||||
.nf
|
||||
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
|
||||
.fi
|
||||
.PP
|
||||
Here's how it works: The _garbhol(x) user-defined function returns 1
|
||||
if and only if (1) \fIx\fR is a Friday and (2) there is at least one
|
||||
OMITted day from the previous Monday up to and including the Friday.
|
||||
.PP
|
||||
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.
|
||||
.RE
|
||||
.TP
|
||||
.B now()
|
||||
@@ -2381,10 +2501,10 @@ For example, the following four lines place moon symbols on the PostScript
|
||||
calendar:
|
||||
.PP
|
||||
.nf
|
||||
REM [trigger(moondate(0))] PS [psmoon(0)]
|
||||
REM [trigger(moondate(1))] PS [psmoon(1)]
|
||||
REM [trigger(moondate(2))] PS [psmoon(2)]
|
||||
REM [trigger(moondate(3))] PS [psmoon(3)]
|
||||
REM [moondate(0)] PS [psmoon(0)]
|
||||
REM [moondate(1)] PS [psmoon(1)]
|
||||
REM [moondate(2)] PS [psmoon(2)]
|
||||
REM [moondate(3)] PS [psmoon(3)]
|
||||
.fi
|
||||
.PP
|
||||
If \fInote\fR is specified, the text is used to annotate the moon
|
||||
@@ -2397,7 +2517,7 @@ 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:
|
||||
.PP
|
||||
.nf
|
||||
REM [trigger(moondate(0))] PS [psmoon(0, -1, moontime(0)+"")]
|
||||
REM [moondate(0)] PS [psmoon(0, -1, moontime(0)+"")]
|
||||
.fi
|
||||
.PP
|
||||
Note how the time is coerced to a string by concatenating the null string.
|
||||
@@ -2449,11 +2569,38 @@ character in the output is converted to a space. Note that if \fBRUN
|
||||
OFF\fR has been executed, or the \fB\-r\fR command-line option has
|
||||
been used, \fBshell()\fR will result in an error, and \fIcmd\fR will
|
||||
not be executed.
|
||||
.RS
|
||||
.PP
|
||||
If \fImaxlen\fR is specified, then \fBshell()\fR returns the first
|
||||
\fImaxlen\fR characters of output (rather than the first 511). If
|
||||
\fImaxlen\fR is specified as a negative number, then \fIall\fR the
|
||||
output from \fIcmd\fR is returned.
|
||||
.RE
|
||||
.TP
|
||||
.B slide(d_start, i_amt [,s_wkday...])
|
||||
This function is the inverse of \fBnonomitted\fR. It adds \fIamt\fR
|
||||
days (which can be negative) to \fIstart\fR, \fInot counting omitted days\fR.
|
||||
The optional \fIwkday\fR arguments are additional weekday names to omit.
|
||||
.RS
|
||||
.PP
|
||||
Consider this example:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 14 May 2009
|
||||
SET a slide('2009-05-13', 5, "Sat", "Sun")
|
||||
.fi
|
||||
.PP
|
||||
In this case, \fIa\fR 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:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 14 May 2009
|
||||
SET a slide('2009-05-21', -5, "Sat", "Sun")
|
||||
.fi
|
||||
.PP
|
||||
takes \fIa\fR back to 2009-05-13.
|
||||
.RE
|
||||
.TP
|
||||
.B strlen(s_str)
|
||||
Returns the length of \fIstr\fR.
|
||||
@@ -2511,15 +2658,18 @@ triggerable \fBREM\fR command had an \fBAT\fR clause. If there was no
|
||||
returns the integer 0.
|
||||
.TP
|
||||
.B trigger(d_date [,t_time [,i_utcflag]]) \fRor\fB trigger(q_datetime [,i_utcflag])
|
||||
Returns a string suitable for use in a \fBREM\fR command, allowing you
|
||||
to calculate trigger dates in advance. (See the section "Expression
|
||||
pasting" for more information.) Note that \fBtrigger()\fR
|
||||
\fIalways\fR returns its result in English, even for foreign-language
|
||||
versions of \fBRemind\fR. This is to avoid problems with certain C
|
||||
libraries that do not handle accented characters properly. Normally,
|
||||
the \fIdate\fR and \fItime\fR are the local date and time; however, if
|
||||
\fIutcflag\fR is non-zero, the \fIdate\fR and \fItime\fR are
|
||||
interpreted as UTC times, and are converted to local time. Examples:
|
||||
Returns a string suitable for use in a \fBREM\fR command or a SCANFROM
|
||||
or UNTIL clause, allowing you to calculate trigger dates in advance.
|
||||
Note that in earlier versions of \fBRemind\fR, \fBtrigger\fR was
|
||||
required to convert a date into something the \fBREM\fR command could
|
||||
consume. However, in this version of \fBRemind\fR, you can omit it.
|
||||
Note that \fBtrigger()\fR \fIalways\fR returns its result in English,
|
||||
even for foreign-language versions of \fBRemind\fR. This is to avoid
|
||||
problems with certain C libraries that do not handle accented
|
||||
characters properly. Normally, the \fIdate\fR and \fItime\fR are the
|
||||
local date and time; however, if \fIutcflag\fR is non-zero, the
|
||||
\fIdate\fR and \fItime\fR are interpreted as UTC times, and are
|
||||
converted to local time. Examples:
|
||||
.RS
|
||||
.PP
|
||||
trigger('1993/04/01')
|
||||
@@ -2596,6 +2746,21 @@ Returns a string specifying the version of \fBRemind\fR. For version
|
||||
\fBRemind\fR are released, the value returned by \fBversion()\fR will
|
||||
strictly increase, according to the rules for string ordering.
|
||||
.TP
|
||||
.B 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 \fBtoday()\fR. If one
|
||||
argument \fIdate\fR is supplied, then returns the ISO 8601 week
|
||||
number for that date. If two arguments are supplied, then
|
||||
\fIwkstart\fR must range from 0 to 6, and represents the first
|
||||
day of the week (with 0 being Sunday and 6 being Saturday.). If
|
||||
\fIwkstart\fR is not supplied, then it defaults to 1. If the
|
||||
third argument \fIdaystart\fR is supplied, then it specifies
|
||||
when Week 1 starts. If \fIdaystart\fR is less than or equal to 7,
|
||||
then Week 1 starts on the first \fIwkstart\fR on or after
|
||||
January \fIdaystart\fR. Otherwise, Week 1 starts on the first
|
||||
\fIwkstart\fR on or after December \fIdaystart\fR. If omitted,
|
||||
\fIdaystart\fR defaults to 29 (following the ISO 8601 definition.)
|
||||
.TP
|
||||
.B wkday(dqi_arg)
|
||||
If \fIarg\fR is a \fBDATE\fR or \fBDATETIME\fR, returns a string
|
||||
representing the day of the week of the date. If \fIarg\fR is an
|
||||
@@ -2618,10 +2783,10 @@ you can "paste" an expression in. To do this, surround the expression
|
||||
with square brackets. For example:
|
||||
.PP
|
||||
.nf
|
||||
REM [trigger(mydate)] MSG foo
|
||||
REM [mydate] MSG foo
|
||||
.fi
|
||||
.PP
|
||||
This evaluates the expression "trigger(mydate)", where "mydate" is
|
||||
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.
|
||||
.PP
|
||||
@@ -2644,8 +2809,16 @@ exceptions:
|
||||
.TP
|
||||
o
|
||||
If \fBRemind\fR is expecting an expression, as in the \fBSET\fR command,
|
||||
or the \fBIF\fR command, then no expression pasting takes place. The
|
||||
expression is simply evaluated as if the square brackets were not there.
|
||||
or the \fBIF\fR command, you should \fBnot\fR include square brackets.
|
||||
FOr example, use:
|
||||
.PP
|
||||
.nf
|
||||
SET a 4+5
|
||||
.fi
|
||||
and not:
|
||||
.nf
|
||||
SET a [4+5]
|
||||
.fi
|
||||
.TP
|
||||
o
|
||||
You cannot use expression pasting for the first token on a line.
|
||||
@@ -2993,7 +3166,7 @@ more complicated sequence:
|
||||
.nf
|
||||
REM 13 SATISFY wkdaynum(trigdate()) == 5
|
||||
IF trigvalid()
|
||||
REM [trigger(trigdate())] +2 MSG \\
|
||||
REM [trigdate()] +2 MSG \\
|
||||
Friday the 13th is %b.
|
||||
ENDIF
|
||||
.fi
|
||||
@@ -3001,8 +3174,7 @@ more complicated sequence:
|
||||
Let's see how this works. The \fBSATISFY\fR clause iterates through
|
||||
all the 13ths of successive months, until a trigger date is found whose
|
||||
day-of-week is Friday (== 5). If a valid date was found, we use the
|
||||
calculated trigger date (converted into a trigger format with the
|
||||
\fBtrigger()\fR function) to set up the next reminder.
|
||||
calculated trigger date to set up the next reminder.
|
||||
.PP
|
||||
We could also have written:
|
||||
.PP
|
||||
@@ -3021,7 +3193,7 @@ could use:
|
||||
.nf
|
||||
# Note: SATISFY 1 is an idiom for "do nothing"
|
||||
REM Mon 1 Sept SATISFY 1
|
||||
OMIT [trigger(trigdate())]
|
||||
OMIT [trigdate()]
|
||||
.fi
|
||||
.PP
|
||||
\fBCAVEAT:\fR This \fIonly\fR omits the \fInext\fR Labour Day, not
|
||||
@@ -3073,6 +3245,10 @@ occurring on odd-numbered days of the month with the following:
|
||||
MSG Here it is!!!
|
||||
.fi
|
||||
.PP
|
||||
Note that \fBSATISFY\fR and \fBOMITFUNC\fR can often be used to solve the
|
||||
same problem, though in different ways. Sometimes a \fBSATISFY\fR is cleaner
|
||||
and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer.
|
||||
.PP
|
||||
.SH DEBUGGING REMINDER SCRIPTS
|
||||
.PP
|
||||
Although the command-line \fB\-d\fR option is useful for debugging, it
|
||||
@@ -3412,24 +3588,26 @@ to ensure that the daemon is not killed when you log out.
|
||||
.PP
|
||||
.SH SORTING REMINDERS
|
||||
.PP
|
||||
The \fB\-g\fR option causes \fBRemind\fR to sort reminders by
|
||||
trigger date, time and priority before issuing them. Note that reminders are
|
||||
still calculated in the order encountered in the script. However, rather
|
||||
than being issued immediately, they are saved in an internal buffer.
|
||||
When \fBRemind\fR has finished processing the script, it issues the
|
||||
saved reminders in sorted order. The \fB\-g\fR option can be followed
|
||||
by up to three characters that must all be "a" or "d". The first character
|
||||
specifies the sort order by trigger date (ascending or descending),
|
||||
the second specifies the sort order by trigger time and the third
|
||||
specifies the sort order by priority. The default is
|
||||
to sort all fields in ascending order.
|
||||
|
||||
The \fB\-g\fR option causes \fBRemind\fR to sort reminders by trigger
|
||||
date, time and priority before issuing them. Note that reminders are
|
||||
still calculated in the order encountered in the script. However,
|
||||
rather than being issued immediately, they are saved in an internal
|
||||
buffer. When \fBRemind\fR has finished processing the script, it
|
||||
issues the saved reminders in sorted order. The \fB\-g\fR option can
|
||||
be followed by up to four characters that must all be "a" or "d". The
|
||||
first character specifies the sort order by trigger date (ascending or
|
||||
descending), the second specifies the sort order by trigger time and
|
||||
the third specifies the sort order by priority. If the fourth
|
||||
character is "d", the untimed reminders are sorted before timed
|
||||
reminders. The default is to sort all fields in ascending order and
|
||||
to sort untimed reminders after timed reminders.
|
||||
.PP
|
||||
In ascending order, reminders are issued with the most imminent first.
|
||||
Descending order is the reverse. Reminders are always sorted by
|
||||
trigger date, and reminders with the same trigger date are then sorted
|
||||
by trigger time. Non-timed reminders are always issued after timed
|
||||
reminders in this mode. If two reminders have the same date and time,
|
||||
then the priority is used to break ties. Reminders with the same date,
|
||||
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.
|
||||
.PP
|
||||
You can define a user-defined function called SORTBANNER that takes one
|
||||
@@ -3782,10 +3960,10 @@ in calendars produced by \fBRem2PS\fR, \fBtkremind\fR and \fBrem2html\fR.)
|
||||
The \fBMOON\fR special replaces the \fBpsmoon()\fR function. Use it
|
||||
like this:
|
||||
.nf
|
||||
REM [trigger(moondate(0))] SPECIAL MOON 0
|
||||
REM [trigger(moondate(1))] SPECIAL MOON 1
|
||||
REM [trigger(moondate(2))] SPECIAL MOON 2
|
||||
REM [trigger(moondate(3))] SPECIAL MOON 3
|
||||
REM [moondate(0)] SPECIAL MOON 0
|
||||
REM [moondate(1)] SPECIAL MOON 1
|
||||
REM [moondate(2)] SPECIAL MOON 2
|
||||
REM [moondate(3)] SPECIAL MOON 3
|
||||
.fi
|
||||
These draw little moons on the various calendars. The complete syntax
|
||||
of the \fBMOON\fR special is as follows:
|
||||
@@ -3823,6 +4001,16 @@ The COLOR special is "doubly special", because in its normal operating
|
||||
mode, \fBremind\fR treats a COLOR special just like a MSG-type reminder.
|
||||
Also, if you invoke \fBRemind\fR with \fB\-cc\fR..., then it approximates
|
||||
SPECIAL COLOR reminders on your terminal.
|
||||
.PP
|
||||
The \fBWEEK\fR special lets you place annotations such as the week
|
||||
number in the calendar. For example, this would number each Monday
|
||||
with the ISO 8601 week number. The week number is shown like this:
|
||||
"(W\fIn\fR)" in this example, but you can put whatever text you like
|
||||
after the WEEK keyword.
|
||||
|
||||
.nf
|
||||
REM Monday SPECIAL WEEK (W[weekno()])
|
||||
.fi
|
||||
|
||||
.SH MISCELLANEOUS
|
||||
.PP
|
||||
@@ -3904,7 +4092,7 @@ This example puts an entry in each box of a calendar showing the number
|
||||
.nf
|
||||
REM Tue 2 Nov SATISFY (year(trigdate())%4) == 0
|
||||
IF trigvalid()
|
||||
REM [trigger(trigdate())] ++5 MSG \\
|
||||
REM [trigdate()] ++5 MSG \\
|
||||
U.S. Presidential Election!!
|
||||
ENDIF
|
||||
.fi
|
||||
@@ -3955,8 +4143,8 @@ in September. It can move over a range of 7 days. Consider the
|
||||
following sequence:
|
||||
.PP
|
||||
.nf
|
||||
REM Mon 1 Sept SCANFROM [trigger(today()-7)] SATISFY 1
|
||||
OMIT [trigger(trigdate())]
|
||||
REM Mon 1 Sept SCANFROM [today()-7] SATISFY 1
|
||||
OMIT [trigdate()]
|
||||
|
||||
REM Mon AFTER MSG Hello
|
||||
.fi
|
||||
@@ -3986,7 +4174,7 @@ will trigger on Mondays and Thursdays between 23 July 2007 and
|
||||
the reminder above as follows:
|
||||
.PP
|
||||
.nf
|
||||
REM Mon Thu SCANFROM [trigger(max(today(), '2007-07-23'))] \\
|
||||
REM Mon Thu SCANFROM [max(today(), '2007-07-23')] \\
|
||||
UNTIL 2 Aug 2007 MSG Test
|
||||
.fi
|
||||
.PP
|
||||
@@ -4079,8 +4267,9 @@ Hebrew dates in \fBRemind\fR change at midnight instead of sunset.
|
||||
.PP
|
||||
Language should be selectable at run-time, not compile-time. Don't
|
||||
expect this to happen soon!
|
||||
\fBRemind\fR has some built-in limits (for example,
|
||||
number of global \fBOMIT\fRs.)
|
||||
.PP
|
||||
\fBRemind\fR has some built-in limits (for example, number of global
|
||||
\fBOMIT\fRs.)
|
||||
.PP
|
||||
.SH BIBLIOGRAPHY
|
||||
.PP
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-1998 David F. Skoll
|
||||
# Copyright (C) 1999-2008 Roaring Penguin Software Inc.
|
||||
# Copyright (C) 1999-2009 Roaring Penguin Software Inc.
|
||||
#
|
||||
#--------------------------------------------------------------
|
||||
|
||||
@@ -208,6 +208,12 @@ proc Initialize {} {
|
||||
exit 1
|
||||
}
|
||||
|
||||
if {[file isdirectory $ReminderFile] && ! [file exists $AppendFile]} {
|
||||
if {![catch {close [open "$AppendFile" "a"]}]} {
|
||||
tk_dialog .error "Created File" "Created blank file `$AppendFile'" info 0 "OK"
|
||||
}
|
||||
}
|
||||
|
||||
if {! [file writable $AppendFile]} {
|
||||
tk_dialog .error Error "Can't write reminder file `$AppendFile'" error 0 Ok
|
||||
exit 1
|
||||
@@ -747,6 +753,13 @@ proc FillCalWindow {} {
|
||||
set month [string trimleft $month 0]
|
||||
set extratags ""
|
||||
switch -exact -- $type {
|
||||
"WEEK" {
|
||||
set stuff [string trimleft $stuff]
|
||||
set stuff [string trimright $stuff]
|
||||
set label [expr $firstWkday + $day - 1]
|
||||
.cal.l$label configure -text "$day $stuff"
|
||||
continue
|
||||
}
|
||||
"SHADE" {
|
||||
DoShadeSpecial $n $stuff
|
||||
continue
|
||||
@@ -2258,7 +2271,7 @@ proc main {} {
|
||||
global AppendFile HighestTagSoFar DayNames
|
||||
catch {
|
||||
puts "\nTkRemind Copyright (C) 1996-1998 David F. Skoll"
|
||||
puts "Copyright (C) 1999-2008 Roaring Penguin Software Inc."
|
||||
puts "Copyright (C) 1999-2009 Roaring Penguin Software Inc."
|
||||
}
|
||||
catch { SetFonts }
|
||||
LoadOptions
|
||||
@@ -2796,7 +2809,7 @@ proc ShowTodaysReminders {} {
|
||||
CenterWindow $w
|
||||
|
||||
# Grab the reminders
|
||||
set stuff [exec -keepnewline $Remind -g -q -a -r $ReminderFile 2>/dev/null]
|
||||
set stuff [exec -keepnewline $Remind -g -q -r $ReminderFile 2>/dev/null]
|
||||
$w.text insert end $stuff
|
||||
$w.text configure -state disabled
|
||||
}
|
||||
|
||||
@@ -748,7 +748,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
Value v;
|
||||
int r;
|
||||
int r, err;
|
||||
int jul;
|
||||
CalEntry *CurCol = CalColumn[col];
|
||||
CalEntry *e;
|
||||
@@ -763,7 +763,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufInit(&pre_buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
|
||||
/* Don't include timed reminders in calendar if -a option supplied. */
|
||||
if (DontIssueAts && tim.ttime != NO_TIME) return OK;
|
||||
@@ -793,7 +793,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (!LastTrigValid) return OK;
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) return r;
|
||||
}
|
||||
|
||||
@@ -845,7 +845,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufInit(&obuf);
|
||||
if ((jul == JulianToday) ||
|
||||
(DoSimpleCalDelta &&
|
||||
ShouldTriggerReminder(&trig, &tim, jul))) {
|
||||
ShouldTriggerReminder(&trig, &tim, jul, &err))) {
|
||||
NumTriggered++;
|
||||
|
||||
if (DoSimpleCalendar || tim.ttime != NO_TIME) {
|
||||
@@ -1265,7 +1265,7 @@ static void SortCol(CalEntry **col)
|
||||
while (cur->next &&
|
||||
CompareRems(0, cur->time, cur->priority,
|
||||
0, cur->next->time, cur->next->priority,
|
||||
SortByDate, SortByTime, SortByPrio) <= 0) {
|
||||
SortByDate, SortByTime, SortByPrio, UntimedBeforeTimed) <= 0) {
|
||||
next = cur->next;
|
||||
/* Swap cur and next */
|
||||
if (!prev) {
|
||||
|
||||
@@ -148,6 +148,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PRT_LEN 40
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* MAX_STR_LEN: If non-zero, Remind will limit the maximum length */
|
||||
/* of string values to avoid eating up all of memory... */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_STR_LEN 65535
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
@@ -148,6 +148,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PRT_LEN 40
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* MAX_STR_LEN: If non-zero, Remind will limit the maximum length */
|
||||
/* of string values to avoid eating up all of memory... */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_STR_LEN 65535
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
155
src/dorem.c
155
src/dorem.c
@@ -29,12 +29,12 @@
|
||||
static char const DontEscapeMe[] =
|
||||
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,";
|
||||
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim);
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
|
||||
static int ParseLocalOmit (ParsePtr s, Trigger *t);
|
||||
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
||||
static int ParsePriority (ParsePtr s, Trigger *t);
|
||||
static int ParseUntil (ParsePtr s, Trigger *t);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -48,7 +48,7 @@ int DoRem(ParsePtr p)
|
||||
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
int r;
|
||||
int r, err;
|
||||
int jul;
|
||||
DynamicBuffer buf;
|
||||
Token tok;
|
||||
@@ -56,7 +56,7 @@ int DoRem(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
|
||||
if (trig.typ == NO_TYPE) return E_EOLN;
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
@@ -90,7 +90,7 @@ int DoRem(ParsePtr p)
|
||||
if (!LastTrigValid) return OK;
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) return r;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ int DoRem(ParsePtr p)
|
||||
/* If we're in daemon mode, do nothing over here */
|
||||
if (Daemon) return OK;
|
||||
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul)) {
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) )
|
||||
{
|
||||
return r;
|
||||
@@ -121,12 +121,14 @@ int DoRem(ParsePtr p)
|
||||
/* trigger structure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
{
|
||||
register int r;
|
||||
DynamicBuffer buf;
|
||||
Token tok;
|
||||
|
||||
int y, m, d;
|
||||
|
||||
DBufInit(&buf);
|
||||
|
||||
trig->y = NO_YR;
|
||||
@@ -145,13 +147,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
trig->priority = DefaultPrio;
|
||||
trig->sched[0] = 0;
|
||||
trig->warn[0] = 0;
|
||||
trig->omitfunc[0] = 0;
|
||||
trig->tag[0] = 0;
|
||||
trig->passthru[0] = 0;
|
||||
tim->ttime = NO_TIME;
|
||||
tim->delta = NO_DELTA;
|
||||
tim->rep = NO_REP;
|
||||
tim->duration = NO_TIME;
|
||||
LastTriggerTime = NO_TIME;
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = NO_TIME;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
/* Read space-delimited string */
|
||||
@@ -161,6 +166,32 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
/* Figure out what we've got */
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch(tok.type) {
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
||||
if (trig->m != NO_MON) return E_MON_TWICE;
|
||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||
FromJulian(tok.val, &y, &m, &d);
|
||||
trig->y = y;
|
||||
trig->m = m;
|
||||
trig->d = d;
|
||||
break;
|
||||
|
||||
case T_DateTime:
|
||||
DBufFree(&buf);
|
||||
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
||||
if (trig->m != NO_MON) return E_MON_TWICE;
|
||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||
FromJulian(tok.val / MINUTES_PER_DAY, &y, &m, &d);
|
||||
trig->y = y;
|
||||
trig->m = m;
|
||||
trig->d = d;
|
||||
tim->ttime = (tok.val % MINUTES_PER_DAY);
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_WkDay:
|
||||
DBufFree(&buf);
|
||||
if (trig->wd & (1 << tok.val)) return E_WD_TWICE;
|
||||
@@ -187,7 +218,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
|
||||
case T_At:
|
||||
DBufFree(&buf);
|
||||
r=ParseTimeTrig(s, tim);
|
||||
r=ParseTimeTrig(s, tim, save_in_globals);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
@@ -257,6 +288,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
|
||||
case T_Omit:
|
||||
DBufFree(&buf);
|
||||
if (trig->omitfunc[0]) {
|
||||
Eprint("Warning: OMIT is ignored if you use OMITFUNC");
|
||||
}
|
||||
|
||||
r = ParseLocalOmit(s, trig);
|
||||
if (r) return r;
|
||||
break;
|
||||
@@ -266,6 +301,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
|
||||
return OK;
|
||||
|
||||
case T_OmitFunc:
|
||||
if (trig->localomit) {
|
||||
Eprint("Warning: OMIT is ignored if you use OMITFUNC");
|
||||
}
|
||||
r=ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
case T_Warn:
|
||||
r=ParseToken(s, &buf);
|
||||
if(r) return r;
|
||||
@@ -322,7 +367,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
/* ParseTimeTrig - parse the AT part of a timed reminder */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
static int ParseTimeTrig(ParsePtr s, TimeTrig *tim, int save_in_globals)
|
||||
{
|
||||
Token tok;
|
||||
int r;
|
||||
@@ -354,7 +399,9 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
|
||||
|
||||
/* Save trigger time in global variable */
|
||||
LastTriggerTime = tim->ttime;
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
}
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -443,6 +490,23 @@ static int ParseUntil(ParsePtr s, Trigger *t)
|
||||
d = tok.val;
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) {
|
||||
Eprint("UNTIL: %s", ErrMsg[E_YR_TWICE]);
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
if (m != NO_MON) {
|
||||
Eprint("UNTIL: %s", ErrMsg[E_MON_TWICE]);
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
if (d != NO_DAY) {
|
||||
Eprint("UNTIL: %s", ErrMsg[E_DAY_TWICE]);
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
FromJulian(tok.val, &y, &m, &d);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]);
|
||||
@@ -518,6 +582,23 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
d = tok.val;
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_YR_TWICE]);
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
if (m != NO_MON) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_MON_TWICE]);
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
if (d != NO_DAY) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_DAY_TWICE]);
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
FromJulian(tok.val, &y, &m, &d);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]);
|
||||
@@ -551,7 +632,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
{
|
||||
int r, y, m, d;
|
||||
char PrioExpr[25];
|
||||
char PrioExpr[VAR_NAME_LEN+25];
|
||||
char tmpBuf[64];
|
||||
DynamicBuffer buf, calRow;
|
||||
DynamicBuffer pre_buf;
|
||||
@@ -744,7 +825,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&buf);
|
||||
NumTriggered++;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -752,12 +833,13 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
/* */
|
||||
/* Return 1 if we should trigger a reminder, based on today's */
|
||||
/* date and the trigger. Return 0 if reminder should not be */
|
||||
/* triggered. */
|
||||
/* triggered. Sets *err non-zero in event of an error. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
||||
{
|
||||
int r;
|
||||
int r, omit;
|
||||
*err = 0;
|
||||
|
||||
/* Handle the ONCE modifier in the reminder. */
|
||||
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
|
||||
@@ -786,7 +868,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return ShouldTriggerBasedOnWarn(t, jul);
|
||||
return ShouldTriggerBasedOnWarn(t, jul, err);
|
||||
}
|
||||
|
||||
/* Move back by delta days, if any */
|
||||
@@ -795,9 +877,22 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
jul = jul + t->delta;
|
||||
else {
|
||||
r = t->delta;
|
||||
while(r && jul > JulianToday) {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
if (max < r*2) max = r*2;
|
||||
while(iter++ < max) {
|
||||
if (!r || (jul <= JulianToday)) {
|
||||
break;
|
||||
}
|
||||
jul--;
|
||||
if (!IsOmitted(jul, t->localomit)) r--;
|
||||
*err = IsOmitted(jul, t->localomit, t->omitfunc, &omit);
|
||||
if (*err) return 0;
|
||||
if (!omit) r--;
|
||||
}
|
||||
if (iter > max) {
|
||||
*err = E_CANT_TRIG;
|
||||
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -824,7 +919,7 @@ int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
|
||||
iter = 0;
|
||||
jul = trig->scanfrom;
|
||||
while (iter++ < MaxSatIter) {
|
||||
jul = ComputeTrigger(jul, trig, &r);
|
||||
jul = ComputeTrigger(jul, trig, &r, 1);
|
||||
if (r) {
|
||||
if (r == E_CANT_TRIG) return OK; else return r;
|
||||
}
|
||||
@@ -953,12 +1048,12 @@ finished:
|
||||
/* function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
|
||||
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
|
||||
{
|
||||
char buffer[VAR_NAME_LEN+32];
|
||||
int i;
|
||||
char const *s;
|
||||
int r;
|
||||
int r, omit;
|
||||
Value v;
|
||||
int lastReturnVal = 0; /* Silence compiler warning */
|
||||
|
||||
@@ -996,9 +1091,21 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
|
||||
if (JulianToday + v.v.val == jul) return 1;
|
||||
} else {
|
||||
int j = jul;
|
||||
while (v.v.val) {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
if (max < v.v.val * 2) max = v.v.val*2;
|
||||
while(iter++ <= max) {
|
||||
j--;
|
||||
if (!IsOmitted(j, t->localomit)) v.v.val++;
|
||||
*err = IsOmitted(j, t->localomit, t->omitfunc, &omit);
|
||||
if (*err) return 0;
|
||||
if (!omit) v.v.val++;
|
||||
if (!v.v.val) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iter > max) {
|
||||
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
|
||||
return 0;
|
||||
}
|
||||
if (j == JulianToday) return 1;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
#define M_BAD_WARN_FUNC 98
|
||||
#define E_CANT_CONVERT_TZ 99
|
||||
#define E_NO_MATCHING_REMS 100
|
||||
#define E_STRING_TOO_LONG 101
|
||||
|
||||
#ifdef MK_GLOBALS
|
||||
#undef EXTERN
|
||||
@@ -232,7 +233,8 @@ EXTERN char *ErrMsg[]
|
||||
"Expecting number",
|
||||
"Bad function in WARN clause",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
|
||||
57
src/expr.c
57
src/expr.c
@@ -42,7 +42,6 @@ static int Multiply(void), Divide(void), Mod(void), Add(void),
|
||||
Compare(int);
|
||||
|
||||
static int MakeValue (char const *s, Value *v, Var *locals);
|
||||
static int ParseLiteralDate (char const **s, int *jul, int *tim);
|
||||
|
||||
/* Binary operators - all left-associative */
|
||||
|
||||
@@ -73,9 +72,7 @@ Operator UnOp[] = {
|
||||
};
|
||||
#define NUM_UN_OPS (sizeof(UnOp) / sizeof(Operator))
|
||||
|
||||
/* Functions have the same definitions as operators, except the prec field
|
||||
is used to indicate how many arguments are needed. */
|
||||
extern Operator Func[];
|
||||
extern BuiltinFunc Func[];
|
||||
|
||||
Operator OpStack[OP_STACK_SIZE];
|
||||
Value ValStack[VAL_STACK_SIZE];
|
||||
@@ -333,7 +330,8 @@ int Evaluate(char const **s, Var *locals)
|
||||
{
|
||||
int OpBase, ValBase;
|
||||
int r;
|
||||
Operator *f;
|
||||
Operator *o;
|
||||
BuiltinFunc *f;
|
||||
int args; /* Number of function arguments */
|
||||
Operator op, op2;
|
||||
Value va;
|
||||
@@ -410,10 +408,10 @@ int Evaluate(char const **s, Var *locals)
|
||||
if (r) return r;
|
||||
}
|
||||
} else { /* Unary operator */
|
||||
f = FindFunc(DBufValue(&ExprBuf), UnOp, NUM_UN_OPS);
|
||||
if (f) {
|
||||
o = FindOperator(DBufValue(&ExprBuf), UnOp, NUM_UN_OPS);
|
||||
if (o) {
|
||||
DBufFree(&ExprBuf);
|
||||
PushOpStack(*f);
|
||||
PushOpStack(*o);
|
||||
continue; /* Still looking for an atomic vlue */
|
||||
} else if (!ISID(*DBufValue(&ExprBuf)) &&
|
||||
*DBufValue(&ExprBuf) != '$' &&
|
||||
@@ -459,13 +457,13 @@ int Evaluate(char const **s, Var *locals)
|
||||
return OK;
|
||||
}
|
||||
/* Must be a binary operator */
|
||||
f = FindFunc(DBufValue(&ExprBuf), BinOp, NUM_BIN_OPS);
|
||||
o = FindOperator(DBufValue(&ExprBuf), BinOp, NUM_BIN_OPS);
|
||||
DBufFree(&ExprBuf);
|
||||
if (!f) return E_EXPECTING_BINOP;
|
||||
if (!o) return E_EXPECTING_BINOP;
|
||||
|
||||
/* While operators of higher or equal precedence are on the stack,
|
||||
pop them off and evaluate */
|
||||
while (OpStackPtr > OpBase && OpStack[OpStackPtr-1].prec >= f->prec) {
|
||||
while (OpStackPtr > OpBase && OpStack[OpStackPtr-1].prec >= o->prec) {
|
||||
PopOpStack(op2);
|
||||
if (r) return r;
|
||||
if (DebugFlag & DB_PRTEXPR)
|
||||
@@ -477,7 +475,7 @@ int Evaluate(char const **s, Var *locals)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
PushOpStack(*f);
|
||||
PushOpStack(*o);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,6 +735,8 @@ static int Add(void)
|
||||
Value v1, v2, v3;
|
||||
int r;
|
||||
|
||||
size_t l1, l2;
|
||||
|
||||
PopValStack(v2);
|
||||
if ( (r = FnPopValStack(&v1)) ) {
|
||||
DestroyValue(v2);
|
||||
@@ -791,7 +791,13 @@ static int Add(void)
|
||||
return r;
|
||||
}
|
||||
v3.type = STR_TYPE;
|
||||
v3.v.str = malloc(strlen(v1.v.str) + strlen(v2.v.str) + 1);
|
||||
l1 = strlen(v1.v.str);
|
||||
l2 = strlen(v2.v.str);
|
||||
if (MaxStringLen && (l1 + l2 > MaxStringLen)) {
|
||||
DestroyValue(v1); DestroyValue(v2);
|
||||
return E_STRING_TOO_LONG;
|
||||
}
|
||||
v3.v.str = malloc(l1 + l2 + 1);
|
||||
if (!v3.v.str) {
|
||||
DestroyValue(v1); DestroyValue(v2);
|
||||
return E_NO_MEM;
|
||||
@@ -1118,7 +1124,28 @@ static int LogNot(void)
|
||||
/* Find a function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
Operator *FindFunc(char const *name, Operator where[], int num)
|
||||
Operator *FindOperator(char const *name, Operator where[], int num)
|
||||
{
|
||||
int top=num-1, bot=0;
|
||||
int mid, r;
|
||||
while (top >= bot) {
|
||||
mid = (top + bot) / 2;
|
||||
r = StrCmpi(name, where[mid].name);
|
||||
if (!r) return &where[mid];
|
||||
else if (r > 0) bot = mid+1;
|
||||
else top = mid-1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FindFunc */
|
||||
/* */
|
||||
/* Find a function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
BuiltinFunc *FindFunc(char const *name, BuiltinFunc where[], int num)
|
||||
{
|
||||
int top=num-1, bot=0;
|
||||
int mid, r;
|
||||
@@ -1194,7 +1221,7 @@ int CopyValue(Value *dest, const Value *src)
|
||||
/* and tim; update s. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ParseLiteralDate(char const **s, int *jul, int *tim)
|
||||
int ParseLiteralDate(char const **s, int *jul, int *tim)
|
||||
{
|
||||
int y, m, d;
|
||||
int hour, min;
|
||||
|
||||
@@ -723,7 +723,7 @@ static void DestroyCache(CachedFile *cf)
|
||||
/***************************************************************/
|
||||
int TopLevel(void)
|
||||
{
|
||||
return !IStackPtr;
|
||||
return IStackPtr <= 1;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
1036
src/funcs.c
1036
src/funcs.c
File diff suppressed because it is too large
Load Diff
@@ -59,6 +59,7 @@ EXTERN INIT( int IgnoreOnce, 0);
|
||||
EXTERN INIT( int SortByTime, 0);
|
||||
EXTERN INIT( int SortByDate, 0);
|
||||
EXTERN INIT( int SortByPrio, 0);
|
||||
EXTERN INIT( int UntimedBeforeTimed, 0);
|
||||
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
||||
EXTERN INIT( long SysTime, -1L);
|
||||
|
||||
@@ -75,6 +76,7 @@ EXTERN INIT( char TimeSep, TIMESEP);
|
||||
EXTERN INIT( int SynthesizeTags, 0);
|
||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||
EXTERN INIT( int MaxSatIter, 150);
|
||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
||||
EXTERN INIT( char *FileName, NULL);
|
||||
EXTERN INIT( int UseStdin, 0);
|
||||
EXTERN FILE *ErrFp;
|
||||
|
||||
41
src/init.c
41
src/init.c
@@ -133,6 +133,11 @@ void InitRemind(int argc, char const *argv[])
|
||||
char const *s;
|
||||
int weeks;
|
||||
|
||||
int jul, tim;
|
||||
|
||||
jul = NO_DATE;
|
||||
tim = NO_TIME;
|
||||
|
||||
/* Initialize global dynamic buffers */
|
||||
DBufInit(&Banner);
|
||||
DBufInit(&LineBuffer);
|
||||
@@ -248,6 +253,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
SortByDate = SORT_ASCEND;
|
||||
SortByTime = SORT_ASCEND;
|
||||
SortByPrio = SORT_ASCEND;
|
||||
UntimedBeforeTimed = 0;
|
||||
if (*arg) {
|
||||
if (*arg == 'D' || *arg == 'd')
|
||||
SortByDate = SORT_DESCEND;
|
||||
@@ -263,6 +269,11 @@ void InitRemind(int argc, char const *argv[])
|
||||
SortByPrio = SORT_DESCEND;
|
||||
arg++;
|
||||
}
|
||||
if (*arg) {
|
||||
if (*arg == 'D' || *arg == 'd')
|
||||
UntimedBeforeTimed = 1;
|
||||
arg++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
@@ -474,18 +485,32 @@ void InitRemind(int argc, char const *argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
case T_DateTime:
|
||||
if (SysTime != -1L) Usage();
|
||||
if (m != NO_MON || d != NO_DAY || y != NO_YR || jul != NO_DATE) Usage();
|
||||
SysTime = (tok.val % MINUTES_PER_DAY) * 60;
|
||||
DontQueue = 1;
|
||||
Daemon = 0;
|
||||
jul = tok.val / MINUTES_PER_DAY;
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
if (m != NO_MON || d != NO_DAY || y != NO_YR || jul != NO_DATE) Usage();
|
||||
jul = tok.val;
|
||||
break;
|
||||
|
||||
case T_Month:
|
||||
if (m != NO_MON) Usage();
|
||||
if (m != NO_MON || jul != NO_DATE) Usage();
|
||||
else m = tok.val;
|
||||
break;
|
||||
|
||||
case T_Day:
|
||||
if (d != NO_DAY) Usage();
|
||||
if (d != NO_DAY || jul != NO_DATE) Usage();
|
||||
else d = tok.val;
|
||||
break;
|
||||
|
||||
case T_Year:
|
||||
if (y != NO_YR) Usage();
|
||||
if (y != NO_YR || jul != NO_DATE) Usage();
|
||||
else y = tok.val;
|
||||
break;
|
||||
|
||||
@@ -494,7 +519,8 @@ void InitRemind(int argc, char const *argv[])
|
||||
else rep = tok.val;
|
||||
break;
|
||||
|
||||
default: Usage();
|
||||
default:
|
||||
Usage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,6 +530,9 @@ void InitRemind(int argc, char const *argv[])
|
||||
Daemon = 0;
|
||||
}
|
||||
|
||||
if (jul != NO_DATE) {
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
}
|
||||
/* Must supply date in the form: day, mon, yr OR mon, yr */
|
||||
if (m != NO_MON || y != NO_YR || d != NO_DAY) {
|
||||
if (m == NO_MON || y == NO_YR) {
|
||||
@@ -549,7 +578,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "Copyright 1999-2008 Roaring Penguin Software Inc.\n");
|
||||
fprintf(ErrFp, "Copyright 1999-2009 Roaring Penguin Software Inc.\n");
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
@@ -576,7 +605,7 @@ void Usage(void)
|
||||
fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
|
||||
fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=150)\n");
|
||||
fprintf(ErrFp, " -kcmd Run `cmd' for MSG-type reminders\n");
|
||||
fprintf(ErrFp, " -g[ddd] Sort reminders by date, time and priority before issuing\n");
|
||||
fprintf(ErrFp, " -g[dddd] Sort reminders by date, time, priority, and 'timedness'\n");
|
||||
fprintf(ErrFp, " -ivar=val Initialize var to val and preserve var\n");
|
||||
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
|
||||
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
|
||||
|
||||
@@ -308,7 +308,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Numero puuttuu",
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#elif IBMEXTENDED
|
||||
"Ok",
|
||||
@@ -411,7 +412,9 @@ EXTERN char *ErrMsg[] =
|
||||
"Numero puuttuu"
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#else
|
||||
"Ok",
|
||||
"Puuttuva ']'",
|
||||
@@ -513,7 +516,9 @@ EXTERN char *ErrMsg[] =
|
||||
"Numero puuttuu",
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -245,7 +245,9 @@ EXTERN char *ErrMsg[] =
|
||||
"Nombre attendu",
|
||||
"Fonction ill\351gale apr\350s WARN",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
|
||||
#else /* ISOLATIN1 */
|
||||
"Ok",
|
||||
"']' manquant",
|
||||
@@ -347,7 +349,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Nombre attendu",
|
||||
"Fonction illegale apres WARN",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -280,7 +280,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Spodziewana liczba",
|
||||
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#else /* ISOLATIN1 */
|
||||
"OK",
|
||||
"Brakujacy ']'",
|
||||
@@ -382,7 +383,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Spodziewana liczba",
|
||||
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -246,7 +246,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Esperando numero",
|
||||
"Funcao ilegal na clausula WARN",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem"
|
||||
"No files matching *.rem",
|
||||
"String too long"
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
|
||||
10
src/main.c
10
src/main.c
@@ -7,7 +7,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1999-2009 by Roaring Penguin Software Inc. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -724,7 +724,7 @@ int DoEndif(ParsePtr p)
|
||||
/***************************************************************/
|
||||
int DoIfTrig(ParsePtr p)
|
||||
{
|
||||
int r;
|
||||
int r, err;
|
||||
unsigned syndrome;
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
@@ -734,12 +734,12 @@ int DoIfTrig(ParsePtr p)
|
||||
if (NumIfs >= IF_NEST) return E_NESTED_IF;
|
||||
if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else {
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else {
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul))
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err))
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else
|
||||
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||
|
||||
58
src/omit.c
58
src/omit.c
@@ -20,6 +20,7 @@
|
||||
#include "protos.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "expr.h"
|
||||
|
||||
static int BexistsIntArray (int array[], int num, int key);
|
||||
static void InsertIntoSortedArray (int *array, int num, int key);
|
||||
@@ -177,26 +178,57 @@ int PopOmitContext(ParsePtr p)
|
||||
/* */
|
||||
/* IsOmitted */
|
||||
/* */
|
||||
/* Return non-zero if date is OMITted, zero if it is not. */
|
||||
/* Set *omit to non-zero if date is omitted, else 0. Returns */
|
||||
/* OK or an error code. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int IsOmitted(int jul, int localomit)
|
||||
int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
|
||||
{
|
||||
int y, m, d;
|
||||
|
||||
/* If we have an omitfunc, we *only* use it and ignore local/global
|
||||
OMITs */
|
||||
if (omitfunc && *omitfunc && UserFuncExists(omitfunc)) {
|
||||
char expr[VAR_NAME_LEN + 32];
|
||||
char const *s;
|
||||
int r;
|
||||
Value v;
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
sprintf(expr, "%s('%04d-%02d-%02d')",
|
||||
omitfunc, y, m+1, d);
|
||||
s = expr;
|
||||
r = EvalExpr(&s, &v);
|
||||
if (r) return r;
|
||||
if (v.type == INT_TYPE && v.v.val != 0) {
|
||||
*omit = 1;
|
||||
} else {
|
||||
*omit = 0;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Is it omitted because of local omits? */
|
||||
if (localomit & (1 << (jul % 7))) return 1;
|
||||
if (localomit & (1 << (jul % 7))) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Is it omitted because of fully-specified omits? */
|
||||
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) return 1;
|
||||
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Get the syndrome */
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
|
||||
return 1;
|
||||
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Not omitted */
|
||||
return 0;
|
||||
*omit = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -262,6 +294,14 @@ int DoOmit(ParsePtr p)
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch (tok.type) {
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) return E_YR_TWICE;
|
||||
if (m != NO_MON) return E_MON_TWICE;
|
||||
if (d != NO_DAY) return E_DAY_TWICE;
|
||||
FromJulian(tok.val, &y, &m, &d);
|
||||
break;
|
||||
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) return E_YR_TWICE;
|
||||
@@ -279,7 +319,7 @@ int DoOmit(ParsePtr p)
|
||||
if (d != NO_DAY) return E_DAY_TWICE;
|
||||
d = tok.val;
|
||||
break;
|
||||
|
||||
|
||||
case T_Delta:
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
16
src/protos.h
16
src/protos.h
@@ -26,11 +26,12 @@ char const *CalendarTime (int tim, int duration);
|
||||
int DoRem (ParsePtr p);
|
||||
int DoFlush (ParsePtr p);
|
||||
void DoExit (ParsePtr p);
|
||||
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim);
|
||||
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int jul);
|
||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul);
|
||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul, int *err);
|
||||
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode);
|
||||
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim);
|
||||
int ParseLiteralDate (char const **s, int *jul, int *tim);
|
||||
int EvalExpr (char const **e, Value *v);
|
||||
int DoCoerce (char type, Value *v);
|
||||
void PrintValue (Value *v, FILE *fp);
|
||||
@@ -42,7 +43,7 @@ int IncludeFile (char const *fname);
|
||||
int GetAccessDate (char const *file);
|
||||
int SetAccessDate (char const *fname, int jul);
|
||||
int TopLevel (void);
|
||||
int CallFunc (Operator *f, int nargs);
|
||||
int CallFunc (BuiltinFunc *f, int nargs);
|
||||
void InitRemind (int argc, char const *argv[]);
|
||||
void Usage (void);
|
||||
int Julian (int year, int month, int day);
|
||||
@@ -75,14 +76,14 @@ int DoClear (ParsePtr p);
|
||||
int DestroyOmitContexts (void);
|
||||
int PushOmitContext (ParsePtr p);
|
||||
int PopOmitContext (ParsePtr p);
|
||||
int IsOmitted (int jul, int localomit);
|
||||
int IsOmitted (int jul, int localomit, char const *omitfunc, int *omit);
|
||||
int DoOmit (ParsePtr p);
|
||||
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, char const *sched);
|
||||
void HandleQueuedReminders (void);
|
||||
char const *FindInitialToken (Token *tok, char const *s);
|
||||
void FindToken (char const *s, Token *tok);
|
||||
void FindNumericToken (char const *s, Token *t);
|
||||
int ComputeTrigger (int today, Trigger *trig, int *err);
|
||||
int ComputeTrigger (int today, Trigger *trig, int *err, int save_in_globals);
|
||||
char *StrnCpy (char *dest, char const *source, int n);
|
||||
int StrMatch (char const *s1, char const *s2, int n);
|
||||
int StrinCmp (char const *s1, char const *s2, int n);
|
||||
@@ -104,7 +105,8 @@ int DoMsgCommand (char const *cmd, char const *msg);
|
||||
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
||||
unsigned int HashVal (char const *str);
|
||||
int DateOK (int y, int m, int d);
|
||||
Operator *FindFunc (char const *name, Operator where[], int num);
|
||||
Operator *FindOperator (char const *name, Operator where[], int num);
|
||||
BuiltinFunc *FindFunc (char const *name, BuiltinFunc where[], int num);
|
||||
int InsertIntoSortBuffer (int jul, int tim, char const *body, int typ, int prio);
|
||||
void IssueSortedReminders (void);
|
||||
int UserFuncExists (char const *fn);
|
||||
@@ -128,7 +130,7 @@ void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
|
||||
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
|
||||
int MoonPhase (int date, int time);
|
||||
void HuntPhase (int startdate, int starttim, int phas, int *date, int *time);
|
||||
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio);
|
||||
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio, int untimed_first);
|
||||
void SigIntHandler (int d);
|
||||
void GotSigInt (void);
|
||||
void SynthesizeTag(char *);
|
||||
|
||||
21
src/rem2ps.c
21
src/rem2ps.c
@@ -30,6 +30,7 @@
|
||||
#define SPECIAL_MOON 3
|
||||
#define SPECIAL_SHADE 4
|
||||
#define SPECIAL_COLOR 5
|
||||
#define SPECIAL_WEEK 6
|
||||
|
||||
typedef struct calentry {
|
||||
struct calentry *next;
|
||||
@@ -306,6 +307,7 @@ void DoPsCal(void)
|
||||
if (!strcmp(passthru, "PostScript") ||
|
||||
!strcmp(passthru, "PSFile") ||
|
||||
!strcmp(passthru, "MOON") ||
|
||||
!strcmp(passthru, "WEEK") ||
|
||||
!strcmp(passthru, "SHADE")) {
|
||||
is_ps = 1;
|
||||
}
|
||||
@@ -324,6 +326,8 @@ void DoPsCal(void)
|
||||
c->special = SPECIAL_SHADE;
|
||||
} else if (!strcmp(passthru, "MOON")) {
|
||||
c->special = SPECIAL_MOON;
|
||||
} else if (!strcmp(passthru, "WEEK")) {
|
||||
c->special = SPECIAL_WEEK;
|
||||
} else {
|
||||
c->special = SPECIAL_PSFILE;
|
||||
}
|
||||
@@ -887,6 +891,7 @@ int DoQueuedPs(void)
|
||||
int fnoff;
|
||||
char buffer[512];
|
||||
char const *size, *extra;
|
||||
char const *s;
|
||||
int num, r, g, b, phase, fontsize, moonsize;
|
||||
unsigned char c;
|
||||
|
||||
@@ -954,6 +959,22 @@ int DoQueuedPs(void)
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
break;
|
||||
|
||||
case SPECIAL_WEEK: /* Week number */
|
||||
printf("gsave Border Border 2 div moveto /EntryFont findfont EntrySize 1.2 div scalefont setfont (");
|
||||
s = e->entry+fnoff;
|
||||
while(*s && isspace(*s)) {
|
||||
s++;
|
||||
}
|
||||
while(*s) {
|
||||
if (*s == '\\' || *s == '(' || *s == ')') {
|
||||
PutChar('\\');
|
||||
}
|
||||
PutChar(*s);
|
||||
s++;
|
||||
}
|
||||
printf(") show grestore\n");
|
||||
break;
|
||||
|
||||
case SPECIAL_MOON: /* Moon phase */
|
||||
num = sscanf(e->entry+fnoff, "%d %d %d", &phase, &moonsize,
|
||||
&fontsize);
|
||||
|
||||
21
src/sort.c
21
src/sort.c
@@ -83,6 +83,7 @@ int InsertIntoSortBuffer(int jul, int tim, char const *body, int typ, int prio)
|
||||
SortByDate = 0;
|
||||
SortByTime = 0;
|
||||
SortByPrio = 0;
|
||||
UntimedBeforeTimed = 0;
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -94,8 +95,8 @@ int InsertIntoSortBuffer(int jul, int tim, char const *body, int typ, int prio)
|
||||
while (cur) {
|
||||
ShouldGoAfter = CompareRems(new->trigdate, new->trigtime, new->priority,
|
||||
cur->trigdate, cur->trigtime, cur->priority,
|
||||
SortByDate, SortByTime, SortByPrio);
|
||||
|
||||
SortByDate, SortByTime, SortByPrio, UntimedBeforeTimed);
|
||||
|
||||
if (ShouldGoAfter <= 0) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
@@ -203,19 +204,27 @@ static void IssueSortBanner(int jul)
|
||||
/***************************************************************/
|
||||
int CompareRems(int dat1, int tim1, int prio1,
|
||||
int dat2, int tim2, int prio2,
|
||||
int bydate, int bytime, int byprio)
|
||||
int bydate, int bytime, int byprio,
|
||||
int untimed_first)
|
||||
{
|
||||
int dafter, tafter, pafter;
|
||||
int dafter, tafter, pafter, uafter;
|
||||
|
||||
dafter = (bydate != SORT_DESCEND) ? 1 : -1;
|
||||
tafter = (bytime != SORT_DESCEND) ? 1 : -1;
|
||||
pafter = (byprio != SORT_DESCEND) ? 1 : -1;
|
||||
uafter = (untimed_first) ? -1 : 1;
|
||||
|
||||
if (dat1 < dat2) return dafter;
|
||||
if (dat1 > dat2) return -dafter;
|
||||
|
||||
if (tim1 == NO_TIME && tim2 != NO_TIME) return -1;
|
||||
if (tim1 != NO_TIME && tim2 == NO_TIME) return 1;
|
||||
if (tim1 == NO_TIME && tim2 != NO_TIME) {
|
||||
return -uafter;
|
||||
}
|
||||
|
||||
if (tim1 != NO_TIME && tim2 == NO_TIME) {
|
||||
return uafter;
|
||||
}
|
||||
|
||||
if (tim1 < tim2) return tafter;
|
||||
if (tim1 > tim2) return -tafter;
|
||||
|
||||
|
||||
19
src/token.c
19
src/token.c
@@ -74,6 +74,7 @@ Token TokArray[] = {
|
||||
{ "november", 3, T_Month, 10 },
|
||||
{ "october", 3, T_Month, 9 },
|
||||
{ "omit", 3, T_Omit, 0 },
|
||||
{ "omitfunc", 8, T_OmitFunc, 0 },
|
||||
{ "once", 3, T_Once, 0 },
|
||||
{ "pop-omit-context", 3, T_Pop, 0 },
|
||||
{ "preserve", 8, T_Preserve, 0 },
|
||||
@@ -255,12 +256,30 @@ void FindToken(char const *s, Token *tok)
|
||||
void FindNumericToken(char const *s, Token *t)
|
||||
{
|
||||
int mult = 1, hour, min;
|
||||
char const *s_orig = s;
|
||||
|
||||
t->type = T_Illegal;
|
||||
t->val = 0;
|
||||
if (isdigit(*s)) {
|
||||
PARSENUM(t->val, s);
|
||||
|
||||
/* If we hit a '-' or a '/', we may have a date or a datetime */
|
||||
if (*s == '-' || *s == '/') {
|
||||
char const *p = s_orig;
|
||||
int jul, tim;
|
||||
if (ParseLiteralDate(&p, &jul, &tim) == OK) {
|
||||
if (*p) return;
|
||||
if (tim == NO_TIME) {
|
||||
t->type = T_Date;
|
||||
t->val = jul;
|
||||
return;
|
||||
}
|
||||
t->type = T_DateTime;
|
||||
t->val = MINUTES_PER_DAY * jul + tim;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we hit a comma, swallow it. This allows stuff
|
||||
like Jan 6, 1998 */
|
||||
if (*s == ',') {
|
||||
|
||||
132
src/trigger.c
132
src/trigger.c
@@ -206,16 +206,27 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
*err = E_BAD_DATE;
|
||||
return -1;
|
||||
}
|
||||
/* Back up a year in case we'll cross a year boundary*/
|
||||
if (y > BASE) {
|
||||
y--;
|
||||
}
|
||||
|
||||
/* Move up to the first valid year */
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
|
||||
/* Try last year */
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
if (j >= startdate) return j;
|
||||
|
||||
/* Try this year */
|
||||
y++;
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
if (j >= startdate) return j;
|
||||
|
||||
/* Must be next year */
|
||||
y = y + 1;
|
||||
y++;
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
@@ -286,7 +297,7 @@ static int JYear(int jul)
|
||||
/***************************************************************/
|
||||
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart)
|
||||
{
|
||||
int simple, mod;
|
||||
int simple, mod, omit;
|
||||
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
if (trig->until != NO_UNTIL &&
|
||||
@@ -294,8 +305,22 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
|
||||
/* Next: If it's an "AFTER"-type skip, back up
|
||||
until we're at the start of a block of holidays */
|
||||
if (trig->skip == AFTER_SKIP)
|
||||
while (IsOmitted(start-1, trig->localomit)) start--;
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(start-1, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
start--;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
/* omitfunc must have returned "true" too often */
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the next simple trigger */
|
||||
simple = NextSimpleTrig(start, trig, err);
|
||||
@@ -309,12 +334,29 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
/* If there's a BACK, back up... */
|
||||
if (trig->back != NO_BACK) {
|
||||
mod = trig->back;
|
||||
if (mod < 0) simple += mod;
|
||||
else
|
||||
while(mod) {
|
||||
simple--;
|
||||
if (!IsOmitted(simple, trig->localomit)) mod--;
|
||||
if (mod < 0) {
|
||||
simple += mod;
|
||||
}
|
||||
else {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
if (max < mod*2) {
|
||||
max = mod*2;
|
||||
}
|
||||
while(iter++ <= max) {
|
||||
if (!mod) {
|
||||
break;
|
||||
}
|
||||
simple--;
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) mod--;
|
||||
}
|
||||
if (iter > max) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's a REP, calculate the next occurrence */
|
||||
@@ -327,12 +369,38 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
|
||||
/* If it's a "BEFORE"-type skip, back up */
|
||||
if (trig->skip == BEFORE_SKIP)
|
||||
while(IsOmitted(simple, trig->localomit)) simple--;
|
||||
if (trig->skip == BEFORE_SKIP) {
|
||||
int iter = 0;
|
||||
while(iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
simple--;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's an "AFTER"-type skip, jump ahead */
|
||||
if (trig->skip == AFTER_SKIP)
|
||||
while (IsOmitted(simple, trig->localomit)) simple++;
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
simple++;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the date */
|
||||
return simple;
|
||||
@@ -346,15 +414,15 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
/* today's date. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
{
|
||||
int nattempts = 0,
|
||||
start = today,
|
||||
nextstart = 0,
|
||||
y, m, d,
|
||||
y, m, d, omit,
|
||||
result;
|
||||
|
||||
LastTrigValid = 0;
|
||||
if (save_in_globals) LastTrigValid = 0;
|
||||
|
||||
/* Assume everything works */
|
||||
*err = OK;
|
||||
@@ -373,8 +441,8 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
*err = E_REP_FULSPEC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
while (nattempts++ < TRIG_ATTEMPTS) {
|
||||
result = GetNextTriggerDate(trig, start, err, &nextstart);
|
||||
|
||||
@@ -389,10 +457,18 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
}
|
||||
|
||||
/* If result is >= today, great! */
|
||||
if (trig->skip == SKIP_SKIP) {
|
||||
*err = IsOmitted(result, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -1;
|
||||
} else {
|
||||
omit = 0;
|
||||
}
|
||||
if (result >= today &&
|
||||
(trig->skip != SKIP_SKIP || !IsOmitted(result, trig->localomit))) {
|
||||
LastTriggerDate = result; /* Save in global var */
|
||||
LastTrigValid = 1;
|
||||
(trig->skip != SKIP_SKIP || !omit)) {
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result; /* Save in global var */
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromJulian(result, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d\n",
|
||||
@@ -414,14 +490,16 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||
}
|
||||
if (result != -1) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (trig->skip == SKIP_SKIP &&
|
||||
IsOmitted(result, trig->localomit) &&
|
||||
omit &&
|
||||
nextstart <= start &&
|
||||
result >= start) {
|
||||
nextstart = result + 1;
|
||||
@@ -430,8 +508,10 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
/* Keep scanning... unless there's no point in doing it.*/
|
||||
if (nextstart <= start) {
|
||||
if (result != -1) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
}
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
|
||||
20
src/types.h
20
src/types.h
@@ -30,6 +30,20 @@ typedef struct {
|
||||
int (*func)(void);
|
||||
} Operator;
|
||||
|
||||
/* Structure for passing in Nargs and out RetVal from functions */
|
||||
typedef struct {
|
||||
int nargs;
|
||||
Value retval;
|
||||
} func_info;
|
||||
|
||||
/* Define the type of user-functions */
|
||||
typedef struct {
|
||||
char const *name;
|
||||
char minargs;
|
||||
char maxargs;
|
||||
int (*func)(func_info *);
|
||||
} BuiltinFunc;
|
||||
|
||||
/* Define the structure of a variable */
|
||||
typedef struct var {
|
||||
struct var *next;
|
||||
@@ -56,6 +70,7 @@ typedef struct {
|
||||
int priority;
|
||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||
char tag[TAG_LEN+1];
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
} Trigger;
|
||||
@@ -132,7 +147,7 @@ enum TokTypes
|
||||
T_IfTrig, T_ErrMsg,
|
||||
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
|
||||
T_WkDay,
|
||||
T_Month, T_Time,
|
||||
T_Month, T_Time, T_Date, T_DateTime,
|
||||
T_Skip, T_At, T_RemType, T_Until, T_Year, T_Day, T_Rep, T_Delta, T_Back,
|
||||
T_Once,
|
||||
T_Empty,
|
||||
@@ -148,7 +163,8 @@ enum TokTypes
|
||||
T_Warn,
|
||||
T_Tag,
|
||||
T_Duration,
|
||||
T_LongTime
|
||||
T_LongTime,
|
||||
T_OmitFunc
|
||||
};
|
||||
|
||||
/* The structure of a token */
|
||||
|
||||
@@ -40,7 +40,7 @@ static UserFunc *FuncHash[FUNC_HASH_SIZE];
|
||||
|
||||
/* Access to built-in functions */
|
||||
extern int NumFuncs;
|
||||
extern Operator Func[];
|
||||
extern BuiltinFunc Func[];
|
||||
|
||||
/* We need access to the expression evaluation stack */
|
||||
extern Value ValStack[];
|
||||
|
||||
@@ -223,7 +223,7 @@ int DoSet (Parser *p)
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r) return r;
|
||||
|
||||
/* Allow option equals-sign: SET var = value */
|
||||
/* Allow optional equals-sign: SET var = value */
|
||||
if (ParseNonSpaceChar(p, &r, 1) == '=') {
|
||||
ParseNonSpaceChar(p, &r, 0);
|
||||
}
|
||||
@@ -488,6 +488,7 @@ static SysVar SysVarArr[] = {
|
||||
{ "LongMin", 1, INT_TYPE, &LongMin, -59, 59 },
|
||||
{ "LongSec", 1, INT_TYPE, &LongSec, -59, 59 },
|
||||
{ "MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
|
||||
{ "MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
|
||||
{ "MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -13*60, 13*60 },
|
||||
{ "NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
|
||||
{ "NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
|
||||
@@ -500,7 +501,8 @@ static SysVar SysVarArr[] = {
|
||||
{ "SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0},
|
||||
{ "SortByTime", 0, INT_TYPE, &SortByTime, 0, 0},
|
||||
{ "SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132},
|
||||
{ "TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 }
|
||||
{ "TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
|
||||
{ "UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0 }
|
||||
};
|
||||
|
||||
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
|
||||
|
||||
3
tests/runinc.rem
Normal file
3
tests/runinc.rem
Normal file
@@ -0,0 +1,3 @@
|
||||
set s shell("echo 3")
|
||||
run on
|
||||
set s shell("echo 3")
|
||||
6
tests/runtest.rem
Normal file
6
tests/runtest.rem
Normal file
@@ -0,0 +1,6 @@
|
||||
run off
|
||||
set a shell("echo 2")
|
||||
run on
|
||||
set a shell("echo 2")
|
||||
run off
|
||||
include ../tests/runinc.rem
|
||||
@@ -60,6 +60,15 @@ chmod 644 include_dir/04cantread.rem
|
||||
echo "Color Test" >> ../tests/test.out
|
||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out
|
||||
|
||||
echo "MON WKDAY DAY across year test" >> ../tests/test.out
|
||||
echo 'REM Mon 29 Dec MSG x' | ../src/remind -dt - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Sort Test" >> ../tests/test.out
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -gaaa - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -gaaad - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
|
||||
../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1
|
||||
|
||||
cmp -s ../tests/test.out ../tests/test.cmp
|
||||
if [ "$?" = "0" ]; then
|
||||
echo "Remind: Acceptance test PASSED"
|
||||
|
||||
257
tests/test.cmp
257
tests/test.cmp
@@ -431,7 +431,7 @@ REM 1 Mar --1 MSG 1 mar --1
|
||||
../tests/test.rem(133): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE
|
||||
../tests/test.rem(134): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
../tests/test.rem(135): Trig = Thursday, 28 February, 1991
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER
|
||||
../tests/test.rem(136): Trig = Thursday, 28 February, 1991
|
||||
@@ -451,7 +451,7 @@ REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
|
||||
|
||||
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
|
||||
../tests/test.rem(146): Trig = Wednesday, 13 March, 1991
|
||||
|
||||
|
||||
# Test BACK
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
|
||||
@@ -488,6 +488,200 @@ REM Fri after MSG 16 Feb 1991
|
||||
16 Feb 1991
|
||||
|
||||
CLEAR-OMIT-CONTEXT
|
||||
|
||||
# Test omitfunc
|
||||
fset _ofunc(x) (day(x) < 7 || day(x) % 2)
|
||||
REM 1 March OMITFUNC _ofunc AFTER MSG OmitFunc Test
|
||||
Entering UserFN _ofunc(1991-02-15)
|
||||
x => 1991-02-15
|
||||
day(1991-02-15) => 15
|
||||
15 < 7 => 0
|
||||
x => 1991-02-15
|
||||
day(1991-02-15) => 15
|
||||
15 % 2 => 1
|
||||
0 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-02-14)
|
||||
x => 1991-02-14
|
||||
day(1991-02-14) => 14
|
||||
14 < 7 => 0
|
||||
x => 1991-02-14
|
||||
day(1991-02-14) => 14
|
||||
14 % 2 => 0
|
||||
0 || 0 => 0
|
||||
Leaving UserFN _ofunc() => 0
|
||||
Entering UserFN _ofunc(1991-03-01)
|
||||
x => 1991-03-01
|
||||
day(1991-03-01) => 1
|
||||
1 < 7 => 1
|
||||
x => 1991-03-01
|
||||
day(1991-03-01) => 1
|
||||
1 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-02)
|
||||
x => 1991-03-02
|
||||
day(1991-03-02) => 2
|
||||
2 < 7 => 1
|
||||
x => 1991-03-02
|
||||
day(1991-03-02) => 2
|
||||
2 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-03)
|
||||
x => 1991-03-03
|
||||
day(1991-03-03) => 3
|
||||
3 < 7 => 1
|
||||
x => 1991-03-03
|
||||
day(1991-03-03) => 3
|
||||
3 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-04)
|
||||
x => 1991-03-04
|
||||
day(1991-03-04) => 4
|
||||
4 < 7 => 1
|
||||
x => 1991-03-04
|
||||
day(1991-03-04) => 4
|
||||
4 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-05)
|
||||
x => 1991-03-05
|
||||
day(1991-03-05) => 5
|
||||
5 < 7 => 1
|
||||
x => 1991-03-05
|
||||
day(1991-03-05) => 5
|
||||
5 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-06)
|
||||
x => 1991-03-06
|
||||
day(1991-03-06) => 6
|
||||
6 < 7 => 1
|
||||
x => 1991-03-06
|
||||
day(1991-03-06) => 6
|
||||
6 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-07)
|
||||
x => 1991-03-07
|
||||
day(1991-03-07) => 7
|
||||
7 < 7 => 0
|
||||
x => 1991-03-07
|
||||
day(1991-03-07) => 7
|
||||
7 % 2 => 1
|
||||
0 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-08)
|
||||
x => 1991-03-08
|
||||
day(1991-03-08) => 8
|
||||
8 < 7 => 0
|
||||
x => 1991-03-08
|
||||
day(1991-03-08) => 8
|
||||
8 % 2 => 0
|
||||
0 || 0 => 0
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(169): Trig = Friday, 8 March, 1991
|
||||
REM 8 March OMITFUNC _ofunc -1 MSG OmitFunc Test 2
|
||||
Entering UserFN _ofunc(1991-03-07)
|
||||
x => 1991-03-07
|
||||
day(1991-03-07) => 7
|
||||
7 < 7 => 0
|
||||
x => 1991-03-07
|
||||
day(1991-03-07) => 7
|
||||
7 % 2 => 1
|
||||
0 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-06)
|
||||
x => 1991-03-06
|
||||
day(1991-03-06) => 6
|
||||
6 < 7 => 1
|
||||
x => 1991-03-06
|
||||
day(1991-03-06) => 6
|
||||
6 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-05)
|
||||
x => 1991-03-05
|
||||
day(1991-03-05) => 5
|
||||
5 < 7 => 1
|
||||
x => 1991-03-05
|
||||
day(1991-03-05) => 5
|
||||
5 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-04)
|
||||
x => 1991-03-04
|
||||
day(1991-03-04) => 4
|
||||
4 < 7 => 1
|
||||
x => 1991-03-04
|
||||
day(1991-03-04) => 4
|
||||
4 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-03)
|
||||
x => 1991-03-03
|
||||
day(1991-03-03) => 3
|
||||
3 < 7 => 1
|
||||
x => 1991-03-03
|
||||
day(1991-03-03) => 3
|
||||
3 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-02)
|
||||
x => 1991-03-02
|
||||
day(1991-03-02) => 2
|
||||
2 < 7 => 1
|
||||
x => 1991-03-02
|
||||
day(1991-03-02) => 2
|
||||
2 % 2 => 0
|
||||
1 || 0 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-03-01)
|
||||
x => 1991-03-01
|
||||
day(1991-03-01) => 1
|
||||
1 < 7 => 1
|
||||
x => 1991-03-01
|
||||
day(1991-03-01) => 1
|
||||
1 % 2 => 1
|
||||
1 || 1 => 1
|
||||
Leaving UserFN _ofunc() => 1
|
||||
Entering UserFN _ofunc(1991-02-28)
|
||||
x => 1991-02-28
|
||||
day(1991-02-28) => 28
|
||||
28 < 7 => 0
|
||||
x => 1991-02-28
|
||||
day(1991-02-28) => 28
|
||||
28 % 2 => 0
|
||||
0 || 0 => 0
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(170): Trig = Thursday, 28 February, 1991
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
../tests/test.rem(176): Warning: OMIT is ignored if you use OMITFUNC
|
||||
Entering UserFN _ofunc(1991-02-15)
|
||||
Leaving UserFN _ofunc() => 0
|
||||
Entering UserFN _ofunc(1991-03-01)
|
||||
Leaving UserFN _ofunc() => 0
|
||||
../tests/test.rem(176): Trig = Friday, 1 March, 1991
|
||||
REM 1 March OMIT Sun AFTER MSG Should trigger 4 March
|
||||
../tests/test.rem(177): Trig = Monday, 4 March, 1991
|
||||
|
||||
# Test shorthand reminders
|
||||
REM 1991-02-28 MSG Feb 28
|
||||
../tests/test.rem(180): Trig = Thursday, 28 February, 1991
|
||||
REM 1991/02/28@14:45 MSG Feb 28
|
||||
../tests/test.rem(181): Trig = Thursday, 28 February, 1991
|
||||
REM Wed UNTIL 1991-01-01 MSG Expired
|
||||
../tests/test.rem(182): Expired
|
||||
REM Wed SCANFROM 1991-02-26 MSG SCANFROM
|
||||
../tests/test.rem(183): Trig = Wednesday, 27 February, 1991
|
||||
|
||||
set a000 abs(1)
|
||||
abs(1) => 1
|
||||
set a001 abs(-1)
|
||||
@@ -510,7 +704,7 @@ set a008 coerce("string", 11:44)
|
||||
coerce("string", 11:44) => "11:44"
|
||||
set a009 coerce("int", "badnews")
|
||||
coerce("int", "badnews") => Can't coerce
|
||||
../tests/test.rem(175): Can't coerce
|
||||
../tests/test.rem(194): Can't coerce
|
||||
set a010 coerce("int", "12")
|
||||
coerce("int", "12") => 12
|
||||
set a011 coerce("int", 11:44)
|
||||
@@ -522,7 +716,7 @@ set a013 date(1992, 2, 2)
|
||||
date(1992, 2, 2) => 1992-02-02
|
||||
set a014 date(1993, 2, 29)
|
||||
date(1993, 2, 29) => Bad date specification
|
||||
../tests/test.rem(180): Bad date specification
|
||||
../tests/test.rem(199): Bad date specification
|
||||
set a015 day(today())
|
||||
today() => 1991-02-16
|
||||
day(1991-02-16) => 16
|
||||
@@ -617,15 +811,15 @@ strlen("sadjflkhsldkfhsdlfjhk") => 21
|
||||
set a050 substr(a049, 2)
|
||||
a049 => 21
|
||||
substr(21, 2) => Type mismatch
|
||||
../tests/test.rem(218): Type mismatch
|
||||
../tests/test.rem(237): Type mismatch
|
||||
set a051 substr(a050, 2, 6)
|
||||
a050 => ../tests/test.rem(219): Undefined variable: a050
|
||||
a050 => ../tests/test.rem(238): Undefined variable: a050
|
||||
set a052 time(1+2, 3+4)
|
||||
1 + 2 => 3
|
||||
3 + 4 => 7
|
||||
time(3, 7) => 03:07
|
||||
rem 10 jan 1992 AT 11:22 CAL
|
||||
../tests/test.rem(221): Trig = Friday, 10 January, 1992
|
||||
../tests/test.rem(240): Trig = Friday, 10 January, 1992
|
||||
set a053 trigdate()
|
||||
trigdate() => 1992-01-10
|
||||
set a054 trigtime()
|
||||
@@ -638,7 +832,7 @@ set a057 value("a05"+"6")
|
||||
"a05" + "6" => "a056"
|
||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
set a058 version()
|
||||
version() => "03.01.05"
|
||||
version() => "03.01.07"
|
||||
set a059 wkday(today())
|
||||
today() => 1991-02-16
|
||||
wkday(1991-02-16) => "Saturday"
|
||||
@@ -717,31 +911,31 @@ y => 11:33
|
||||
x => "foo"
|
||||
y => 11:33
|
||||
"foo" * 11:33 => Type mismatch
|
||||
../tests/test.rem(244): `*': Type mismatch
|
||||
../tests/test.rem(263): `*': Type mismatch
|
||||
Leaving UserFN h() => Type mismatch
|
||||
set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
|
||||
dosubst("%a %b %c %d %e %f %g %h", 1992-05-05) => "on Tuesday, 5 May, 1992 in 444 days' tim"...
|
||||
msg [a074]%
|
||||
../tests/test.rem(246): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(265): Trig = Saturday, 16 February, 1991
|
||||
a074 => "on Tuesday, 5 May, 1992 in 444 days' tim"...
|
||||
on Tuesday, 5 May, 1992 in 444 days' time on Tuesday 5 on 05-05-1992 on 05-05-1992 on Tuesday, 5 May on 05-05
|
||||
set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
|
||||
dosubst("%i %j %k %l %m %n %o %p", 1992-05-05) => "on 05-05 on Tuesday, May 5th, 1992 on Tu"...
|
||||
msg [a075]%
|
||||
../tests/test.rem(248): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(267): Trig = Saturday, 16 February, 1991
|
||||
a075 => "on 05-05 on Tuesday, May 5th, 1992 on Tu"...
|
||||
on 05-05 on Tuesday, May 5th, 1992 on Tuesday, May 5th on 1992-05-05 May 5 s
|
||||
set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
|
||||
dosubst("%q %r %s %t %u %v %w %x", 1992-05-05) => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
|
||||
msg [a076]%
|
||||
../tests/test.rem(250): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(269): Trig = Saturday, 16 February, 1991
|
||||
a076 => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
|
||||
s' 05 th 05 on Tuesday, 5th May, 1992 on Tuesday, 5th May Tuesday 444
|
||||
set a077 dosubst("%y %z", '1992/5/5')
|
||||
dosubst("%y %z", 1992-05-05) => "1992 92
|
||||
"
|
||||
msg [a077]%
|
||||
../tests/test.rem(252): Trig = Saturday, 16 February, 1991
|
||||
../tests/test.rem(271): Trig = Saturday, 16 February, 1991
|
||||
a077 => "1992 92
|
||||
"
|
||||
1992 92
|
||||
@@ -753,6 +947,16 @@ easterdate(1992) => 1992-04-19
|
||||
set a080 easterdate(1995)
|
||||
easterdate(1995) => 1995-04-16
|
||||
set a081 ""
|
||||
OMIT 1991-03-11
|
||||
set a082 slide('1991-03-01', 7, "Sat", "Sun")
|
||||
slide(1991-03-01, 7, "Sat", "Sun") => 1991-03-13
|
||||
set a083 slide('1991-04-01', -7, "Sat")
|
||||
- 7 => -7
|
||||
slide(1991-04-01, -7, "Sat") => 1991-03-24
|
||||
set a084 nonomitted('1991-03-01', '1991-03-13', "Sat", "Sun")
|
||||
nonomitted(1991-03-01, 1991-03-13, "Sat", "Sun") => 7
|
||||
set a085 nonomitted('1991-03-24', '1991-04-01', "Sat")
|
||||
nonomitted(1991-03-24, 1991-04-01, "Sat") => 7
|
||||
dump
|
||||
Variable Value
|
||||
|
||||
@@ -764,6 +968,7 @@ dump
|
||||
a027 0
|
||||
a046 "ies"
|
||||
a065 1
|
||||
a084 7
|
||||
a018 1
|
||||
a037 1991-02-15
|
||||
a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
@@ -771,6 +976,7 @@ dump
|
||||
a028 1
|
||||
a047 -1
|
||||
a066 0
|
||||
a085 7
|
||||
a019 0
|
||||
a038 33
|
||||
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
@@ -779,7 +985,7 @@ dump
|
||||
a048 "foo"
|
||||
a067 "INT"
|
||||
a039 "February"
|
||||
a058 "03.01.05"
|
||||
a058 "03.01.07"
|
||||
a077 "1992 92
|
||||
"
|
||||
a049 21
|
||||
@@ -827,6 +1033,7 @@ dump
|
||||
a025 4
|
||||
a044 "s"
|
||||
a063 0
|
||||
a082 1991-03-13
|
||||
a016 28
|
||||
a035 1
|
||||
a054 11:22
|
||||
@@ -834,6 +1041,7 @@ dump
|
||||
a026 7
|
||||
a045 "iess"
|
||||
a064 1
|
||||
a083 1991-03-24
|
||||
|
||||
|
||||
Test 2
|
||||
@@ -1922,4 +2130,23 @@ Color Test
|
||||
(0x(B (0x(B (0x(B[37;1mBright[0m (0x(B (0x(B (0x(B (0x(B (0x(B
|
||||
(0x(B (0x(B (0x(B[37;1mWhite[0m (0x(B (0x(B (0x(B (0x(B (0x(B
|
||||
(0mqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqvqqqqqqqqqqj(B
|
||||
|
||||
MON WKDAY DAY across year test
|
||||
-(1): Trig = Monday, 3 January, 2000
|
||||
No reminders.
|
||||
Sort Test
|
||||
Reminders for Saturday, 1st January, 2000:
|
||||
|
||||
Untimed
|
||||
|
||||
Timed
|
||||
|
||||
Reminders for Saturday, 1st January, 2000:
|
||||
|
||||
Timed
|
||||
|
||||
Untimed
|
||||
|
||||
../tests/runtest.rem(2): shell(): RUN disabled
|
||||
../tests/runinc.rem(1): shell(): RUN disabled
|
||||
../tests/runinc.rem(3): shell(): RUN disabled
|
||||
No reminders.
|
||||
|
||||
@@ -132,7 +132,7 @@ CLEAR-OMIT-CONTEXT
|
||||
REM 1 Mar -1 MSG 1 mar -1
|
||||
REM 1 Mar --1 MSG 1 mar --1
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER
|
||||
|
||||
POP-OMIT-CONTEXT
|
||||
@@ -144,7 +144,7 @@ REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
|
||||
|
||||
|
||||
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
|
||||
|
||||
|
||||
# Test BACK
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
|
||||
@@ -163,6 +163,25 @@ REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
|
||||
OMIT [trigger(trigdate())]
|
||||
REM Fri after MSG 16 Feb 1991
|
||||
CLEAR-OMIT-CONTEXT
|
||||
|
||||
# Test omitfunc
|
||||
fset _ofunc(x) (day(x) < 7 || day(x) % 2)
|
||||
REM 1 March OMITFUNC _ofunc AFTER MSG OmitFunc Test
|
||||
REM 8 March OMITFUNC _ofunc -1 MSG OmitFunc Test 2
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
REM 1 March OMIT Sun AFTER MSG Should trigger 4 March
|
||||
|
||||
# Test shorthand reminders
|
||||
REM 1991-02-28 MSG Feb 28
|
||||
REM 1991/02/28@14:45 MSG Feb 28
|
||||
REM Wed UNTIL 1991-01-01 MSG Expired
|
||||
REM Wed SCANFROM 1991-02-26 MSG SCANFROM
|
||||
|
||||
set a000 abs(1)
|
||||
set a001 abs(-1)
|
||||
set a002 asc("foo")
|
||||
@@ -254,4 +273,9 @@ set a078 easterdate(today())
|
||||
set a079 easterdate(1992)
|
||||
set a080 easterdate(1995)
|
||||
set a081 ""
|
||||
OMIT 1991-03-11
|
||||
set a082 slide('1991-03-01', 7, "Sat", "Sun")
|
||||
set a083 slide('1991-04-01', -7, "Sat")
|
||||
set a084 nonomitted('1991-03-01', '1991-03-13', "Sat", "Sun")
|
||||
set a085 nonomitted('1991-03-24', '1991-04-01', "Sat")
|
||||
dump
|
||||
|
||||
18
www/rem2html
18
www/rem2html
@@ -9,7 +9,7 @@ my %Options;
|
||||
|
||||
my $rem2html_version = '2.0';
|
||||
|
||||
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst,
|
||||
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
|
||||
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
|
||||
|
||||
my $TIDY_PROGNAME = $0;
|
||||
@@ -186,6 +186,7 @@ sub parse_input
|
||||
undef $shades;
|
||||
undef $moons;
|
||||
undef $classes;
|
||||
undef $weeks;
|
||||
|
||||
my $found_data = 0;
|
||||
while(<STDIN>) {
|
||||
@@ -232,10 +233,16 @@ sub parse_input
|
||||
next unless m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/;
|
||||
my ($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
||||
($1, $2, $3, $4, $5, $6, $7, $8);
|
||||
my $d1 = $d;
|
||||
$d1 =~ s/^0+//;
|
||||
if ($special eq 'HTML') {
|
||||
push(@{$days->[$d]}, $body);
|
||||
} elsif ($special eq 'HTMLCLASS') {
|
||||
$classes->[$d] = $body;
|
||||
} elsif ($special eq 'WEEK') {
|
||||
$body =~ s/^\s+//;
|
||||
$body =~ s/\s+$//;
|
||||
$weeks->{$d1} = $body;
|
||||
} elsif ($special eq 'MOON') {
|
||||
if ($body =~ /(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
|
||||
my ($phase, $moonsize, $fontsize, $msg) = ($1, $2, $3, $4);
|
||||
@@ -362,7 +369,6 @@ sub output_calendar
|
||||
# Last column
|
||||
my $last_col = ($first_col + $Numdays - 1) % 7;
|
||||
|
||||
|
||||
# Start the table
|
||||
my $class;
|
||||
if ($Options{'nostyle'}) {
|
||||
@@ -475,6 +481,10 @@ sub draw_day_cell
|
||||
{
|
||||
my($day) = @_;
|
||||
my $shade = $shades->[$day];
|
||||
my $week = '';
|
||||
if (exists($weeks->{$day})) {
|
||||
$week = ' ' . $weeks->{$day};
|
||||
}
|
||||
my $class;
|
||||
if ($Options{'nostyle'}) {
|
||||
$class = $classes->[$day] || '';
|
||||
@@ -529,10 +539,10 @@ sub draw_day_cell
|
||||
}
|
||||
|
||||
if ($Options{'nostyle'}) {
|
||||
print "<div style=\"float: right\">$day</div>\n";
|
||||
print "<div style=\"float: right\">$day$week</div>\n";
|
||||
print "<p> </p>\n";
|
||||
} else {
|
||||
print "<div class=\"rem-daynumber\">$day</div>\n";
|
||||
print "<div class=\"rem-daynumber\">$day$week</div>\n";
|
||||
}
|
||||
if ($days->[$day]) {
|
||||
print(join("\n", @{$days->[$day]}));
|
||||
|
||||
Reference in New Issue
Block a user