Compare commits

..

181 Commits

Author SHA1 Message Date
Dianne Skoll
504bc6a875 Update docs 2020-11-09 08:25:28 -05:00
Dianne Skoll
9cfdd0b53f Bump version to 3.3.3. 2020-11-09 07:26:14 -05:00
Dianne Skoll
d59024f399 Fix startup crash if ShowTodaysReminders option is set. 2020-11-09 07:23:19 -05:00
Dianne Skoll
24e0178d1a Fix tests for 3.3.2 release. 2020-11-08 16:01:57 -05:00
Dianne Skoll
1ede5775f2 Prep for 3.3.2 release. 2020-11-08 16:01:39 -05:00
Dianne Skoll
a5c9b07052 Fix for calendar alignment for reminders with embedded tabs.
Convert all whitespace chars to space in calendar mode.
2020-11-03 08:41:24 -05:00
Dianne Skoll
22353d4833 Fix typo (patch from Yigit Sever) 2020-11-02 08:31:28 -05:00
Dianne Skoll
7499ada891 Properly fix combining-char-word-wrapping. 2020-11-01 12:05:21 -05:00
Dianne Skoll
3f0a4e5c39 Fix another instance of mis-counting display width. 2020-11-01 10:13:51 -05:00
Dianne Skoll
b8d6472974 Add UTF-8 test. 2020-11-01 10:06:48 -05:00
Dianne Skoll
6358297724 Fix column misalignment with UTF-8 text. 2020-11-01 10:03:32 -05:00
Dianne Skoll
4f6dcde980 Upper-case section references.
Prevent potential null pointer dereference.
2020-10-31 16:57:13 -04:00
Dianne Skoll
8a7985c48e Highlight that longitude sign is opposite from the usual convention. 2020-10-12 18:54:26 -04:00
Dianne Skoll
4ddbe54e55 Fix typo 2020-09-25 22:27:48 -04:00
Dianne Skoll
ef0bf73a29 Document MAYBE-UNCOMPUTABLE. 2020-09-25 22:20:16 -04:00
Dianne Skoll
beda9014d8 Add test for MAYBE-UNCOMPUTABLE 2020-09-25 22:11:56 -04:00
Dianne Skoll
498a429b2c Add MAYBE-UNCOMPUTABLE modifier to trigger. 2020-09-25 22:08:49 -04:00
Dianne Skoll
6aa2aa0fb3 Align system vars in output. 2020-09-20 17:43:51 -04:00
Dianne Skoll
1bef88fccd Update released notes. 2020-09-20 17:40:58 -04:00
Dianne Skoll
8308068067 Don't bother aligning "DUMP" output.
It looks ridiculous with 64-char long variable names.
2020-09-20 17:39:33 -04:00
Dianne Skoll
8385c7f1b0 Update custom.h 2020-09-20 17:35:24 -04:00
Dianne Skoll
0537d02fef Increase max variable length from 16 to 64 characters.
Modern computers have plenty of memory, so meh.
2020-09-20 17:32:22 -04:00
Dianne Skoll
c33a1a3b0b Mention that variables are global. 2020-09-20 12:45:29 -04:00
Dianne Skoll
fd39999128 Fix bugs where month numbers with leading zeros are misinterpreted as octal instead of decimal.
Reported by Peter Geddes.
2020-09-13 12:34:27 -04:00
Dianne Skoll
0aa40094fa Make TwentyFourHourMode global. 2020-08-18 15:24:19 -04:00
Dianne Skoll
e3bbbe07be Respect 24-hour mode option. 2020-08-18 15:24:13 -04:00
Dianne Skoll
5633798d33 Document that time is fed to reminder command. 2020-08-18 15:24:09 -04:00
Dianne Skoll
0e7e1b1b75 When feeding reminder on stdin, prefix with "$time: " 2020-08-18 15:24:04 -04:00
Dianne Skoll
4d3790bc1a More tweaking of defs.rem to remove cruft and modernize usage. 2020-08-18 15:24:00 -04:00
Dianne Skoll
2002c7f1f8 Fix up defs.rem. 2020-08-18 15:23:51 -04:00
Dianne Skoll
1be14e99a2 Update docs for -itkremind=1 and -itkprint=1 options in TkRemind. 2020-06-11 15:06:09 -04:00
Dianne Skoll
78efdaf85f Fix bug that broke printing by putting cmdline options in wrong spot. 2020-06-10 10:26:06 -04:00
Dianne Skoll
0e98a1c656 Always set tkremind=1; set tkprint=1 if we're printing. 2020-06-10 10:22:46 -04:00
Dianne Skoll
7aa483e201 Fix bug reported by Jurgen Bollerhey
I have a
"REM Mon SPECIAL WEEK (W[weekno()])"
in my reminders file.
With tkremind -m the week number is displayed on the 2nd column which is
Tuesday and the date of this Tuesday is taken from the monday of the
next week, sometimes of Monday the same week.
2020-03-30 11:29:19 -04:00
Dianne Skoll
a6dbf05af4 Update WHATSNEW. 2020-03-20 09:18:48 -04:00
Dianne Skoll
8ab78fd8be Suppress compile warnings on Ubuntu 18.04 2020-03-19 20:27:45 -04:00
Dianne Skoll
4f119031a4 One more warning to suppress. 2020-03-19 20:24:53 -04:00
Dianne Skoll
19bdd6c2db Avoid warning about ignoring return value of fgets. 2020-03-19 20:24:01 -04:00
Dianne Skoll
f1557b8243 Try to suppress fallthrough warning. 2020-03-19 20:21:29 -04:00
Dianne Skoll
85f96e2e01 Update man page. 2020-03-14 11:37:11 -04:00
Dianne Skoll
47331cd919 Make ampm() function accept a DATETIME and obey $TimeSep, $DateSep and $DateTimeSep 2020-03-14 11:32:35 -04:00
Dianne Skoll
d9f18ed6a7 Don't use many-json2dict 2020-03-03 11:43:54 -05:00
Dianne Skoll
efa4816371 Properly-form JSON output. 2020-03-03 10:36:01 -05:00
Dianne Skoll
2dc8c63adb Proper prefix for beta versions. 2020-02-29 09:38:51 -05:00
Dianne Skoll
c3c1781021 Update COPYRIGHT date. 2020-02-28 08:56:49 -05:00
Dianne Skoll
cd39480a98 Remove extraneous spaces. 2020-02-27 16:50:44 -05:00
Dianne Skoll
281a1a206e Implement JSONQUEUE daemon command. 2020-02-27 15:18:23 -05:00
Dianne Skoll
cbff2a7bf2 Document ampm() 2020-02-27 08:39:21 -05:00
Dianne Skoll
2a08be8fd0 Fix up unit tests. 2020-02-26 17:43:47 -05:00
Dianne Skoll
0826678209 Make coerce from string to time and datetime accept ampm 2020-02-26 17:41:51 -05:00
Dianne Skoll
f2e421bfa5 Add acceptance tests for ampm() function. 2020-02-26 17:25:09 -05:00
Dianne Skoll
ce53a9b91a Add "ampm" built-in function. 2020-02-26 17:21:34 -05:00
Dianne Skoll
b166b1cf82 Fix up test file. 2020-02-24 15:17:07 -05:00
Dianne Skoll
d09fbb03b2 Bump version to 3.3.1. 2020-02-24 15:16:20 -05:00
Dianne Skoll
7a835f3b10 Update docs. 2020-02-23 16:02:59 -05:00
Dianne Skoll
6b991cdf9c Refactor saving of trigger info. 2020-02-23 11:38:17 -05:00
Dianne Skoll
018e9d0323 JSON can handle newlines (the literal newlines will be escaped to "\n" by the JSON writer.) 2020-02-23 11:17:59 -05:00
Dianne Skoll
f499ae096f Don't include filename or line number in synthesized tag. 2020-02-23 11:15:38 -05:00
Dianne Skoll
725e046a15 Fix bug in recording trigdate() for SATISFY-type reminders. :( 2020-02-22 19:15:24 -05:00
Dianne Skoll
275b1f62b6 For overlapping reminders, prefer the *later* version. 2020-02-22 16:50:42 -05:00
Dianne Skoll
6e58dea198 Handle overlapping events better. 2020-02-22 16:30:08 -05:00
Dianne Skoll
ad4e62c8c3 Test specifying DURATION as an integer. 2020-02-22 12:48:07 -05:00
Dianne Skoll
a5768d55d8 Update man page to document integer form of DURATION. 2020-02-22 12:46:57 -05:00
Dianne Skoll
7db49971c8 Update man page. 2020-02-22 12:40:32 -05:00
Dianne Skoll
45ca6631ac Make sure AM/PM is case-insensitive. 2020-02-22 12:32:52 -05:00
Dianne Skoll
d51944f36c Allow duration to be specified as a single number, meaning minutes.
Don't convert 90-99 to 1990-1999 when parsing numbers.
2020-02-22 12:31:17 -05:00
Dianne Skoll
037c79fb0f Allow times to have am/pm specifications. 2020-02-22 12:24:37 -05:00
Dianne Skoll
993373414f Parse times and datetimes with trailing am/pm 2020-02-22 12:14:18 -05:00
Dianne Skoll
38a0a9992a Leave a space after the asterisk row. 2020-02-12 11:19:30 -05:00
Dianne Skoll
a82bbe3776 Highlight today in month mode also. 2020-02-12 11:17:21 -05:00
Dianne Skoll
a32ba217ba Update man page. 2020-02-08 15:11:15 -05:00
Dianne Skoll
d322cf54ac Allow $FormWidth to be as large as 500. 2020-02-08 15:10:48 -05:00
Dianne Skoll
b1d07a231d Document $FormWidth. 2020-02-08 15:06:09 -05:00
Dianne Skoll
97851a08e6 Clamp min cal width at 72 2020-02-08 15:04:59 -05:00
Dianne Skoll
8547b30a8f Set $FormWidth to terminal width - 8 on startup. 2020-02-08 15:04:48 -05:00
Dianne Skoll
405c7d9ed0 Set release date. 2020-01-31 11:17:55 -05:00
Dianne Skoll
ac5b641d93 Note that back-ends MUST ignore unknown SPECIALs. 2020-01-30 16:07:57 -05:00
Dianne Skoll
06a79989c0 Minor tweaks. 2020-01-28 15:16:41 -05:00
Dianne Skoll
671db64436 Fix various typos. 2020-01-28 09:51:12 -05:00
Dianne Skoll
33344cefe6 Fix typo 2020-01-28 09:47:06 -05:00
Dianne Skoll
5ef0341537 Avoid memory leak. 2020-01-28 09:43:42 -05:00
Dianne Skoll
6abca08189 Add test to ensure rem2ps ignores unknown SPECIALs. 2020-01-28 09:42:13 -05:00
Dianne Skoll
35670ce651 Update docs 2020-01-28 09:38:06 -05:00
Dianne Skoll
e230d53d84 Ignore unknown SPECIALs in rem2ps. 2020-01-28 09:37:35 -05:00
Dianne Skoll
88537a3471 Remove ancient pointer to doe.carleton.ca 2020-01-28 09:29:42 -05:00
Dianne Skoll
7c9d74da73 Fix typo 2020-01-27 16:46:57 -05:00
Dianne Skoll
3b582935ee Sign beta tarballs too. 2020-01-27 16:46:07 -05:00
Dianne Skoll
508fafb875 Update WHATSNEW. 2020-01-27 16:28:57 -05:00
Dianne Skoll
6f718f0fe5 Update rem2ps man page. 2020-01-27 13:29:33 -05:00
Dianne Skoll
53acbf2052 Don't swallow %" %" markers in -ppp mode. 2020-01-27 13:21:48 -05:00
Dianne Skoll
1606dbbe77 Rework -@ option and tests. 2020-01-27 11:49:41 -05:00
Dianne Skoll
adced3ac6c Rework -@ option to be n,m 2020-01-27 11:44:16 -05:00
Dianne Skoll
14f207140a Better clamping algorithm for true colors 2020-01-27 11:31:57 -05:00
Dianne Skoll
d2da32de6c Don't hard-code number. 2020-01-26 18:26:03 -05:00
Dianne Skoll
e5d6a36f05 Update WHATSNEW 2020-01-26 18:10:11 -05:00
Dianne Skoll
68ecfcf876 Update test for change to rem2ps 2020-01-26 18:09:27 -05:00
Dianne Skoll
fcb14b9dfe Add PageBoundingBox comment. 2020-01-26 18:09:06 -05:00
Dianne Skoll
6a4b4257a6 Fix compilation failure on pre-C99 compilers. 2020-01-26 17:47:00 -05:00
Dianne Skoll
385b57e269 Update whatsnew 2020-01-25 17:43:10 -05:00
Dianne Skoll
a8e81e3984 Update WHATSNEW. 2020-01-25 17:41:47 -05:00
Dianne Skoll
46c5f0e752 Update man page for exact color setting. 2020-01-25 16:18:09 -05:00
Dianne Skoll
454d859fdd Support true RGB coloring. 2020-01-25 16:16:51 -05:00
Dianne Skoll
57134a182c Make SPECIALs case-insensitive. 2020-01-25 16:07:18 -05:00
Dianne Skoll
5801e143ea Make specials case-insensitive. 2020-01-25 16:04:53 -05:00
Dianne Skoll
4e0d0ff98b Test Xterm 256-color mode. 2020-01-25 15:16:30 -05:00
Dianne Skoll
d4ac1849ae Add comment for Xterm 256 colors. 2020-01-25 15:12:13 -05:00
Dianne Skoll
c16ac1bd8c Support 256-color mode on XTerm and other terminals. 2020-01-25 15:06:43 -05:00
Dianne Skoll
16222ac3bc Fix to man page. 2020-01-25 14:35:20 -05:00
Dianne Skoll
8d88931fb1 Fix indentation. 2020-01-25 14:27:25 -05:00
Dianne Skoll
63f0356e70 Fix man page wording. 2020-01-25 14:26:32 -05:00
Dianne Skoll
786b0dee6f Add test for =@ 2020-01-25 14:23:52 -05:00
Dianne Skoll
e7ef9dc295 Document -@ 2020-01-25 14:12:56 -05:00
Dianne Skoll
f59461b95d Convert black-on-black or white-on-white to grey. 2020-01-25 14:00:28 -05:00
Dianne Skoll
566a86b9fd Obey default color settings. 2020-01-25 11:29:06 -05:00
Dianne Skoll
8589a3730d Put -@[n] in help. 2020-01-25 11:13:50 -05:00
Dianne Skoll
c05fd366df Implement -@, -@0 and -@1 options to colorize reminders. 2020-01-25 11:12:10 -05:00
Dianne Skoll
fc9fd1e53c Start adding support for colored reminders in Agenda Mode. 2020-01-24 16:31:01 -05:00
Dianne Skoll
a5e6eb9f7c Add -@ commandline option. Yuck. 2020-01-24 16:26:55 -05:00
Dianne Skoll
a9430fea5f Make Remind adjust calendar to fit terminal. 2020-01-18 15:11:28 -05:00
Dianne Skoll
828a0d6589 Emit prevmonthyear and nextmonthyear items in -ppp format. 2020-01-18 14:52:17 -05:00
Dianne Skoll
32601da748 Update tests. 2020-01-18 14:48:27 -05:00
Dianne Skoll
ac50f119cf Document that -pp and -ppp enable -l 2020-01-18 14:45:23 -05:00
Dianne Skoll
7622ebaa0a Document remind -ppp format. 2020-01-18 14:43:21 -05:00
Dianne Skoll
a586d5cd37 Fix bug that incorrectly printed # fileinfo lines for -ppp format. 2020-01-18 14:43:04 -05:00
Dianne Skoll
edbc88bd19 Reformat error message. 2020-01-16 20:00:38 -05:00
Dianne Skoll
94f99f3414 Make rem2ps bail out if fed "-ppp"-format. 2020-01-16 19:59:30 -05:00
Dianne Skoll
fd4f84349e Include filename and lineno in tag synthesis. 2020-01-16 19:19:13 -05:00
Dianne Skoll
f86350b2ff More man page tweakage. 2020-01-16 18:56:28 -05:00
Dianne Skoll
564b72066a Document $DefaultColor 2020-01-16 18:53:30 -05:00
Dianne Skoll
2890c52090 Fix typo in man page 2020-01-15 11:27:43 -05:00
Dianne Skoll
c1d45485c1 Update test suite. 2020-01-15 09:20:31 -05:00
Dianne Skoll
8b2a69cf8d Do a small bit of refactoring to get rid of some copy/paste code. 2020-01-15 09:18:32 -05:00
Dianne Skoll
034c1341b3 Fix typos. 2020-01-14 21:47:26 -05:00
Dianne Skoll
29bbf1a030 Be strict in what we accept for SET $DefaultColor "r g b" 2020-01-14 21:44:08 -05:00
Dianne Skoll
be6661d6be Don't assume a potentially-colored reminder unless it's MSG/MSF/CAL type. 2020-01-14 21:43:46 -05:00
Dianne Skoll
3f876e792c Reset $DefaultColor each time we iterate. 2020-01-14 21:15:27 -05:00
Dianne Skoll
f2457b90ff Add patch for $DefaultColor, courtesy of Tim Chase. 2020-01-14 21:07:20 -05:00
Dianne Skoll
e999e9009b Minor formatting tweak. 2020-01-14 20:17:38 -05:00
Dianne Skoll
46326c001b Output true JSON if you invoke as "remind -ppp" 2020-01-14 20:09:24 -05:00
Dianne Skoll
b84c2c403c Add more balloon help. 2020-01-13 21:19:45 -05:00
Dianne Skoll
861ad72187 Add popup help. 2020-01-13 18:26:40 -05:00
Dianne Skoll
7dbbc34ccc Make Remind compile on older gcc that doesn't allow declarations in for(...) 2020-01-13 10:00:25 -05:00
Dianne Skoll
4ea45d1d14 Update rem2ps man page. 2020-01-12 20:03:43 -05:00
Dianne Skoll
c1b9243e2f Document new REM2PS format. 2020-01-12 19:56:45 -05:00
Dianne Skoll
a41c40c7a4 Document -pp option. 2020-01-12 19:24:21 -05:00
Dianne Skoll
318d4547ef Use r, g, b settings from SHADE special. 2020-01-12 18:11:35 -05:00
Dianne Skoll
6f98b60a6a Output "r", "g", "b" for shade-style reminders. 2020-01-12 18:09:41 -05:00
Dianne Skoll
baa8f7f3c4 Add test that OMITFUNC raises nonconst_expr indicator. 2020-01-12 17:51:06 -05:00
Dianne Skoll
6297622072 Write JSON using English day names. 2020-01-12 17:47:41 -05:00
Dianne Skoll
9f3ba0bf2b More intelligent filling out of GUI. 2020-01-12 17:27:50 -05:00
Dianne Skoll
9591dec708 Write out fully-specified dates in Reminders more compactly. 2020-01-12 17:15:38 -05:00
Dianne Skoll
ee2d0b7518 Production file location! 2020-01-12 14:05:55 -05:00
Dianne Skoll
2d46749c58 Add blank line when *first* creating AppendFile. 2020-01-12 14:01:20 -05:00
Dianne Skoll
494664d1b6 Take out blank line from warning header lines. 2020-01-12 14:00:04 -05:00
Dianne Skoll
49686210ae Better reverse-engineering of ordinal. 2020-01-12 13:57:25 -05:00
Dianne Skoll
ddfa44188b Reset HighestTagSoFar when we rewrite the appendfile after deletion. 2020-01-12 13:52:17 -05:00
Dianne Skoll
73cf93d27b Renumber tags when we delete a tagged reminder. 2020-01-12 13:34:22 -05:00
Dianne Skoll
60d1a34bf0 Fix up AM/PM handling; delete old comment lines. 2020-01-12 13:28:45 -05:00
Dianne Skoll
6f80986801 New version of tkremind seems to be decent... 2020-01-12 13:14:32 -05:00
Dianne Skoll
2078f087b2 An OMITFUNC should set the nonconst_expr flag. 2020-01-12 13:06:55 -05:00
Dianne Skoll
68d110826e First version of TkRemind that can reverse-engineer reminder without needing comments to set up GUI. 2020-01-12 12:45:34 -05:00
Dianne Skoll
9fb04c54ae Start work on reverse-engineering reminder dialog from JSON instead of relying on comments. 2020-01-11 19:08:35 -05:00
Dianne Skoll
d82314594b Make rem2html understand JSON interchange format. 2020-01-10 15:06:59 -05:00
Dianne Skoll
ad169a5248 Eliminate compiler warnings. 2020-01-10 13:57:13 -05:00
Dianne Skoll
a9bab81226 Test that rem2ps can parse "remind -pp" output. 2020-01-10 13:48:58 -05:00
Dianne Skoll
fa63a9ba51 Add comments. 2020-01-10 13:46:20 -05:00
Dianne Skoll
1e7a630737 rem2ps can read the new-style JSON output of "remind -pp" 2020-01-10 13:41:27 -05:00
Dianne Skoll
de1afce8da Suppress unused param warnings. 2020-01-09 18:53:00 -05:00
Dianne Skoll
ac3cb19c26 Simplify code. 2020-01-09 18:42:14 -05:00
Dianne Skoll
af0479d11d Start preparing rem2ps for parsing JSON input. 2020-01-09 18:38:08 -05:00
Dianne Skoll
0d9c04707f Output nonconst_expr and if_depth indicators in JSON mode. 2020-01-08 08:42:23 -05:00
Dianne Skoll
c2218f133b Preserve RGB info for a COLOR reminder. 2020-01-07 13:27:22 -05:00
Dianne Skoll
1ad0645fab Only print rawbody if it differs from body. 2020-01-06 22:25:49 -05:00
Dianne Skoll
3c16f6839a Pass raw body through to back-end in JSON mode. 2020-01-06 22:19:22 -05:00
Dianne Skoll
e8bac1e469 More info over JSON via -pp commandline switch. 2020-01-05 17:15:37 -05:00
Dianne Skoll
b3b69596f4 Output SKIP value in JSON. 2020-01-05 12:18:10 -05:00
Dianne Skoll
6a7bcb0956 Print the "wd" entry as array of weekday names. 2020-01-05 12:15:20 -05:00
Dianne Skoll
f18a0704c1 More work on emitting JSON. 2020-01-05 12:10:05 -05:00
Dianne Skoll
d6f24b7c1e rem2ps will only support "remind -p" protocol and not "remind -pp" 2020-01-03 18:00:21 -05:00
Dianne Skoll
e2c9bbf94c Start working on JSON-based alternate "remind -p" protocol. 2020-01-03 17:24:01 -05:00
Dianne Skoll
f53aa4f656 Start working on Version 2 of Rem2PS protocol. 2020-01-03 16:51:47 -05:00
43 changed files with 7688 additions and 766 deletions

View File

@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
1. REMIND refers to the entire set of files and documentation in the 1. REMIND refers to the entire set of files and documentation in the
REMIND package. REMIND package.
2. REMIND is Copyright 1992-2018 Dianne Skoll, except where noted in 2. REMIND is Copyright 1992-2020 Dianne Skoll, except where noted in
individual files. individual files.
3. DISTRIBUTION AND USE 3. DISTRIBUTION AND USE

2
configure vendored
View File

@@ -3991,7 +3991,7 @@ _ACEOF
fi fi
done done
VERSION=03.02.00 VERSION=03.03.03
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h" ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"

View File

@@ -75,6 +75,6 @@ if test "$GCC" = yes; then
fi fi
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale) AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
VERSION=03.02.00 VERSION=03.03.03
AC_SUBST(VERSION) AC_SUBST(VERSION)
AC_OUTPUT(src/Makefile www/Makefile src/version.h) AC_OUTPUT(src/Makefile www/Makefile src/version.h)

View File

@@ -1,5 +1,103 @@
CHANGES TO REMIND CHANGES TO REMIND
* VERSION 3.3 Patch 3 - 2020-11-09
- BUG FIX: Fix startup crash in TkRemind if "Show Today's Reminders on
Startup" is enabled (which, unfortunately, is the default.) Bug reported
by Martin Ziemer.
* VERSION 3.3 Patch 2 - 2020-11-08
- MINOR NEW FEATURE: Add MAYBE-UNCOMPUTABLE keyword; see the man page
and discussion at
https://dianne.skoll.ca/pipermail/remind-fans/2020/003745.html
- CHANGE: TkRemind always invokes Remind with the "-itkremind=1" option,
even when printing. NOTE INCOMPATIBILITY: This is a behavior change!
When you print from TkRemind, we also invoke Remind with "-itkprint=1"
so you can detect that PostScript is being generated.
- CHANGE: The maxmimum length of a variable name has been increased from
16 characters to 64 characters. Modern computers have plenty of memory.
- BUG FIXES: Minor documentation updates, typo fixes, clarifications, etc.
- BUG FIX: Fix calendar-drawing alignment errors when displaying UTF-8
strings with zero-width combining characters and strings with tabs.
- BUG FIX: TkRemind would mess up placement of the WEEK special if invoked
with the "-m" option. This has been fixed.
- BUG FIX: TkRemind would sometimes fail with an error message when editing
a reminder; this is because it was interpreting months 08 and 09 as
illegal octal numbers. This has been fixed.
* VERSION 3.3 Patch 1 - 2020-03-20
- CHANGE: For overlapping multi-day events, issue a reminder for the
most *recent* event rather than the earliest event. NOTE
INCOMPATIBILITY: This is a behavior change!
- CHANGE: Do not convert 90-99 to 1990-1999 when parsing numbers to
recognize years. NOTE INCOMPATIBILITY: This is a behavior change!
- CHANGE: Revert change to -y option that included filename and line
number in the hash.
- CHANGE: Retain newlines (produced by %_) in JSON output.
- FIX: Document $FormWidth system variable
- FIX: Highlight today's date in "remind -c" output
- FIX: Eliminate compiler warnings on Ubuntu 18.04.
- IMPROVEMENT: Allow times to be specified either in 24-hour mode
(HH:MM or HH.MM) or AM/PM mode (HH:MMam; HH:MMpm, etc.)
- IMPROVEMENT: Allow DURATION to be specified as a time (1:30) or a
number of minutes (90).
- IMPROVEMENT: If terminal size can be determined, set $FormWidth to
terminal width - 8; if not, set $FormWidth to 72.
- MINOR IMPROVEMENT: Add the "ampm()" built-in function.
* Version 3.3 Patch 0 - 2020-01-31
- FIX: rem2ps: Add a %%PageBoundingBox: document structuring convention
comment.
- FIX: rem2ps: Ignore unknown SPECIAL-type reminders.
- IMPROVEMENT: In calendar mode ("-c" option), Remind automatically adjusts
the width of the calendar to fit the terminal window if standard output
is a TTY.
- IMPROVEMENT: Add JSON-based output with "remind -pp" and "remind -ppp"
The JSON-based intermediate format preserves a lot more information
about the original reminder, allowing back-ends more insight into
the intent of the reminder, the recurrence used, etc. See the documentation
in "man rem2ps"
- IMPROVEMENT: TkRemind can "reverse-engineer" reminders that it creates
using the additional information in the "remind -pp" format, so it
doesn't create or use ugly comment blocks to delimit the reminders
it creates.
- IMPROVEMENT: TkRemind: Add popup help to most buttons and controls.
- NEW FEATURE: Add support for $DefaultColor system variable, suggested
by Tim Chase.
- NEW FEATURE: The "-@[n][,m]" command-line option allows colored reminders
in Agenda Mode as well as in Calendar Mode. It also adds support for
terminal emulators that can handle the xterm 256-color escape sequences
as well as the true 24-bit color escape sequences.
- CHANGE: SPECIALs are now case-insensitive. Before, only SPECIAL COLOR
would work. Now you can use Special Color, special color, etc.
* Version 3.2 Patch 0 - 2020-01-03 * Version 3.2 Patch 0 - 2020-01-03
- IMPROVEMENT: Add support for events spanning multiple days (with AT - IMPROVEMENT: Add support for events spanning multiple days (with AT

View File

@@ -26,8 +26,8 @@ RUN OFF
################################################ ################################################
# Ensure required version of remind is used... # # Ensure required version of remind is used... #
################################################ ################################################
IF version() < "03.01.08" IF version() < "03.01.09"
ERRMSG This file requires at least version 03.01.08 of Remind.% ERRMSG This file requires at least version 03.01.09 of Remind.%
ERRMSG This version is version [version()]. ERRMSG This version is version [version()].
EXIT EXIT
ENDIF ENDIF
@@ -84,7 +84,6 @@ SET December 12
########################################################### ###########################################################
# Other symbolic constants and functions for "pasting"... # # Other symbolic constants and functions for "pasting"... #
########################################################### ###########################################################
SET Quote CHAR(34) SET Quote CHAR(34)
# Handy constants/function for specifing week of month... # Handy constants/function for specifing week of month...
@@ -95,29 +94,17 @@ SET Week_4 22
FSET _last(mo) "1 " + MON((mo%12)+1) + " --7" FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
# Handy function to provide SCANFROM dates... # Handy function to provide SCANFROM dates...
FSET _back(days) TODAY()-days FSET _back(days) $U-days
###########################################################
# Function which returns a string in "am/pm" format based #
# on the time. For example, set a am_pm(NOW())... #
###########################################################
FSET _am_pm(tm) IIF(tm<01:00, tm+12*60+"am", \
tm<12:00, tm+"am", \
tm<13:00, tm+"pm", \
tm-12*60+"pm")
################################################################# #################################################################
# Function which removes a single leading zero from a string... # # Function that removes a single leading zero from a string... #
################################################################# #################################################################
FSET _no_lz(s) IIF(SUBSTR(s, 1, 1)=="0", SUBSTR(s, 2), s) FSET _no_lz(s) IIF(SUBSTR(s, 1, 1)=="0", SUBSTR(s, 2), s)
################################################################# #################################################################
# Return the length of the daylight/night portion of a date, # # Return the length of the daylight/night portion of a date, #
# in minutes. # # in minutes. #
################################################################# #################################################################
FSET _light_len(date) MAX(SUNSET(date)-SUNRISE(date), 0) FSET _light_len(date) MAX(SUNSET(date)-SUNRISE(date), 0)
FSET _dark_len(date) 1440-_light_len(date) FSET _dark_len(date) 1440-_light_len(date)
@@ -125,26 +112,12 @@ FSET _dark_len(date) 1440-_light_len(date)
# Function to calculate number of years since a given year # # Function to calculate number of years since a given year #
# or number of months since a given month and year... # # or number of months since a given month and year... #
############################################################ ############################################################
FSET _yr_num(yr) ORD($Ty - yr)
FSET _yr_num(yr) ORD(YEAR(TRIGDATE()) - yr) FSET _mo_num(mo, yr) ORD(12 * ($Ty - yr) + $Tm - mo)
FSET _mo_num(mo, yr) ORD(12 * (YEAR(TRIGDATE()) - yr) + \
MONNUM(TRIGDATE()) - mo)
# Here's an example of how to use them: # Here's an example of how to use them:
REM 1 Nov ++12 MSG %"Dean's [_yr_num(1984)] birthday%" is %b. REM 1 Nov ++12 MSG %"John's [_yr_num(1984)] birthday%" is %b.
REM 1 MSG Dean's [_mo_num(11, 1984)] 'monthly' anniversary REM 1 MSG John's [_mo_num(11, 1984)] 'monthly' anniversary
###########################################################
# Function to send mail via elm's "fastmail" (by GMS!)... #
###########################################################
#FSET _mail(from, subj) "mailx -s " + \
# Quote + from + " : " + subj + Quote \
# GETENV("LOGNAME") + " < /dev/null 1>&0"
FSET _mail(from, subj) "fastmail -f " + \
Quote + from + Quote + \
" -s " + Quote + subj + Quote + \
" /dev/null " + GETENV("LOGNAME")
############################################################################# #############################################################################
# Here's a tricky problem: The 4th of July is a holiday in the U.S. # Here's a tricky problem: The 4th of July is a holiday in the U.S.
@@ -158,29 +131,28 @@ FSET _mail(from, subj) "fastmail -f " + \
# dependent upon the current date, it's tricky and results may not be # dependent upon the current date, it's tricky and results may not be
# what you expect. You should try to make sure that the OMIT context # what you expect. You should try to make sure that the OMIT context
# "near" any current reminders will not change during a calendar run. # "near" any current reminders will not change during a calendar run.
# The SCANFROM clause should help make these OMITs very safe. # The SCANFROM clause will make these OMITs safe.
############################################################################ ############################################################################
# Calculate the weekday of the holiday. # Calculate the weekday of the holiday.
REM 4 July SCANFROM [_back(7)] SATISFY 1 REM 4 July SCANFROM [_back(7)] SATISFY 1
IF WKDAYNUM(TRIGDATE()) == Sat SET iday $T
REM [TRIGDATE()] MSG Independence day (actual) IF WKDAYNUM(iday) == Sat
OMIT [TRIGDATE()-1] MSG Independence day (observed) REM [iday] MSG Independence day (actual)
OMIT [iday-1] MSG Independence day (observed)
ELSE ELSE
IF WKDAYNUM(TRIGDATE()) == Sun IF WKDAYNUM(iday) == Sun
REM [TRIGDATE()] MSG Independence day (actual) REM [iday] MSG Independence day (actual)
OMIT [TRIGDATE()+1] MSG Independence day (observed) OMIT [iday+1] MSG Independence day (observed)
ELSE ELSE
OMIT [TRIGDATE()] MSG Independence day OMIT [iday] MSG Independence day
ENDIF ENDIF
ENDIF ENDIF
############################################################################ ############################################################################
# #
# A meeting on the first Monday of every month which is moved to the # # A meeting on the first Monday of every month which is moved to the #
# second Monday in the event of a holiday. # # second Monday in the event of a holiday. #
# #
############################################################################ ############################################################################
# First, the normal meeting. However, the SKIP keyword means this # First, the normal meeting. However, the SKIP keyword means this
@@ -192,68 +164,21 @@ REM Mon 8 SATISFY 1
# But only actually trigger the delayed meeting if the previous # But only actually trigger the delayed meeting if the previous
# Monday was a holiday # Monday was a holiday
IF ISOMITTED(TRIGDATE()-7) IF ISOMITTED($T-7)
REM [TRIGDATE()] MSG Delayed meeting REM [$T] MSG Delayed meeting
ENDIF ENDIF
############################################################################
# #
# A very complicated reminder sent in by a Remind user. #
# This person gets paid every two weeks, starting from 8 January 1993. #
# If a pay date occurs before the twelfth of a month, then that #
# he pays his mortgage on that pay date. Otherwise, he pays the mortgage #
# on the previous pay date. Furthermore, he has to schedule his #
# mortgage payment six days before it is due. He wants to be reminded #
# a further four days before the scheduling deadline. He also #
# wants to be mailed a notice two weeks before the scheduling deadline. #
# #
# Here's the solution - if you can follow this, consider yourself a #
# Remind programmer extraordinaire! #
# #
############################################################################
# A function to determine whether or not a pay-date is a mortgage-date.
FSET _IsMortDate(x) DAY(x) < 12 || (DAY(x+14) >= 12 && DAY(x+14) <= 14)
# Paydays - for reference
REM 8 Jan 1993 *14 MSG Payday
# Calculate the mortgage payment six days ahead of time. Note that this
# is done "implicitly" by subtracting 6 from the starting date - we start
# on 2 Jan rather than 8 Jan. We add 6 to TRIGDATE() in _IsMortDate to
# compensate.
REM 2 Jan 1993 *14 ++4 SATISFY [_IsMortDate(TRIGDATE()+6)] \
MSG %"Schedule mortgage payment%" for %a.
# Now the mail reminder two weeks before the payment date - because two
# weeks before a payment date is also a payment date, no pre-compensation
# in the starting date of 8 Jan is necessary - convince yourself of this!
# This uses the _mail() function defined earlier.
REM ONCE 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE()+14)] \
RUN [_mail("Decatur Federal", \
"Pay mortgage by the " + ORD(DAY(TRIGDATE()+14)))]
# Make an entry on the calendar when the mortgage should be paid
REM 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE())] \
CAL Mortgage payment
########################################################################## ##########################################################################
# # # #
# On our UNIX system, I run a program which queries the university # # On our UNIX system, I run a program that queries the university #
# library and creates a file called ".booksdue". This file is # # library and creates a file called ".booksdue". This file is #
# a REMIND script to tell me when my library books are due. Here's # # a REMIND script to tell me when my library books are due. Here's #
# an example from my reminder file - it shows the use of filedate(). # # an example from my reminder file - it shows the use of filedate(). #
# When the .booksdue file is at least 7 days old, I create a new version # # When the .booksdue file is at least 7 days old, I create a new version #
# by querying the library computer. Note the use of realtoday() rather # # by querying the library computer. Note the use of realtoday() rather #
# than today. # # than today(). #
# # # #
########################################################################## ##########################################################################
IF !$RunOff && !$CalMode && !$SimpleCal IF !$RunOff && !$CalMode && !$SimpleCal
IF REALTODAY()-FILEDATE("/home/dfs/.booksdue") >= 7 IF REALTODAY()-FILEDATE("/home/dfs/.booksdue") >= 7
REM RUN /home/dfs/bilge/library/getbooks REM RUN /home/dfs/bilge/library/getbooks
@@ -283,7 +208,7 @@ REM Sat Sun SPECIAL SHADE 220
############################################################################# #############################################################################
SET SaveTrig $NumTrig SET SaveTrig $NumTrig
SET easter EASTERDATE(YEAR(TODAY())) SET easter EASTERDATE($Uy)
REM [easter-46] MSG %"Ash Wednesday%" REM [easter-46] MSG %"Ash Wednesday%"
REM [easter-7] MSG %"Palm Sunday%" REM [easter-7] MSG %"Palm Sunday%"
OMIT [easter-2] MSG %"Good Friday%" OMIT [easter-2] MSG %"Good Friday%"
@@ -301,7 +226,7 @@ REM Mon Jan [Week_3] MSG Martin Luther King - %"MLK Day%"
REM Feb 2 MSG %"Ground Hog Day%" REM Feb 2 MSG %"Ground Hog Day%"
REM Feb 14 MSG %"Valentine's%" Day REM Feb 14 MSG %"Valentine's%" Day
REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1 REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"President's Day%" OMIT [$T] MSG %"President's Day%"
REM Mar 17 MSG %"St. Patrick's%" Day REM Mar 17 MSG %"St. Patrick's%" Day
# The DST rules are accurate for most locations in # The DST rules are accurate for most locations in
@@ -319,23 +244,23 @@ REM Sat May [Week_1] MSG %"Kentucky Derby%"
REM Sun May [Week_2] MSG %"Mother's Day%" REM Sun May [Week_2] MSG %"Mother's Day%"
REM Sat May [Week_3] MSG %"Armed Forces Day%" REM Sat May [Week_3] MSG %"Armed Forces Day%"
REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1 REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Memorial Day%" OMIT [$T] MSG %"Memorial Day%"
REM Jun 14 MSG %"Flag Day%" REM Jun 14 MSG %"Flag Day%"
REM Sun Jun [Week_3] MSG %"Father's Day%" REM Sun Jun [Week_3] MSG %"Father's Day%"
REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1 REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Labor Day%" OMIT [$T] MSG %"Labor Day%"
REM Mon Oct [Week_2] MSG %"Columbus Day%" REM Mon Oct [Week_2] MSG %"Columbus Day%"
REM Nov 11 MSG %"Veterans Day%" REM Nov 11 MSG %"Veterans Day%"
REM Oct 30 MSG %"Mischief Night%" REM Oct 30 MSG %"Mischief Night%"
REM Oct 31 MSG %"Halloween%" REM Oct 31 MSG %"Halloween%"
REM Tue Nov 2 SCANFROM [_back(7)] \ REM Tue Nov 2 SCANFROM [_back(7)] \
SATISFY [(YEAR(TRIGDATE()) % 4) == 0] \ SATISFY [($Ty % 4) == 0] \
MSG %"Election%" Day MSG %"Election%" Day
REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1 REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Thanksgiving%" Day OMIT [$T] MSG %"Thanksgiving%" Day
REM Fri Nov [Week_4+1] SCANFROM [_back(7)] SATISFY 1 REM Fri Nov [Week_4+1] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Thanksgiving%" (cont.) OMIT [$T] MSG %"Thanksgiving%" (cont.)
OMIT Dec 24 MSG %"Christmas Eve%" OMIT Dec 24 MSG %"Christmas Eve%"
OMIT Dec 25 MSG %"Christmas%" Day OMIT Dec 25 MSG %"Christmas%" Day
@@ -350,13 +275,6 @@ if $NumTrig > SaveTrig
REM SPECIAL SHADE 220 REM SPECIAL SHADE 220
endif endif
# Seasons (valid from 1992 to 2000)...
REM Mar 20 MSG %"Spring%" begins
REM Jun [IIF(YEAR(TODAY())%4, 21, 20)] MSG %"Summer%" begins
REM Sep [CHOOSE(YEAR(TODAY())-1991, 22,22,23,23,22,22,22,23,22)] \
MSG %"Fall%" begins
REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
#PSSTUFF2 #PSSTUFF2
########################################################################## ##########################################################################
# # # #
@@ -370,7 +288,7 @@ REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
# example, I recommend that you use the -sd 10 option for Rem2PS. # example, I recommend that you use the -sd 10 option for Rem2PS.
REM PS Border Border moveto \ REM PS Border Border moveto \
/DayFont findfont DaySize scalefont setfont \ /DayFont findfont DaySize scalefont setfont \
([hebday(today())] [hebmon(today())]) show ([hebday($U)] [hebmon($U)]) show
# Fill in the phases of the moon on the PostScript calendar # Fill in the phases of the moon on the PostScript calendar
[moondate(0)] SPECIAL MOON 0 [moondate(0)] SPECIAL MOON 0
@@ -382,7 +300,7 @@ REM PS Border Border moveto \
# calendar - the sizes are hard-coded, however, and work best in landscape. # calendar - the sizes are hard-coded, however, and work best in landscape.
REM PS Border Border 5 sub moveto \ REM PS Border Border 5 sub moveto \
/SmallFont findfont 4 scalefont setfont \ /SmallFont findfont 4 scalefont setfont \
(Sunrise: [sunrise(trigdate())] Sunset: [sunset(trigdate())]) show (Sunrise: [sunrise($T)] Sunset: [sunset($T)]) show
# The next one puts the day number (1-366) and days left in the year at the # The next one puts the day number (1-366) and days left in the year at the
# bottom of the post-script calendar. Again, the hard-coded sizes work best # bottom of the post-script calendar. Again, the hard-coded sizes work best
@@ -390,7 +308,7 @@ REM PS Border Border 5 sub moveto \
FSET _DayOfYear(x) x-(date(year(x),1,1) - 1) FSET _DayOfYear(x) x-(date(year(x),1,1) - 1)
REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \ REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \
/SmallFont findfont 4 scalefont setfont \ /SmallFont findfont 4 scalefont setfont \
([_DayOfYear(today())]([365+isleap(today())-_DayOfYear(today())])) show ([_DayOfYear($U)]([365+isleap($U)-_DayOfYear($U)])) show
#JHOLS #JHOLS
########################################################################## ##########################################################################
@@ -430,7 +348,7 @@ SET Reform 0
# Convenient function definition to save typing # Convenient function definition to save typing
FSET _h(x, y) HEBDATE(x,y) FSET _h(x, y) HEBDATE(x,y)
FSET _h2(x, y) HEBDATE(x, y, TODAY()-7) FSET _h2(x, y) HEBDATE(x, y, $U-7)
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _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 _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) FSET _PastMon(x, y) IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1)
@@ -464,7 +382,7 @@ ELSE
ENDIF ENDIF
# Because Kislev can change length, we must be more careful about Chanukah # Because Kislev can change length, we must be more careful about Chanukah
FSET _chan(x) HEBDATE(24, "Kislev", today()-9)+x FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b. [_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
[_chan(2)] MSG %"Chanukah 2%" [_chan(2)] MSG %"Chanukah 2%"
[_chan(3)] MSG %"Chanukah 3%" [_chan(3)] MSG %"Chanukah 3%"
@@ -553,9 +471,9 @@ ENDIF
# Counting the omer - do the whole spiel, i.e: # Counting the omer - do the whole spiel, i.e:
# "This is the xth day of the omer, being y weeks and z days of the omer." # "This is the xth day of the omer, being y weeks and z days of the omer."
# Nice Remind programming example here! # Nice Remind programming example here!
SET ostart HEBDATE(16, "Nisan", TODAY()-50) SET ostart HEBDATE(16, "Nisan", $U-50)
IF ostart <= TODAY() && (TODAY() - ostart < 49) IF ostart <= $U && ($U - ostart < 49)
SET odays TODAY()-ostart+1 SET odays $U-ostart+1
IF odays < 7 IF odays < 7
MSG %"%"Today is the [ORD(odays)] day of the Omer. MSG %"%"Today is the [ORD(odays)] day of the Omer.
ELSE ELSE
@@ -573,8 +491,8 @@ ENDIF
### for Friday and Saturday. Note: You must set your latitude, longitude ### for Friday and Saturday. Note: You must set your latitude, longitude
### and possibly time zone for these to work properly! ### and possibly time zone for these to work properly!
REM Friday CAL Candle lighting at [sunset(trigdate())-18] REM Friday CAL Candle lighting at [sunset($T)-18]
REM Saturday CAL Havdalah at [sunset(trigdate())+42] REM Saturday CAL Havdalah at [sunset($T)+42]
#COLORS #COLORS
########################################################################## ##########################################################################

View File

@@ -5,9 +5,9 @@ rem2ps \- draw a PostScript calendar from Remind output
.SH SYNOPSIS .SH SYNOPSIS
.B rem2ps [\fIoptions\fR] .B rem2ps [\fIoptions\fR]
.SH DESCRIPTION .SH DESCRIPTION
\fBRem2ps\fR reads the standard input, which should be the results of running \fBRem2ps\fR reads the standard input, which should be the results of
\fBRemind\fR with the \fB\-p\fR option. It emits PostScript code (which running \fBRemind\fR with the \fB\-p\fR or \fB\-pp\fR option. It
draws a calendar) to the standard output. emits PostScript code (which draws a calendar) to the standard output.
.PP .PP
See the section "Rem2PS Input Format" for details about the \fB\-p\fR See the section "Rem2PS Input Format" for details about the \fB\-p\fR
data. This may be useful if you wish to create other \fBRemind\fR data. This may be useful if you wish to create other \fBRemind\fR
@@ -267,7 +267,7 @@ hold:
.TP .TP
o o
The PostScript origin is at the bottom left-hand corner of the page, and The PostScript origin is at the bottom left-hand corner of the page, and
PostScript units of 1/72" are in effect. PostScript units of 1/72 inch are in effect.
.TP .TP
o o
The variables MinX, MinY, MaxX and MaxY define the bounding box within The variables MinX, MinY, MaxX and MaxY define the bounding box within
@@ -313,7 +313,13 @@ Use that file with the \fBRem2ps\fR \fB\-p\fR option to create calendars
with the year and month in large grey letters in the background of the with the year and month in large grey letters in the background of the
calendar. calendar.
.PP .PP
.SH REM2PS INPUT FORMAT .SH REM2PS INPUT FORMAT (-P OPTION)
The \fB\-p\fR option is an older, simpler interchange format used by
\fBRemind\fR to communicate with back-ends. New back-ends are
encoraged to support the new \fB\-pp\fR format preferably, though they
are encouraged to support the older \fB\-p\fR format as well if the
older format contains enough information for them to work properly.
.PP
\fBRemind \-p\fR sends the following lines to standard output. \fBRemind \-p\fR sends the following lines to standard output.
The information is designed to be easily parsed by back-end programs: The information is designed to be easily parsed by back-end programs:
.TP .TP
@@ -375,6 +381,9 @@ was provided.
.PP .PP
\fIbody\fR is the body of the reminder. \fIbody\fR is the body of the reminder.
.PP .PP
Future versions of \fBRemind\fR may add additional keys to the JSON
object. Back-ends \fImust\fR ignore keys they don't recognize.
.PP
After a month's worth of reminders have been emitted, \fBRemind\fR After a month's worth of reminders have been emitted, \fBRemind\fR
emits the line: emits the line:
.PP .PP
@@ -393,6 +402,247 @@ the line number and file name of the file containing the reminder. Back-ends
that don't care about this information should ignore lines starting with that don't care about this information should ignore lines starting with
"#" (except, of course, for the # rem2ps lines.) "#" (except, of course, for the # rem2ps lines.)
.PP .PP
.SH REM2PS PARTIAL JSON INPUT FORMAT (-PP OPTION)
\fBRemind \-pp\fR sends the following lines to standard output. They
are designed to be easily parsed, but contain much more information
than the old-style \fBremind -p\fR output. The extra information
contains a representation of the parsed "REM" statement, which could
allow converters to better preserve semantics of a reminder. For
example, this format passes enough information to allow a back-end to
(in many cases) determine a reminder's recurrence rather than just treating
each reminder as a one-off event.
.PP
The lines emitted by \fBremind \-pp\fR are as follows:
.TP
.B # rem2ps2 begin
This line signifies the start of calendar data. Back-ends can search
for it to verify they are being fed correct information. Note the
"2" after "rem2ps", which distinguishes this format from the older \fB\-p\fR
format.
.TP
\fImonth_name year num_days first_day monday_first\fR
Same as the \fB\-p\fR format
.TP
\fIsun mon tue wed thu fri sat\fR
Same as the \fB\-p\fR format
.TP
\fInext_mon next_days\fR
Same as the \fB\-p\fR format
.TP
\fIprev_mon prev_days\fR
Same as the \fB\-p\fR format
.PP
.B CALENDAR ENTRIES
.PP
The remaining data consists of calendar entries expressed as a JSON object
on a single line. Each such line will begin with "{" and will be a well-formed
JSON object. The keys that may be present in the JSON object are as
follows:
.TP
.B date \fIYYYY-MM-DD\fR
The \fbdate\fR key will \fIalways\fR be present; it is the trigger date
of the reminder expressed as a string in the format \fIYYYY-MM-DD\fR
.TP
.B filename \fIf\fR
The filename in which the reminder was found.
.TP
.B lineno \fIn\fR
The line number within the file on which the reminder was found.
.TP
.B nonconst_expr 1
If the reminder contained a non-constant expression that had to be evaluated
to determine the trigger date, this key will be present with the value 1.
If this key is present, then it is unsafe for a back-end to rely on
recurrence semantics or even the semantics of any part of the parsed
reminder, as they may have been computed in a way that cannot be expressed
in JSON.
.TP
.B if_depth \fIn\fR
If the reminder is inside one or more IF or ELSE statements, this key
will be present and the value will be the number of nested IFs from
the top-level to the reminder. Back-ends should be wary of
interpreting recurrence semantics of reminders within an IF or ELSE
block.
.TP
.B passthru \fIspecial\fR
If the reminder was a SPECIAL reminder, the \fBpassthru\fR key will be
present and the value will be the type of SPECIAL (such as SHADE, COLOR,
MOON, etc.)
.TP
.B tags \fIdata\fR
If any TAG clauses are present, the \fBtag\fR key will be present and consist
of a comma-separated list of tags.
.TP
.B time \fIt\fR
If an AT clause was present, this key will contain the time of the AT clause
in minutes after midnight.
.TP
.B tdelta \fIn\fR
If a time delta (+n after an AT clause) was present, this key contains the
delta value in minutes.
.TP
.B trep \fIn\fR
If a time repeat (*n after an AT clause) was present, this key contains the
repeat value in minutes.
.TP
.B eventduration \fIn\fR
If a DURATION clause was present, this key contains the event duration in
minutes.
.TP
.B duration \fIn\fR
If a DURATION clause was present, this key contains today's duration in
minutes. See the \fBremind(1)\fR man page, "MULTI-DAY EVENTS", for a
discussion of duration vs. event duration.
.TP
.B eventstart \fIdt\fR
If an AT clause was present, this key contains the event start time in
the format \fIYYYY-MM-DDTHH:MM\fR.
.TP
.B back \fIn\fR
If the reminder contained a "back" clause (\-n or \-\-n), this key
contains the back value. If the "back" value was \-n, the value will
be positive; if it was \-\-n, the value will be negative.
.TP
.B delta \fIn\fR
If the reminder contained a "delta" clause (\+n or \+\+n), this key
contains the delta value. If the "delta" value was \+n, the value will
be positive; if it was \+\+n, the value will be negative.
.TP
.B rep \fIn\fR
If the reminder contained a "repeat" clause (*n), this key contains
the repeat value.
.TP
.B skip \fItype\fR
If the reminder contained a SKIP, BEFORE or AFTER keyword, then this
key will contain that keyword.
.TP
.B localomit \fIarray\fR
If the reminder contains a local OMIT keyword, this key will be present.
Its value will be an array of English day names that are OMITted.
.TP
.B wd \fIarray\fR
If the reminder contains one or more weekdays, this key will be present.
Its value will be an array of English day names that are present.
.TP
.B d \fIn\fR
If a day-of-month is present in the reminder specification, this key
will be present and its value will be the day number.
.TP
.B m \fIn\fR
If a month is present in the reminder specification, this key
will be present and its value will be the month number.
.TP
.B y \fIn\fR
If a year is present in the reminder specification, this key
will be present and its value will be the year.
.TP
.B until \fIYYYY-MM-DD\fR
If the reminder contains an UNTIL or THROUGH clause, this key
will be present. Its value will be a string of the form YYYY-MM-DD.
.TP
.B once 1
If the reminder contains a ONCE keyword, this key will be present
with a value of 1.
.TP
.B scanfrom \fIYYYY-MM-DD\fR
If the reminder contains a SCANFROM keyword, this key will be present
and its value will be a string of the form YYYY-MM-DD.
.TP
.B from \fIYYYY-MM-DD\fR
If the reminder contains a FROM keyword, this key will be present
and its value will be a string of the form YYYY-MM-DD.
.TP
.B priority \fIn\fR
The priority of the reminder. Always present; if no PRIORITY keyword
is specified, then a reminder has a default priority of 5000.
.TP
.B r \fIn\fR
For a SHADE or COLOR special, the red color component.
.TP
.B g \fIn\fR
For a SHADE or COLOR special, the green color component.
.TP
.B b \fIn\fR
For a SHADE or COLOR special, the blue color component.
.TP
.B body \fIbody\fR
The body of the reminder to issue. Always present.
.TP
.B rawbody \fIraw\fR
The "raw" body of the reminder, before any expression-pasting or
substitution-sequence processing. If the raw body would be the same
as the processed body, then this key is not present.
.PP
After a month's worth of reminders have been emitted, \fBRemind\fR
emits the line:
.PP
\fB# rem2ps2 end
.PP
However, back-ends should keep reading until EOF in case more data for
subsequent months is forthcoming.
.PP
.SH REM2PS PURE JSON INPUT FORMAT (-PPP OPTION)
\fBRemind \-ppp\fR emits \fIpure JSON\fR output. The format is
as follows:
.PP
\fBRemind\fR outputs a JSON array. Each element of the array is a
\fImonth descriptor\fR.
.PP
Each month descriptor is a JSON object with the following elements:
.TP
.B monthname \fIname\fR
The name of the month.
.TP
.B year \fIyyyy\fR
The year.
.TP
.B daysinmonnth \fIn\fR
The number of days in the current month.
.TP
.B firstwkday \fIn\fR
The weekday of the first day of the month (0 = Sunday, 1 = Monday, 6 = Saturday).
.TP
.B mondayfirst \fIn\fR
An indicator of whether or not the calendar week should start with
Sunday (n=0) or Monday (n=1).
.TP
.B daynames \fR[\fIdays\fR]
A seven-element array of day names; each element is a string representing
the names of the days from Sunday through Saturday.
.TP
.B prevmonthname \fIname\fR
The name of the previous month.
.TP
.B daysinprevmonth \fIn\fR
The number of days in the previous month.
.TP
.B prevmonthyear \fIyyyy\fR
The year of the previous month. (The same as \fByear\fR unless the current
month is January.)
.TP
.B nextmonthname \fIname\fR
The name of the following month.
.TP
.B daysinnextmonth \fIn\fR
The number of days in the following month.
.TP
.B nextmonthyear \fIyyyy\fR
The year of the following month. (The same as \fByear\fR unless the
current month is December.)
.TP
.B entries \fR[\fIarray\fR]
The \fBentries\fR key consists of an array of calendar entries; each
entry is a JSON object that has the same format as described in the
\fBCALENDAR ENTRIES\fR section in the \fB\-PP FORMAT\fR section,
\fIwith the following difference\fR: In \fB\-PP\fR mode, if a reminder
has \fB%"\fR markers, only the text between the markers
is included in the \fBbody\fR element. In \fB\-PPP\fR mode, the
entire text \fIincluding\fR the \fB%"\fR markers is included and it's up to
the back-end to extract the portion between the markers if that
is desired.
.SH AUTHOR .SH AUTHOR
Rem2PS was written by Dianne Skoll <dianne@skoll.ca> Rem2PS was written by Dianne Skoll <dianne@skoll.ca>
.SH BUGS .SH BUGS

View File

@@ -26,7 +26,7 @@ Anything after the __EOF__ marker is completely ignored.
.SH OPTIONS .SH OPTIONS
\fBRemind\fR has a slew of options. If you're new to the program, \fBRemind\fR has a slew of options. If you're new to the program,
ignore them for now and skip to the section "Reminder Files". ignore them for now and skip to the section "REMINDER FILES".
.TP .TP
.B \-n .B \-n
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
@@ -46,7 +46,8 @@ The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
sent to standard output. If you supply a number \fIn\fR, then a sent to standard output. If you supply a number \fIn\fR, then a
calendar will be generated for \fIn\fR months, starting with the calendar will be generated for \fIn\fR months, starting with the
current month. By default, a calendar for only the current month is current month. By default, a calendar for only the current month is
produced. produced.
.RS
.PP .PP
You can precede \fIn\fR (if any) with a set of flags. The flags You can precede \fIn\fR (if any) with a set of flags. The flags
are as follows: are as follows:
@@ -72,24 +73,54 @@ only work on terminals that are set to UTF-8 character encoding.
.TP .TP
.B 'c' .B 'c'
causes \fBRemind\fR to use VT100 escape sequences to approximate causes \fBRemind\fR to use VT100 escape sequences to approximate
SPECIAL COLOR reminders. The approximation is (of necessity) very SPECIAL COLOR reminders. Note that this flag is kept for
backwards-compatibility; you should use the \fB\-@\fI[n][,m]\fR
command-line option instead.
.RE
.TP
.B \-@\fR[\fIn\fR][,\fIm\fR]
Tells \fBRemind\fR to approximate SPECIAL COLOR reminders using VT100
escape sequences. The approximation is (of necessity) very
coarse, because the VT100 only has eight different color sequences, coarse, because the VT100 only has eight different color sequences,
each with one of two brightnesses. A color component greater than each with one of two brightnesses. A color component greater than
64 is considered "on", and if any of the three color components is 64 is considered "on", and if any of the three color components is
greater than 128, the color is considered "bright". greater than 128, the color is considered "bright".
.RS
.PP
If you supply the optional numeric parameters, the have the following
meanings: \fIn\fR=0 tells \fBRemind\fR to use the standard 16 VT100
colors. \fIn\fR=1 tells it to use an extended 256-color palette supported
by many terminal emulators such as xterm. And \fIn\fR=2 tells it to
use escape sequences that support true 24-bit colors, again supported
by many terminal emulators such as xterm.
.PP
If the optional \fIm\fR parameter is supplied following a comma,
then \fIm\fR=0 tells \fBRemind\fR that the terminal background is dark,
and \fBRemind\fR will brighten up dark colors to make them visible. If
\fIm\fR=1, then \fBRemind\fR assumes the terminal background is light
and it will darken bright colors to make them visible. If no \fIm\fR
is supplied, then \fBRemind\fR does not perform any adjustments, and
some reminders may be hard or impossible to see if the color is too close
to the terminal background color.
.RE
.TP .TP
.B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]] .B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]]
The \fB\-w\fR option specifies the output width, padding and spacing The \fB\-w\fR option specifies the output width, padding and spacing
of the formatted calendar output. \fICol\fR specifies the number of of the formatted calendar output. \fICol\fR specifies the number of
columns in the output device, and defaults to 80. \fIPad\fR specifies columns in the output device. If not specified, or specified as 0,
how many lines to use to "pad" empty calendar boxes. This defaults to it defaults to the larger of 71 or the actual width of your terminal,
5. If you have many reminders on certain days that make your calendar or to 80 if standard output is not a terminal.
too large to fit on a page, you can try reducing \fIpad\fR to make the
empty boxes smaller. \fISpc\fR specifies how many blank lines to leave
between the day number and the first reminder entry. It defaults to 1.
.RS .RS
.PP .PP
\fIPad\fR specifies how many lines
to use to "pad" empty calendar boxes. This defaults to 5. If you
have many reminders on certain days that make your calendar too large
to fit on a page, you can try reducing \fIpad\fR to make the empty
boxes smaller. \fISpc\fR specifies how many blank lines to leave
between the day number and the first reminder entry. It defaults to
1.
.PP
Any of \fIcol\fR, \fIpad\fR or \fIspc\fR can be omitted, providing you Any of \fIcol\fR, \fIpad\fR or \fIspc\fR can be omitted, providing you
provide the correct number of commas. Don't use any spaces in the option. provide the correct number of commas. Don't use any spaces in the option.
.RE .RE
@@ -106,17 +137,27 @@ If you immediately follow the \fBs\fR with the letter
day they actually occur \fIas well as\fR on any preceding days specified day they actually occur \fIas well as\fR on any preceding days specified
by the reminder's \fIdelta\fR. by the reminder's \fIdelta\fR.
.TP .TP
.B \-p\fR[\fBa\fR]\fIn\fR .B \-p\fR[\fBa\fR][\fBp\fR][\fBp\fR]\fIn\fR
The \fB\-p\fR option is very similar to the \fB\-s\fR option, except The \fB\-p\fR option is very similar to the \fB\-s\fR option, except
that the output contains additional information for use by the that the output contains additional information for use by the
\fBRem2PS\fR program, which creates a PostScript calendar. For this \fBRem2PS\fR program, which creates a PostScript calendar, and various
other back-end programs. For this
option, \fIn\fR cannot start with "+"; it must specify a number of months. option, \fIn\fR cannot start with "+"; it must specify a number of months.
The format of the \fB\-p\fR output is described in the \fBrem2ps(1)\fR The format of the \fB\-p\fR output is described in the \fBrem2ps(1)\fR
man page. If you immediately follow the \fBp\fR with the letter man page. If you immediately follow the \fBp\fR with the letter
\fBa\fR, then \fBRemind\fR displays reminders on the calendar on the \fBa\fR, then \fBRemind\fR displays reminders on the calendar on the
day they actually occur \fIas well as\fR on any preceding days specified day they actually occur \fIas well as\fR on any preceding days specified
by the reminder's \fIdelta\fR. by the reminder's \fIdelta\fR. If you follow the \fBp\fR with another
\fBp\fR, then \fBRemind\fR uses a more comprehensive JSON-based
format rather than the "simple calendar" format. This format is
also documented in the \fBrem2ps(1)\fR man page. Finally, if you use
three p's, as in \fB\-ppp\fR, then \fBRemind\fR uses a pure JSON
format, again documented in \fBrem2ps(1)\fR.
.RS
.PP
Note that the \fB\-pp\fR or \fB\-ppp\fR options also enable the \fB\-l\fR
option.
.RE
.TP .TP
.B \-l .B \-l
If you use the \-l option in conjunction with the \-p option, then If you use the \-l option in conjunction with the \-p option, then
@@ -207,7 +248,7 @@ encountered in the reminder script. The \fB\-g\fR option cause
\fBRemind\fR to sort reminders by date and time prior to issuing them. \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 The optional \fBa\fR and \fBd\fR characters specify the sort order
(ascending or descending) for the date, time and priority fields. See (ascending or descending) for the date, time and priority fields. See
the section "Sorting Reminders" for more information. the section "SORTING REMINDERS" for more information.
.TP .TP
\fB\-b\fR[\fIn\fR] \fB\-b\fR[\fIn\fR]
@@ -282,7 +323,7 @@ TAG clause.
\fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR \fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR
Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR
\fIvar\fR. \fIExpr\fR can be any valid \fBRemind\fR expression. See the \fIvar\fR. \fIExpr\fR can be any valid \fBRemind\fR expression. See the
section "Initializing Variables on the Command Line" for more details. section "INITIALIZING VARIABLES ON THE COMMAND LINE" for more details.
.TP .TP
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR \fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
Allows you to define a function on the command line. Allows you to define a function on the command line.
@@ -293,14 +334,15 @@ If you supply a \fIdate\fR on the command line, it must consist of
of the month, and \fIyear\fR is a year (all 4 digits) from 1990 to of the month, and \fIyear\fR is a year (all 4 digits) from 1990 to
about 2075. You can leave out the \fIday\fR, which then defaults to 1. about 2075. You can leave out the \fIday\fR, which then defaults to 1.
.PP .PP
If you do supply a \fIdate\fR on the command line, then \fBRemind\fR uses If you do supply a \fIdate\fR on the command line, then \fBRemind\fR
it, rather than the actual system date, as its notion of "today." uses it, rather than the actual system date, as its notion of "today."
This lets you create calendars for future months, or test to see This lets you create calendars for future months, or test to see how
how your reminders will be triggered in the future. Similarly, your reminders will be triggered in the future. Similarly, you can
you can supply a \fItime\fR (in 24-hour format -- for example, 17:15) to supply a \fItime\fR to set \fBRemind\fR's notion of "now" to a
set \fBRemind\fR's notion of "now" to a particular time. Supplying particular time. Supplying a \fItime\fR on the command line also
a \fItime\fR on the command line also implicitly enables the \fB\-q\fR implicitly enables the \fB\-q\fR option and disables the \fB\-z\fR
option and disables the \fB\-z\fR option. option. The \fItime\fR may be specified in 24-hour format (eg, 13:20)
or common "AM/PM" format (1:20pm).
.PP .PP
If you would rather specify the date more succinctly, you can supply 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 it as YYYY-MM-DD or YYYY/MM/DD. You can even supply a date and
@@ -310,7 +352,7 @@ 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, 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 with the date incrementing on each iteration. You may have to enclose
the parameter in quotes to avoid shell expansion. See the subsection the parameter in quotes to avoid shell expansion. See the subsection
"Repeated Execution" in the section "Calendar Mode" for more "Repeated Execution" in the section "CALENDAR MODE" for more
information. information.
.SH REMINDER FILES .SH REMINDER FILES
.PP .PP
@@ -397,7 +439,7 @@ These keywords denote the \fItype\fR
of the reminder. (\fBSATISFY\fR is more complicated and will be explained of the reminder. (\fBSATISFY\fR is more complicated and will be explained
later.) A \fBMSG\fR-type reminder normally prints a message to the standard later.) A \fBMSG\fR-type reminder normally prints a message to the standard
output, after passing the \fIbody\fR through a special substitution filter, output, after passing the \fIbody\fR through a special substitution filter,
described in the section "The Substitution Filter." However, if you have described in the section "THE SUBSTITUTION FILTER." However, if you have
used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are
passed to the appropriate program. Note that the options \fB\-c\fR, passed to the appropriate program. Note that the options \fB\-c\fR,
\fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option. \fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option.
@@ -415,7 +457,7 @@ The \fBMSF\fR keyword is almost the same as the \fBMSG\fR keyword,
except that the reminder is formatted to fit into a paragraph-like except that the reminder is formatted to fit into a paragraph-like
format. Three system variables control the formatting of \fBMSF\fR-type format. Three system variables control the formatting of \fBMSF\fR-type
reminders - they are \fB$FirstIndent\fR, \fB$SubsIndent\fR and reminders - they are \fB$FirstIndent\fR, \fB$SubsIndent\fR and
\fB$FormWidth\fR. They are discussed in the section "System Variables." \fB$FormWidth\fR. They are discussed in the section "SYSTEM VARIABLES."
The \fBMSF\fR keyword causes the spacing of your reminder to be altered - The \fBMSF\fR keyword causes the spacing of your reminder to be altered -
extra spaces are discarded, and two spaces are placed after periods and extra spaces are discarded, and two spaces are placed after periods and
other characters, as specified by the system variables \fB$EndSent\fR and other characters, as specified by the system variables \fB$EndSent\fR and
@@ -448,7 +490,8 @@ of a special reminder depends on the back-end. For the \fBRem2PS\fR
back-end, \fBSPECIAL PostScript\fR is equivalent to a \fBPS\fR-type back-end, \fBSPECIAL PostScript\fR is equivalent to a \fBPS\fR-type
reminder, and \fBSPECIAL PSFile\fR is equivalent to a \fBPSFILE\fR-type reminder, and \fBSPECIAL PSFile\fR is equivalent to a \fBPSFILE\fR-type
reminder. The body of a \fBSPECIAL\fR reminder is obviously dependent reminder. The body of a \fBSPECIAL\fR reminder is obviously dependent
upon the back-end. upon the back-end. A back-end \fImust\fR ignore a \fBSPECIAL\fR that
it does not recognize.
.PP .PP
.B DATE SPECIFICATIONS .B DATE SPECIFICATIONS
.PP .PP
@@ -475,7 +518,7 @@ characters must be used. The following are examples of the various parts of a
JANUARY, feb, March, ApR, may, Aug JANUARY, feb, March, ApR, may, Aug
.TP .TP
.I year: .I year:
1990, 1993, 2030, 95 (interpreted as 1995). The year can range 1990, 1993, 2030. The year can range
from 1990 to 2075. from 1990 to 2075.
.TP .TP
.I weekday: .I weekday:
@@ -772,7 +815,7 @@ the initial date, and does not affect the repetition period.
.B SCANFROM \fRand\fB FROM .B SCANFROM \fRand\fB FROM
.PP .PP
The \fBSCANFROM\fR and \fBFROM\fR keywords are for advanced \fBRemind\fR programmers The \fBSCANFROM\fR and \fBFROM\fR keywords are for advanced \fBRemind\fR programmers
only, and will be explained in the section "Details about Trigger Computation" only, and will be explained in the section "DETAILS ABOUT TRIGGER COMPUTATION"
near the end of this manual. Note that \fBSCANFROM\fR is available only near the end of this manual. Note that \fBSCANFROM\fR is available only
in versions of \fBRemind\fR from 03.00.04 up. \fBFROM\fR is available only in versions of \fBRemind\fR from 03.00.04 up. \fBFROM\fR is available only
from 03.01.00 and later. from 03.01.00 and later.
@@ -784,7 +827,7 @@ It is used in calendar mode and when sorting reminders. If two reminders
have the same trigger date and time, then they are sorted by priority. have the same trigger date and time, then they are sorted by priority.
If the \fBPRIORITY\fR keyword is not supplied, a default priority of 5000 If the \fBPRIORITY\fR keyword is not supplied, a default priority of 5000
is used. (This default can be changed by adjusting the system variable is used. (This default can be changed by adjusting the system variable
\fB$DefaultPrio\fR. See the section "System Variables" for more \fB$DefaultPrio\fR. See the section "SYSTEM VARIABLES" for more
information.) information.)
.PP .PP
.B EXPIRY DATES .B EXPIRY DATES
@@ -925,8 +968,13 @@ it terminates the search after the \fBSATISFY\fR iteration limit
.PP .PP
Timed reminders are those that have an \fBAT\fR keyword followed Timed reminders are those that have an \fBAT\fR keyword followed
by a \fItime\fR and optional \fItdelta\fR and \fItrepeat\fR. The \fItime\fR by a \fItime\fR and optional \fItdelta\fR and \fItrepeat\fR. The \fItime\fR
must be specified in 24-hour format, with 0:00 representing midnight, may be specified in 24-hour format, with 0:00 representing midnight,
12:00 representing noon, and 23:59 representing one minute to midnight. 12:00 representing noon, and 23:59 representing one minute to midnight.
Alternatively, it may be specified in common "AM/PM" format; in this case,
the hour must range from 1 to 12. 12:00am represents midnight, 12:00pm
represents noon, and 11:59pm represents one minute to midnight. The "am"
and "pm" portions are case-insensitive and the "m" is optional.
.PP
You can use either a colon or a period to separate the hours from the You can use either a colon or a period to separate the hours from the
minutes. That is, 13:39 and 13.39 are equivalent. minutes. That is, 13:39 and 13.39 are equivalent.
.PP .PP
@@ -953,7 +1001,7 @@ The following reminder will be triggered on Thursdays and Fridays,
but will only be queued on Fridays: but will only be queued on Fridays:
.PP .PP
.nf .nf
REM Fri ++1 AT 13:00 MSG Lunch at 1pm Friday. REM Fri ++1 AT 1:00PM MSG Lunch at 1pm Friday.
.fi .fi
.PP .PP
The \fItdelta\fR and \fItrepeat\fR have the same form as a \fIrepeat\fR The \fItdelta\fR and \fItrepeat\fR have the same form as a \fIrepeat\fR
@@ -1013,7 +1061,7 @@ of timed reminders, and the \fBWARN\fR keyword allows precise control
over the advance triggering of all types of reminders. over the advance triggering of all types of reminders.
However, discussion must be deferred until after However, discussion must be deferred until after
expressions and user-defined functions are explained. See the subsection expressions and user-defined functions are explained. See the subsection
"Precise Scheduling" further on. "PRECISE SCHEDULING" further on.
.PP .PP
.B TAG AND DURATION .B TAG AND DURATION
.PP .PP
@@ -1035,15 +1083,21 @@ to each distinct REM command.
.PP .PP
The \fBDURATION\fR keyword makes sense only for timed reminders; it The \fBDURATION\fR keyword makes sense only for timed reminders; it
specifies the duration of an event. For example, if you have a specifies the duration of an event. For example, if you have a
90-minute meeting starting at 1:00pm, you could use: 90-minute meeting starting at 1:00pm, you could use any of the following:
.PP .PP
.nf .nf
REM 5 March 1999 AT 13:00 DURATION 1:30 MSG Meeting REM 5 March 2021 AT 13:00 DURATION 1:30 MSG Meeting
REM 5 March 2021 AT 13:00 DURATION 90 MSG Meeting
REM 5 March 2021 AT 1:00pm DURATION 1:30 MSG Meeting
REM 5 March 2021 AT 1:00pm DURATION 90 MSG Meeting
.fi .fi
.PP .PP
Note that \fIduration\fR is specified in hours and minutes. If you
specify a duration of 00:00, then \fBRemind\fR behaves exactly as if Note that \fIduration\fR is specified either in hours and minutes as a
no \fBDURATION\fR at all had been present. \fItime\fR, or in minutes as an \fIinteger\fR. If you specify a
duration of 00:00 or 0, then \fBRemind\fR behaves exactly as if no
\fBDURATION\fR at all had been present.
.PP .PP
.SH THE SUBSTITUTION FILTER .SH THE SUBSTITUTION FILTER
.PP .PP
@@ -1269,7 +1323,7 @@ is similar to \fB%3\fR but displays the current time.
used by the substitution filter, used by the substitution filter,
but is used to tell \fBRemind\fR which text to include in a calendar but is used to tell \fBRemind\fR which text to include in a calendar
entry when the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR option is chosen. entry when the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR option is chosen.
See "Calendar Mode" See "CALENDAR MODE"
.PP .PP
Notes: Notes:
.TP .TP
@@ -1623,13 +1677,15 @@ in C.
.RE .RE
.TP .TP
.B TIME constants .B TIME constants
12:33, 0:01, 14:15, 16:42, 12.16, 13.00, 1.11 12:33, 0:01, 14:15, 16:42, 12.16, 13.00, 1.11, 4:30PM, 12:20am
.PP .PP
.RS .RS
Note that \fBTIME\fR constants are written in 24-hour format. Either the Note that \fBTIME\fR constants may be written in 24-hour format or in
period or colon can be used to separate the minutes from the hours. common "AM/PM" format. If you use "AM/PM" format, then the hour can
However, Remind will consistently output times using only one separator range from 1 to 12. Either a period or colon can be used to separate
character. (The output separator character is chosen at compile-time.) the minutes from the hours. However, Remind will consistently output
times in 24-hour format using only one separator character. (The
output separator character is chosen at compile-time.)
.RE .RE
.TP .TP
.B DATE constants .B DATE constants
@@ -1652,11 +1708,12 @@ versions prior to 03.00.02 did not support the '-' date separator.
.RE .RE
.TP .TP
.B DATETIME constants .B DATETIME constants
\fBDATETIME\fR constants are expressed similarly to \fBDATE\fR constants \fBDATETIME\fR constants are expressed similarly to \fBDATE\fR
with the addition of an "@HH:MM" part. For example: constants with the addition of an "@HH:MM" part, optionally followed
by "am" or "pm". For example:
.PP .PP
.RS .RS
\'2008-04-05@23:11', '1999/02/03@14:06', '2001-04-07@08:30' \'2008-04-05@23:11', '1999/02/03@14:06', '2001-04-07@08:30', '2020-01-01@3:20pm'
.PP .PP
\fBDATETIME\fR values are printed without the quotes. Notes about date \fBDATETIME\fR values are printed without the quotes. Notes about date
and time separator characters for \fBDATE\fR and \fBTIME\fR constants apply and time separator characters for \fBDATE\fR and \fBTIME\fR constants apply
@@ -1843,6 +1900,9 @@ variable. Examples:
Note that variables themselves have no type. They take on the type of Note that variables themselves have no type. They take on the type of
whatever you store in them. whatever you store in them.
.PP .PP
Variables set with SET or on the command-line with \fB\-i\fR\fIvar\fB=\fR\fIexpr\fR
have global scope.
.PP
To delete a variable, use the \fBUNSET\fR command: To delete a variable, use the \fBUNSET\fR command:
.PP .PP
\fBUNSET\fR \fIvar\fR [\fIvar\fR...] \fBUNSET\fR \fIvar\fR [\fIvar\fR...]
@@ -1895,6 +1955,22 @@ This variable can be set only to "/" or "-". It holds the character
used to separate portions of a date when \fBRemind\fR prints a DATE or used to separate portions of a date when \fBRemind\fR prints a DATE or
DATETIME value. DATETIME value.
.TP .TP
.B $DefaultColor
This variable can be set to a string that has the form of three
space-separated numbers. Each number must be an integer from 0 to
255, or all three numbers must be -1. The default value of
\fB$DefaultColor\fR is "-1 -1 -1", which suppresses default coloring
of MSG-type reminders. If you set \fB$DefaultColor\fR to any other
value, then all MSG-, MSF- and CAL-type reminders are effectively
converted into SPECIAL COLOR reminders whose color value is specified
by \fB$DefaultColor\fR.
.RS
.PP
Unlike other system variables, the value of \fB$DefaultColor\fR is
\fInot\fR preserved between calendar iterations; rather, it is reset
to "-1 -1 -1" at the start of each iteration.
.RE
.TP
.B $DefaultPrio .B $DefaultPrio
The default priority assigned to reminders without a \fBPRIORITY\fR The default priority assigned to reminders without a \fBPRIORITY\fR
clause. You can set this as required to adjust the priorities of clause. You can set this as required to adjust the priorities of
@@ -1953,9 +2029,11 @@ for years greater than 2037.
.TP .TP
.B $FormWidth .B $FormWidth
The maximum width of each line of text for formatting \fBMSF\fR-type The maximum width of each line of text for formatting \fBMSF\fR-type
reminders. The default is 72. If an \fBMSF\fR-type reminder contains reminders. The default is the width of the terminal in columns, minus
a word too long to fit in this width, it will not be truncated - the 8, but clamped at a minimum of 20 and a maximum of 500. If standard
width limit will be ignored. output is not a terminal, then the default is 72.If an \fBMSF\fR-type
reminder contains a word too long to fit in this width, it will not be
truncated - the width limit will be ignored.
.TP .TP
.B $HushMode (read-only) .B $HushMode (read-only)
If non-zero, then the \fB\-h\fR option was supplied on the command line. If non-zero, then the \fB\-h\fR option was supplied on the command line.
@@ -1984,8 +2062,13 @@ the latitude and longitude system variables.
These specify the longitude of your location. \fB$LongDeg\fR can These specify the longitude of your location. \fB$LongDeg\fR can
range from \-180 to 180. Western longitudes are positive; eastern range from \-180 to 180. Western longitudes are positive; eastern
ones are negative. Note that all three components should have the ones are negative. Note that all three components should have the
same sign: All positive for Western longitudes and all negative same sign: All positive for Western longitudes and all negative for
for Eastern longitudes. Eastern longitudes. Note that for historical reasons, the sign for
longitude is \fIdifferent\fR from the usual convention! If you find
the longitude of your location from a search engine, you will most
likely \fIneed to invert the sign to have it work correctly with
Remind.\fR
.RS .RS
.PP .PP
The latitude and longitude information is required for the functions The latitude and longitude information is required for the functions
@@ -2148,6 +2231,23 @@ is supplied, only the date component is used.
Returns the time of "astronomical twilight" on the specified \fIdate\fR. If Returns the time of "astronomical twilight" on the specified \fIdate\fR. If
\fIdate\fR is omitted, defaults to \fBtoday()\fR. \fIdate\fR is omitted, defaults to \fBtoday()\fR.
.TP .TP
.B ampm(tq_time [,s_am [,s_pm]])
Returns a \fBSTRING\fR that is the result of converting \fItime\fR
(which is either a \fBTIME\R or a \fBDATETIME\fR object) to "AM/PM"
format. The optional arguments \fIam\fR and \fIpm\fR are the strings
to append in the AM and PM case, respectively; they default to "AM"
and "PM". The function obeys the system variables $DateSep,
$TimeSep and $DateTimeSep when formatting its output. For example:
.RS
.PP
.nf
ampm(0:22) returns "12:22AM"
ampm(17:45, "am", "pm") returns "5:45pm"
ampm('2020-03-14@21:34') returns "2020-03-14@9:34PM"
.fi
.PP
.RE
.TP
.B args(s_fname) .B args(s_fname)
Returns the number of arguments expected by the user-defined function Returns the number of arguments expected by the user-defined function
\fIfname\fR, or \-1 if no such user-defined function exists. Note that \fIfname\fR, or \-1 if no such user-defined function exists. Note that
@@ -2394,16 +2494,16 @@ variables are generally case-sensitive; thus, getenv("HOME") is not
the same as getenv("home"). the same as getenv("home").
.TP .TP
.B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]]) .B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]])
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP .TP
.B hebday(dq_date) .B hebday(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP .TP
.B hebmon(dq_date) .B hebmon(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP .TP
.B hebyear(dq_date) .B hebyear(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP .TP
.B hour(tq_time) .B hour(tq_time)
Returns the hour component of \fItime\fR. Returns the hour component of \fItime\fR.
@@ -3057,12 +3157,12 @@ is an implementation artifact.
.B SELF-OVERLAPPING EVENTS .B SELF-OVERLAPPING EVENTS
.PP .PP
A multi-day event has the possibility of "overlapping itself". When this A multi-day event has the possibility of "overlapping itself". When this
happens, \fBRemind\fR prefers the \fIearlier\fR event (only one copy of happens, \fBRemind\fR prefers the \fIlater\fR event (only one copy of
an event is ever triggered for a given date.) Consider this example: an event is ever triggered for a given date.) Consider this example:
.PP .PP
.nf .nf
#!/bin/sh #!/bin/sh
remind - '*4' 11 Feb 1991 <<'EOF' remind - '*5' 10 Feb 1991 <<'EOF'
BANNER % BANNER %
REM MON at 0:00 DURATION 192:0 MSG [today()] [trigeventstart()] [trigduration()]% REM MON at 0:00 DURATION 192:0 MSG [today()] [trigeventstart()] [trigduration()]%
@@ -3073,17 +3173,16 @@ an event is ever triggered for a given date.) Consider this example:
The output is: The output is:
.PP .PP
.nf .nf
1991-02-11 1991-02-04@00:00 24:00 1991-02-10 1991-02-04@00:00 48:00
1991-02-11 1991-02-11@00:00 192:00
1991-02-12 1991-02-11@00:00 168:00 1991-02-12 1991-02-11@00:00 168:00
1991-02-13 1991-02-11@00:00 144:00 1991-02-13 1991-02-11@00:00 144:00
1991-02-14 1991-02-11@00:00 120:00 1991-02-14 1991-02-11@00:00 120:00
.fi .fi
.PP .PP
Although 1991-02-11 is a Monday (which should cause the event to be Although the event from 1991-02-04 still has 24 hours left on 1991-02-11,
triggered, the 8-day-long event that started on 1991-02-04 \fIhas not the fresh occurrence on 1991-02-11 takes precedences and is the one that
finished yet\fR, so that is the one that is triggered. The next day, is triggered.
the event starting on 1991-02-04 \fIhas\fR finished, so the 1991-02-11
event triggers, with a remaining duration of 168:00, or 7 days.
.PP .PP
I do not recommend constructing self-overlapping multi-day events. I do not recommend constructing self-overlapping multi-day events.
.PP .PP
@@ -3533,7 +3632,7 @@ However, when \fBRemind\fR gets around to calculating the trigger
for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be
omitting Labour Day for 1993, and the "Mon AFTER" command omitting Labour Day for 1993, and the "Mon AFTER" command
will not be triggered. (But see the description of \fBSCANFROM\fR will not be triggered. (But see the description of \fBSCANFROM\fR
in the section "Details about Trigger Computation.") in the section "DETAILS ABOUT TRIGGER COMPUTATION.")
.PP .PP
It is probably best to stay away from computing \fBOMIT\fR It is probably best to stay away from computing \fBOMIT\fR
trigger dates unless you keep these pitfalls in mind. trigger dates unless you keep these pitfalls in mind.
@@ -3569,6 +3668,35 @@ 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 same problem, though in different ways. Sometimes a \fBSATISFY\fR is cleaner
and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer. and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer.
.PP .PP
.SH POSSIBLY-UNCOMPUTABLE TRIGGERS
.PP
Occasionally, you may wish to suppress the "Can't compute trigger" warnings
for reminders for which a trigger date cannot be compute. For example,
the following reminder is triggered on a Monday that is not a holiday
if the following Tuesday is a holiday:
.PP
.nf
REM Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
.fi
.PP
However, if there are no Mondays after today's date that satisfy the
condition, Remind will print the "Can't compute trigger" error. To
suppress this, use the \fBMAYBE-UNCOMPUTABLE\fR keyword:
.PP
.nf
REM MAYBE-UNCOMPUTABLE Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
.fi
.PP
It's almost never appropriate to use \fBMAYBE-UNCOMPUTABLE\fR, but it is
provided for those rare occasions when it makes sense. If you use
\fBMAYBE-UNCOMPUTABLE\fR inside the \fBevaltrig()\fR function, then
untriggerable triggers return -1. For example:
.PP
.nf
SET a evaltrig("MAYBE-UNCOMPUTABLE Mon SKIP OMIT Mon")
.fi
.PP
will set a to -1.
.SH DEBUGGING REMINDER SCRIPTS .SH DEBUGGING REMINDER SCRIPTS
.PP .PP
Although the command-line \fB\-d\fR option is useful for debugging, it Although the command-line \fB\-d\fR option is useful for debugging, it
@@ -3731,7 +3859,7 @@ iterations. On the next iteration, the commands are skipped, since
initialized has remained defined. Thus, time-consuming operations that initialized has remained defined. Thus, time-consuming operations that
do not depend on the value of \fBtoday()\fR are done only once. do not depend on the value of \fBtoday()\fR are done only once.
.PP .PP
System variables (those whose names start with '$') are automatically Most system variables (those whose names start with '$') are automatically
preserved between calendar iterations. preserved between calendar iterations.
.PP .PP
Note that for efficiency, \fBRemind\fR caches the reminder script Note that for efficiency, \fBRemind\fR caches the reminder script
@@ -4320,7 +4448,7 @@ They are used only when piping data from a \fBremind \-p\fR line.
equivalent of MSG in \fBremind's\fR normal mode of operation.) equivalent of MSG in \fBremind's\fR normal mode of operation.)
.PP .PP
The various \fBSPECIAL\fRs recognized are particular for each The various \fBSPECIAL\fRs recognized are particular for each
backend; however, there are three \fBSPECIAL\fRs that all backends backend; however, there are four \fBSPECIAL\fRs that all backends
should attempt to support. They are currently supported by should attempt to support. They are currently supported by
\fBRem2PS\fR, \fBtkremind\fR and \fBrem2html\fR. \fBRem2PS\fR, \fBtkremind\fR and \fBrem2html\fR.
.PP .PP
@@ -4383,9 +4511,12 @@ The rest of the line is the text to put in the calendar.
.PP .PP
The COLOR special is "doubly special", because in its normal operating The COLOR special is "doubly special", because in its normal operating
mode, \fBremind\fR treats a COLOR special just like a MSG-type reminder. 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 Also, if you invoke \fBRemind\fR with \fB\-@\fR[\fIn\fR], then it approximates
SPECIAL COLOR reminders on your terminal. SPECIAL COLOR reminders on your terminal.
.PP .PP
See also the documentation of the \fB$DefaultColor\fR system variable
in the section "SYSTEM VARIABLES".
.PP
The \fBWEEK\fR special lets you place annotations such as the week The \fBWEEK\fR special lets you place annotations such as the week
number in the calendar. For example, this would number each Monday number in the calendar. For example, this would number each Monday
with the ISO 8601 week number. The week number is shown like this: with the ISO 8601 week number. The week number is shown like this:

View File

@@ -125,10 +125,11 @@ Select the appropriate paper size and orientation. Activate
be the normal case unless you have many reminders in a particular be the normal case unless you have many reminders in a particular
day. (See the \fBRem2PS\fR documentation.) day. (See the \fBRem2PS\fR documentation.)
Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel. Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel. Note
Note that during printing, \fBRemind\fR is \fInot\fR called with that during printing, \fBRemind\fR is called with the
the \fB-itkremind=1\fR option, because it is operated in normal \fB-itkremind=1\fR option and also an additional \fB-itkprint=1\fR
PostScript-producing mode. option.
.SH EDITING REMINDERS .SH EDITING REMINDERS
@@ -210,7 +211,8 @@ background reminder pops up.
.TP .TP
.B Feed popped-up reminder to command's standard input .B Feed popped-up reminder to command's standard input
If selected, feeds the text of the reminder to the command described If selected, feeds the text of the reminder to the command described
above. above. The text of the reminder is prefixed by "HH:MM ", where HH:MM
is the time of the reminder.
.TP .TP
.B E-mail reminders here if popup not dismissed .B E-mail reminders here if popup not dismissed

File diff suppressed because it is too large Load Diff

View File

@@ -45,8 +45,8 @@ test: remind
$(REMINDOBJS): $(REMINDHDRS) $(REMINDOBJS): $(REMINDHDRS)
rem2ps: rem2ps.o dynbuf.o rem2ps: rem2ps.o dynbuf.o json.o
@CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o @CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o json.o -lm
remind: $(REMINDOBJS) remind: $(REMINDOBJS)
@CC@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@ @CC@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@
@@ -74,7 +74,7 @@ clobber:
rm -f *.o *~ remind rem2ps test.out core *.bak rm -f *.o *~ remind rem2ps test.out core *.bak
depend: depend:
gccmakedep @DEFS@ $(REMINDSRCS) rem2ps.c gccmakedep @DEFS@ $(REMINDSRCS) rem2ps.c json.c
# The next targets are not very useful to you. I use them to build # The next targets are not very useful to you. I use them to build
# distributions, etc. # distributions, etc.
@@ -86,8 +86,9 @@ distro:
gpg --detach-sign -u dianne@skoll.ca remind-$(VERSION).tar.gz gpg --detach-sign -u dianne@skoll.ca remind-$(VERSION).tar.gz
beta-tgz: beta-tgz:
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION)-BETA-$(BETA).tar cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)-BETA-$(BETA)/ HEAD > src/remind-$(VERSION)-BETA-$(BETA).tar
gzip -f -v -9 remind-$(VERSION)-BETA-$(BETA).tar gzip -f -v -9 remind-$(VERSION)-BETA-$(BETA).tar
gpg --detach-sign -u dianne@skoll.ca remind-$(VERSION)-BETA-$(BETA).tar.gz
#---------------- Stuff after this added by "make depend" ----------------- #---------------- Stuff after this added by "make depend" -----------------

File diff suppressed because it is too large Load Diff

View File

@@ -146,7 +146,7 @@
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */ /* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
/* any less than 12. */ /* any less than 12. */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
#define VAR_NAME_LEN 16 #define VAR_NAME_LEN 64
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* MAX_PRT_LEN: The maximum number of characters to print when */ /* MAX_PRT_LEN: The maximum number of characters to print when */
@@ -220,6 +220,9 @@
#define PSBEGIN "# rem2ps begin" #define PSBEGIN "# rem2ps begin"
#define PSEND "# rem2ps end" #define PSEND "# rem2ps end"
#define PSBEGIN2 "# rem2ps2 begin"
#define PSEND2 "# rem2ps2 end"
#ifdef BROKEN_PUTC #ifdef BROKEN_PUTC
#define Putc SafePutc #define Putc SafePutc
#define PutChar SafePutChar #define PutChar SafePutChar

View File

@@ -146,7 +146,7 @@
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */ /* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
/* any less than 12. */ /* any less than 12. */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
#define VAR_NAME_LEN 16 #define VAR_NAME_LEN 64
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* MAX_PRT_LEN: The maximum number of characters to print when */ /* MAX_PRT_LEN: The maximum number of characters to print when */
@@ -220,6 +220,9 @@
#define PSBEGIN "# rem2ps begin" #define PSBEGIN "# rem2ps begin"
#define PSEND "# rem2ps end" #define PSEND "# rem2ps end"
#define PSBEGIN2 "# rem2ps2 begin"
#define PSEND2 "# rem2ps2 end"
#ifdef BROKEN_PUTC #ifdef BROKEN_PUTC
#define Putc SafePutc #define Putc SafePutc
#define PutChar SafePutChar #define PutChar SafePutChar

View File

@@ -43,7 +43,7 @@ ComputeTrigDuration(TimeTrig *t)
t->duration == NO_TIME) { t->duration == NO_TIME) {
return 0; return 0;
} }
return (t->ttime + t->duration - 1) / 1440; return (t->ttime + t->duration - 1) / MINUTES_PER_DAY;
} }
/***************************************************************/ /***************************************************************/
@@ -81,6 +81,9 @@ int DoRem(ParsePtr p)
PurgeEchoLine("%s\n", CurLine); PurgeEchoLine("%s\n", CurLine);
r=DoSatRemind(&trig, &tim, p); r=DoSatRemind(&trig, &tim, p);
if (r) { if (r) {
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
}
FreeTrig(&trig); FreeTrig(&trig);
if (r == E_EXPIRED) return OK; if (r == E_EXPIRED) return OK;
return r; return r;
@@ -134,6 +137,9 @@ int DoRem(ParsePtr p)
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]); PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
PurgeEchoLine("%s\n", CurLine); PurgeEchoLine("%s\n", CurLine);
} }
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
}
FreeTrig(&trig); FreeTrig(&trig);
return r; return r;
} }
@@ -219,6 +225,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->duration_days = 0; trig->duration_days = 0;
trig->eventstart = NO_TIME; trig->eventstart = NO_TIME;
trig->eventduration = NO_TIME; trig->eventduration = NO_TIME;
trig->maybe_uncomputable = 0;
DBufInit(&(trig->tags)); DBufInit(&(trig->tags));
trig->passthru[0] = 0; trig->passthru[0] = 0;
tim->ttime = NO_TIME; tim->ttime = NO_TIME;
@@ -276,6 +283,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->m = tok.val; trig->m = tok.val;
break; break;
case T_MaybeUncomputable:
trig->maybe_uncomputable = 1;
break;
case T_Skip: case T_Skip:
DBufFree(&buf); DBufFree(&buf);
if (trig->skip != NO_SKIP) return E_SKIP_ERR; if (trig->skip != NO_SKIP) return E_SKIP_ERR;
@@ -389,6 +400,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
r=ParseToken(s, &buf); r=ParseToken(s, &buf);
if (r) return r; if (r) return r;
StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN); StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
/* An OMITFUNC counts as a nonconst_expr! */
s->expr_happened = 1;
s->nonconst_expr = 1;
DBufFree(&buf); DBufFree(&buf);
break; break;
@@ -413,6 +428,9 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
switch(tok.type) { switch(tok.type) {
case T_Time: case T_Time:
case T_LongTime: case T_LongTime:
case T_Year:
case T_Day:
case T_Number:
if (tok.val != 0) { if (tok.val != 0) {
tim->duration = tok.val; tim->duration = tok.val;
} else { } else {
@@ -759,20 +777,24 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
char const *s; char const *s;
Value v; Value v;
int red = -1, green = -1, blue = -1;
int is_color = 0;
DBufInit(&buf); DBufInit(&buf);
DBufInit(&calRow); DBufInit(&calRow);
DBufInit(&pre_buf); DBufInit(&pre_buf);
if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED; if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
if ((t->typ == PASSTHRU_TYPE && strcmp(t->passthru, "COLOR") && strcmp(t->passthru, "COLOUR")) || if ((t->typ == PASSTHRU_TYPE && StrCmpi(t->passthru, "COLOR") && StrCmpi(t->passthru, "COLOUR")) ||
t->typ == CAL_TYPE || t->typ == CAL_TYPE ||
t->typ == PS_TYPE || t->typ == PS_TYPE ||
t->typ == PSF_TYPE) t->typ == PSF_TYPE)
return OK; return OK;
/* Handle COLOR types */ /* Handle COLOR types */
if (t->typ == PASSTHRU_TYPE && (!strcmp(t->passthru, "COLOR") || !strcmp(t->passthru, "COLOUR"))) { if (t->typ == PASSTHRU_TYPE && (!StrCmpi(t->passthru, "COLOR") || !StrCmpi(t->passthru, "COLOUR"))) {
/* Strip off three tokens */ /* Strip off three tokens */
r = ParseToken(p, &buf); r = ParseToken(p, &buf);
sscanf(DBufValue(&buf), "%d", &red);
if (!NextMode) { if (!NextMode) {
DBufPuts(&pre_buf, DBufValue(&buf)); DBufPuts(&pre_buf, DBufValue(&buf));
DBufPutc(&pre_buf, ' '); DBufPutc(&pre_buf, ' ');
@@ -780,6 +802,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
DBufFree(&buf); DBufFree(&buf);
if (r) return r; if (r) return r;
r = ParseToken(p, &buf); r = ParseToken(p, &buf);
sscanf(DBufValue(&buf), "%d", &green);
if (!NextMode) { if (!NextMode) {
DBufPuts(&pre_buf, DBufValue(&buf)); DBufPuts(&pre_buf, DBufValue(&buf));
DBufPutc(&pre_buf, ' '); DBufPutc(&pre_buf, ' ');
@@ -787,6 +810,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
DBufFree(&buf); DBufFree(&buf);
if (r) return r; if (r) return r;
r = ParseToken(p, &buf); r = ParseToken(p, &buf);
sscanf(DBufValue(&buf), "%d", &blue);
if (!NextMode) { if (!NextMode) {
DBufPuts(&pre_buf, DBufValue(&buf)); DBufPuts(&pre_buf, DBufValue(&buf));
DBufPutc(&pre_buf, ' '); DBufPutc(&pre_buf, ' ');
@@ -870,6 +894,23 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
return OK; return OK;
} }
/* Correct colors */
if (UseVTColors) {
if (red == -1 && green == -1 && blue == -1) {
if (DefaultColorR != -1 && DefaultColorG != -1 && DefaultColorB != -1) {
red = DefaultColorR;
green = DefaultColorG;
blue = DefaultColorB;
}
}
if (red >= 0 && green >= 0 && blue >= 0) {
is_color = 1;
if (red > 255) red = 255;
if (green > 255) green = 255;
if (blue > 255) blue = 255;
}
}
/* Put the substituted string into the substitution buffer */ /* Put the substituted string into the substitution buffer */
/* Don't use msgprefix() on RUN-type reminders */ /* Don't use msgprefix() on RUN-type reminders */
@@ -880,6 +921,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
r = EvalExpr(&s, &v, NULL); r = EvalExpr(&s, &v, NULL);
if (!r) { if (!r) {
if (!DoCoerce(STR_TYPE, &v)) { if (!DoCoerce(STR_TYPE, &v)) {
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
}
if (DBufPuts(&buf, v.v.str) != OK) { if (DBufPuts(&buf, v.v.str) != OK) {
DBufFree(&buf); DBufFree(&buf);
DestroyValue(v); DestroyValue(v);
@@ -891,6 +935,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
} }
} }
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
}
if ( (r=DoSubst(p, &buf, t, tim, jul, NORMAL_MODE)) ) return r; if ( (r=DoSubst(p, &buf, t, tim, jul, NORMAL_MODE)) ) return r;
if (t->typ != RUN_TYPE) { if (t->typ != RUN_TYPE) {
if (UserFuncExists("msgsuffix") == 1) { if (UserFuncExists("msgsuffix") == 1) {
@@ -899,6 +946,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
r = EvalExpr(&s, &v, NULL); r = EvalExpr(&s, &v, NULL);
if (!r) { if (!r) {
if (!DoCoerce(STR_TYPE, &v)) { if (!DoCoerce(STR_TYPE, &v)) {
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
}
if (DBufPuts(&buf, v.v.str) != OK) { if (DBufPuts(&buf, v.v.str) != OK) {
DBufFree(&buf); DBufFree(&buf);
DestroyValue(v); DestroyValue(v);
@@ -910,6 +960,10 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
} }
} }
if (is_color) {
DBufPuts(&buf, Decolorize(red, green, blue));
}
if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) { if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
if (DBufPutc(&buf, '\n') != OK) { if (DBufPutc(&buf, '\n') != OK) {
DBufFree(&buf); DBufFree(&buf);
@@ -944,7 +998,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
break; break;
case RUN_TYPE: case RUN_TYPE:
system(DBufValue(&buf)); System(DBufValue(&buf));
break; break;
default: /* Unknown/illegal type? */ default: /* Unknown/illegal type? */
@@ -1059,10 +1113,24 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
iter = 0; iter = 0;
start = trig->scanfrom; start = trig->scanfrom;
while (iter++ < MaxSatIter) { while (iter++ < MaxSatIter) {
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1); jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
if (r) { if (r) {
if (r == E_CANT_TRIG) return OK; else return r; if (r == E_CANT_TRIG) return OK; else return r;
} }
if (jul != start && trig->duration_days) {
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, trig->duration_days);
if (r) {
if (r == E_CANT_TRIG) return OK; else return r;
}
} else if (jul == start) {
if (tt->ttime != NO_TIME) {
trig->eventstart = MINUTES_PER_DAY * r + tt->ttime;
if (tt->duration != NO_TIME) {
trig->eventduration = tt->duration;
}
}
SaveAllTriggerInfo(trig, tt, jul, tt->ttime, 1);
}
if (jul == -1) { if (jul == -1) {
return E_EXPIRED; return E_EXPIRED;
} }
@@ -1200,7 +1268,7 @@ int DoMsgCommand(char const *cmd, char const *msg)
} }
r = OK; r = OK;
system(DBufValue(&execBuffer)); System(DBufValue(&execBuffer));
finished: finished:
DBufFree(&buf); DBufFree(&buf);

View File

@@ -644,10 +644,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
break; break;
case '_': case '_':
if (mode != CAL_MODE && mode != ADVANCE_MODE && !MsgCommand) if (PsCal == PSCAL_LEVEL2 || PsCal == PSCAL_LEVEL3 || (mode != CAL_MODE && mode != ADVANCE_MODE && !MsgCommand)) {
sprintf(s, "%s", NL); sprintf(s, "%s", NL);
else } else {
sprintf(s, " "); sprintf(s, " ");
}
SHIP_OUT(s); SHIP_OUT(s);
break; break;
@@ -656,8 +657,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
break; break;
case '"': case '"':
if (DBufPutc(dbuf, QUOTE_MARKER) != OK) return E_NO_MEM; if (PsCal != PSCAL_LEVEL3) {
has_quote = 1; if (DBufPutc(dbuf, QUOTE_MARKER) != OK) return E_NO_MEM;
has_quote = 1;
} else {
if (DBufPutc(dbuf, '%') != OK) return E_NO_MEM;
if (DBufPutc(dbuf, c) != OK) return E_NO_MEM;
}
break; break;
default: default:

View File

@@ -150,7 +150,9 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
we can usually save some unnecessary copying */ we can usually save some unnecessary copying */
*(dbuf->buffer) = 0; *(dbuf->buffer) = 0;
fgets(dbuf->buffer, dbuf->allocatedLen, fp); if (fgets(dbuf->buffer, dbuf->allocatedLen, fp) == NULL) {
return OK;
}
if (!*(dbuf->buffer)) return OK; if (!*(dbuf->buffer)) return OK;
dbuf->len = strlen(dbuf->buffer); dbuf->len = strlen(dbuf->buffer);
l = dbuf->len - 1; l = dbuf->len - 1;
@@ -162,7 +164,7 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
while(busy) { while(busy) {
*tmp = 0; *tmp = 0;
fgets(tmp, 256, fp); if (fgets(tmp, 256, fp) == NULL) return OK;
if (!*tmp) return OK; if (!*tmp) return OK;
l = strlen(tmp) - 1; l = strlen(tmp) - 1;
if (tmp[l] == '\n') { if (tmp[l] == '\n') {

View File

@@ -492,6 +492,7 @@ static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
{ {
int len; int len;
int h, m, r; int h, m, r;
int ampm = 0;
if (*s == '\"') { /* It's a literal string "*/ if (*s == '\"') { /* It's a literal string "*/
len = strlen(s)-1; len = strlen(s)-1;
@@ -532,7 +533,27 @@ static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
m += *s - '0'; m += *s - '0';
s++; s++;
} }
/* Check for p[m] or a[m] */
if (*s == 'A' || *s == 'a' || *s == 'P' || *s == 'p') {
ampm = tolower(*s);
s++;
if (*s == 'm' || *s == 'M') {
s++;
}
}
if (*s || h>23 || m>59) return E_BAD_TIME; if (*s || h>23 || m>59) return E_BAD_TIME;
if (ampm) {
if (h < 1 || h > 12) return E_BAD_TIME;
if (ampm == 'a') {
if (h == 12) {
h = 0;
}
} else if (ampm == 'p') {
if (h < 12) {
h += 12;
}
}
}
v->type = TIME_TYPE; v->type = TIME_TYPE;
v->v.val = h*60 + m; v->v.val = h*60 + m;
return OK; return OK;
@@ -701,26 +722,12 @@ int DoCoerce(char type, Value *v)
return OK; return OK;
case STR_TYPE: case STR_TYPE:
h = 0;
m = 0;
s = v->v.str; s = v->v.str;
if (!isdigit(*s)) return E_CANT_COERCE; if (ParseLiteralTime(&s, &i)) return E_CANT_COERCE;
while (isdigit(*s)) { if (*s) return E_CANT_COERCE;
h *= 10;
h += *s++ - '0';
}
if (*s != ':' && *s != '.' && *s != TimeSep)
return E_CANT_COERCE;
s++;
if (!isdigit(*s)) return E_CANT_COERCE;
while (isdigit(*s)) {
m *= 10;
m += *s++ - '0';
}
if (*s || h>23 || m>59) return E_CANT_COERCE;
v->type = TIME_TYPE; v->type = TIME_TYPE;
free(v->v.str); free(v->v.str);
v->v.val = h*60+m; v->v.val = i;
return OK; return OK;
default: return E_CANT_COERCE; default: return E_CANT_COERCE;
@@ -1222,6 +1229,48 @@ int CopyValue(Value *dest, const Value *src)
return OK; return OK;
} }
int ParseLiteralTime(char const **s, int *tim)
{
int h=0;
int m=0;
int ampm=0;
if (!isdigit(**s)) return E_BAD_TIME;
while(isdigit(**s)) {
h *= 10;
h += *(*s)++ - '0';
}
if (**s != ':' && **s != '.' && **s != TimeSep) return E_BAD_TIME;
(*s)++;
if (!isdigit(**s)) return E_BAD_TIME;
while(isdigit(**s)) {
m *= 10;
m += *(*s)++ - '0';
}
/* Check for p[m] or a[m] */
if (**s == 'A' || **s == 'a' || **s == 'P' || **s == 'p') {
ampm = tolower(**s);
(*s)++;
if (**s == 'm' || **s == 'M') {
(*s)++;
}
}
if (h>23 || m>59) return E_BAD_TIME;
if (ampm) {
if (h < 1 || h > 12) return E_BAD_TIME;
if (ampm == 'a') {
if (h == 12) {
h = 0;
}
} else if (ampm == 'p') {
if (h < 12) {
h += 12;
}
}
}
*tim = h * 60 + m;
return OK;
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* ParseLiteralDate */ /* ParseLiteralDate */
@@ -1233,10 +1282,9 @@ int CopyValue(Value *dest, const Value *src)
int ParseLiteralDate(char const **s, int *jul, int *tim) int ParseLiteralDate(char const **s, int *jul, int *tim)
{ {
int y, m, d; int y, m, d;
int hour, min; int r;
y=0; m=0; d=0; y=0; m=0; d=0;
hour=0; min=0;
*tim = NO_TIME; *tim = NO_TIME;
if (!isdigit(**s)) return E_BAD_DATE; if (!isdigit(**s)) return E_BAD_DATE;
@@ -1266,20 +1314,9 @@ int ParseLiteralDate(char const **s, int *jul, int *tim)
/* Do we have a time part as well? */ /* Do we have a time part as well? */
if (**s == ' ' || **s == '@' || **s == 'T' || **s == 't') { if (**s == ' ' || **s == '@' || **s == 'T' || **s == 't') {
(*s)++; (*s)++;
while(isdigit(**s)) { r = ParseLiteralTime(s, tim);
hour *= 10; if (r != OK) return r;
hour += *(*s)++ - '0';
}
if (**s != ':' && **s != '.' && **s != TimeSep) return E_BAD_TIME;
(*s)++;
while(isdigit(**s)) {
min *= 10;
min += *(*s)++ - '0';
}
if (hour > 23 || min > 59) return E_BAD_TIME;
*tim = hour * 60 + min;
} }
return OK; return OK;
} }

View File

@@ -366,12 +366,12 @@ static int CacheFile(char const *fname)
cl = NULL; cl = NULL;
/* Create a file header */ /* Create a file header */
cf = NEW(CachedFile); cf = NEW(CachedFile);
cf->cache = NULL;
if (!cf) { if (!cf) {
ShouldCache = 0; ShouldCache = 0;
FCLOSE(fp); FCLOSE(fp);
return E_NO_MEM; return E_NO_MEM;
} }
cf->cache = NULL;
cf->filename = StrDup(fname); cf->filename = StrDup(fname);
if (!cf->filename) { if (!cf->filename) {
ShouldCache = 0; ShouldCache = 0;

View File

@@ -57,6 +57,7 @@ static int FADawn (func_info *);
static int FADusk (func_info *); static int FADusk (func_info *);
static int FAbs (func_info *); static int FAbs (func_info *);
static int FAccess (func_info *); static int FAccess (func_info *);
static int FAmpm (func_info *);
static int FArgs (func_info *); static int FArgs (func_info *);
static int FAsc (func_info *); static int FAsc (func_info *);
static int FBaseyr (func_info *); static int FBaseyr (func_info *);
@@ -206,6 +207,7 @@ BuiltinFunc Func[] = {
{ "access", 2, 2, 0, FAccess }, { "access", 2, 2, 0, FAccess },
{ "adawn", 0, 1, 0, FADawn}, { "adawn", 0, 1, 0, FADawn},
{ "adusk", 0, 1, 0, FADusk}, { "adusk", 0, 1, 0, FADusk},
{ "ampm", 1, 3, 1, FAmpm },
{ "args", 1, 1, 0, FArgs }, { "args", 1, 1, 0, FArgs },
{ "asc", 1, 1, 1, FAsc }, { "asc", 1, 1, 1, FAsc },
{ "baseyr", 0, 0, 1, FBaseyr }, { "baseyr", 0, 0, 1, FBaseyr },
@@ -886,6 +888,76 @@ static int FSgn(func_info *info)
return OK; return OK;
} }
/***************************************************************/
/* */
/* FAmpm - return a time as a string with "AM" or "PM" suffix */
/* */
/***************************************************************/
static int FAmpm(func_info *info)
{
int h, m;
int yr=0, mo=0, da=0;
char const *am = "AM";
char const *pm = "PM";
char const *ampm = NULL;
char outbuf[128];
if (ARG(0).type != DATETIME_TYPE && ARG(0).type != TIME_TYPE) {
return E_BAD_TYPE;
}
if (HASDATE(ARG(0))) {
FromJulian(DATEPART(ARG(0)), &yr, &mo, &da);
}
if (Nargs >= 2) {
ASSERT_TYPE(1, STR_TYPE);
am = ARGSTR(1);
if (Nargs >= 3) {
ASSERT_TYPE(2, STR_TYPE);
pm = ARGSTR(2);
}
}
h = TIMEPART(ARG(0)) / 60;
m = TIMEPART(ARG(0)) % 60;
if (h <= 11) {
/* AM */
if (h == 0) {
if (ARG(0).type == DATETIME_TYPE) {
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c12%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, TimeSep, m);
} else {
snprintf(outbuf, sizeof(outbuf), "12%c%02d", TimeSep, m);
}
} else {
if (ARG(0).type == DATETIME_TYPE) {
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
} else {
snprintf(outbuf, sizeof(outbuf), "%d%c%02d", h, TimeSep, m);
}
}
ampm = am;
} else {
if (h > 12) {
h -= 12;
}
if (ARG(0).type == DATETIME_TYPE) {
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
} else {
snprintf(outbuf, sizeof(outbuf), "%d%c%02d", h, TimeSep, m);
}
ampm = pm;
}
RetVal.type = STR_TYPE;
RetVal.v.str = malloc(strlen(outbuf) + strlen(ampm) + 1);
if (!RetVal.v.str) {
RetVal.type = ERR_TYPE;
return E_NO_MEM;
}
strcpy(RetVal.v.str, outbuf);
strcat(RetVal.v.str, ampm);
return OK;
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* FOrd - returns a string containing ordinal number. */ /* FOrd - returns a string containing ordinal number. */
@@ -2845,6 +2917,10 @@ FEvalTrig(func_info *info)
} }
jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0); jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
} }
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = 0;
jul = -1;
}
FreeTrig(&trig); FreeTrig(&trig);
if (r) return r; if (r) return r;
if (jul < 0) { if (jul < 0) {

View File

@@ -46,7 +46,7 @@ EXTERN INIT( int DoPrefixLineNo, 0);
EXTERN INIT( int MondayFirst, 0); EXTERN INIT( int MondayFirst, 0);
EXTERN INIT( int Iterations, 1); EXTERN INIT( int Iterations, 1);
EXTERN INIT( int PsCal, 0); EXTERN INIT( int PsCal, 0);
EXTERN INIT( int CalWidth, 80); EXTERN INIT( int CalWidth, -1);
EXTERN INIT( int CalWeeks, 0); EXTERN INIT( int CalWeeks, 0);
EXTERN INIT( int CalMonths, 0); EXTERN INIT( int CalMonths, 0);
EXTERN INIT( int Hush, 0); EXTERN INIT( int Hush, 0);
@@ -73,6 +73,9 @@ EXTERN INIT( int Daemon, 0);
EXTERN INIT( char DateSep, DATESEP); EXTERN INIT( char DateSep, DATESEP);
EXTERN INIT( char TimeSep, TIMESEP); EXTERN INIT( char TimeSep, TIMESEP);
EXTERN INIT( char DateTimeSep, DATETIMESEP); EXTERN INIT( char DateTimeSep, DATETIMESEP);
EXTERN INIT( int DefaultColorR, -1);
EXTERN INIT( int DefaultColorB, -1);
EXTERN INIT( int DefaultColorG, -1);
EXTERN INIT( int SynthesizeTags, 0); EXTERN INIT( int SynthesizeTags, 0);
EXTERN INIT( int ScFormat, SC_AMPM); EXTERN INIT( int ScFormat, SC_AMPM);
EXTERN INIT( int MaxSatIter, 150); EXTERN INIT( int MaxSatIter, 150);
@@ -100,6 +103,9 @@ EXTERN INIT( int CalPad, 1);
EXTERN INIT( int UseVTChars, 0); EXTERN INIT( int UseVTChars, 0);
EXTERN INIT( int UseUTF8Chars, 0); EXTERN INIT( int UseUTF8Chars, 0);
EXTERN INIT( int UseVTColors, 0); EXTERN INIT( int UseVTColors, 0);
EXTERN INIT( int Use256Colors, 0);
EXTERN INIT( int UseTrueColors, 0);
EXTERN INIT( int TerminalBackground, TERMINAL_BACKGROUND_UNKNOWN);
/* Latitude and longitude */ /* Latitude and longitude */
EXTERN INIT( int LatDeg, LAT_DEG); EXTERN INIT( int LatDeg, LAT_DEG);

View File

@@ -23,6 +23,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h> #include <pwd.h>
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h>
#include "types.h" #include "types.h"
#include "protos.h" #include "protos.h"
@@ -38,6 +39,7 @@
* simple calendar format. * simple calendar format.
* -r = Disallow RUN mode * -r = Disallow RUN mode
* -c[n] = Produce a calendar for n months (default = 1) * -c[n] = Produce a calendar for n months (default = 1)
* -@[n,m] = Colorize n=0 VT100 n=1 85 n=2 True m=0 dark terminal m=1 light
* -w[n,n,n] = Specify output device width, padding and spacing * -w[n,n,n] = Specify output device width, padding and spacing
* -s[n] = Produce calendar in "simple calendar" format * -s[n] = Produce calendar in "simple calendar" format
* -p[n] = Produce calendar in format compatible with rem2ps * -p[n] = Produce calendar in format compatible with rem2ps
@@ -135,7 +137,7 @@ void InitRemind(int argc, char const *argv[])
int InvokedAsRem = 0; int InvokedAsRem = 0;
char const *s; char const *s;
int weeks; int weeks;
int x;
int jul; int jul;
#if defined(__APPLE__) #if defined(__APPLE__)
@@ -146,6 +148,17 @@ void InitRemind(int argc, char const *argv[])
jul = NO_DATE; jul = NO_DATE;
/* If stdout is a terminal, initialize $FormWidth to terminal width-8,
but clamp to [20, 500] */
if (isatty(STDOUT_FILENO)) {
struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
FormWidth = w.ws_col - 8;
if (FormWidth < 20) FormWidth = 20;
if (FormWidth > 500) FormWidth = 500;
}
}
/* Initialize global dynamic buffers */ /* Initialize global dynamic buffers */
DBufInit(&Banner); DBufInit(&Banner);
DBufInit(&LineBuffer); DBufInit(&LineBuffer);
@@ -190,6 +203,7 @@ void InitRemind(int argc, char const *argv[])
/* Parse the command-line options */ /* Parse the command-line options */
i = 1; i = 1;
while (i < argc) { while (i < argc) {
arg = argv[i]; arg = argv[i];
if (*arg != '-') break; /* Exit the loop if it's not an option */ if (*arg != '-') break; /* Exit the loop if it's not an option */
@@ -204,6 +218,27 @@ void InitRemind(int argc, char const *argv[])
while (*arg) { while (*arg) {
switch(*arg++) { switch(*arg++) {
case '@':
UseVTColors = 1;
if (*arg) {
PARSENUM(x, arg);
if (x == 1) {
Use256Colors = 1;
} else if (x == 2) {
UseTrueColors = 1;
}
}
if (*arg == ',') {
arg++;
PARSENUM(x, arg);
if (x == 0) {
TerminalBackground = TERMINAL_BACKGROUND_DARK;
} else if (x == 1) {
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
}
}
break;
case 'j': case 'j':
case 'J': case 'J':
PurgeMode = 1; PurgeMode = 1;
@@ -400,9 +435,21 @@ void InitRemind(int argc, char const *argv[])
case 'p': case 'p':
case 'P': case 'P':
DoSimpleCalendar = 1; DoSimpleCalendar = 1;
PsCal = 1; PsCal = PSCAL_LEVEL1;
if (*arg == 'a' || *arg == 'A') { while (*arg == 'a' || *arg == 'A' ||
DoSimpleCalDelta = 1; *arg == 'p' || *arg == 'P') {
if (*arg == 'a' || *arg == 'A') {
DoSimpleCalDelta = 1;
} else if (*arg == 'p' || *arg == 'P') {
/* JSON interchange formats always include
file and line number info */
DoPrefixLineNo = 1;
if (PsCal == PSCAL_LEVEL1) {
PsCal = PSCAL_LEVEL2;
} else {
PsCal = PSCAL_LEVEL3;
}
}
arg++; arg++;
} }
PARSENUM(CalMonths, arg); PARSENUM(CalMonths, arg);
@@ -418,7 +465,10 @@ void InitRemind(int argc, char const *argv[])
case 'W': case 'W':
if (*arg != ',') { if (*arg != ',') {
PARSENUM(CalWidth, arg); PARSENUM(CalWidth, arg);
if (CalWidth < 71) CalWidth = 71; if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
if (CalWidth == 0) {
CalWidth = -1;
}
} }
if (*arg == ',') { if (*arg == ',') {
arg++; arg++;
@@ -607,6 +657,7 @@ void Usage(void)
fprintf(ErrFp, "Options:\n"); fprintf(ErrFp, "Options:\n");
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n"); fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
fprintf(ErrFp, " -r Disable RUN directives\n"); fprintf(ErrFp, " -r Disable RUN directives\n");
fprintf(ErrFp, " -@[n,m] Colorize COLOR reminders\n");
fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n"); fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n");
fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n"); fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n"); fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");

1045
src/json.c Normal file

File diff suppressed because it is too large Load Diff

280
src/json.h Normal file
View File

@@ -0,0 +1,280 @@
/* vim: set et ts=3 sw=3 sts=3 ft=c:
*
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
* https://github.com/udp/json-parser
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _JSON_H
#define _JSON_H
#ifndef json_char
#define json_char char
#endif
#ifndef json_int_t
#ifndef _MSC_VER
#include <inttypes.h>
#define json_int_t int64_t
#else
#define json_int_t __int64
#endif
#endif
#include <stdlib.h>
#ifdef __cplusplus
#include <string.h>
extern "C"
{
#endif
typedef struct
{
unsigned long max_memory;
int settings;
/* Custom allocator support (leave null to use malloc/free)
*/
void * (* mem_alloc) (size_t, int zero, void * user_data);
void (* mem_free) (void *, void * user_data);
void * user_data; /* will be passed to mem_alloc and mem_free */
size_t value_extra; /* how much extra space to allocate for values? */
} json_settings;
#define json_enable_comments 0x01
typedef enum
{
json_none,
json_object,
json_array,
json_integer,
json_double,
json_string,
json_boolean,
json_null
} json_type;
extern const struct _json_value json_value_none;
typedef struct _json_object_entry
{
json_char * name;
unsigned int name_length;
struct _json_value * value;
} json_object_entry;
typedef struct _json_value
{
struct _json_value * parent;
json_type type;
union
{
int boolean;
json_int_t integer;
double dbl;
struct
{
unsigned int length;
json_char * ptr; /* null terminated */
} string;
struct
{
unsigned int length;
json_object_entry * values;
#if defined(__cplusplus) && __cplusplus >= 201103L
decltype(values) begin () const
{ return values;
}
decltype(values) end () const
{ return values + length;
}
#endif
} object;
struct
{
unsigned int length;
struct _json_value ** values;
#if defined(__cplusplus) && __cplusplus >= 201103L
decltype(values) begin () const
{ return values;
}
decltype(values) end () const
{ return values + length;
}
#endif
} array;
} u;
union
{
struct _json_value * next_alloc;
void * object_mem;
} _reserved;
#ifdef JSON_TRACK_SOURCE
/* Location of the value in the source JSON
*/
unsigned int line, col;
#endif
/* Some C++ operator sugar */
#ifdef __cplusplus
public:
inline _json_value ()
{ memset (this, 0, sizeof (_json_value));
}
inline const struct _json_value &operator [] (int index) const
{
if (type != json_array || index < 0
|| ((unsigned int) index) >= u.array.length)
{
return json_value_none;
}
return *u.array.values [index];
}
inline const struct _json_value &operator [] (const char * index) const
{
if (type != json_object)
return json_value_none;
for (unsigned int i = 0; i < u.object.length; ++ i)
if (!strcmp (u.object.values [i].name, index))
return *u.object.values [i].value;
return json_value_none;
}
inline operator const char * () const
{
switch (type)
{
case json_string:
return u.string.ptr;
default:
return "";
};
}
inline operator json_int_t () const
{
switch (type)
{
case json_integer:
return u.integer;
case json_double:
return (json_int_t) u.dbl;
default:
return 0;
};
}
inline operator bool () const
{
if (type != json_boolean)
return false;
return u.boolean != 0;
}
inline operator double () const
{
switch (type)
{
case json_integer:
return (double) u.integer;
case json_double:
return u.dbl;
default:
return 0;
};
}
#endif
} json_value;
json_value * json_parse (const json_char * json,
size_t length);
#define json_error_max 128
json_value * json_parse_ex (json_settings * settings,
const json_char * json,
size_t length,
char * error);
void json_value_free (json_value *);
/* Not usually necessary, unless you used a custom mem_alloc and now want to
* use a custom mem_free.
*/
void json_value_free_ex (json_settings * settings,
json_value *);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@@ -127,11 +127,7 @@ int main(int argc, char *argv[])
} }
} }
if (Iterations) { if (Iterations) {
ClearGlobalOmits(); PerIterationInit();
DestroyOmitContexts();
DestroyVars(0);
NumTriggered = 0;
ClearLastTriggers();
JulianToday++; JulianToday++;
} }
} }
@@ -149,6 +145,19 @@ void PurgeEchoLine(char const *fmt, ...)
} }
void
PerIterationInit(void)
{
ClearGlobalOmits();
DestroyOmitContexts();
DestroyVars(0);
DefaultColorR = -1;
DefaultColorG = -1;
DefaultColorB = -1;
NumTriggered = 0;
ClearLastTriggers();
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* DoReminders */ /* DoReminders */
@@ -804,9 +813,11 @@ int DoIfTrig(ParsePtr p)
if (trig.typ != NO_TYPE) return E_PARSE_ERR; if (trig.typ != NO_TYPE) return E_PARSE_ERR;
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1); jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) { if (r) {
if (!Hush || r != E_RUN_DISABLED) { if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
Eprint("%s", ErrMsg[r]); if (!Hush || r != E_RUN_DISABLED) {
} Eprint("%s", ErrMsg[r]);
}
}
syndrome = IF_TRUE | BEFORE_ELSE; syndrome = IF_TRUE | BEFORE_ELSE;
} }
else { else {
@@ -1361,6 +1372,16 @@ ClearLastTriggers(void)
LastTimeTrig.duration = NO_TIME; LastTimeTrig.duration = NO_TIME;
} }
void
SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid)
{
SaveLastTrigger(t);
SaveLastTimeTrig(tt);
LastTriggerDate = trigdate;
LastTriggerTime = trigtime;
LastTrigValid = valid;
}
void void
SaveLastTrigger(Trigger const *t) SaveLastTrigger(Trigger const *t)
{ {
@@ -1373,3 +1394,14 @@ SaveLastTimeTrig(TimeTrig const *t)
{ {
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig)); memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
} }
/* Wrapper to ignore warnings about ignoring return value of system() */
void
System(char const *cmd)
{
int r;
r = system(cmd);
if (r == 0) {
r = 1;
}
}

View File

@@ -37,6 +37,7 @@ 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 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 DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim);
int ParseLiteralDate (char const **s, int *jul, int *tim); int ParseLiteralDate (char const **s, int *jul, int *tim);
int ParseLiteralTime (char const **s, int *tim);
int EvalExpr (char const **e, Value *v, ParsePtr p); int EvalExpr (char const **e, Value *v, ParsePtr p);
int DoCoerce (char type, Value *v); int DoCoerce (char type, Value *v);
void PrintValue (Value *v, FILE *fp); void PrintValue (Value *v, FILE *fp);
@@ -89,7 +90,7 @@ char const *FindInitialToken (Token *tok, char const *s);
void FindToken (char const *s, Token *tok); void FindToken (char const *s, Token *tok);
void FindNumericToken (char const *s, Token *t); void FindNumericToken (char const *s, Token *t);
int ComputeTrigger (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals); int ComputeTrigger (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals);
int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals); int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals, int duration_days);
int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals); int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals);
int ComputeScanStart(int today, Trigger *trig, TimeTrig *tt); int ComputeScanStart(int today, Trigger *trig, TimeTrig *tt);
char *StrnCpy (char *dest, char const *source, int n); char *StrnCpy (char *dest, char const *source, int n);
@@ -148,3 +149,15 @@ char const *SynthesizeTag(void);
void ClearLastTriggers(void); void ClearLastTriggers(void);
void SaveLastTrigger(Trigger const *t); void SaveLastTrigger(Trigger const *t);
void SaveLastTimeTrig(TimeTrig const *t); void SaveLastTimeTrig(TimeTrig const *t);
void SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid);
void PerIterationInit(void);
char const *Decolorize(int r, int g, int b);
char const *Colorize(int r, int g, int b);
void PrintJSONString(char const *s);
void PrintJSONKeyPairInt(char const *name, int val);
void PrintJSONKeyPairString(char const *name, char const *val);
void PrintJSONKeyPairDate(char const *name, int jul);
void PrintJSONKeyPairDateTime(char const *name, int dt);
void PrintJSONKeyPairTime(char const *name, int t);
void System(char const *cmd);

View File

@@ -246,11 +246,7 @@ void HandleQueuedReminders(void)
/* Set up global variables so some functions like trigdate() /* Set up global variables so some functions like trigdate()
and trigtime() work correctly */ and trigtime() work correctly */
LastTriggerDate = JulianToday; SaveAllTriggerInfo(&(q->t), &(q->tt), JulianToday, q->tt.ttime, 1);
LastTriggerTime = q->tt.ttime;
LastTrigValid = 1;
SaveLastTrigger(&(q->t));
SaveLastTimeTrig(&(q->tt));
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday); (void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
if (Daemon < 0) { if (Daemon < 0) {
printf("NOTE endreminder\n"); printf("NOTE endreminder\n");
@@ -452,6 +448,70 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
} }
} }
/* Dump the queue in JSON format */
static void
json_queue(QueuedRem const *q)
{
int done = 0;
printf("[");
while(q) {
if (q->tt.nexttime == NO_TIME) {
q = q->next;
continue;
}
if (done) {
printf(",");
}
done = 1;
printf("{");
switch(q->typ) {
case NO_TYPE: PrintJSONKeyPairString("type", "NO_TYPE"); break;
case MSG_TYPE: PrintJSONKeyPairString("type", "MSG_TYPE"); break;
case RUN_TYPE: PrintJSONKeyPairString("type", "RUN_TYPE"); break;
case CAL_TYPE: PrintJSONKeyPairString("type", "CAL_TYPE"); break;
case SAT_TYPE: PrintJSONKeyPairString("type", "SAT_TYPE"); break;
case PS_TYPE: PrintJSONKeyPairString("type", "PS_TYPE"); break;
case PSF_TYPE: PrintJSONKeyPairString("type", "PSF_TYPE"); break;
case MSF_TYPE: PrintJSONKeyPairString("type", "MSF_TYPE"); break;
case PASSTHRU_TYPE: PrintJSONKeyPairString("type", "PASSTHRU_TYPE"); break;
default: PrintJSONKeyPairString("type", "?"); break;
}
PrintJSONKeyPairInt("rundisabled", q->RunDisabled);
PrintJSONKeyPairInt("ntrig", q->ntrig);
PrintJSONKeyPairTime("ttime", q->tt.ttime);
PrintJSONKeyPairTime("nextttime", q->tt.nexttime);
PrintJSONKeyPairInt("delta", q->tt.delta);
if (q->tt.rep != NO_TIME) {
PrintJSONKeyPairInt("rep", q->tt.rep);
}
if (q->tt.duration != NO_TIME) {
PrintJSONKeyPairInt("duration", q->tt.duration);
}
if (q->passthru[0]) {
PrintJSONKeyPairString("passthru", q->passthru);
}
if (q->sched[0]) {
PrintJSONKeyPairString("sched", q->sched);
}
if (DBufLen(&(q->tags))) {
PrintJSONKeyPairString("tags", DBufValue(&(q->tags)));
}
/* Last one is a special case - no trailing comma */
printf("\"");
PrintJSONString("body");
printf("\":\"");
if (q->text) {
PrintJSONString(q->text);
} else {
PrintJSONString("");
}
printf("\"}");
q = q->next;
}
printf("]\n");
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* DaemonWait */ /* DaemonWait */
@@ -536,6 +596,11 @@ static void DaemonWait(unsigned int sleeptime)
} }
printf("NOTE endqueue\n"); printf("NOTE endqueue\n");
fflush(stdout); fflush(stdout);
} else if (!strcmp(cmdLine, "JSONQUEUE\n")) {
printf("NOTE JSONQUEUE\n");
json_queue(QueueHead);
printf("NOTE ENDJSONQUEUE\n");
fflush(stdout);
} else if (!strcmp(cmdLine, "REREAD\n")) { } else if (!strcmp(cmdLine, "REREAD\n")) {
printf("NOTE reread\n"); printf("NOTE reread\n");
fflush(stdout); fflush(stdout);

View File

@@ -20,6 +20,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include "rem2ps.h" #include "rem2ps.h"
#include "json.h"
#define NEW(type) (malloc(sizeof(type))) #define NEW(type) (malloc(sizeof(type)))
@@ -30,6 +31,7 @@
#define SPECIAL_COLOR 4 #define SPECIAL_COLOR 4
#define SPECIAL_WEEK 5 #define SPECIAL_WEEK 5
#define SPECIAL_SHADE 6 #define SPECIAL_SHADE 6
#define SPECIAL_UNKNOWN 7
/* Array holding how specials sort */ /* Array holding how specials sort */
static int SpecialSortOrder[] = { static int SpecialSortOrder[] = {
@@ -46,6 +48,7 @@ typedef struct calentry {
struct calentry *next; struct calentry *next;
int special; int special;
char *entry; char *entry;
int daynum;
} CalEntry; } CalEntry;
typedef struct { typedef struct {
@@ -137,6 +140,172 @@ void WriteOneEntry (CalEntry *c);
void GetSmallLocations (void); void GetSmallLocations (void);
char const *EatToken(char const *in, char *out, int maxlen); char const *EatToken(char const *in, char *out, int maxlen);
/***************************************************************/
/* */
/* StrCmpi */
/* */
/* Compare strings, case insensitive. */
/* */
/***************************************************************/
int StrCmpi(char const *s1, char const *s2)
{
int r;
while (*s1 && *s2) {
r = toupper(*s1) - toupper(*s2);
if (r) return r;
s1++;
s2++;
}
return toupper(*s1) - toupper(*s2);
}
/***************************************************************/
/* */
/* Parse the new-style JSON intermediate format */
/* */
/***************************************************************/
static CalEntry *
JSONToCalEntry(DynamicBuffer *buf)
{
CalEntry *c;
json_value *val;
val = json_parse(DBufValue(buf), DBufLen(buf));
if (!val) {
fprintf(stderr, "Unable to parse JSON line `%s'\n", DBufValue(buf));
exit(1);
}
if (val->type != json_object) {
fprintf(stderr, "Expecting JSON object; found `%s'\n",
DBufValue(buf));
exit(1);
}
c = NEW(CalEntry);
if (!c) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
c->next = NULL;
c->special = SPECIAL_NORMAL;
int got_date = 0, got_body = 0;
size_t i;
for (i=0; i<val->u.object.length; i++) {
char const *nm = val->u.object.values[i].name;
json_value *v = val->u.object.values[i].value;
char const *s;
if (!strcmp(nm, "date")) {
if (v->type == json_string) {
s = v->u.string.ptr;
c->daynum = (s[8] - '0') * 10 + s[9] - '0';
got_date = 1;
}
} else if (!strcmp(nm, "body")) {
if (v->type == json_string) {
s = v->u.string.ptr;
c->entry = malloc(strlen(s)+1);
if (!c->entry) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
strcpy(c->entry, s);
got_body = 1;
}
} else if (!strcmp(nm, "passthru")) {
if (v->type == json_string) {
s = v->u.string.ptr;
if (!StrCmpi(s, "PostScript")) {
c->special = SPECIAL_POSTSCRIPT;
} else if (!StrCmpi(s, "SHADE")) {
c->special = SPECIAL_SHADE;
} else if (!StrCmpi(s, "MOON")) {
c->special = SPECIAL_MOON;
} else if (!StrCmpi(s, "WEEK")) {
c->special = SPECIAL_WEEK;
} else if (!StrCmpi(s, "PSFile")) {
c->special = SPECIAL_PSFILE;
} else if (!StrCmpi(s, "COLOUR") ||
!StrCmpi(s, "COLOR")) {
c->special = SPECIAL_COLOR;
} else {
c->special = SPECIAL_UNKNOWN;
}
}
}
}
json_value_free(val);
if (!got_body || !got_date) {
fprintf(stderr, "Could not parse line `%s'\n", DBufValue(buf));
exit(1);
}
return c;
}
/***************************************************************/
/* */
/* Parse the old-style REM2PS intermediate format */
/* */
/***************************************************************/
static CalEntry *
TextToCalEntry(DynamicBuffer *buf)
{
char const *startOfBody;
char passthru[PASSTHRU_LEN+1];
CalEntry *c = NEW(CalEntry);
if (!c) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
c->next = NULL;
c->special = SPECIAL_NORMAL;
c->daynum = (DBufValue(buf)[8] - '0') * 10 + DBufValue(buf)[9] - '0';
/* Skip the tag, duration and time */
startOfBody = DBufValue(buf)+10;
/* Eat the passthru */
startOfBody = EatToken(startOfBody, passthru, PASSTHRU_LEN);
/* Eat the tag */
startOfBody = EatToken(startOfBody, NULL, 0);
/* Eat the duration */
startOfBody = EatToken(startOfBody, NULL, 0);
/* Eat the time */
startOfBody = EatToken(startOfBody, NULL, 0);
c->entry = malloc(strlen(startOfBody) + 1);
if (!c->entry) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
strcpy(c->entry, startOfBody);
/* Save the type of SPECIAL */
if (!StrCmpi(passthru, "PostScript")) {
c->special = SPECIAL_POSTSCRIPT;
} else if (!StrCmpi(passthru, "SHADE")) {
c->special = SPECIAL_SHADE;
} else if (!StrCmpi(passthru, "MOON")) {
c->special = SPECIAL_MOON;
} else if (!StrCmpi(passthru, "WEEK")) {
c->special = SPECIAL_WEEK;
} else if (!StrCmpi(passthru, "PSFile")) {
c->special = SPECIAL_PSFILE;
} else if (!StrCmpi(passthru, "COLOUR") ||
!StrCmpi(passthru, "COLOR")) {
c->special = SPECIAL_COLOR;
} else if (StrCmpi(passthru, "*")) {
c->special = SPECIAL_UNKNOWN;
}
return c;
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* MAIN PROGRAM */ /* MAIN PROGRAM */
@@ -154,10 +323,17 @@ int main(int argc, char *argv[])
Usage("Input should not come from a terminal"); Usage("Input should not come from a terminal");
} }
int first_line = 1;
/* Search for a valid input file */ /* Search for a valid input file */
while (!feof(stdin)) { while (!feof(stdin)) {
DBufGets(&buf, stdin); DBufGets(&buf, stdin);
if (!strcmp(DBufValue(&buf), PSBEGIN)) { if (first_line && (!strcmp(DBufValue(&buf), "["))) {
fprintf(stderr, "Rem2PS: It appears that you have invoked Remind with the -ppp option.\n Please use either -p or -pp, but not -ppp.\n");
exit(1);
}
first_line = 0;
if (!strcmp(DBufValue(&buf), PSBEGIN) ||
!strcmp(DBufValue(&buf), PSBEGIN2)) {
if (!validfile) { if (!validfile) {
if (Verbose) { if (Verbose) {
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2020 by Dianne Skoll\n\n", VERSION); fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2020 by Dianne Skoll\n\n", VERSION);
@@ -191,10 +367,7 @@ void DoPsCal(void)
int days, wkday, prevdays, nextdays; int days, wkday, prevdays, nextdays;
int sfirst; int sfirst;
int i; int i;
int is_ps;
int firstcol; int firstcol;
char const *startOfBody;
char passthru[PASSTHRU_LEN+1];
DynamicBuffer buf; DynamicBuffer buf;
CalEntry *c, *d, *p; CalEntry *c, *d, *p;
@@ -230,6 +403,7 @@ void DoPsCal(void)
printf("%%%%Page: %c%c%c%c%c %d\n", month[0], month[1], month[2], printf("%%%%Page: %c%c%c%c%c %d\n", month[0], month[1], month[2],
year[2], year[3], validfile); year[2], year[3], validfile);
printf("%%%%PageBoundingBox: 0 0 %d %d\n", CurPage->xsize, CurPage->ysize);
/* Emit PostScript to do the heading */ /* Emit PostScript to do the heading */
if (!PortraitMode) printf("90 rotate 0 XSIZE neg translate\n"); if (!PortraitMode) printf("90 rotate 0 XSIZE neg translate\n");
@@ -272,80 +446,48 @@ void DoPsCal(void)
} }
DBufGets(&buf, stdin); DBufGets(&buf, stdin);
if (!strcmp(DBufValue(&buf), PSEND)) { if (!strcmp(DBufValue(&buf), PSEND) ||
!strcmp(DBufValue(&buf), PSEND2)) {
DBufFree(&buf); DBufFree(&buf);
break; break;
} }
/* Ignore lines beginning with '#' */ /* Ignore lines beginning with '#' */
if (DBufValue(&buf)[0] == '#') { if (DBufValue(&buf)[0] == '#') {
DBufFree(&buf);
continue; continue;
} }
/* Read the day number - a bit of a hack! */
DayNum = (DBufValue(&buf)[8] - '0') * 10 + DBufValue(&buf)[9] - '0'; if (DBufValue(&buf)[0] == '{') {
if (DayNum != CurDay) { /* Starts with '{', so assume new-style JSON format */
for(; CurDay<DayNum; CurDay++) { c = JSONToCalEntry(&buf);
} else {
/* Assume it's the old-style rem2ps intermediate format */
c = TextToCalEntry(&buf);
}
/* If it's an unknown special, ignore */
if (c->special == SPECIAL_UNKNOWN) {
DBufFree(&buf);
free(c);
c = NULL;
continue;
}
if (c->daynum != CurDay) {
for(; CurDay<c->daynum; CurDay++) {
WriteCalEntry(); WriteCalEntry();
WkDayNum = (WkDayNum + 1) % 7; WkDayNum = (WkDayNum + 1) % 7;
} }
} }
/* Add the text */ if (c->special == SPECIAL_POSTSCRIPT ||
c = NEW(CalEntry); c->special == SPECIAL_SHADE ||
if (!c) { c->special == SPECIAL_MOON ||
fprintf(stderr, "malloc failed - aborting.\n"); c->special == SPECIAL_WEEK ||
exit(1); c->special == SPECIAL_PSFILE) {
} if (!PsEntries[c->daynum]) {
c->next = NULL; PsEntries[c->daynum] = c;
c->special = SPECIAL_NORMAL;
/* Skip the tag, duration and time */
startOfBody = DBufValue(&buf)+10;
/* Eat the passthru */
startOfBody = EatToken(startOfBody, passthru, PASSTHRU_LEN);
/* Eat the tag */
startOfBody = EatToken(startOfBody, NULL, 0);
/* Eat the duration */
startOfBody = EatToken(startOfBody, NULL, 0);
/* Eat the time */
startOfBody = EatToken(startOfBody, NULL, 0);
is_ps = 0;
if (!strcmp(passthru, "PostScript") ||
!strcmp(passthru, "PSFile") ||
!strcmp(passthru, "MOON") ||
!strcmp(passthru, "WEEK") ||
!strcmp(passthru, "SHADE")) {
is_ps = 1;
}
c->entry = malloc(strlen(startOfBody) + 1);
if (!c->entry) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
strcpy(c->entry, startOfBody);
if (is_ps) {
/* Save the type of SPECIAL */
if (!strcmp(passthru, "PostScript")) {
c->special = SPECIAL_POSTSCRIPT;
} else if (!strcmp(passthru, "SHADE")) {
c->special = SPECIAL_SHADE;
} else if (!strcmp(passthru, "MOON")) {
c->special = SPECIAL_MOON;
} else if (!strcmp(passthru, "WEEK")) {
c->special = SPECIAL_WEEK;
} else { } else {
c->special = SPECIAL_PSFILE; d = PsEntries[c->daynum];
}
if (!PsEntries[DayNum]) {
PsEntries[DayNum] = c;
} else {
d = PsEntries[DayNum];
p = NULL; p = NULL;
/* Slot it into the right place */ /* Slot it into the right place */
while (d->next && (SpecialSortOrder[c->special] <= SpecialSortOrder[d->special])) { while (d->next && (SpecialSortOrder[c->special] <= SpecialSortOrder[d->special])) {
@@ -359,14 +501,12 @@ void DoPsCal(void)
if (p) { if (p) {
p->next = c; p->next = c;
} else { } else {
PsEntries[DayNum] = c; PsEntries[c->daynum] = c;
} }
c->next = d; c->next = d;
} }
} }
} else if (!strcmp(passthru, "*") || } else {
!strcmp(passthru, "COLOUR") ||
!strcmp(passthru, "COLOR")) {
/* Put on linked list */ /* Put on linked list */
if (!CurEntries) { if (!CurEntries) {
CurEntries = c; CurEntries = c;
@@ -375,10 +515,6 @@ void DoPsCal(void)
while(d->next) d = d->next; while(d->next) d = d->next;
d->next = c; d->next = c;
} }
if (!strcmp(passthru, "COLOR") ||
!strcmp(passthru, "COLOUR")) {
c->special = SPECIAL_COLOR;
}
} }
} }
for(; CurDay<=days; CurDay++) { for(; CurDay<=days; CurDay++) {

View File

@@ -150,7 +150,7 @@ void IssueSortedReminders(void)
break; break;
case RUN_TYPE: case RUN_TYPE:
system(cur->text); System(cur->text);
break; break;
} }

View File

@@ -67,6 +67,7 @@ Token TokArray[] = {
{ "june", 3, T_Month, 5 }, { "june", 3, T_Month, 5 },
{ "march", 3, T_Month, 2 }, { "march", 3, T_Month, 2 },
{ "may", 3, T_Month, 4 }, { "may", 3, T_Month, 4 },
{ "maybe-uncomputable", 5, T_MaybeUncomputable, 0},
{ "monday", 3, T_WkDay, 0 }, { "monday", 3, T_WkDay, 0 },
{ "msf", 3, T_RemType, MSF_TYPE }, { "msf", 3, T_RemType, MSF_TYPE },
{ "msg", 3, T_RemType, MSG_TYPE }, { "msg", 3, T_RemType, MSG_TYPE },
@@ -257,6 +258,7 @@ void FindNumericToken(char const *s, Token *t)
{ {
int mult = 1, hour, min; int mult = 1, hour, min;
char const *s_orig = s; char const *s_orig = s;
int ampm = 0;
t->type = T_Illegal; t->type = T_Illegal;
t->val = 0; t->val = 0;
@@ -284,10 +286,6 @@ void FindNumericToken(char const *s, Token *t)
like Jan 6, 1998 */ like Jan 6, 1998 */
if (*s == ',') { if (*s == ',') {
s++; s++;
/* Special hack - convert years between 90 and
99 to 1990 and 1999 */
if (t->val >= 90 && t->val <= 99) t->val += 1900;
/* Classify the number we've got */ /* Classify the number we've got */
if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year; if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
else if (t->val >= 1 && t->val <= 31) t->type = T_Day; else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
@@ -299,7 +297,29 @@ void FindNumericToken(char const *s, Token *t)
s++; s++;
hour = t->val; hour = t->val;
PARSENUM(min, s); PARSENUM(min, s);
if (*s || min > 59) return; /* Illegal time */ if (min > 59) return; /* Illegal time */
/* Check for p[m] or a[m] */
if (*s == 'A' || *s == 'a' || *s == 'P' || *s == 'p') {
ampm = tolower(*s);
s++;
if (*s == 'm' || *s == 'M') {
s++;
}
}
if (*s) return; /* Illegal time */
if (ampm) {
if (hour < 1 || hour > 12) return;
if (ampm == 'a') {
if (hour == 12) {
hour = 0;
}
} else if (ampm == 'p') {
if (hour < 12) {
hour += 12;
}
}
}
t->val = hour*60 + min; /* Convert to minutes past midnight */ t->val = hour*60 + min; /* Convert to minutes past midnight */
if (hour <= 23) { if (hour <= 23) {
t->type = T_Time; t->type = T_Time;

View File

@@ -454,11 +454,7 @@ AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int sav
} }
if (save_in_globals) { if (save_in_globals) {
LastTriggerTime = tim->ttime; SaveAllTriggerInfo(trig, tim, r, tim->ttime, 1);
SaveLastTimeTrig(tim);
SaveLastTrigger(trig);
LastTriggerDate = r;
LastTrigValid = 1;
} }
return r; return r;
} }
@@ -474,10 +470,29 @@ AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int sav
int ComputeTrigger(int today, Trigger *trig, TimeTrig *tim, int ComputeTrigger(int today, Trigger *trig, TimeTrig *tim,
int *err, int save_in_globals) int *err, int save_in_globals)
{ {
int r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals); int r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals, 0);
if (*err != OK) { if (*err != OK) {
return r; return r;
} }
if (r == today) {
if (tim->ttime != NO_TIME) {
trig->eventstart = MINUTES_PER_DAY * r + tim->ttime;
if (tim->duration != NO_TIME) {
trig->eventduration = tim->duration;
}
}
if (save_in_globals) {
SaveAllTriggerInfo(trig, tim, r, tim->ttime, 1);
}
return r;
}
if (trig->duration_days) {
r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals, trig->duration_days);
if (*err != OK) {
return r;
}
}
r = AdjustTriggerForDuration(today, r, trig, tim, save_in_globals); r = AdjustTriggerForDuration(today, r, trig, tim, save_in_globals);
return r; return r;
} }
@@ -491,10 +506,10 @@ int ComputeTrigger(int today, Trigger *trig, TimeTrig *tim,
/* */ /* */
/***************************************************************/ /***************************************************************/
int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim, int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
int *err, int save_in_globals) int *err, int save_in_globals, int duration_days)
{ {
int nattempts = 0, int nattempts = 0,
start = today - trig->duration_days, start = today - duration_days,
nextstart = 0, nextstart = 0,
y, m, d, omit, y, m, d, omit,
result; result;
@@ -561,7 +576,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
} }
/** FIXME: Fix bad interaction with SATISFY... need to rethink!!! */ /** FIXME: Fix bad interaction with SATISFY... need to rethink!!! */
if (result+trig->duration_days >= today && if (result+duration_days >= today &&
(trig->skip != SKIP_SKIP || !omit)) { (trig->skip != SKIP_SKIP || !omit)) {
if (save_in_globals) { if (save_in_globals) {
LastTriggerDate = result; /* Save in global var */ LastTriggerDate = result; /* Save in global var */

View File

@@ -73,6 +73,7 @@ typedef struct {
int duration_days; /* Duration converted to days to search */ int duration_days; /* Duration converted to days to search */
int eventstart; /* Original event start (datetime) */ int eventstart; /* Original event start (datetime) */
int eventduration; /* Original event duration (minutes) */ int eventduration; /* Original event duration (minutes) */
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
char sched[VAR_NAME_LEN+1]; /* Scheduling function */ char sched[VAR_NAME_LEN+1]; /* Scheduling function */
char warn[VAR_NAME_LEN+1]; /* Warning function */ char warn[VAR_NAME_LEN+1]; /* Warning function */
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */ char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
@@ -171,7 +172,8 @@ enum TokTypes
T_Duration, T_Duration,
T_LongTime, T_LongTime,
T_OmitFunc, T_OmitFunc,
T_Through T_Through,
T_MaybeUncomputable
}; };
/* The structure of a token */ /* The structure of a token */
@@ -216,3 +218,18 @@ typedef struct {
/* Flags for FROM / SCANFROM */ /* Flags for FROM / SCANFROM */
#define SCANFROM_TYPE 0 #define SCANFROM_TYPE 0
#define FROM_TYPE 1 #define FROM_TYPE 1
/* PS Calendar levels */
/* Original interchange format */
#define PSCAL_LEVEL1 1
/* Line-by-line JSON */
#define PSCAL_LEVEL2 2
/* Pure JSON */
#define PSCAL_LEVEL3 3
#define TERMINAL_BACKGROUND_UNKNOWN 0
#define TERMINAL_BACKGROUND_DARK 1
#define TERMINAL_BACKGROUND_LIGHT 2

View File

@@ -168,6 +168,45 @@ static int datetime_sep_func(int do_set, Value *val)
return OK; return OK;
} }
static int default_color_func(int do_set, Value *val)
{
int col_r, col_g, col_b;
if (!do_set) {
/* 12 = strlen("255 255 255\0") */
val->v.str = malloc(12);
if (!val->v.str) return E_NO_MEM;
snprintf(val->v.str, 12, "%d %d %d",
DefaultColorR,
DefaultColorG,
DefaultColorB
);
val->type = STR_TYPE;
return OK;
}
if (val->type != STR_TYPE) return E_BAD_TYPE;
if (sscanf(val->v.str, "%d %d %d", &col_r, &col_g, &col_b) != 3) {
return E_BAD_TYPE;
}
/* They either all have to be -1, or all between 0 and 255 */
if (col_r == -1 && col_g == -1 && col_b == -1) {
DefaultColorR = -1;
DefaultColorG = -1;
DefaultColorB = -1;
return OK;
}
if (col_r < 0) return E_2LOW;
if (col_r > 255) return E_2HIGH;
if (col_g < 0) return E_2LOW;
if (col_g > 255) return E_2HIGH;
if (col_b < 0) return E_2LOW;
if (col_b > 255) return E_2HIGH;
DefaultColorR = col_r;
DefaultColorG = col_g;
DefaultColorB = col_b;
return OK;
}
static int date_sep_func(int do_set, Value *val) static int date_sep_func(int do_set, Value *val)
{ {
if (!do_set) { if (!do_set) {
@@ -436,17 +475,17 @@ int DoDump(ParsePtr p)
DumpVarTable(); DumpVarTable();
return OK; return OK;
} }
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE); fprintf(ErrFp, "%s %s\n\n", VARIABLE, VALUE);
while(1) { while(1) {
if (*DBufValue(&buf) == '$') { if (*DBufValue(&buf) == '$') {
DumpSysVarByName(DBufValue(&buf)+1); DumpSysVarByName(DBufValue(&buf)+1);
} else { } else {
v = FindVar(DBufValue(&buf), 0); v = FindVar(DBufValue(&buf), 0);
DBufValue(&buf)[VAR_NAME_LEN] = 0; DBufValue(&buf)[VAR_NAME_LEN] = 0;
if (!v) fprintf(ErrFp, "%*s %s\n", VAR_NAME_LEN, if (!v) fprintf(ErrFp, "%s %s\n",
DBufValue(&buf), UNDEF); DBufValue(&buf), UNDEF);
else { else {
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name); fprintf(ErrFp, "%s ", v->name);
PrintValue(&(v->v), ErrFp); PrintValue(&(v->v), ErrFp);
fprintf(ErrFp, "\n"); fprintf(ErrFp, "\n");
} }
@@ -474,12 +513,12 @@ void DumpVarTable(void)
register Var *v; register Var *v;
register int i; register int i;
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE); fprintf(ErrFp, "%s %s\n\n", VARIABLE, VALUE);
for (i=0; i<VAR_HASH_SIZE; i++) { for (i=0; i<VAR_HASH_SIZE; i++) {
v = VHashTbl[i]; v = VHashTbl[i];
while(v) { while(v) {
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name); fprintf(ErrFp, "%s ", v->name);
PrintValue(&(v->v), ErrFp); PrintValue(&(v->v), ErrFp);
fprintf(ErrFp, "\n"); fprintf(ErrFp, "\n");
v = v->next; v = v->next;
@@ -608,6 +647,7 @@ static SysVar SysVarArr[] = {
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0 }, {"Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 }, {"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 }, {"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 },
{"DefaultColor", 1, SPECIAL_TYPE, default_color_func, 0, 0 },
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999}, {"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999},
{"DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0 }, {"DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0 },
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0 }, {"DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
@@ -617,7 +657,7 @@ static SysVar SysVarArr[] = {
{"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 }, {"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 },
{"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 }, {"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 },
{"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 }, {"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 },
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 132 }, {"FormWidth", 1, INT_TYPE, &FormWidth, 20, 500 },
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 }, {"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 }, {"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 }, {"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
@@ -795,7 +835,7 @@ static void DumpSysVar(char const *name, const SysVar *v)
return; return;
} }
if (name) strcat(buffer, name); else strcat(buffer, v->name); if (name) strcat(buffer, name); else strcat(buffer, v->name);
fprintf(ErrFp, "%*s ", VAR_NAME_LEN+1, buffer); fprintf(ErrFp, "%16s ", buffer);
if (v) { if (v) {
if (v->type == SPECIAL_TYPE) { if (v->type == SPECIAL_TYPE) {
Value val; Value val;

View File

@@ -28,3 +28,5 @@ REM Fri SPECIAL SHADE 255 204 204
REM Sat SPECIAL SHADE 204 255 204 REM Sat SPECIAL SHADE 204 255 204
REM Sun SPECIAL SHADE 204 204 255 REM Sun SPECIAL SHADE 204 204 255
# This should be ignored by rem2ps
REM SPECIAL HTML <b>FOO</b>

View File

@@ -79,6 +79,7 @@ rm -f ../tests/purge_dir/*.rem.purged >> ../tests/test.out 2>&1
../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1 ../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1
../src/remind -p ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1 ../src/remind -p ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
../src/remind -pp ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
# The sun tests can fail due to math roundoff error changing the times # The sun tests can fail due to math roundoff error changing the times
# by a minute... # by a minute...
@@ -99,7 +100,198 @@ REM 1 Jan 2012 AT 10:00 MSG 10am: Should show up
MSG [$DontTrigAts] MSG [$DontTrigAts]
EOF EOF
# An OMITFUNC should indicate nonconst_expr
../src/remind -pp - 1 jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
REM Mon OMITFUNC foo MSG bar
EOF
# Test default color
../src/remind -ppp - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
REM 2 MSG Normal
SET $DefaultColor "255 0 0"
REM 3 MSG Red
SET $DefaultColor "-1 -1 -1"
REM 4 MSG Normal
# Should give an error
SET $DefaultColor "256 0 0"
EOF
# Test -@ option
../src/remind -w,0,0 -@0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@0
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@0,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@0,0
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@0,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@0,1
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@1
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@1,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@1,0
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@1,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@1,1
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@2 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@2
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@2,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@2,0
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@2,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@2,1
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
export LC_ALL=en_US.utf-8
export LANG=en_US.utf-8
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
cmp -s ../tests/test.out ../tests/test.cmp cmp -s ../tests/test.out ../tests/test.cmp
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
echo "Remind: Acceptance test PASSED" echo "Remind: Acceptance test PASSED"

File diff suppressed because it is too large Load Diff

View File

@@ -337,7 +337,7 @@ set a103 trigtimedelta()
set a104 trigtimerep() set a104 trigtimerep()
set a105 trigduration() set a105 trigduration()
REM 2010-09-03 +3 -4 UNTIL 2012-01-01 PRIORITY 7 *14 AT 14:41 +15 *2 DURATION 3:33 MSG foo REM 2010-09-03 +3 -4 UNTIL 2012-01-01 PRIORITY 7 *14 AT 14:41 +15 *2 DURATION 213 MSG foo
set a106 trigback() set a106 trigback()
set a107 trigdelta() set a107 trigdelta()
set a108 trigrep() set a108 trigrep()
@@ -376,6 +376,14 @@ set a133 trigduration()
set a134 trigeventstart() set a134 trigeventstart()
set a135 trigeventduration() set a135 trigeventduration()
# These will issue errors
REM Mon OMIT Mon SKIP MSG Never ever ever...
REM Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
# These will just silently not trigger
REM MAYBE-UNCOMPUTABLE Mon OMIT Mon SKIP MSG Never ever ever...
REM MAYBE-UNCOMPUTABLE Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
dump dump
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OMIT 2010-09-03 THROUGH 2010-09-15 OMIT 2010-09-03 THROUGH 2010-09-15
@@ -386,6 +394,9 @@ OMIT DUMP
# Regression test for bugfix in Hebrew calendar Adar jahrzeit # Regression test for bugfix in Hebrew calendar Adar jahrzeit
[_i(14, "Adar", today(), 5761)] MSG Purim [_i(14, "Adar", today(), 5761)] MSG Purim
# Regression test for bug found by Larry Hynes
REM SATISFY [day(trigdate()-25) == 14] MSG Foo
# Check combo of SATISFY and long-duration events # Check combo of SATISFY and long-duration events
REM 14 SATISFY [$Tw == 4] MSG Thursday, the 14th REM 14 SATISFY [$Tw == 4] MSG Thursday, the 14th
REM 14 AT 16:00 DURATION 8:00 SATISFY [$Tw == 4] MSG Thursday, the 14th REM 14 AT 16:00 DURATION 8:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
@@ -397,6 +408,134 @@ REM 14 AT 16:00 DURATION 40:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
# This is now an error # This is now an error
REM DURATION 15:00 MSG Should fail... need AT if you have DURATION. REM DURATION 15:00 MSG Should fail... need AT if you have DURATION.
# Parsing of AM/PM times
REM AT 0:00am MSG foo 0a
REM AT 1:00AM MSG foo 1a
REM AT 2:00am MSG foo 2a
REM AT 3:00AM MSG foo 3a
REM AT 4:00am MSG foo 4a
REM AT 5:00AM MSG foo 5a
REM AT 6:00am MSG foo 6a
REM AT 7:00AM MSG foo 7a
REM AT 8:00am MSG foo 8a
REM AT 9:00AM MSG foo 9a
REM AT 10:00am MSG foo 10a
REM AT 11:00AM MSG foo 11a
REM AT 12:00am MSG foo 12a
REM AT 13:00AM MSG foo 13a
REM AT 0:00pm MSG foo 0p
REM AT 1:00PM MSG foo 1p
REM AT 2:00pm MSG foo 2p
REM AT 3:00PM MSG foo 3p
REM AT 4:00pm MSG foo 4p
REM AT 5:00PM MSG foo 5p
REM AT 6:00pm MSG foo 6p
REM AT 7:00PM MSG foo 7p
REM AT 8:00pm MSG foo 8p
REM AT 9:00PM MSG foo 9p
REM AT 10:00pm MSG foo 10p
REM AT 11:00PM MSG foo 11p
REM AT 12:00pm MSG foo 12p
REM AT 13:00PM MSG foo 13p
DEBUG +x
SET x 0:00am + 0
SET x 1:00AM + 0
SET x 2:00am + 0
SET x 3:00AM + 0
SET x 4:00am + 0
SET x 5:00AM + 0
SET x 6:00am + 0
SET x 7:00AM + 0
SET x 8:00am + 0
SET x 9:00AM + 0
SET x 10:00am + 0
SET x 11:00AM + 0
SET x 12:00am + 0
SET x 13:00AM + 0
SET x 0:00pm + 0
SET x 1:00PM + 0
SET x 2:00pm + 0
SET x 3:00PM + 0
SET x 4:00pm + 0
SET x 5:00PM + 0
SET x 6:00pm + 0
SET x 7:00PM + 0
SET x 8:00pm + 0
SET x 9:00PM + 0
SET x 10:00pm + 0
SET x 11:00PM + 0
SET x 12:00pm + 0
SET x 13:00PM + 0
SET x '2015-02-03@0:00am' + 0
SET x '2015-02-03@1:00AM' + 0
SET x '2015-02-03@2:00am' + 0
SET x '2015-02-03@3:00AM' + 0
SET x '2015-02-03@4:00am' + 0
SET x '2015-02-03@5:00AM' + 0
SET x '2015-02-03@6:00am' + 0
SET x '2015-02-03@7:00AM' + 0
SET x '2015-02-03@8:00am' + 0
SET x '2015-02-03@9:00AM' + 0
SET x '2015-02-03@10:00am' + 0
SET x '2015-02-03@11:00AM' + 0
SET x '2015-02-03@12:00am' + 0
SET x '2015-02-03@13:00AM' + 0
SET x '2015-02-03@0:00pm' + 0
SET x '2015-02-03@1:00PM' + 0
SET x '2015-02-03@2:00pm' + 0
SET x '2015-02-03@3:00PM' + 0
SET x '2015-02-03@4:00pm' + 0
SET x '2015-02-03@5:00PM' + 0
SET x '2015-02-03@6:00pm' + 0
SET x '2015-02-03@7:00PM' + 0
SET x '2015-02-03@8:00pm' + 0
SET x '2015-02-03@9:00PM' + 0
SET x '2015-02-03@10:00pm' + 0
SET x '2015-02-03@11:00PM' + 0
SET x '2015-02-03@12:00pm' + 0
SET x '2015-02-03@13:00PM' + 0
# Test the ampm function
set x ampm(0:12) + ""
set x ampm(1:12) + ""
set x ampm(2:12) + ""
set x ampm(3:12) + ""
set x ampm(4:12) + ""
set x ampm(5:12) + ""
set x ampm(6:12) + ""
set x ampm(7:12) + ""
set x ampm(8:12) + ""
set x ampm(9:12) + ""
set x ampm(10:12) + ""
set x ampm(11:12) + ""
set x ampm(12:12) + ""
set x ampm(13:12) + ""
set x ampm(14:12) + ""
set x ampm(15:12) + ""
set x ampm(16:12) + ""
set x ampm(17:12) + ""
set x ampm(18:12) + ""
set x ampm(19:12) + ""
set x ampm(20:12) + ""
set x ampm(21:12) + ""
set x ampm(22:12) + ""
set x ampm(23:12) + ""
# Coerce with am/pm
set x coerce("TIME", "12:45am")
set x coerce("TIME", "12:45")
set x coerce("TIME", "1:45pm")
set x coerce("DATETIME", "2020-05-05@12:45am")
set x coerce("DATETIME", "2020-05-05@12:45")
set x coerce("DATETIME", "2020-05-05@1:45pm")
# Don't want Remind to queue reminders
EXIT
__EOF__ __EOF__
REM This line should not even be seen REM This line should not even be seen
And you can put whatever you like here. And you can put whatever you like here.

4
tests/utf-8.rem Normal file
View File

@@ -0,0 +1,4 @@
MSG ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский
MSG עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית
Wed MSG With tabs and spaces

View File

@@ -69,6 +69,7 @@ install:
sed $(SEDSCRIPT) < moon.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/moon.rem sed $(SEDSCRIPT) < moon.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/moon.rem
sed $(SEDSCRIPT) < sunrise.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunrise.rem sed $(SEDSCRIPT) < sunrise.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
sed $(SEDSCRIPT) < sunset.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunset.rem sed $(SEDSCRIPT) < sunset.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunset.rem
cp blank.rem $(DESTDIR)$(SCRIPTDIR)/blank.rem
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
sed $(SEDSCRIPT2) < rem2html > $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX) sed $(SEDSCRIPT2) < rem2html > $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
@@ -76,6 +77,7 @@ install:
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunset.rem chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunset.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/blank.rem
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX) chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
chmod 755 $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX) chmod 755 $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)

View File

@@ -9,7 +9,7 @@ only tested it with Linux running NCSA's httpd and Apache's httpd, but
it should work on any UNIX web server. it should work on any UNIX web server.
To install it, you need the Remind package, available via ftp from To install it, you need the Remind package, available via ftp from
ftp://ftp.doe.carleton.ca/pub/remind-3.0. You should install Remind, https://dianne.skoll.ca/projects/remind/ You should install Remind,
setting the lattitude, longitude, location and time zone as appropriate setting the lattitude, longitude, location and time zone as appropriate
for your machine. for your machine.
@@ -38,12 +38,8 @@ where "what" is one of:
hebps -- get a PostScript calendar with Jewish holidays. hebps -- get a PostScript calendar with Jewish holidays.
hebhtml -- get an HTML version of the above (requires Perl.) hebhtml -- get an HTML version of the above (requires Perl.)
(Visit http://www.doe.carleton.ca/~dfs/ for previews.)
All of these links will be set up in a sample HTML document All of these links will be set up in a sample HTML document
called "calendar.html" and installed in the HTMLDIR you specified called "calendar.html" and installed in the HTMLDIR you specified
in the Makefile. in the Makefile.
4) Enjoy! 4) Enjoy!

5
www/blank.rem Normal file
View File

@@ -0,0 +1,5 @@
[moondate(0)] SPECIAL MOON 0
[moondate(1)] SPECIAL MOON 1
[moondate(2)] SPECIAL MOON 2
[moondate(3)] SPECIAL MOON 3
REM Monday SPECIAL WEEK (W[weekno()])

View File

@@ -7,5 +7,5 @@
echo "Content-type: application/postscript" echo "Content-type: application/postscript"
echo echo
$REMIND -p /dev/null | $REM2PS -e -c3 -l $REMIND -p $DIR/blank.rem | $REM2PS -e -c3 -l
exit 0 exit 0

View File

@@ -29,6 +29,8 @@ ENDIF
# # # #
########################################################################## ##########################################################################
SET n $NumTrig
# --- HERE ARE THE JEWISH HOLIDAYS --- # --- HERE ARE THE JEWISH HOLIDAYS ---
# Set the variable InIsrael to 1 if you live in Israel. Otherwise, # Set the variable InIsrael to 1 if you live in Israel. Otherwise,
# you get the Diaspora versions of Jewish holidays # you get the Diaspora versions of Jewish holidays
@@ -138,6 +140,10 @@ ENDIF
fset msgprefix(x) "" fset msgprefix(x) ""
IF $NumTrig > n
REM SPECIAL SHADE 224 224 255
ENDIF
# Counting the omer - do the whole spiel, i.e: # Counting the omer - do the whole spiel, i.e:
# "This is the xth day of the omer, being y weeks and z days of the omer." # "This is the xth day of the omer, being y weeks and z days of the omer."
# Nice Remind programming example here! # Nice Remind programming example here!
@@ -165,7 +171,7 @@ ELSE
[trigger(moondate(2))] SPECIAL MOON 2 [trigger(moondate(2))] SPECIAL MOON 2
[trigger(moondate(3))] SPECIAL MOON 3 [trigger(moondate(3))] SPECIAL MOON 3
REM PS Border Border moveto /DayFont findfont 10 scalefont setfont ([hebday(today())] [hebmon(today())]) show REM PS Border Border moveto /DayFont findfont 10 scalefont setfont ([hebday(today())] [hebmon(today())]) show
REM SPECIAL HTML <P><FONT SIZE=-1>[hebday(today())] [hebmon(today())]</FONT></P> REM SPECIAL HTML <P>[hebday(today())] [hebmon(today())]</P>
ENDIF ENDIF

View File

@@ -4,10 +4,11 @@ use strict;
use warnings; use warnings;
use Getopt::Long; use Getopt::Long;
use JSON::Any;
my %Options; my %Options;
my $rem2html_version = '2.0'; my $rem2html_version = '2.1';
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks, my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen); @Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
@@ -191,7 +192,7 @@ sub parse_input
my $found_data = 0; my $found_data = 0;
while(<STDIN>) { while(<STDIN>) {
chomp; chomp;
last if /^\# rem2ps begin$/; last if /^\# rem2ps2? begin$/;
} }
my $line; my $line;
@@ -228,13 +229,29 @@ sub parse_input
} }
while(<STDIN>) { while(<STDIN>) {
chomp; chomp;
last if /^\# rem2ps end$/; last if /^\# rem2ps2? end$/;
next if /^\#/; next if /^\#/;
next unless m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/; my ($y, $m, $d, $special, $tag, $duration, $time, $body);
my ($y, $m, $d, $special, $tag, $duration, $time, $body) = if (m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/) {
($1, $2, $3, $4, $5, $6, $7, $8); ($y, $m, $d, $special, $tag, $duration, $time, $body) =
($1, $2, $3, $4, $5, $6, $7, $8);
} elsif (/\{/) {
my $obj = JSON::Any->jsonToObj($_);
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
$y = $1;
$m = $2;
$d = $3;
$special = $obj->{passthru} || '*';
$tag = $obj->{tags} || '*';
$duration = $obj->{duration} || '*';
$time = $obj->{time} || '*';
$body = $obj->{body};
} else {
next;
}
my $d1 = $d; my $d1 = $d;
$d1 =~ s/^0+//; $d1 =~ s/^0+//;
$special = uc($special);
if ($special eq 'HTML') { if ($special eq 'HTML') {
push(@{$days->[$d]}, $body); push(@{$days->[$d]}, $body);
} elsif ($special eq 'HTMLCLASS') { } elsif ($special eq 'HTMLCLASS') {