Compare commits

...

97 Commits

Author SHA1 Message Date
Dianne Skoll
5258e98f54 Add translations for various astronomical events in German localization, courtesy of Gunther Reißig. 2022-10-12 08:39:02 -04:00
Dianne Skoll
af9d42721c Separate Sun from Moon output. 2022-10-11 15:44:19 -04:00
Dianne Skoll
8ed43f5c3e Update WHATSNEW 2022-10-11 14:19:32 -04:00
Dianne Skoll
ec02a87c2b Fix some bugs in US holidays. 2022-10-11 14:19:00 -04:00
Dianne Skoll
6c2ec04d40 Visual tweaks. 2022-10-11 13:57:00 -04:00
Dianne Skoll
9f91cdf0b9 Update WHATSNEW. 2022-10-11 13:23:55 -04:00
Dianne Skoll
8ada68ce54 Add the "columns(str)" variant. 2022-10-11 13:18:44 -04:00
Dianne Skoll
d7975634af Update WHATSNEW 2022-10-11 11:56:41 -04:00
Dianne Skoll
87be68fecf Document rows() and columns() 2022-10-11 11:54:52 -04:00
Dianne Skoll
b42d5fd412 Add rows() and columns() built-in function. 2022-10-11 11:52:35 -04:00
Dianne Skoll
603228b944 Update prerequisite list. 2022-10-11 10:41:57 -04:00
Dianne Skoll
c62f676813 Diagnose unterminated %{...} sequence 2022-10-11 10:35:31 -04:00
Dianne Skoll
c7654c27a6 Update WHATSNEW. 2022-10-11 09:16:04 -04:00
Dianne Skoll
b00bf05fea Add test for %{custom} substitution. 2022-10-11 09:14:47 -04:00
Dianne Skoll
29bd07d4ef Document %{name} substitution sequences. 2022-10-11 09:11:12 -04:00
Dianne Skoll
b7047da89e Allow user-defined substitutions of the form: %{name} or %*{name} that call subst_name. 2022-10-11 09:07:08 -04:00
Dianne Skoll
f26334e25f Add doc about %_ to insert a blank line if $AddBlankLines is 0. 2022-10-11 08:31:13 -04:00
Dianne Skoll
b80bc5f788 Test that ending a reminder with %_ does add a blank line. 2022-10-11 08:30:17 -04:00
Dianne Skoll
91549e18ce Make use of $AddBlankLines 2022-10-10 22:52:48 -04:00
Dianne Skoll
07fd975935 Add the $AddBlankLines system variable. 2022-10-10 22:49:28 -04:00
Dianne Skoll
f9d968cf68 Fix CI script. 2022-10-10 17:31:14 -04:00
Dianne Skoll
6a7e696a60 Minor doc tweak 2022-10-10 17:17:31 -04:00
Dianne Skoll
6734fae1db Update docs/WHATSNEW 2022-10-10 17:15:21 -04:00
Dianne Skoll
481fbc20a1 Bump version to 04.02.00 2022-10-10 17:05:00 -04:00
Dianne Skoll
3c120bf561 Avoid compiler warning. 2022-10-10 17:04:51 -04:00
Dianne Skoll
ee65e04974 Top-level test does not depend on top-level all. 2022-10-10 17:04:35 -04:00
Dianne Skoll
4ee6bb0eca Add test for embedded %_ in MSF reminders. 2022-10-10 11:12:47 -04:00
Dianne Skoll
b9839421f2 make "MSF" correctly wrap UTF-8 text. 2022-10-10 11:05:38 -04:00
Dianne Skoll
67601507fa More robust handling of ANSI color escape sequences. 2022-10-09 22:00:06 -04:00
Dianne Skoll
c2e5534462 Make "REM ... MSF ..." handle ANSI color escape sequences correctly. 2022-10-09 21:55:09 -04:00
Dianne Skoll
f4ea3af6fc Update test output. 2022-10-09 21:32:04 -04:00
Dianne Skoll
e0998a3991 Implement trigtags() 2022-10-09 21:31:24 -04:00
Dianne Skoll
d67e580d0a More tweaks 2022-10-09 18:24:49 -04:00
Dianne Skoll
d6ce54eea4 Tweak astro example script. 2022-10-09 18:22:56 -04:00
Dianne Skoll
8b9ec43029 Add "astro" example script. 2022-10-09 18:21:03 -04:00
Dianne Skoll
9d68134f0f Make PrintValue escape only byte values < 32 2022-10-09 17:53:40 -04:00
Dianne Skoll
3d91371870 Correct and clarify man page. 2022-10-09 17:53:21 -04:00
Dianne Skoll
d1c0ef63b0 Fix inconsistency in man page. 2022-10-09 17:34:09 -04:00
Dianne Skoll
2a59da61e1 Update man page. 2022-10-09 13:40:21 -04:00
Dianne Skoll
2bc5e21627 Document ansicolor and the new color-related special variables. 2022-10-09 13:36:41 -04:00
Dianne Skoll
7d77bfd12a Add tests for invalid ansicolor() calls. 2022-10-09 13:10:28 -04:00
Dianne Skoll
0ff589c288 Merge branch 'utf8' into 'master'
Convert files to UTF-8
2022-10-09 17:02:45 +00:00
Dianne Skoll
f3cca092be Add tests for ansicolors function and new $Use...Colors variables. 2022-10-09 12:59:52 -04:00
Dianne Skoll
7218d55f08 Add $TerminalBackground special variable. 2022-10-09 12:40:48 -04:00
Dianne Skoll
ec72c74016 Add $Use256Colors, $UseBGVTColors, $UseTrueColors and $UseVTColors special variables. 2022-10-09 12:16:33 -04:00
Dianne Skoll
c946f08235 Fix spelling error. 2022-10-07 18:55:07 -04:00
Dianne Skoll
a8543ac349 Fix regression test. 2022-10-06 17:53:01 -04:00
Dianne Skoll
dd3c0e14ed Make wording more consistent. 2022-10-06 17:52:19 -04:00
Dianne Skoll
a2bc0acd3c Use English day names in "OMIT DUMP" 2022-10-06 15:20:37 -04:00
Dianne Skoll
a34266741a Clarify that we use the union of globally- and locally-omitted weekdays. 2022-10-06 08:40:05 -04:00
Dianne Skoll
dedb9766c9 Make a SATISFY-type reminder with ADDOMIT but no MSG actually add to the omits.
Previously, something like: REM 1 May ADDOMIT SATISFY 1
would not add to the global OMIT list.
2022-10-06 08:35:50 -04:00
Dianne Skoll
aedd759f50 Tweak wording. 2022-10-05 16:39:18 -04:00
Dianne Skoll
a24c2f6905 Refactor code. 2022-10-05 16:36:08 -04:00
Dianne Skoll
fac31a10b8 Add the timezone() built-in function. 2022-10-05 16:28:38 -04:00
Dianne Skoll
fba9f139ed Add global OMIT of the form:
OMIT wkday [wkday...]

For example:  OMIT Saturday Sunday
2022-10-05 14:12:53 -04:00
Dianne Skoll
588d9debe8 Simplify American Independence Day example. 2022-10-05 11:12:21 -04:00
Dianne Skoll
805c2e0c69 Implement the utctolocal and localtoutc functions. 2022-10-04 16:23:45 -04:00
Dianne Skoll
2c2b1440b3 Make tests work in non-utf-8 locale. 2022-09-27 21:49:33 -04:00
Jochen Sprickerhof
6973f62d74 Convert files to UTF-8 2022-09-26 20:03:05 +02:00
Dianne Skoll
f547c1e714 Update release notes. 2022-09-26 12:08:49 -04:00
Dianne Skoll
f8ea124b1f Add OS error message if we can't open file. 2022-09-24 10:57:32 -04:00
Dianne Skoll
820e2aec4d Document that "-wcol" also sets $FormWidth 2022-09-24 10:48:43 -04:00
Dianne Skoll
01ce6b2d8f Clamp min CalWidth at 71. 2022-09-24 10:40:04 -04:00
Dianne Skoll
b39e0eab7e Get rid of ComputeCalWidth - it's obsolete 2022-09-24 10:39:05 -04:00
Dianne Skoll
d6fc451d74 Refactor code. 2022-09-24 10:34:05 -04:00
Dianne Skoll
ac91556fc2 Make '-wn' initialize FormWidth as well. 2022-09-24 10:29:23 -04:00
Dianne Skoll
ccf639efe6 Make '-wt' accept FormWidth as well as CalWidth 2022-09-24 10:27:19 -04:00
Dianne Skoll
a8aa3b328b Add "-wt" option to size calendar according to terminal window. 2022-09-24 10:26:06 -04:00
Dianne Skoll
74a3b3e73d Yet more doc fixes. 2022-09-24 09:56:16 -04:00
Dianne Skoll
c0e68b57ea Fix pod 2022-09-24 09:53:11 -04:00
Dianne Skoll
0ad4ea26eb Properly set version and release date in man pages for rem2html and rem2pdf 2022-09-24 09:50:15 -04:00
Dianne Skoll
ea7aafaf5e Refactor code to reduce copy-paste coding. 2022-09-24 09:16:50 -04:00
Dianne Skoll
18043080ba Properly detect missing quote after escape sequence. 2022-09-23 20:42:57 -04:00
Dianne Skoll
7cd8cf3a77 Dump strings more sensibly in PrintValue. 2022-09-23 19:10:36 -04:00
Dianne Skoll
21da52ec36 Update unit tests. 2022-09-23 19:05:51 -04:00
Dianne Skoll
7a0c164843 Dump strings more sensibly. 2022-09-23 19:05:26 -04:00
Dianne Skoll
5cf4961f19 More clarification. 2022-09-23 08:38:00 -04:00
Dianne Skoll
68926d145b Fix innacuracy in how string constants are described. 2022-09-23 08:32:12 -04:00
Dianne Skoll
fdc3e4d23d Update WHATSNEW 2022-09-22 15:00:30 -04:00
Dianne Skoll
f179c837e1 Update regression tests. 2022-09-22 08:56:58 -04:00
Dianne Skoll
740bb44956 Don't consider IFTRIG true if we could not compute a trigger date.
Bug noted by Gunther Reißig
2022-09-22 08:48:19 -04:00
Dianne Skoll
5b953769fe Obey $DefaultColor in a SATISFY-type reminder.
Bug found by Gunther Reißig.
2022-09-22 08:37:37 -04:00
Dianne Skoll
1ae00ce778 No need to reset NumTriggered. 2022-09-21 19:11:30 -04:00
Dianne Skoll
a01e05c1db Fix bug introduced in commit 98c5bf511e:
Don't print a banner when issuing a queued reminder.
2022-09-21 18:17:25 -04:00
Dianne Skoll
63fb3e99f3 Make "test" depend on "all" rather than just "remind" 2022-09-19 13:56:11 -04:00
Dianne Skoll
6cf7f5d2d8 Merge branch 'add_ci' into 'master'
Add ci

See merge request dskoll/remind!2
2022-09-19 17:54:45 +00:00
Jochen Sprickerhof
316eb43303 Add Gitlab CI 2022-09-19 19:51:15 +02:00
Dianne Skoll
576112a39a Merge branch 'drop_fgrep' into 'master'
Replace deprecated fgrep by grep

See merge request dskoll/remind!1
2022-09-19 17:50:03 +00:00
Jochen Sprickerhof
6607223abb Replace deprecated fgrep by grep -F 2022-09-19 19:49:20 +02:00
Dianne Skoll
9e85b1932d Mark today in bold iff "remind -c" color output is enabled. 2022-09-19 11:32:10 -04:00
Dianne Skoll
4ba7f5b1f2 Only embolden today if stdout is a tty 2022-09-19 10:44:21 -04:00
Dianne Skoll
fc93ae890a Allow NULL pointers to be supplied to FromJulian if we are not interested in specific values 2022-09-17 23:04:34 -04:00
Dianne Skoll
8051d01945 Document change in Makefile install/install-stripped targets. 2022-09-17 09:07:27 -04:00
Dianne Skoll
63430c59f7 Make "make install" *not* strip debugging symbols; add "make install-stripped" target to strip them. 2022-09-17 09:04:45 -04:00
Dianne Skoll
c646bfc63f Make today's date bold in -c mode. 2022-09-16 21:01:10 -04:00
Dianne Skoll
58dea8f69b Support greyscale version of SHADE. 2022-09-16 20:44:59 -04:00
Jochen Sprickerhof
712aa08fbc make test depend on all 2022-09-08 16:32:04 +02:00
38 changed files with 3464 additions and 859 deletions

13
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,13 @@
tests:
image: 'debian:stable-slim'
before_script:
- apt update && apt-get -y install gcc make
- useradd --create-home testuser
- chown -R testuser .
- chmod -R go-w .
script:
- LANG=C.UTF-8 su testuser -c './configure && make test'
artifacts:
when: always
paths:
- tests/test.out

View File

@@ -12,11 +12,11 @@ all: src/Makefile
@$(MAKE) -C rem2pdf -f Makefile.top
install:
@echo ""
@echo "*********************"
@echo "* *"
@echo "* Installing REMIND *"
@echo "* *"
@echo "*********************"
@echo "**********************************"
@echo "* *"
@echo "* Installing REMIND (unstripped) *"
@echo "* *"
@echo "**********************************"
@echo ""
@$(MAKE) -C src install
@$(MAKE) -C rem2html install
@@ -27,15 +27,15 @@ clean:
-$(MAKE) -C src clean
-$(MAKE) -C rem2pdf clean
install-nostripped:
install-stripped:
@echo ""
@echo "**********************************"
@echo "* *"
@echo "* Installing REMIND (unstripped) *"
@echo "* *"
@echo "********************************"
@echo "* *"
@echo "* Installing REMIND (stripped) *"
@echo "* *"
@echo "**********************************"
@echo ""
@$(MAKE) -C src install-nostripped
@$(MAKE) -C src install-stripped
@$(MAKE) -C rem2html install
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)

21
README
View File

@@ -34,5 +34,26 @@ If you do NOT have Tcl/Tk or are NOT running X Windows:
5) Type: "make install" -- you may need to be root to do this.
PREREQUISITES:
--------------
Remind and rem2ps have no prerequisites beyond the standard C library and
the standard math library.
Rem2HTML requires the JSON::MaybeXS Perl module; on Debian-like
systems, you can install that with:
apt install libjson-maybexs-perl
Rem2PDF requires the JSON::MaybeXS, Pango and Cairo Perl modules. On
Debian-like systems, install with:
apt install libjson-maybexs-perl libpango-perl libcairo-perl
TkRemind requires Tcl/Tk and the tcllib library. On Debian-like systems
install with:
apt install tcl tk tcllib
Contact info: mailto:dianne@skoll.ca
Home page: https://dianne.skoll.ca/projects/remind/

2
configure vendored
View File

@@ -4015,7 +4015,7 @@ _ACEOF
fi
done
VERSION=04.01.00
VERSION=04.02.00

View File

@@ -73,7 +73,7 @@ if test "$?" != 0 ; then
exit 1
fi
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups)
VERSION=04.01.00
VERSION=04.02.00
AC_SUBST(VERSION)
AC_SUBST(PERL)
AC_SUBST(PERLARTIFACTS)

View File

@@ -1,6 +1,55 @@
CHANGES TO REMIND
* VERSION 4.1 Patch 0 - ????-??-??
* VERSION 4.2 Patch 0 - 2022-??-??
- NEW FEATURE: remind: Allow weekdays to be globally-omitted. For example:
OMIT Saturday Sunday
globally-omits all Saturdays and Sundays.
- NEW FEATURE: remind: Add ansicolor() built-in function to make it easier
to colorize reminders on the terminal. Suggested by Tim Chase.
- NEW FEATURE: remind: Add several special variables related to the color
mode: $UseVTColors, $UseBGVTColors, $Use256Colors, $UseTrueColors and
$TerminalBackground. Based on a suggestion by Tim Chase.
- NEW FEATURE: remind: Add utctolocal() and localtoutc() built-in functions.
- NEW FEATURE: remind: Add timezone() built-in function.
- NEW FEATURE: remind: Add trigtags() function per suggestion from Tim Chase.
- NEW FEATURE: remind: The $AddBlankLines system variable controls whether or
not a blank line is added after each reminder.
- NEW FEATURE: remind: The built-in functions columns() and rows() return the
width and height of the terminal (in character positions) respectively.
- NEW FEATURE: remind: The built-in function columns("string") returns the
number of columns occupied by "string" on the terminal, taking into account
double-width Unicode characters and zero-width ANSI escape sequences.
- NEW FEATURE: remind: You can add custom substitution sequences of the form
%{name} or %*{name} that end up calling the function subst_name and using
its return value as the replacement for the substitution sequence.
- BUG FIX: remind: Make MSF correctly format UTF-8 text and text with
embedded ANSI color-changing codes.
- BUG FIX: remind: Make ADDOMIT actually work correctly in a SATISFY-type
REM command. Bug found by Gunther Reißig
- BUG FIX: Convert documentation files and src/lang.h to UTF-8. Patch
from Jochen Sprickerhof.
- BUG FIX: Fix tests in non-UTF-8 locales.
- BUG FIX: Fix a few problems with the include include/holidays/us.rem
file.
* VERSION 4.1 Patch 0 - 2022-09-25
- NEW FEATURE: remind: "remind -c" now supports the MOON special, printing
the moon phases in the calendar if the locale supports UTF-8 encoding.
@@ -16,8 +65,19 @@ CHANGES TO REMIND
output is going to terminal, "FILE" if it's redirected to a plain file,
or "PIPE" if it's going to a pipe. See the man page for all the details.
- IMPROVEMENT: Add "make install-nostripped" top-level target for people who
want to build Remind with debugging symbols intact.
- NEW FEATURE: Add the "-wt" option to set the calendar width to the terminal
width even if standard output is a pipe. Useful for situations like this:
remind -wt -c .reminders | less -R
- CHANGE: "make install" now no longer strips debugging symbols from the
remind and rem2ps executables. Use "make install-stripped" if you want
them stripped.
- CHANGE: remind: "remind -c" highlights today's date in bold, if
colors are enabled.
- CHANGE: Dump string values with control characters escaped.
- DOCUMENTATION FIX: Document behavior of DO and filedir() with respect
to symbolic links.
@@ -28,12 +88,24 @@ CHANGES TO REMIND
- DOCUMENTATION FIX: Make date in man pages actually be the release date.
Include Remind version in man pages. Also suggested by Ian! D. Allen.
- DOCUMENTATION FIX: Fix inaccuracy in how string constants were documented.
- BUG FIX: Makefiles: Pass CFLAGS at link-time so link-time optimization
actually happens. Pointed out by Zolan Puskas.
actually happens. Pointed out by Zoltan Puskas.
- BUG FIX: If the first REM command to trigger was a RUN command, the banner
would not print. This has been fixed.
- BUG FIX: replace deprecated 'fgrep' with 'grep -F' (Jochen Sprickerhof)
- BUG FIX: make "make test" depend on "make all" (Jochen Sprickerhof)
- BUG FIX: make "REM ... SATISFY ... MSG foo" respect $DefaultColor. Bug
reported by Gunther Reißig.
- BUG FIX: Don't consider IFTRIG true if we could not compute a trigger date.
Bug noted by Gunther Reißig.
* VERSION 4.0 Patch 3 - 2022-08-16
- IMPROVEMENT: remind: add plain_body and calendar_body JSON keys in -pp...
@@ -1101,7 +1173,7 @@ CHANGES TO REMIND
- Fixed dates for Yom Hazikaron and Yom Ha'atzmaut if 5 Iyar falls on a
Saturday. (Hebrew calendar fix.)
- Added support for the Icelandic language, courtesy of Björn Davíðsson.
- Added support for the Icelandic language, courtesy of Björn Davíðsson.
+ BUG FIXES
@@ -1248,7 +1320,7 @@ CHANGES TO REMIND
- Made parser _very_ forgiving -- the type of reminder now defaults
to MSG. This lets you have lines in the reminder file like this:
Feb 9, 1998 Meeting with Joe.
Feb 9, 1998 Meeting with Joe.
But I don't recommend abusing it. It's mostly to ease migration from
UNIX calendar(1) files.
@@ -1839,7 +1911,7 @@ CHANGES TO REMIND
- Removed identifiers in the C source beginning with "_" to conform
to ANSI practice.
- Fixed a bug in the -u option which resulted in environment variables
SHELL and USER not being set correctly. Also made -u set the LOGNAME
environment variable.
@@ -1912,7 +1984,7 @@ CHANGES TO REMIND
- Fixed all the source files to include "config.h" first.
- Changed the way triggers are calculated so that trigger dates are
- Changed the way triggers are calculated so that trigger dates are
always valid if year, month and day are specified, and there is no
UNTIL clause. See MAN page section "DETAILS ABOUT TRIGVALID()."
@@ -2054,6 +2126,3 @@ CHANGES TO REMIND
* Version 1.0
- never publicly released.

18
examples/alignment.rem Normal file
View File

@@ -0,0 +1,18 @@
# Demo the columns() function
#
# Run as: remind -@2 alignment.rem
SET $AddBlankLines 0
BANNER %
FSET center(x) pad("", " ", (columns() - columns(x))/2) + x
FSET right(x) pad("", " ", columns() - columns(x)) + x
MSG This is left-aligned.
MSG [ansicolor(0,255,0)]This is also left-aligned.[ansicolor("")]
MSG [center("This is centered.")]
MSG [ansicolor(255,255,0) + center("🌕 🌕 🌕 🌕 This is also centered. ") + ansicolor("")]
msg [right("This is right-aligned.")]
msg [ansicolor(255,0,0) + right("This is also right-aligned. 🌕 🌕 🌕") + ansicolor("")]

34
examples/astro Executable file
View File

@@ -0,0 +1,34 @@
#!/bin/sh
#
# A little demo script that displays astronomical events
#
# Best used in a UTF-8 environment.
remind -g -@2 - <<'EOF'
# Set this variable to 1 if your terminal has a dark background or 0 if
# it is light.
SET bg_dark 1
SET $AddBlankLines 0
BANNER %
IF bg_dark
SPECIAL COLOR 255 255 0 Sunrise: 🌅 [sunrise()] today and [sunrise(today()+1)] tomorrow
SPECIAL COLOR 255 128 0 Sunset: 🌇 [sunset()] today and [sunset(today()+1)] tomorrow%_
REM [moondate(0)] +60 SPECIAL COLOR 255 255 0 New moon: 🌑 [moondate(0)] (%b)
REM [moondate(1)] +60 SPECIAL COLOR 255 255 128 First Quarter: 🌓 [moondate(1)] (%b)
REM [moondate(2)] +60 SPECIAL COLOR 255 255 255 Full moon: 🌕 [moondate(2)] (%b)
REM [moondate(3)] +60 SPECIAL COLOR 255 255 128 Last Quarter: 🌗 [moondate(3)] (%b)
ELSE
SPECIAL COLOR 128 128 0 Sunrise: 🌅 [sunrise()] today and [sunrise(today()+1)] tomorrow
SPECIAL COLOR 128 32 0 Sunset: 🌇 [sunset()] today and [sunset(today()+1)] tomorrow%_
REM [moondate(0)] +60 SPECIAL COLOR 128 128 0 New moon: 🌑 [moondate(0)] (%b)
REM [moondate(1)] +60 SPECIAL COLOR 128 128 64 First Quarter: 🌓 [moondate(1)] (%b)
REM [moondate(2)] +60 SPECIAL COLOR 0 0 0 Full moon: 🌕 [moondate(2)] (%b)
REM [moondate(3)] +60 SPECIAL COLOR 128 128 64 Last Quarter: 🌗 [moondate(3)] (%b)
ENDIF
EOF

View File

@@ -77,16 +77,16 @@ REM 1 MSG John's [_mo_num(11, 1984)] 'monthly' anniversary
############################################################################
# If it falls on a Saturday, bump to previous Friday
REM 4 July OMIT SAT SCANFROM -1 BEFORE ADDOMIT SATISFY [$Td != 4] MSG Independence day (observed)
REM 3 JULY SCANFROM -7 ADDOMIT SATISFY [$Tw == 5] MSG Independence day (observed)
# If it falls on a Sunday, bump to following Monday
REM 4 July OMIT SUN SCANFROM -7 AFTER ADDOMIT SATISFY [$Td != 4] MSG Independence day (observed)
REM 5 July SCANFROM -7 ADDOMIT SATISFY [$Tw == 1] MSG Independence day (observed)
# If it falls on Sat or Sun, note the actual day
REM 4 July SATISFY [$Tw == 0 || $Tw == 6] MSG Independence day (actual)
REM 4 July SCANFROM -7 ADDOMIT SATISFY [$Tw == 0 || $Tw == 6] MSG Independence day (actual)
# Otherwise observed and actual is on the 4th
REM 4 July OMIT SAT SUN SKIP SCANFROM -7 ADDOMIT MSG Independence Day
REM 4 July SCANFROM -7 ADDOMIT SATISFY [$Tw >= 1 && $Tw <= 5] MSG Independence Day
##########################################################################
# #

View File

@@ -19,13 +19,9 @@ REM Feb 14 MSG %"Valentine's Day%"
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG %"President's Day%"
REM Mar 17 MSG %"St. Patrick's Day%"
# The DST rules are accurate for most locations in
# North America
REM Sun Apr 1 ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
REM Sun Mar 8 ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
REM Last Sunday in October ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
REM First Sunday in November ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
# These are accurate for most places in North America
REM MAYBE-UNCOMPUTABLE Sun November SATISFY [isdst($T) != isdst($T+1)] MSG Daylight Saving Time Ends
REM MAYBE-UNCOMPUTABLE Sun March SATISFY [isdst($T) != isdst($T+1)] MSG Daylight Saving Time Starts
REM Apr 1 MSG %"April Fool's%" Day
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
@@ -35,15 +31,24 @@ REM Second Sun in May MSG %"Mother's Day%"
REM Third Sat in May MSG %"Armed Forces Day%"
REM Last Monday in May SCANFROM -7 ADDOMIT MSG %"Memorial Day%"
REM Jun 14 MSG %"Flag Day%"
REM July 4 SCANFROM -7 ADDOMIT MSG Independence Day
REM July 3 SCANFROM -7 ADDOMIT SATISFY [$Tw == 5] MSG Independence Day (observed)
REM July 5 SCANFROM -7 ADDOMIT SATISFY [$Tw == 1] MSG Independence Day (observed)
REM Third Sun in June MSG %"Father's Day%"
REM First Mon in Sep SCANFROM -7 ADDOMIT MSG %"Labor Day%"
REM Second Mon in Oct MSG %"Columbus Day%"
REM Second Mon in Oct MSG %"Columbus Day / Indigenous Peoples' Day%"
REM Nov 11 MSG %"Veterans Day%"
REM Oct 30 MSG %"Mischief Night%"
REM Oct 31 MSG %"Halloween%"
REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG %"Election Day%"
REM Last Thu in Nov SCANFROM -7 ADDOMIT MSG %"Thanksgiving Day%"
REM Fri Nov [Week_4+1] SCANFROM -7 ADDOMIT MSG %"Thanksgiving (cont.)%"
REM Thu 22 Nov SCANFROM -7 ADDOMIT MSG %"Thanksgiving Day%"
REM Fri 23 Nov SCANFROM -7 ADDOMIT MSG %"Thanksgiving (cont.)%"
REM Dec 24 MSG %"Christmas Eve%"
OMIT Dec 25 MSG %"Christmas%" Day

View File

@@ -61,3 +61,29 @@ FSET subst_gx(alt, d, t) iif(alt, subst_g_alt(d), $On + " " + subst_g_alt(d))
FSET subst_ux(alt, d, t) subst_ax(alt, d, t)
FSET subst_vx(alt, d, t) subst_gx(alt, d, t)
FSET subst_p(alt, d, t) iif(d == today()+1, "", "en")
# Localization of various astronomical events
# Perihelion
SET earthseasons_Perihelion_str "Perihel"
# Vernal equinox
SET earthseasons_EquinoxMar_str "Frühlingsanfang"
# Summer solstice
SET earthseasons_SolsticeJun_str "Sommeranfang"
# Aphelion
SET earthseasons_Aphelion_str "Aphel"
# Autumnal Equinox
SET earthseasons_EquinoxSep_str "Herbstanfang"
# Winter Solstice
SET earthseasons_SolsticeDec_str "Winteranfang"
# Daylight saving time starts
SET daylightST_starts_str "Beginn Sommerzeit"
# Daylight saving time ends
SET daylightST_ends_str "Ende Sommerzeit"

View File

@@ -125,10 +125,27 @@ then you know what you are doing.
.B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]]
The \fB\-w\fR option specifies the output width, padding and spacing
of the formatted calendar output. \fICol\fR specifies the number of
columns in the output device. If not specified, or specified as 0,
it defaults to the larger of 71 or the actual width of your terminal,
or to 80 if standard output is not a terminal.
columns in the output device. If \fIcol\fR is not specified, or is
specified as 0, it defaults to the larger of 71 or the actual width of
your terminal, or to 80 if standard output is not a terminal. If
\fIcol\fR is specified as the letter \fBt\fR, then \fBRemind\fR
attempts to get the width of the \fB/dev/tty\fR terminal device. This
is useful, for example, if you pipe calendar output into \fBless\fR;
even though standard output is a pipe, you want the calendar to be
sized correctly for your terminal window:
.RS
.PP
.nf
remind -c -wt .reminders | less
.fi
.RE
.RS
.PP
Note that the value of \fIcol\fR is also used to set the system variable
$FormWidth, which is initialized to \fIcol\fR - 8. See "SYSTEM VARIABLES"
for details.
.PP
\fIPad\fR specifies how many lines
to use to "pad" empty calendar boxes. This defaults to 5. If you
@@ -393,7 +410,7 @@ information.
.SH REMINDER FILES
.PP
\fBRemind\fR uses scripts to control its operation. You can use any
text editor capable of creating plain ASCII files to create a
text editor capable of creating plain-text files to create a
\fBRemind\fR script. The commands inside a script can range from the
very simple and almost immediately understandable:
.PP
@@ -987,6 +1004,18 @@ also. See "The OMIT command" for more details.)
By comparison, if we had used "\-\-1", the reminder would be triggered on
the last day of the month, regardless of the \fBOMIT\fR.
.PP
If you locally omit weekdays but also have globally-omitted weekdays, then
the list of ommitted weekdays is the union of the two. Consider this
example:
.PP
.nf
OMIT Sat Sun
REM 15 OMIT Fri Sat MSG Whatever
.fi
.PP
In the REM command, the effective list of omitted weekdays will
be Friday, Saturday and Sunday.
.PP
.B COMPUTED LOCAL OMITS
.PP
The \fBOMITFUNC\fR phrase of the \fBREM\fR command allows you to
@@ -1160,7 +1189,8 @@ tags; see their documentation for details.
.PP
The \fBTAG\fR keyword is followed by a tag consisting of up to
48 characters. You can have as many TAG clauses as you like in
a given REM statement.
a given REM statement. A tag can contain any character except for
whitespace and a comma.
.PP
If you supply the \fB\-y\fR option to \fBRemind\fR, then any
reminder that lacks a \fBTAG\fR will have one synthesized. The
@@ -1496,7 +1526,8 @@ Notes:
o
.B Remind
normally prints a blank line after each reminder; if the last character
of the body is "%", the blank line will not be printed.
of the body is "%", the blank line will not be printed. You can globally
suppress the extra blank lines by setting \fB$AddBlankLines\fR to 0.
.TP
o
Substitutions a, b, c, e, f, g, h, i, j, k, l, u and v all are replaced
@@ -1545,6 +1576,10 @@ In addition to being a keyword in the \fBREM\fR command,
\fBOMIT\fR is a command in its own right. Its syntax is:
.PP
.RS
\fBOMIT\fR \fIweekday\fR [\fIweekday\fR...]
.PP
or:
.PP
\fBOMIT\fR [\fIday\fR] \fImonth\fR [\fIyear\fR]
.PP
or:
@@ -1558,6 +1593,7 @@ The \fBOMIT\fR command is used to "globally" omit certain days
"\-\-" and "\+\+" forms. Some examples:
.PP
.nf
OMIT Saturday Sunday
OMIT 1 Jan
OMIT 7 Sep 1992
OMIT 15 Jan THROUGH 14 Feb
@@ -1567,8 +1603,13 @@ The \fBOMIT\fR command is used to "globally" omit certain days
OMIT Jun THROUGH July # Equivalent to OMIT Jun 1 THROUGH July 31
.fi
.PP
The first example specifies a holiday that occurs on the same date each
year - New Year's Day. The second example specifies a holiday that
The first example omits every Saturday and Sunday. This is useful for
reminders that shouldn't trigger on weekends.
.PP
The second example specifies a holiday that occurs on the same date each
year - New Year's Day.
.PP
The third example specifies a holiday that
changes each year - Labour Day. For these types of holidays, you
must create an \fBOMIT\fR command for each year. (Later, in the
description of expressions and some of the more advanced features of
@@ -1938,12 +1979,16 @@ The following examples illustrate constants in \fBRemind\fR expressions:
12, 36, \-10, 0, 1209
.TP
.B STRING constants
"Hello there", "This is a test", "\\n\\gosd\\w", ""
"Hello there", "This is a test", "\\nHello\\tThere", ""
.PP
.RS
Note that the empty string is represented by "", and that
backslashes in a string are \fInot\fR interpreted specially, as in they are
in C.
Note that the empty string is represented by "". Remind supports
the escape sequences "\\a", "\\b", "\\f", "\\n", "\\r", "\\t"
and "\\v" which have the same meanings as their counterparts in C.
To include a quote in a string, use "\\"". Any other character
preceded by a backslash is inserted into the string as-is, but the
backslash itself is removed. To include a backslash in a string,
use "\\\\".
.RE
.TP
.B TIME constants
@@ -2230,6 +2275,16 @@ The following system variables are defined. Those marked
"read-only" cannot be changed with the \fBSET\fR command.
All system variables hold values of type \fBINT\fR, unless otherwise
specified.
.TP
.B $AddBlankLines
If set to 1 (the default), then \fBRemind\fR normally prints a blank
line after the banner and each reminder. (This can be suppressed by
ending the reminder or banner with a single percent sign.) If
$AddBlankLines is set to 0, then Remind does not print the blank line.
In this case, ending a reminder with % has no effect. If you \fIdo\fR
want a blank line after a reminder, end it with \fB%_\fR to insert a
newline.
.TP
.B $CalcUTC
If 1 (the default), then \fBRemind\fR uses C library functions
@@ -2555,6 +2610,23 @@ Equivalent to \fBwkdaynum(today())\fR.
.TP
.B $Uy (read-only)
Equivalent to \fByear(today())\fR.
.TP
.B $UseVTColors (read-only)
Set to 1 if the \fB\-@\fR or \fB\-cc\fR options were used; 0 otherwise.
.TP
.B $UseBGVTColors (read-only)
Set to 1 if the \fB\-@,,1\fR option was used; 0 otherwise.
.TP
.B $Use256Colors (read-only)
Set to 1 if the \fB\-@1\fR option was used; 0 otherwise.
.TP
.B $UseTrueColors (read-only)
Set to 1 if the \fB\-@2\fR option was used; 0 otherwise.
.TP
.B $TerminalBackground (read-only)
Returns -1 if the terminal background color was not specified,
0 if it was specified as dark with the \fB\-@,0\fR option or
1 if it was specified as light with the \fB\-@,1\fR option.
.PP
Note: If any of the calendar modes are in effect, then the
values of $Daemon, $DontFork, $DontTrigAts, $DontQueue, $HushMode,
@@ -2617,6 +2689,60 @@ $TimeSep and $DateTimeSep when formatting its output. For example:
.PP
.RE
.TP
.B ansicolor(i_red, i_green, i_blue [,i_bg [,i_clamp]])
Returns a \fBSTRING\fR that contains an ANSI escape sequence for changing
the terminal text color. The parameters \fIred\fR, \fIgreen\fR and \fIblue\fR
are integers from 0 to 255 specifying the value of the respective color
component. As a special case, all three values can be -1, in which case
the ANSI sequence "ESC[0m" is returned, which resets all text attributes
to normal.
.RS
.PP
The string returned by \fBansicolor\fR depends on the color mode that
\fBRemind\fR is running in, as specified by the \fB\-@\fR option. If color
mode is not enabled, then \fBansicolor\fR always returns the empty string.
Otherwise, it returns the escape sequence that best approximates the color
according to the \fB\-@\fR color mode.
.PP
The optional \fIbg\fR argument is either 0 or 1. If 0 (the default), then
the foreground color is set. If 1, then the background color is set. Note
that setting the background color only works in 256-color or true-color
mode.
.PP
The optional \fIclamp\fR argument is either 0 or 1. If 0 (the default),
then colors are not adjusted based on the terminal background color. If
1, then \fBRemind\fR attempts to adjust dark or bright colors so they have
enough contrast to be visible in the terminal.
.PP
The first three arguments may alternatively be specified as a string
consisting of three space-separated numbers, as in this example: "128 128 0"
.PP
As a special case, \fBansicolor("")\fR is equivalent to
\fBansicolor(-1,-1,-1)\fR and returns the ANSI sequence to reset all text
attributes to normal.
.PP
Note that inserting ANSI color sequences in calendar mode \fIwill
produce garbled results\fR. Therefore, we recommend defining
functions such as the ones below that return the empty string in
calendar mode:
.PP
.nf
IF $CalMode
FSET fg(r,g,b) ""
FSET bg(r,g,b) ""
ELSE
FSET fg(r,g,b) ansicolor(r,g,b)
FSET bg(r,g,b) ansicolor(r,g,b,1)
ENDIF
REM [fg(255,0,0)][bg(64,64,64)]Red on Gray[fg(-1,-1,-1)] in normal mode
REM SPECIAL COLOR 0 255 0 Green in normal and calendar mode
.fi
.PP
If you use the \fBansicolor\fR function, don't forget to reset the color
back to normal with \fBansicolor(-1,-1,-1)\fR or subsequent reminders
will continue to be colored.
.RE
.TP
.B args(s_fname)
Returns the number of arguments expected by the user-defined function
\fIfname\fR, or \-1 if no such user-defined function exists. Note that
@@ -2627,7 +2753,10 @@ available only in versions of \fBRemind\fR from 03.00.04 and up.
.TP
.B asc(s_string)
Returns an \fBINT\fR that is the ASCII code of the first character
in \fIstring\fR. As a special case, \fBasc("")\fR returns 0.
in \fIstring\fR. As a special case, \fBasc("")\fR returns 0. For UTF-8
strings, this will return the UTF-8 byte with which the string
begins, which is not likely to be very useful (and may indeed be negative
on machines where \fBchar\fR is a signed type.)
.TP
.B baseyr()
Returns the "base year" that was compiled into \fBRemind\fR (normally
@@ -2636,14 +2765,10 @@ Returns the "base year" that was compiled into \fBRemind\fR (normally
.TP
.B char(i_i1 [,i_i2...])
This function can take any number of \fBINT\fR arguments. It returns
a \fBSTRING\fR consisting of the characters specified by the arguments.
Note that none of the arguments can be 0, unless there is only one
a \fBSTRING\fR consisting of the bytes specified by the arguments.
It is easy to create invalid UTF-8 sequences; \fBchar\fR does not check
for this. Note that none of the arguments can be 0, unless there is only one
argument. As a special case, \fBchar(0)\fR returns "".
.PP
.RS
Note that because \fBRemind\fR does not support escaping of characters
in strings, the only way to get a double-quote in a string is to use
\fBchar(34)\fR.
.RE
.TP
.B choose(i_index, x_arg1 [,x_arg2...])
@@ -2702,6 +2827,22 @@ arguments are converted using the reverse of procedures described
above. A \fBSTRING\fR \fIarg\fR is converted by parsing it as an
integer.
.RE
.TP
.B columns([s_arg])
If called with no arguments, \fBcolumns()\fR behaves as follows:
If standard output is a TTY, returns the width of the terminal in columns.
If standard output is not a TTY, attempts to open "/dev/tty" to obtain
the terminal size. If this fails, returns -1.
.RS
.PP
If called with a single string argument, \fBcolumns(str)\fR returns
the number of columns \fBstr\fR will occupy if printed to a terminal.
ANSI color-changing sequences occupy zero columns whereas some Unicode
characters occupy two columns. \fBcolumns(str)\fR takes all of that
into account. Note that if Remind was compiled without Unicode support,
\fBcolumns(str)\fR returns a type mismatch error.
.RE
.TP
.B current()
Returns the current date and time as a DATETIME object. This may be the
@@ -2949,6 +3090,10 @@ other languages, this function will return the English name of the
language (e.g. "German") Note that \fBlanguage()\fR is not available
in versions of \fBRemind\fR prior to 03.00.02.
.TP
.B localtoutc(q_datetime)
Given a \fBDATETIME\fR object interpreted in the local time zone, return
a \fBDATETIME\fR object that expresses the same time in UTC.
.TP
.B lower(s_string)
Returns a \fBSTRING\fR with all upper-case characters in \fIstring\fR
converted to lower-case.
@@ -3220,6 +3365,11 @@ Returns the date as provided by the operating system. This is in contrast to
\fBRemind\fR's concept of "today", which may be changed if it is running
in calendar mode, or if a date has been supplied on the command line.
.TP
.B rows()
If standard output is a TTY, returns the height of the terminal in rows.
If standard output is not a TTY, attempts to open "/dev/tty" to obtain
the terminal size. If this fails, returns -1.
.TP
.B sgn(i_num)
Returns \-1 if \fInum\fR is negative, 1 if \fInum\fR is positive,
and 0 if \fInum\fR is zero.
@@ -3338,6 +3488,12 @@ Creates a \fBTIME\fR with the hour and minute components specified by
Returns a \fBTIME\fR object representing the time portion of
\fIdatetime\fR.
.TP
.B timezone([dq_datetime])
Returns a string representing the local time zone name of the given
\fBDATETIME\fR. If no argument is supplied, \fBRemind\fR uses the
value of \fBcurrent()\fR. If a \fBDATE\fR rather than \fBDATETIME\fR
is supplied, \fBRemind\fR uses a time part of 00:00.
.TP
.B today()
Returns \fBRemind\fR's notion of "today." This may be the actual system
date, or a date supplied on the command line, or the date of the
@@ -3564,6 +3720,12 @@ returns "30 November 1994 AT 22:00" for EST, which is 5 hours behind UTC.
The value for your time zone may differ.
.RE
.TP
.B trigtags()
Returns a comma-separated list of the TAGs associated with the most recent
\fBREM\fR command that was triggered. Returns the empty string if there
were no TAGs. If there are multiple tags, they are each separated by
a single comma, not a comma and a space.
.TP
.B trigtime()
Returns the time of the last \fBREM\fR command with an \fBAT\fR
clause. If the last \fBREM\fR did not have an \fBAT\fR clause,
@@ -3605,6 +3767,11 @@ values. Here is an example:
Returns a \fBSTRING\fR with all lower-case characters in \fIstring\fR
converted to upper-case.
.TP
.B utctolocal(q_datetime)
Given a \fBDATETIME\fR object interpreted in UTC, return a
\fBDATETIME\fR object that expresses the same time in the local time
zone.
.TP
.B value(s_varname [,x_default])
Returns the value of the specified variable. For example, value("X"+"Y")
returns the value of variable XY, if it is defined. If XY is not defined,
@@ -3618,7 +3785,7 @@ defined, and the value of XY if it is defined.
.TP
.B version()
Returns a string specifying the version of \fBRemind\fR. For version
03.00.04, returns "03.00.04". It is guaranteed that as new versions of
@VERSION@, returns "@VERSION@". It is guaranteed that as new versions of
\fBRemind\fR are released, the value returned by \fBversion()\fR will
strictly increase, according to the rules for string ordering.
.TP
@@ -3951,13 +4118,13 @@ Notes:
.TP
o
If you access a variable in \fIexpr\fR that is not in the list of arguments,
the "global" value (if any) is used.
the global value (if any) is used.
.TP
o
Function and parameter names are significant only to 12 characters.
Function and parameter names are significant to 64 characters.
.TP
o
The \fBvalue()\fR function \fIalways\fR accesses the "global" value of a
The \fBvalue()\fR function \fIalways\fR accesses the global value of a
variable, even if it has the same name as an argument. For example:
.RS
.PP
@@ -4866,17 +5033,17 @@ This function is passed a single integer, namely a day of the month from
turn it into an ordinal number. In English, for example, the function
might return "st", "nd", "rd" or "th", depending on \fId\fR.
.TP
.B subst_N(alt, date, time)
.B subst_\fIN\fR\fB(alt, date, time)\fR
This is actually a \fIfamily\fR of functions, where \fIN\fR is a letter
or number. This function \fIcompletely overrides\fR the substitution
sequence "%X". The three arguments are an integer \fIalt\fR which,
sequence "%N". The three arguments are an integer \fIalt\fR which,
if non-zero, indicates that the alternate-mode substitution sequence
"%*X" was encountered; \fIdate\fR which is the trigger date of the
"%*N" was encountered; \fIdate\fR which is the trigger date of the
reminder and \fItime\fR which is the trigger time.
.TP
.B subst_Nx(alt, date, time)
.B subst_\fIN\fR\fBx(alt, date, time)\fR
Again, this is a \fIfamily\fR of functions. It is similar to the
\fBsubst_N\fR family except it is only called if \fIdate\fR is two or
\fBsubst_\fIN\fR family except it is only called if \fIdate\fR is two or
more days away from \fItoday()\fR. This is useful if you don't want to
override the "today" or "tomorrow" output for most substitution sequences.
.PP
@@ -4916,6 +5083,17 @@ as:
FSET subst_bx(a,d,t) iif(d==today()+2, "the day after tomorrow", 0)
.fi
.PP
You can define your own substitution sequences in addition to the built-in
ones as follows: If you define a function named \fBsubst_\fIname\fB(alt, date, time)\fR, then the sequence \fB%{name}\fR calls the function with \fBalt\fR
set to 0 and \fBdate\fR and \fRtime\fR to the trigger date and time,
respectively. The \fB%{name}\fR sequence is replaced with whatever the
function returns. The sequence \fB%*{name}\fR is similar, but calls
the function with \fBalt\fR set to 1.
.PP
If you use a \fB%{name}\fR sequence and the function \fBsubst_\fIname\fR is
not defined or returns an error, then \fB%{name}\fR is replaced with the
empty string.
.PP
.SH LANGUAGE PACKS
.PP
\fBRemind\fR ships with a number of language packs, which are simply reminder

View File

@@ -19,7 +19,7 @@ install:
$(PERL) -M$$m -e 1 > /dev/null 2>&1; \
if test $$? != 0 ; then echo "Not installing rem2html; missing $$m"; exit 0; fi; \
done; \
pod2man rem2html > rem2html.1 && mkdir -p $(DESTDIR)$(mandir)/man1 && cp rem2html.1 $(DESTDIR)$(mandir)/man1/rem2html.1 || true; \
pod2man --center "VERSION @VERSION@" --date "@RELEASE_DATE@" rem2html > rem2html.1 && mkdir -p $(DESTDIR)$(mandir)/man1 && cp rem2html.1 $(DESTDIR)$(mandir)/man1/rem2html.1 || true; \
echo "Installing rem2html in $(DESTDIR)$(bindir)"; \
mkdir -p $(DESTDIR)$(bindir) && sed -e 's|^#!perl|#!$(PERL)|' < rem2html > $(DESTDIR)$(bindir)/rem2html && chmod 755 $(DESTDIR)$(bindir)/rem2html && exit 0; \
exit 1;

View File

@@ -1,4 +1,15 @@
use ExtUtils::MakeMaker;
{
# Override pod2man options
package MY;
sub manifypods {
my ($self,%attribs) = @_;
my $result = $self->SUPER::manifypods(%attribs);
$result =~ s/^(POD2MAN_EXE\s*=\s*)(.+)$/$1$2 --center 'VERSION @VERSION@' --date '@RELEASE_DATE@'/m;
return $result;
}
}
WriteMakefile(
NAME => 'Remind::PDF',
AUTHOR => q{Dianne Skoll <dianne@skoll.ca>},

View File

@@ -443,14 +443,14 @@ B<-p>, B<-pp> or B<-ppp> options into B<rem2pdf>. The PDF output
will be sent to standard output. So for example, to print a 12-month
calendar for the year 2030, use:
remind -pp12 /dev/null Jan 2030 | rem2pdf -e -l -c=3 | lpr
remind -pp12 /dev/null Jan 2030 | rem2pdf -e -l -c3 | lpr
You can concatenate multiple B<remind> runs. For example, the following
will produce a PDF calendar for January through March of 2023, and
June of 2023 (for a total of four pages);
(remind -pp3 Jan 2023 /dev/null ; \
remind -p June 2023 /dev/null) | rem2pdf -e -l -c=3 > cal.pdf
(remind -pp3 /dev/null Jan 2023 ; \
remind -pp /dev/null June 2023) | rem2pdf -e -l -c3 > cal.pdf
=head1 FORMATTED TEXT

View File

@@ -36,7 +36,7 @@ REMINDOBJS= $(REMINDSRCS:.c=.o)
all: remind rem2ps
test: remind
test: all
@sh ../tests/test-rem
.c.o:
@@ -50,7 +50,7 @@ rem2ps: rem2ps.o dynbuf.o json.o
remind: $(REMINDOBJS)
@CC@ @CFLAGS@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@
install-nostripped: all
install: all
-mkdir -p $(DESTDIR)$(bindir) || true
for prog in $(PROGS) $(SCRIPTS) ; do \
$(INSTALL_PROGRAM) $$prog $(DESTDIR)$(bindir) || exit 1; \
@@ -64,7 +64,7 @@ install-nostripped: all
-mkdir -p $(DESTDIR)$(datarootdir)/remind || true
cp -R ../include/* $(DESTDIR)$(datarootdir)/remind
install: install-nostripped
install-stripped: install
strip $(DESTDIR)$(bindir)/remind || true
strip $(DESTDIR)$(bindir)/rem2ps || true

View File

@@ -9,7 +9,7 @@
/* */
/***************************************************************/
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#include "config.h"
#include "custom.h"
@@ -301,8 +301,8 @@ static void WriteCalDays (void);
static int
DayOf(int jul)
{
int y, m, d;
FromJulian(jul, &y, &m, &d);
int d;
FromJulian(jul, NULL, NULL, &d);
return d;
}
@@ -313,7 +313,7 @@ Backgroundize(int d)
return;
}
if (!UseBGVTChars) {
if (!UseBGVTColors) {
return;
}
if (bgcolor[d][0] < 0) {
@@ -329,7 +329,7 @@ UnBackgroundize(int d)
return;
}
if (!UseBGVTChars) {
if (!UseBGVTColors) {
return;
}
if (bgcolor[d][0] < 0) {
@@ -474,7 +474,7 @@ void PrintJSONKeyPairTime(char const *name, int t)
}
#ifdef REM_USE_WCHAR
static void PutWideChar(wchar_t const wc)
void PutWideChar(wchar_t const wc)
{
char buf[MB_CUR_MAX+1];
int len;
@@ -687,27 +687,6 @@ static void ColorizeEntry(CalEntry const *e, int clamp)
printf("%s", Colorize(e->r, e->g, e->b, 0, clamp));
}
static int
ComputeCalWidth(int x)
{
struct winsize w;
if (x >= 71) {
/* Has been set with -w option */
return x;
}
if (!isatty(STDOUT_FILENO)) {
/* Output is not a TTY... assume 80 */
return 80;
}
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) {
return 80;
}
if (w.ws_col < 71) {
return 71;
}
return w.ws_col;
}
static void
InitMoonsAndShades(void)
{
@@ -720,7 +699,7 @@ InitMoonsAndShades(void)
}
/* Clear SHADEs */
if (UseBGVTChars) {
if (UseBGVTColors) {
for (i=0; i<=31; i++) {
bgcolor[i][0] = -1;
bgcolor[i][1] = -1;
@@ -740,12 +719,16 @@ SetShadeEntry(int jul, char const *shade)
int y, m, d;
int r, g, b;
/* Don't bother if we're not doing SHADE specials */
if (!UseBGVTChars) {
if (!UseBGVTColors) {
return;
}
if (sscanf(shade, "%d %d %d", &r, &g, &b) != 3) {
return;
if (sscanf(shade, "%d", &r) != 1) {
return;
}
g = r;
b = r;
}
if (r < 0 || g < 0 || b < 0 || r > 255 || g > 255 || b > 255) {
return;
@@ -818,8 +801,6 @@ void ProduceCalendar(void)
}
ShouldCache = 1;
CalWidth = ComputeCalWidth(CalWidth);
ColSpaces = (CalWidth - 9) / 7;
CalWidth = 7*ColSpaces + 8;
@@ -914,10 +895,18 @@ static void DoCalendarOneWeek(int nleft)
snprintf(buf, sizeof(buf), "%d %s ", d, get_month_abbrev(mon));
}
}
if (OrigJul+i == RealToday)
PrintLeft(buf, ColSpaces, '*');
else
if (OrigJul+i == RealToday) {
if (UseVTColors) {
printf("\x1B[1m"); /* Bold */
}
PrintLeft(buf, ColSpaces-1, '*');
if (UseVTColors) {
printf("\x1B[0m"); /* Normal */
}
putchar(' ');
} else {
PrintLeft(buf, ColSpaces, ' ');
}
gon();
DRAW(tb);
goff();
@@ -1129,7 +1118,13 @@ static int WriteCalendarRow(void)
}
}
if (Julian(y, m, d+i-wd) == RealToday) {
if (UseVTColors) {
printf("\x1B[1m"); /* Bold */
}
PrintLeft(buf, ColSpaces-1, '*');
if (UseVTColors) {
printf("\x1B[0m"); /* Normal */
}
putchar(' ');
} else {
PrintLeft(buf, ColSpaces, ' ');
@@ -1391,7 +1386,7 @@ static int WriteOneColLine(int col)
int clamp = 1;
int numwritten = 0;
int d = ColToDay[col];
if (d && UseBGVTChars && bgcolor[d][0] != -1) {
if (d && UseBGVTColors && bgcolor[d][0] != -1) {
clamp = 0;
}
/* Print as many characters as possible within the column */
@@ -1834,6 +1829,19 @@ static int DoCalRem(ParsePtr p, int col)
DBufFree(&buf);
}
trig.typ = tok.val;
if (trig.typ == MSG_TYPE ||
trig.typ == CAL_TYPE ||
trig.typ == MSF_TYPE) {
is_color = (
DefaultColorR != -1
&& DefaultColorG != -1
&& DefaultColorB != -1);
if (is_color) {
col_r = DefaultColorR;
col_g = DefaultColorG;
col_b = DefaultColorB;
}
}
jul = LastTriggerDate;
if (!LastTrigValid) {
FreeTrig(&trig);

View File

@@ -96,9 +96,13 @@ int DoRem(ParsePtr p)
FindToken(DBufValue(&buf), &tok);
DBufFree(&buf);
if (tok.type == T_Empty || tok.type == T_Comment) {
r = OK;
if (trig.addomit) {
r = AddGlobalOmit(LastTriggerDate);
}
DBufFree(&buf);
FreeTrig(&trig);
return OK;
return r;
}
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
DBufFree(&buf);
@@ -470,7 +474,12 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
case T_Tag:
r = ParseToken(s, &buf);
if (r) return r;
if (strchr(DBufValue(&buf), ',')) {
DBufFree(&buf);
return E_PARSE_ERR;
}
AppendTag(&(trig->tags), DBufValue(&buf));
DBufFree(&buf);
break;
case T_Duration:
@@ -869,7 +878,6 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
}
}
static int DidMsgReminder = 0;
/***************************************************************/
/* */
@@ -937,8 +945,8 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
if (!DoSubstFromString(DBufValue(&Banner), &buf,
JulianToday, NO_TIME) &&
DBufLen(&buf)) {
printf("%s\n", DBufValue(&buf));
}
printf("%s\n", DBufValue(&buf));
}
DBufFree(&buf);
}

View File

@@ -51,6 +51,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
int d, m, y;
int tim = tt->ttime;
int h, min, hh, ch, cmin, chh;
int i;
char const *pm, *cpm;
int tdiff, adiff, mdiff, hdiff;
char const *mplu, *hplu, *when, *plu;
@@ -190,8 +191,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
}
if (c == '\n') continue;
if (!c) {
if (mode != CAL_MODE && mode != ADVANCE_MODE &&
t->typ != RUN_TYPE && !MsgCommand) {
if (AddBlankLines &&
mode != CAL_MODE &&
mode != ADVANCE_MODE &&
t->typ != RUN_TYPE &&
!MsgCommand) {
if (DBufPutc(dbuf, '\n') != OK) return E_NO_MEM;
}
break;
@@ -221,6 +225,45 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
break;
}
}
if (c == '{') {
i = 0;
ss = s + snprintf(s, sizeof(s), "subst_");
while (1) {
c = ParseChar(p, &err, 0);
if (err) {
DBufFree(dbuf);
return err;
}
if (c == '}' || !c) {
break;
}
if (i < 64) {
*ss++ = c;
*ss = 0;
i++;
}
}
if (!c) {
Wprint("Warning: Unterminated %{...} substitution sequence");
}
if (UserFuncExists(s) != 3) {
continue;
}
snprintf(ss, sizeof(s) - (ss-s), "(%d,'%04d-%02d-%02d',%02d:%02d)",
altmode ? 1 : 0, y, m+1, d, h, min);
expr = (char const *) s;
r = EvalExpr(&expr, &v, NULL);
if (r == OK) {
if (!DoCoerce(STR_TYPE, &v)) {
if (DBufPuts(dbuf, v.v.str) != OK) {
DestroyValue(v);
return E_NO_MEM;
}
}
DestroyValue(v);
}
continue;
}
done = 0;
snprintf(uf, sizeof(uf), "subst_%c", c);
if (UserFuncExists(uf) == 3) {

View File

@@ -253,6 +253,10 @@ static int ParseExprToken(DynamicBuffer *buf, char const **in)
DBufFree(buf);
return E_NO_MEM;
}
if (!**in) {
DBufFree(buf);
return E_MISS_QUOTE;
}
continue;
}
c = *(*in)++;
@@ -1240,12 +1244,31 @@ BuiltinFunc *FindFunc(char const *name, BuiltinFunc where[], int num)
void PrintValue (Value *v, FILE *fp)
{
int y, m, d;
char const *s;
unsigned char const *s;
if (v->type == STR_TYPE) {
s=v->v.str;
s = (unsigned char const *) v->v.str;
putc('"', fp);
for (y=0; y<MAX_PRT_LEN && *s; y++) putc(*s++, fp);
for (y=0; y<MAX_PRT_LEN && *s; y++) {
switch(*s) {
case '\a': fprintf(ErrFp, "\\a"); break;
case '\b': fprintf(ErrFp, "\\b"); break;
case '\f': fprintf(ErrFp, "\\f"); break;
case '\n': fprintf(ErrFp, "\\n"); break;
case '\r': fprintf(ErrFp, "\\r"); break;
case '\t': fprintf(ErrFp, "\\t"); break;
case '\v': fprintf(ErrFp, "\\v"); break;
case '"': fprintf(ErrFp, "\\\""); break;
case '\\': fprintf(ErrFp, "\\\\"); break;
default:
if (*s < 32) {
fprintf(ErrFp, "\\x%02x", (unsigned int) *s);
} else {
putc(*s, ErrFp); break;
}
}
s++;
}
putc('"',fp);
if (*s) fprintf(fp, "...");
}

View File

@@ -13,12 +13,19 @@
#include "version.h"
#include "config.h"
#ifdef REM_USE_WCHAR
#define _XOPEN_SOURCE 600
#include <wctype.h>
#include <wchar.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <sys/ioctl.h>
#include <unistd.h>
@@ -58,6 +65,7 @@ static int FADusk (func_info *);
static int FAbs (func_info *);
static int FAccess (func_info *);
static int FAmpm (func_info *);
static int FAnsicolor (func_info *);
static int FTrig (func_info *);
static int FIsAny (func_info *);
static int FArgs (func_info *);
@@ -66,6 +74,7 @@ static int FBaseyr (func_info *);
static int FChar (func_info *);
static int FChoose (func_info *);
static int FCoerce (func_info *);
static int FColumns (func_info *);
static int FCurrent (func_info *);
static int FDate (func_info *);
static int FDateTime (func_info *);
@@ -94,6 +103,7 @@ static int FIsdst (func_info *);
static int FIsleap (func_info *);
static int FIsomitted (func_info *);
static int FLanguage (func_info *);
static int FLocalToUTC (func_info *);
static int FLower (func_info *);
static int FMax (func_info *);
static int FMin (func_info *);
@@ -118,6 +128,7 @@ static int FPsshade (func_info *);
static int FRealCurrent (func_info *);
static int FRealnow (func_info *);
static int FRealtoday (func_info *);
static int FRows (func_info *);
static int FSgn (func_info *);
static int FShell (func_info *);
static int FSlide (func_info *);
@@ -128,6 +139,7 @@ static int FSunrise (func_info *);
static int FSunset (func_info *);
static int FTime (func_info *);
static int FTimepart (func_info *);
static int FTimezone (func_info *);
static int FToday (func_info *);
static int FTrig (func_info *);
static int FTrigback (func_info *);
@@ -140,6 +152,7 @@ static int FTrigeventstart (func_info *);
static int FTrigfrom (func_info *);
static int FTrigger (func_info *);
static int FTrigpriority (func_info *);
static int FTrigtags (func_info *);
static int FTrigrep (func_info *);
static int FTrigscanfrom (func_info *);
static int FTrigtime (func_info *);
@@ -150,6 +163,7 @@ static int FTrigvalid (func_info *);
static int FTypeof (func_info *);
static int FTzconvert (func_info *);
static int FUpper (func_info *);
static int FUTCToLocal (func_info *);
static int FValue (func_info *);
static int FVersion (func_info *);
static int FWeekno (func_info *);
@@ -161,6 +175,7 @@ static int FShellescape (func_info *);
static int CleanUpAfterFunc (func_info *);
static int CheckArgs (BuiltinFunc *f, int nargs);
static int SunStuff (int rise, double cosz, int jul);
static int tz_set_tz (char const *tz);
/* "Overload" the struct Operator definition */
#define NO_MAX 127
@@ -214,12 +229,14 @@ BuiltinFunc Func[] = {
{ "adawn", 0, 1, 0, FADawn},
{ "adusk", 0, 1, 0, FADusk},
{ "ampm", 1, 3, 1, FAmpm },
{ "ansicolor", 1, 5, 1, FAnsicolor },
{ "args", 1, 1, 0, FArgs },
{ "asc", 1, 1, 1, FAsc },
{ "baseyr", 0, 0, 1, FBaseyr },
{ "char", 1, NO_MAX, 1, FChar },
{ "choose", 2, NO_MAX, 1, FChoose },
{ "coerce", 2, 2, 1, FCoerce },
{ "columns", 0, 1, 0, FColumns },
{ "current", 0, 0, 0, FCurrent },
{ "date", 3, 3, 1, FDate },
{ "datepart", 1, 1, 1, FDatepart },
@@ -249,6 +266,7 @@ BuiltinFunc Func[] = {
{ "isleap", 1, 1, 1, FIsleap },
{ "isomitted", 1, 1, 0, FIsomitted },
{ "language", 0, 0, 1, FLanguage },
{ "localtoutc", 1, 1, 1, FLocalToUTC },
{ "lower", 1, 1, 1, FLower },
{ "max", 1, NO_MAX, 1, FMax },
{ "min", 1, NO_MAX, 1, FMin },
@@ -273,6 +291,7 @@ BuiltinFunc Func[] = {
{ "realcurrent", 0, 0, 0, FRealCurrent},
{ "realnow", 0, 0, 0, FRealnow},
{ "realtoday", 0, 0, 0, FRealtoday },
{ "rows", 0, 0, 0, FRows },
{ "sgn", 1, 1, 1, FSgn },
{ "shell", 1, 2, 0, FShell },
{ "shellescape", 1, 1, 1, FShellescape },
@@ -284,6 +303,7 @@ BuiltinFunc Func[] = {
{ "sunset", 0, 1, 0, FSunset },
{ "time", 2, 2, 1, FTime },
{ "timepart", 1, 1, 1, FTimepart },
{ "timezone", 0, 1, 1, FTimezone },
{ "today", 0, 0, 0, FToday },
{ "trig", 0, NO_MAX, 0, FTrig },
{ "trigback", 0, 0, 0, FTrigback },
@@ -298,6 +318,7 @@ BuiltinFunc Func[] = {
{ "trigpriority", 0, 0, 0, FTrigpriority },
{ "trigrep", 0, 0, 0, FTrigrep },
{ "trigscanfrom", 0, 0, 0, FTrigscanfrom },
{ "trigtags", 0, 0, 0, FTrigtags },
{ "trigtime", 0, 0, 0, FTrigtime },
{ "trigtimedelta",0, 0, 0, FTrigtimedelta },
{ "trigtimerep", 0, 0, 0, FTrigtimerep },
@@ -306,6 +327,7 @@ BuiltinFunc Func[] = {
{ "typeof", 1, 1, 1, FTypeof },
{ "tzconvert", 2, 3, 0, FTzconvert },
{ "upper", 1, 1, 1, FUpper },
{ "utctolocal", 1, 1, 1, FUTCToLocal },
{ "value", 1, 2, 0, FValue },
{ "version", 0, 0, 1, FVersion },
{ "weekno", 0, 3, 1, FWeekno },
@@ -904,6 +926,87 @@ static int FSgn(func_info *info)
return OK;
}
static int parse_color_helper(char const *str, int *r, int *g, int *b)
{
if (!*str) {
/* Empty string means "reset to normal" */
*r = -1;
*g = -1;
*b = -1;
return OK;
}
if (sscanf(str, "%d %d %d", r, g, b) != 3) {
return E_BAD_TYPE;
}
return OK;
}
/***************************************************************/
/* */
/* FAnsicolor - return an ANSI terminal color sequence */
/* */
/***************************************************************/
static int FAnsicolor(func_info *info)
{
int r=0, g=0, b=0, bg=0, clamp=1;
int status = 0;
int index = 0;
bg = 0;
clamp = 1;
/* If first arg is a string: Parse out the colors */
if (ARG(0).type == STR_TYPE) {
/* If first arg is a string: Parse out the colors */
status = parse_color_helper(ARGSTR(0), &r, &g, &b);
if (status != 0) {
return status;
}
index = 1;
} else if (ARG(0).type == INT_TYPE) {
/* Must be at least three arguments */
if (Nargs < 3) return E_2FEW_ARGS;
ASSERT_TYPE(1, INT_TYPE);
ASSERT_TYPE(2, INT_TYPE);
r = ARGV(0);
g = ARGV(1);
b = ARGV(2);
index = 3;
}
if (r < -1 || g < -1 || b < -1) return E_2LOW;
if (r > 255 || g > 255 || b > 255) return E_2HIGH;
/* If any is -1, then all must be -1 */
if (r == -1 || g == -1 || b == -1) {
if (r != -1 || g != -1 || b != -1) {
return E_2LOW;
}
}
if (Nargs > index) {
ASSERT_TYPE(index, INT_TYPE);
if (ARGV(index) < 0) return E_2LOW;
if (ARGV(index) > 1) return E_2HIGH;
bg = ARGV(index);
index++;
if (Nargs > index) {
ASSERT_TYPE(index, INT_TYPE);
if (ARGV(index) < 0) return E_2LOW;
if (ARGV(index) > 1) return E_2HIGH;
clamp = ARGV(index);
}
}
/* All righ! We have our parameters; now return the string */
if (!UseVTColors) {
/* Not using any colors: Empty strin */
return RetStrVal("", info);
}
if (r < 0) {
/* Return ANSI "reset to normal" string */
return RetStrVal(Decolorize(), info);
}
return RetStrVal(Colorize(r, g, b, bg, clamp), info);
}
/***************************************************************/
/* */
/* FAmpm - return a time as a string with "AM" or "PM" suffix */
@@ -1469,6 +1572,11 @@ static int FTrigrep(func_info *info)
return OK;
}
static int FTrigtags(func_info *info)
{
return RetStrVal(DBufValue(&(LastTrigger.tags)), info);
}
static int FTrigpriority(func_info *info)
{
RetVal.type = INT_TYPE;
@@ -2225,6 +2333,115 @@ static int FTimeStuff(int wantmins, func_info *info)
return OK;
}
static int FTimezone(func_info *info)
{
int yr, mon, day, hr, min, jul, now;
struct tm local, *withzone;
time_t t;
char buf[64];
if (Nargs == 0) {
jul = JulianToday;
now = (SystemTime(0) / 60);
} else {
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
jul = DATEPART(ARG(0));
if (HASTIME(ARG(0))) {
now = TIMEPART(ARG(0));
} else {
now = 0;
}
}
FromJulian(jul, &yr, &mon, &day);
hr = now / 60;
min = now % 60;
memset(&local, 0, sizeof(local));
local.tm_sec = 0;
local.tm_min = min;
local.tm_hour = hr;
local.tm_mday = day;
local.tm_mon = mon;
local.tm_year = yr-1900;
local.tm_isdst = -1;
t = mktime(&local);
withzone = localtime(&t);
buf[0] = 0;
strftime(buf, sizeof(buf), "%Z", withzone);
return RetStrVal(buf, info);
}
static int FLocalToUTC(func_info *info)
{
int yr, mon, day, hr, min, jul;
time_t loc_t;
struct tm local, *utc;
ASSERT_TYPE(0, DATETIME_TYPE);
FromJulian(DATEPART(ARG(0)), &yr, &mon, &day);
hr = TIMEPART(ARG(0))/60;
min = TIMEPART(ARG(0))%60;
memset(&local, 0, sizeof(local));
local.tm_sec = 0;
local.tm_min = min;
local.tm_hour = hr;
local.tm_mday = day;
local.tm_mon = mon;
local.tm_year = yr-1900;
local.tm_isdst = -1;
loc_t = mktime(&local);
if (loc_t == -1) {
return E_MKTIME_PROBLEM;
}
utc = gmtime(&loc_t);
jul = Julian(utc->tm_year+1900, utc->tm_mon, utc->tm_mday);
RetVal.type = DATETIME_TYPE;
RETVAL = MINUTES_PER_DAY * jul + utc->tm_hour*60 + utc->tm_min;
return OK;
}
static int FUTCToLocal(func_info *info)
{
int yr, mon, day, hr, min, jul;
time_t utc_t;
struct tm *local, utc;
char const *old_tz;
ASSERT_TYPE(0, DATETIME_TYPE);
FromJulian(DATEPART(ARG(0)), &yr, &mon, &day);
hr = TIMEPART(ARG(0))/60;
min = TIMEPART(ARG(0))%60;
old_tz = getenv("TZ");
tz_set_tz("UTC");
memset(&utc, 0, sizeof(utc));
utc.tm_sec = 0;
utc.tm_min = min;
utc.tm_hour = hr;
utc.tm_mday = day;
utc.tm_mon = mon;
utc.tm_year = yr-1900;
utc.tm_isdst = 0;
utc_t = mktime(&utc);
tz_set_tz(old_tz);
if (utc_t == -1) {
return E_MKTIME_PROBLEM;
}
local = localtime(&utc_t);
jul = Julian(local->tm_year+1900, local->tm_mon, local->tm_mday);
RetVal.type = DATETIME_TYPE;
RETVAL = MINUTES_PER_DAY * jul + local->tm_hour*60 + local->tm_min;
return OK;
}
/***************************************************************/
/* */
/* Sunrise and sunset functions. */
@@ -2926,11 +3143,11 @@ FSlide(func_info *info)
}
/* If ALL weekdays are omitted... barf! */
if (localomit == 127 && amt != 0) return E_2MANY_LOCALOMIT;
if ((WeekdayOmits | localomit) == 0x7F && amt != 0) return E_2MANY_LOCALOMIT;
if (amt > 0) {
while(amt) {
d++;
r = IsOmitted(d, localomit, NULL,&omit);
r = IsOmitted(d, localomit, NULL, &omit);
if (r) return r;
if (!omit) amt--;
}
@@ -2938,7 +3155,7 @@ FSlide(func_info *info)
while(amt) {
d--;
if (d < 0) return E_DATE_OVER;
r = IsOmitted(d, localomit, NULL,&omit);
r = IsOmitted(d, localomit, NULL, &omit);
if (r) return r;
if (!omit) amt++;
}
@@ -3165,3 +3382,77 @@ FTrig(func_info *info)
}
return OK;
}
static int
rows_or_cols(func_info *info, int want_rows)
{
struct winsize w;
int fd = STDOUT_FILENO;
RetVal.type = INT_TYPE;
if (!isatty(fd)) {
fd = open("/dev/tty", O_RDONLY);
if (fd < 0) {
RETVAL = -1;
return OK;
}
}
if (ioctl(fd, TIOCGWINSZ, &w) == 0) {
if (want_rows) RETVAL = w.ws_row;
else RETVAL = w.ws_col;
} else {
RETVAL = -1;
}
if (fd != STDOUT_FILENO) {
close(fd);
}
return OK;
}
static int FRows(func_info *info)
{
return rows_or_cols(info, 1);
}
static int FColumns(func_info *info)
{
#ifdef REM_USE_WCHAR
size_t len;
wchar_t *buf, *s;
int width;
#endif
if (Nargs == 0) {
return rows_or_cols(info, 0);
}
ASSERT_TYPE(0, STR_TYPE);
#ifdef REM_USE_WCHAR
len = mbstowcs(NULL, ARGSTR(0), 0);
if (len == (size_t) -1) return E_NO_MEM;
buf = calloc(len+1, sizeof(wchar_t));
if (!buf) return E_NO_MEM;
(void) mbstowcs(buf, ARGSTR(0), len+1);
s = buf;
width = 0;
while (*s) {
if (*s == 0x1B && *(s+1) == '[') {
/* Skip escape sequences */
s += 2;
while (*s && (*s < 0x40 || *s > 0x7E)) {
s++;
}
if (*s) {
s++;
}
continue;
}
width += wcwidth(*s);
s++;
}
free(buf);
RetVal.type = INT_TYPE;
RETVAL = width;
return OK;
#else
return E_BAD_TYPE;
#endif
}

View File

@@ -58,9 +58,10 @@ EXTERN INIT( int DoSimpleCalendar, 0);
EXTERN INIT( int DoSimpleCalDelta, 0);
EXTERN INIT( int DoPrefixLineNo, 0);
EXTERN INIT( int MondayFirst, 0);
EXTERN INIT( int AddBlankLines, 1);
EXTERN INIT( int Iterations, 1);
EXTERN INIT( int PsCal, 0);
EXTERN INIT( int CalWidth, -1);
EXTERN INIT( int CalWidth, 80);
EXTERN INIT( int CalWeeks, 0);
EXTERN INIT( int CalMonths, 0);
EXTERN INIT( int Hush, 0);
@@ -80,6 +81,7 @@ EXTERN INIT( long SysTime, -1L);
EXTERN char const *InitialFile;
EXTERN int FileAccessDate;
EXTERN INIT( int WeekdayOmits, 0);
EXTERN INIT( int DontSuppressQuoteMarkers, 0);
EXTERN INIT( int DontFork, 0);
EXTERN INIT( int DontQueue, 0);
@@ -111,12 +113,13 @@ EXTERN INIT( int LastTriggerTime, 0);
EXTERN INIT( int ShouldCache, 0);
EXTERN char const *CurLine;
EXTERN INIT( int NumTriggered, 0);
EXTERN INIT( int DidMsgReminder, 0);
EXTERN int ArgC;
EXTERN char const **ArgV;
EXTERN INIT( int CalLines, CAL_LINES);
EXTERN INIT( int CalPad, 1);
EXTERN INIT( int UseVTChars, 0);
EXTERN INIT( int UseBGVTChars, 0);
EXTERN INIT( int UseBGVTColors, 0);
EXTERN INIT( int UseUTF8Chars, 0);
EXTERN INIT( int UseVTColors, 0);
EXTERN INIT( int Use256Colors, 0);

View File

@@ -21,6 +21,10 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/ioctl.h>
@@ -95,6 +99,25 @@ static void AddTrustedUser(char const *username);
static DynamicBuffer default_filename_buf;
static void
InitCalWidthAndFormWidth(int fd)
{
struct winsize w;
if (!isatty(fd)) {
return;
}
if (ioctl(fd, TIOCGWINSZ, &w) == 0) {
CalWidth = w.ws_col;
if (CalWidth < 71) {
CalWidth = 71;
}
FormWidth = w.ws_col - 8;
if (FormWidth < 20) FormWidth = 20;
if (FormWidth > 500) FormWidth = 500;
}
}
/***************************************************************/
/* */
/* DefaultFilename */
@@ -142,19 +165,13 @@ void InitRemind(int argc, char const *argv[])
int weeks;
int x;
int jul;
int ttyfd;
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;
}
}
InitCalWidthAndFormWidth(STDOUT_FILENO);
/* Initialize global dynamic buffers */
DBufInit(&Banner);
@@ -262,7 +279,7 @@ void InitRemind(int argc, char const *argv[])
argv[0]);
x = 0;
}
UseBGVTChars = x;
UseBGVTColors = x;
}
break;
@@ -510,11 +527,27 @@ void InitRemind(int argc, char const *argv[])
case 'w':
case 'W':
if (*arg != ',') {
PARSENUM(CalWidth, arg);
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
if (CalWidth == 0) {
CalWidth = -1;
}
if (*arg == 't') {
arg++;
/* -wt means get width from /dev/tty */
ttyfd = open("/dev/tty", O_RDONLY);
if (!ttyfd) {
fprintf(stderr, "%s: `-wt': Cannot open /dev/tty: %s\n",
argv[0], strerror(errno));
} else {
InitCalWidthAndFormWidth(ttyfd);
close(ttyfd);
}
} else {
PARSENUM(CalWidth, arg);
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
if (CalWidth == 0) {
CalWidth = -1;
}
FormWidth = CalWidth - 8;
if (FormWidth < 20) FormWidth = 20;
if (FormWidth > 500) FormWidth = 500;
}
}
if (*arg == ',') {
arg++;

View File

@@ -23,7 +23,7 @@
#define ITALIAN 9 /* translated by Valerio Aimale */
#define ROMANIAN 10 /* translated by Liviu Daia */
#define SPANISH 11 /* translated by Rafa Couto */
#define ICELANDIC 12 /* translated by Björn Davíðsson */
#define ICELANDIC 12 /* translated by Björn Davíðsson */
/* Add more languages here - but please e-mail dianne@skoll.ca
to have your favorite language assigned a number. If you add a

View File

@@ -10,8 +10,10 @@
/* */
/***************************************************************/
#define _XOPEN_SOURCE 600
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
@@ -35,6 +37,10 @@
#endif
#include <sys/types.h>
#ifdef REM_USE_WCHAR
#include <wctype.h>
#include <wchar.h>
#endif
#include "types.h"
#include "protos.h"
@@ -67,6 +73,7 @@ int main(int argc, char *argv[])
ArgV = (char const **) argv;
InitRemind(argc, (char const **) argv);
DBufInit(&(LastTrigger.tags));
ClearLastTriggers();
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
@@ -176,7 +183,7 @@ static void DoReminders(void)
}
if (FileAccessDate < 0) {
fprintf(ErrFp, "%s: `%s'.\n", ErrMsg[E_CANTACCESS], InitialFile);
fprintf(ErrFp, "%s: `%s': %s.\n", ErrMsg[E_CANTACCESS], InitialFile, strerror(errno));
exit(1);
}
@@ -329,7 +336,8 @@ int Julian(int year, int month, int day)
/* */
/* FromJulian */
/* */
/* Convert a Julian date to year, month, day. */
/* Convert a Julian date to year, month, day. You may supply */
/* NULL for y, m or d if you're not interested in that value */
/* */
/***************************************************************/
void FromJulian(int jul, int *y, int *m, int *d)
@@ -358,9 +366,15 @@ void FromJulian(int jul, int *y, int *m, int *d)
try_mon++;
t = DaysInMonth(try_mon, try_yr);
}
*y = try_yr;
*m = try_mon;
*d = jul + 1;
if (y) {
*y = try_yr;
}
if (m) {
*m = try_mon;
}
if (d) {
*d = jul + 1;
}
return;
}
@@ -857,19 +871,19 @@ int DoIfTrig(ParsePtr p)
Eprint("%s", ErrMsg[r]);
}
}
syndrome = IF_TRUE | BEFORE_ELSE;
syndrome = IF_FALSE | BEFORE_ELSE;
}
else {
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
syndrome = IF_TRUE | BEFORE_ELSE;
} else {
syndrome = IF_FALSE | BEFORE_ELSE;
if (PurgeMode) {
PurgeEchoLine("%s\n", "#!P: The next IFTRIG did not trigger.");
PurgeEchoLine("%s\n", "#!P: REM statements in IFTRIG block not checked for purging.");
}
}
}
if (syndrome == (IF_FALSE | BEFORE_ELSE) && PurgeMode) {
PurgeEchoLine("%s\n", "#!P: The next IFTRIG did not trigger.");
PurgeEchoLine("%s\n", "#!P: REM statements in IFTRIG block not checked for purging.");
}
FreeTrig(&trig);
}
NumIfs++;
@@ -1176,6 +1190,8 @@ int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
local.tm_sec = 0;
local.tm_min = tim % 60;
local.tm_hour = tim / 60;
local.tm_mday = day;
local.tm_mon = mon;
local.tm_year = yr-1900;
@@ -1204,6 +1220,144 @@ int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
return 0;
}
static char const *OutputEscapeSequences(char const *s, int print)
{
while (*s == 0x1B && *(s+1) == '[') {
if (print) putchar(*s);
s++;
if (print) putchar(*s);
s++;
while (*s && (*s < 0x40 || *s > 0x7E)) {
if (print) putchar(*s);
s++;
}
if (*s) {
if (print) putchar(*s);
s++;
}
}
return s;
}
#ifdef REM_USE_WCHAR
#define ISWBLANK(c) (iswspace(c) && (c) != '\n')
static wchar_t const *OutputEscapeSequencesWS(wchar_t const *s, int print)
{
while (*s == 0x1B && *(s+1) == '[') {
if (print) PutWideChar(*s);
s++;
if (print) PutWideChar(*s);
s++;
while (*s && (*s < 0x40 || *s > 0x7E)) {
if (print) PutWideChar(*s);
s++;
}
if (*s) {
if (print) PutWideChar(*s);
s++;
}
}
return s;
}
static void
FillParagraphWCAux(wchar_t const *s)
{
int line = 0;
int i, j;
int doublespace = 1;
int pendspace;
int len;
wchar_t const *t;
int roomleft;
/* Start formatting */
while(1) {
/* If it's a carriage return, output it and start new paragraph */
if (*s == '\n') {
putchar('\n');
s++;
line = 0;
while(ISWBLANK(*s)) s++;
continue;
}
if (!*s) {
return;
}
/* Over here, we're at the beginning of a line. Emit the correct
number of spaces */
j = line ? SubsIndent : FirstIndent;
for (i=0; i<j; i++) {
putchar(' ');
}
/* Calculate the amount of room left on this line */
roomleft = FormWidth - j;
pendspace = 0;
/* Emit words until the next one won't fit */
while(1) {
while(ISWBLANK(*s)) s++;
if (*s == '\n') break;
while(1) {
t = s;
s = OutputEscapeSequencesWS(s, 1);
if (s == t) break;
while(ISWBLANK(*s)) s++;
}
t = s;
len = 0;
while(*s && !iswspace(*s)) {
if (*s == 0x1B && *(s+1) == '[') {
s = OutputEscapeSequencesWS(s, 0);
continue;
}
len += wcwidth(*s);
s++;
}
if (s == t) {
return;
}
if (!pendspace || len+pendspace <= roomleft) {
for (i=0; i<pendspace; i++) {
putchar(' ');
}
while(t < s) {
PutWideChar(*t);
if (strchr(EndSent, *t)) doublespace = 2;
else if (!strchr(EndSentIg, *t)) doublespace = 1;
t++;
}
} else {
s = t;
putchar('\n');
line++;
break;
}
roomleft -= len+doublespace;
pendspace = doublespace;
}
}
}
static int
FillParagraphWC(char const *s)
{
size_t len;
wchar_t *buf;
len = mbstowcs(NULL, s, 0);
if (len == (size_t) -1) return E_NO_MEM;
buf = calloc(len+1, sizeof(wchar_t));
if (!buf) return E_NO_MEM;
(void) mbstowcs(buf, s, len+1);
FillParagraphWCAux(buf);
free(buf);
return OK;
}
#endif
/***************************************************************/
/* */
/* FillParagraph */
@@ -1230,11 +1384,17 @@ void FillParagraph(char const *s)
char const *t;
int roomleft;
if (!s || !*s) return;
/* Skip leading spaces */
while(ISBLANK(*s)) s++;
if (!*s) return;
#ifdef REM_USE_WCHAR
if (FillParagraphWC(s) == OK) {
return;
}
#endif
/* Start formatting */
while(1) {
@@ -1265,10 +1425,23 @@ void FillParagraph(char const *s)
while(1) {
while(ISBLANK(*s)) s++;
if (*s == '\n') break;
while(1) {
t = s;
s = OutputEscapeSequences(s, 1);
if (s == t) break;
while(ISBLANK(*s)) s++;
}
t = s;
while(*s && !isspace(*s)) s++;
len = s - t;
if (!len) {
len = 0;
while(*s && !isspace(*s)) {
if (*s == 0x1B && *(s+1) == '[') {
s = OutputEscapeSequences(s, 0);
continue;
}
s++;
len++;
}
if (s == t) {
return;
}
if (!pendspace || len+pendspace <= roomleft) {
@@ -1414,6 +1587,7 @@ ClearLastTriggers(void)
LastTrigger.warn[0] = 0;
LastTrigger.omitfunc[0] = 0;
LastTrigger.passthru[0] = 0;
DBufFree(&(LastTrigger.tags));
LastTimeTrig.ttime = NO_TIME;
LastTimeTrig.delta = NO_DELTA;
@@ -1434,8 +1608,10 @@ SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigt
void
SaveLastTrigger(Trigger const *t)
{
DBufFree(&(LastTrigger.tags));
memcpy(&LastTrigger, t, sizeof(LastTrigger));
DBufInit(&(LastTrigger.tags));
DBufPuts(&(LastTrigger.tags), DBufValue(&(t->tags)));
}
void

View File

@@ -28,6 +28,8 @@ static void InsertIntoSortedArray (int *array, int num, int key);
static int FullOmitArray[MAX_FULL_OMITS];
static int PartialOmitArray[MAX_PARTIAL_OMITS];
/* WeekdayOmits is declared in global.h */
/* How many of each omit types do we have? */
static int NumFullOmits, NumPartialOmits;
@@ -37,6 +39,7 @@ typedef struct omitcontext {
int numfull, numpart;
int *fullsave;
int *partsave;
int weekdaysave;
} OmitContext;
/* The stack of saved omit contexts */
@@ -52,6 +55,7 @@ static OmitContext *SavedOmitContexts = NULL;
int ClearGlobalOmits(void)
{
NumFullOmits = NumPartialOmits = 0;
WeekdayOmits = 0;
return OK;
}
@@ -113,6 +117,7 @@ int PushOmitContext(ParsePtr p)
context->numfull = NumFullOmits;
context->numpart = NumPartialOmits;
context->weekdaysave = WeekdayOmits;
context->fullsave = malloc(NumFullOmits * sizeof(int));
if (NumFullOmits && !context->fullsave) {
free(context);
@@ -154,6 +159,7 @@ int PopOmitContext(ParsePtr p)
if (!c) return E_POP_NO_PUSH;
NumFullOmits = c->numfull;
NumPartialOmits = c->numpart;
WeekdayOmits = c->weekdaysave;
/* Copy the context over */
for (i=0; i<NumFullOmits; i++)
@@ -213,6 +219,12 @@ int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
return OK;
}
/* Is it omitted because of global weekday omits? */
if (WeekdayOmits & (1 << (jul % 7))) {
*omit = 1;
return OK;
}
/* Is it omitted because of fully-specified omits? */
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) {
*omit = 1;
@@ -289,6 +301,7 @@ int DoOmit(ParsePtr p)
int syndrome;
int not_first_token = -1;
int start, end, tmp;
int wd = 0;
int mc, dc;
@@ -301,9 +314,15 @@ int DoOmit(ParsePtr p)
if ( (r=ParseToken(p, &buf)) ) return r;
FindToken(DBufValue(&buf), &tok);
switch (tok.type) {
case T_Dumpvars:
if (not_first_token) return E_PARSE_ERR;
case T_WkDay:
DBufFree(&buf);
if (wd & (1 << tok.val)) return E_WD_TWICE;
wd |= (1 << tok.val);
break;
case T_Dumpvars:
DBufFree(&buf);
if (not_first_token) return E_PARSE_ERR;
r = VerifyEoln(p);
if (r != OK) return r;
DumpOmits();
@@ -341,6 +360,7 @@ int DoOmit(ParsePtr p)
case T_Through:
DBufFree(&buf);
if (wd) return E_PARSE_ERR;
if (seen_through) return E_UNTIL_TWICE;
seen_through = 1;
break;
@@ -363,6 +383,18 @@ int DoOmit(ParsePtr p)
}
}
if (wd) {
if (y[0] != NO_YR || m[0] != NO_MON || d[0] != NO_DAY) {
return E_PARSE_ERR;
}
if ((WeekdayOmits | wd) == 0x7F) {
return E_2MANY_LOCALOMIT;
}
WeekdayOmits |= wd;
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
return OK;
}
if (!seen_through) {
/* We must have at least a month */
if (m[0] == NO_MON) return E_SPEC_MON;
@@ -482,5 +514,15 @@ DumpOmits(void)
printf("\t%02d%c%02d\n", m+1, DateSep, d);
}
}
printf("Global Weekday OMITs:\n");
if (WeekdayOmits == 0) {
printf("\tNone.\n");
} else {
for (i=0; i<7; i++) {
if (WeekdayOmits & (1<<i)) {
printf("\t%s\n", EnglishDayName[i]);
}
}
}
}

View File

@@ -177,3 +177,9 @@ void clear_callstack(void);
int have_callstack(void);
int print_callstack(FILE *fp);
void pop_call(void);
#ifdef REM_USE_WCHAR
#define _XOPEN_SOURCE 600
#include <wctype.h>
#include <wchar.h>
void PutWideChar(wchar_t const wc);
#endif

View File

@@ -127,7 +127,7 @@ void HandleQueuedReminders(void)
struct sigaction sa;
/* Suppress the BANNER from being issued */
NumTriggered = 1;
DidMsgReminder = 1;
/* Turn off sorting -- otherwise, TriggerReminder has no effect! */
SortByDate = 0;

View File

@@ -530,7 +530,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
*err = OK;
/* But check for obvious problems... */
if (trig->localomit == 1 + 2 + 4 + 8 + 16 + 32 + 64) {
if ((WeekdayOmits | trig->localomit) == 0x7F) {
*err = E_2MANY_LOCALOMIT;
return -1;
}

View File

@@ -238,6 +238,6 @@ typedef struct {
/* Pure JSON */
#define PSCAL_LEVEL3 3
#define TERMINAL_BACKGROUND_UNKNOWN 0
#define TERMINAL_BACKGROUND_DARK 1
#define TERMINAL_BACKGROUND_LIGHT 2
#define TERMINAL_BACKGROUND_UNKNOWN -1
#define TERMINAL_BACKGROUND_DARK 0
#define TERMINAL_BACKGROUND_LIGHT 1

View File

@@ -776,6 +776,7 @@ typedef struct {
/* All of the system variables sorted alphabetically */
static SysVar SysVarArr[] = {
/* name mod type value min/mal max validate*/
{"AddBlankLines", 1, INT_TYPE, &AddBlankLines, 0, 1, NULL },
{"Ago", 1, STR_TYPE, &DynamicAgo, 0, 0, NULL },
{"Am", 1, STR_TYPE, &DynamicAm, 0, 0, NULL },
{"And", 1, STR_TYPE, &DynamicAnd, 0, 0, NULL },
@@ -854,6 +855,7 @@ static SysVar SysVarArr[] = {
{"SysInclude", 0, STR_TYPE, &SysDir, 0, 0, NULL },
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0, NULL },
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0, NULL },
{"TerminalBackground", 0, INT_TYPE, &TerminalBackground, 0, 0, NULL },
{"Thursday", 1, STR_TYPE, &DynamicDayName[3], 0, 0, NULL },
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0, NULL },
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0, NULL },
@@ -866,6 +868,10 @@ static SysVar SysVarArr[] = {
{"Ud", 0, SPECIAL_TYPE, today_day_func, 0, 0, NULL },
{"Um", 0, SPECIAL_TYPE, today_mon_func, 0, 0, NULL },
{"UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0, NULL },
{"Use256Colors", 0, INT_TYPE, &Use256Colors, 0, 0, NULL },
{"UseBGVTColors", 0, INT_TYPE, &UseBGVTColors, 0, 0, NULL },
{"UseTrueColors", 0, INT_TYPE, &UseTrueColors, 0, 0, NULL },
{"UseVTColors", 0, INT_TYPE, &UseVTColors, 0, 0, NULL },
{"Uw", 0, SPECIAL_TYPE, today_wday_func, 0, 0, NULL },
{"Uy", 0, SPECIAL_TYPE, today_year_func, 0, 0, NULL },
{"Was", 1, STR_TYPE, &DynamicWas, 0, 0, NULL },
@@ -1023,6 +1029,7 @@ void DumpSysVarByName(char const *name)
static void DumpSysVar(char const *name, const SysVar *v)
{
char buffer[VAR_NAME_LEN+10];
Value vtmp;
if (name && !*name) name=NULL;
if (!v && !name) return; /* Shouldn't happen... */
@@ -1036,32 +1043,20 @@ static void DumpSysVar(char const *name, const SysVar *v)
fprintf(ErrFp, "%16s ", buffer);
if (v) {
if (v->type == SPECIAL_TYPE) {
Value val;
SysVarFunc f = (SysVarFunc) v->value;
f(0, &val);
PrintValue(&val, ErrFp);
f(0, &vtmp);
PrintValue(&vtmp, ErrFp);
putc('\n', ErrFp);
DestroyValue(val);
DestroyValue(vtmp);
} else if (v->type == STR_TYPE) {
char const *s = *((char **)v->value);
int y;
putc('"', ErrFp);
for (y=0; y<MAX_PRT_LEN && *s; y++) {
if (*s == '"') {
fprintf(ErrFp, "\" + char(34) + \"");
s++;
} else {
putc(*s++, ErrFp);
}
}
putc('"', ErrFp);
if (*s) fprintf(ErrFp, "...");
vtmp.type = STR_TYPE;
vtmp.v.str = * ((char **)v->value);
PrintValue(&vtmp, ErrFp);
putc('\n', ErrFp);
} else if (v->type == DATE_TYPE) {
Value val;
val.type = DATE_TYPE;
val.v.val = * (int *) v->value;
PrintValue(&val, ErrFp);
vtmp.type = DATE_TYPE;
vtmp.v.val = * (int *) v->value;
PrintValue(&vtmp, ErrFp);
putc('\n', ErrFp);
} else {
if (!v->modifiable) fprintf(ErrFp, "%d\n", *((int *)v->value));

49
tests/ansicolors.rem Normal file
View File

@@ -0,0 +1,49 @@
BANNER %
MSG TerminalBackground is: [$TerminalBackground]%
MSG UseVTColors is: [$UseVTColors]%
MSG Use256Colors is: [$Use256Colors]%
MSG UseTrueColors is: [$UseTrueColors]%
MSG UseBGVTColors is: [$UseBGVTColors]%
set n ansicolor("")]
MSG This is [ansicolor(0,255,0)]green[n], [ansicolor("255 0 0")]red[n] and [ansicolor("0 0 255")]blue[n] text.%
MSG This is [ansicolor(0,0,0)][ansicolor(0,255,0,1)]black text on a green background[n]%
MSG This is [ansicolor(0,0,0,0,1)]clamped black text[n]%
MSG This is [ansicolor(255,255,255,0,1)]clamped white text[n]
FLUSH
# Test that MSF ignores ansi color sequences
set r ansicolor(255, 0, 0)
set g ansicolor(0, 255, 0)
set b ansicolor(0, 0, 255)
set n ansicolor("")
REM MSF Here we have a formatted reminder. It should be word-wrapped nicely and neatly by Remind. Although it is very long and unwieldy, the MSF keyword will wrap it so it's pleasantly readable.%_Here we have a formatted reminder. It should be word-wrapped nicely and neatly by Remind. Although it is very long and unwieldy, the MSF keyword will wrap it so it's pleasantly readable.
# Should have exactly the same word breaks
REM MSF [r]Here [g]we [b]have [r]a [g]formatted [b]reminder. [r]It [g]should[b] be [r]word-wrapped[g] nicely [b]and [r]neatly [g]by Remind. [b]Although [r]it [g]is [b]very [r]long [g]and [b]u[r]n[g]w[b]i[r]e[g]l[b]d[r]y[g], [r]the [g]MSF [b]keyword [r]will [r] [g] [b] [g]wrap [b]it [r]so [g]it's [b]pleasantly [r]readable.[n]%_[r]Here [g]we [b]have [r]a [g]formatted [b]reminder. [r]It [g]should[b] be [r]word-wrapped[g] nicely [b]and [r]neatly [g]by Remind. [b]Although [r]it [g]is [b]very [r]long [g]and [b]u[r]n[g]w[b]i[r]e[g]l[b]d[r]y[g], [r]the [g]MSF [b]keyword [r]will [r] [g] [b] [g]wrap [b]it [r]so [g]it's [b]pleasantly [r]readable.[n]
REM MSF Εδώ έχουμε μια μορφοποιημένη υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅%_Εδώ έχουμε μια μορφοποιημένη υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅
REM MSF [r]Εδώ [g]έχουμε [b]μια [r]μ[g]ο[b]ρ[r]φοποιημένη[n] υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅%_[r]Εδώ [g]έχουμε [b]μια [r]μ[g]ο[b]ρ[r]φοποιημένη[n] υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅
FLUSH
# Some invalid combos
set a ansicolor(1)
set a ansicolor(-1, 0, 0)
set a ansicolor(42, 42, 256)
set a ansicolor("foo")
set a ansicolor("1 1")
set a ansicolor("-1 -1 0");
set a ansicolor("256 1 1");
set a ansicolor(128, 128, 128, 2)
set a ansicolor(128, 128, 128, -1)
set a ansicolor(128, 128, 128, 0, 2)
set a ansicolor(128, 128, 128, 0, -1)
set a ansicolor(128,0,0)
set str a + "foo: 🌅"
set w columns(str)
MSG Width of [str] is: [w]

5
tests/blanks.rem Normal file
View File

@@ -0,0 +1,5 @@
MSG $AddBlankLines=[$AddBlankLines]%_
MSG Hello
MSG Hi
MSF How are you?
MSG OK

View File

@@ -15,3 +15,6 @@ REM 28 SPECIAL COLOUR 129 0 129 Bright Magenta
REM 28 SPECIAL COLOUR 129 129 0 Bright Yellow
REM 28 SPECIAL COLOUR 129 129 129 Bright White
SET $DefaultColor "255 255 0"
REM 23 SATISFY [1] MSG DefaultColor_Yellow

View File

@@ -26,11 +26,30 @@ if test `id -u` = 0 ; then
exit 1
fi
# If we're already in a utf-8 locale, do
# nothing; otherwise, set LC_ALL
OK=0
if echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
OK=1
fi
if test -z "$LC_ALL" ; then
if echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
export LC_ALL="$LANG"
OK=1
fi
fi
if test "$OK" = 0 ; then
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
fi
chmod 000 include_dir/04cantread.rem
TEST_GETENV="foo bar baz" ; export TEST_GETENV
echo "Test 1" > ../tests/test.out
echo "" >> ../tests/test.out
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 >> ../tests/test.out 2>&1
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 12:13 >> ../tests/test.out 2>&1
echo "" >> ../tests/test.out
echo "Test 2" >> ../tests/test.out
echo "" >> ../tests/test.out
@@ -76,6 +95,32 @@ echo 'REM Mon 31 2021 MSG [$T]' | ../src/remind -dt - 31 dec 2021 >> ../tests/te
echo "Color Test" >> ../tests/test.out
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
echo "ANSI Color Test" >> ../tests/test.out
../src/remind ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,0 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,0 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,0 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,0,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,0,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,0,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,1,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,1,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,1,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
echo '$AddBlankLines test' >> ../tests/test.out
../src/remind ../tests/blanks.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind '-i$AddBlankLines=1' ../tests/blanks.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind '-i$AddBlankLines=0' ../tests/blanks.rem 1 Jan 2022 >> ../tests/test.out 2>&1
echo "MON WKDAY DAY across year test" >> ../tests/test.out
echo 'REM Mon 29 Dec MSG x' | ../src/remind -dt - 1 Jan 2000 >> ../tests/test.out 2>&1
@@ -344,33 +389,17 @@ rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
# If we're already in a utf-8 locale, do
# nothing; otherwise, set LC_ALL
OK=0
if echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
OK=1
fi
if test -z "$LC_ALL" ; then
if echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
export LC_ALL="$LANG"
OK=1
fi
fi
if test "$OK" = 0 ; then
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
fi
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
../src/remind -c ../tests/test-addomit.rem 1 Sep 2021 >> ../tests/test.out
../src/remind -cu ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
../src/remind -cu '-i$SuppressLRM=1' ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
TZ=America/Toronto ../src/remind -dxe ../tests/tz.rem >> ../tests/test.out 2>&1
TZ=Europe/Berlin ../src/remind -dxe ../tests/tz.rem >> ../tests/test.out 2>&1
# Remove references to SysInclude, which is build-specific
fgrep -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
grep -F -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
cmp -s ../tests/test.out ../tests/test.cmp
if [ "$?" = "0" ]; then
echo "Remind: Acceptance test PASSED"

File diff suppressed because it is too large Load Diff

View File

@@ -146,8 +146,14 @@ REM Tue 28 Jan 1992 MSG Tue 28 Jan 1992
# Try some Backs
CLEAR-OMIT-CONTEXT
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun
REM 1 -1 OMIT thu MSG 1 -1 OMIT Thu
REM 1 --1 OMIT thu MSG 1 --1 OMIT Thu
PUSH-OMIT-CONTEXT
OMIT Thu
REM 1 -1 MSG 1 -1 OMIT Thu globally
REM 1 --1 MSG 1 --1 OMIT Thu globally
POP-OMIT-CONTEXT
OMIT 28 Feb
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun (28 Feb omitted)
@@ -227,6 +233,15 @@ REM Wed UNTIL 1991-01-01 MSG Expired
REM Wed SCANFROM 1991-02-26 MSG SCANFROM
CLEAR-OMIT-CONTEXT
# Test trigtags and tag parsing
REM tag ill,egal MSG bad tag
REM MSG The tags are: [trigtags()]
REM TAG foo The tags are: [trigtags()]
REM TAG foo TAG bar TAG quux TAG znort TAG cabbage The tags are: [trigtags()]
REM MSG The tags are: [trigtags()]
# Test ADDOMIT
REM Mon 15 Feb ADDOMIT MSG Family Day
@@ -731,6 +746,11 @@ msg [a]
set x psshade(50)
set x psmoon(0)
# Recursive expression evaluation
FSET _f(x) 0
SET tmp evaltrig("Wed SKIP OMITFUNC _f",date(1992,1,8))
REM MSG [tmp]
# Trig
IF trig("sun +1") || trig("thu +1")
REM [trig()] +1 MSG Foo %b
@@ -814,6 +834,17 @@ OMIT 2000-01-01 THROUGH 2020-12-31
OMIT Dec 5 2029 through Dec 4 2029
# Test MSF
REM MSF This is a very long reminder. It should be wrapped. Will it be wrapped? I'm interested to see it it's wrapped. Please wrap this, ok?
# Custom substitution sequences
FSET subst_custom(a, d, t) "Custom: a=" + a + "; d=" + d + "; t=" + t
REM MSG Here: %{custom}
REM MSG There: %*{custom}
REM MSG Bad: %{custom
# Don't want Remind to queue reminders
EXIT

30
tests/tz.rem Normal file
View File

@@ -0,0 +1,30 @@
# Test conversion between local time and UTC
set a localtoutc('2022-01-01@12:00')
set a localtoutc('2022-03-13@02:59')
set a localtoutc('2022-03-13@03:00')
set a localtoutc('2022-03-13@03:01')
set a localtoutc('2022-06-01@12:00')
set a localtoutc('2022-11-06@01:59')
set a localtoutc('2022-11-06@02:00')
set a localtoutc('2022-11-06@02:01')
set a localtoutc('2022-12-01@12:00')
set b utctolocal('2022-01-01@17:00')
set b utctolocal('2022-03-13@06:00')
set b utctolocal('2022-03-13@06:01')
set b utctolocal('2022-03-13@06:59')
set b utctolocal('2022-03-13@07:00')
set b utctolocal('2022-03-13@07:01')
set b utctolocal('2022-03-13@07:59')
set b utctolocal('2022-06-01@16:00')
set b utctolocal('2022-11-06@05:59')
set b utctolocal('2022-11-06@06:00')
set b utctolocal('2022-11-06@06:01')
set b utctolocal('2022-11-06@06:59')
set b utctolocal('2022-11-06@07:00')
set b utctolocal('2022-11-06@07:01')
set b utctolocal('2022-12-01@17:00')
set c timezone('2022-07-01')
set c timezone('2022-12-01')