mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-05-04 06:37:51 +02:00
Compare commits
38 Commits
05.00.05
...
739d285e36
| Author | SHA1 | Date | |
|---|---|---|---|
| 739d285e36 | |||
| ee1c931932 | |||
| 0806b6738f | |||
| 020e82d575 | |||
| a20f2b588e | |||
| 631e721a96 | |||
| 8453e17c6c | |||
| 76c1e2abb3 | |||
| 3389f1c91b | |||
| b2d47ae979 | |||
| e2c615f310 | |||
| e8492a4303 | |||
| 4695efaabd | |||
| c433f42587 | |||
| 4708e59a43 | |||
| d56ac6332a | |||
| b054baf590 | |||
| 42f5e3467d | |||
| 97013ae89b | |||
| 2acead9118 | |||
| a53a80acb4 | |||
| 56e62b1b4d | |||
| c645db5ede | |||
| ef6b9c3783 | |||
| 019bee26cb | |||
| 152cd4090b | |||
| b7fc2b5776 | |||
| 723aba9b7c | |||
| 8a5b88338b | |||
| 7236441e02 | |||
| e4bab0dda4 | |||
| 5b7d4a07ec | |||
| 8c3d2c4003 | |||
| f485d607ff | |||
| a0effa5f0b | |||
| 7d501cda6f | |||
| 5d7f55c8d5 | |||
| 097bf92bea |
@@ -0,0 +1,3 @@
|
||||
The upstream GitHub project for ical2rem is:
|
||||
|
||||
https://github.com/jbalcorn/ical2rem
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Justin B. Alcorn
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,103 @@
|
||||
# ical2rem
|
||||
The original iCal to Remind script, first released in 2005.
|
||||
|
||||
Reads iCal files and outputs remind-compatible files. Tested ONLY with
|
||||
calendar files created by Mozilla Calendar/Sunbird. Use at your own risk.
|
||||
|
||||
## License
|
||||
In 2005, this was released with the Gnu Public License V2. However, I am changing it to the MIT License, since that provides greater freedom to do with this code what you want.
|
||||
|
||||
Copyright (c) 2005, 2007, 2019 Justin B. Alcorn
|
||||
|
||||
## How I use Remind and Google Calendar together
|
||||
|
||||
- My family has a Google Email domain, and our email addresses all end in the same domain. We all use Google Calendars and I want to mail reminders to each of the family members containing both Google Calendar and .reminder information.
|
||||
- Under my ~/.rem/ directory each family member has a directory. Each directory contains a standard remind file called 'reminders' that at the very least has the line "INCLUDE /home/jalcorn/.rem/<username>/ical2rem" and flag files indicating whether they want Daily or Weekly reminders. My reminders files references my standard .reminders file, and I also have a flag so if I run a Test run I'll get it. There's actually a lot more files (I have a big family).
|
||||
````
|
||||
./rem
|
||||
./son1:
|
||||
drwxrwxr-x 2 jalcorn jalcorn 4096 Dec 12 14:02 .
|
||||
drwxr-xr-x 12 jalcorn jalcorn 4096 Dec 12 14:13 ..
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 51 Mar 3 06:10 ical2rem
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 33 Oct 27 2016 son1.ics -> /home/jalcorn/calendars/son1.ics
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 976 Dec 12 14:02 reminders
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 0 Oct 27 2016 Weekly
|
||||
|
||||
./justin:
|
||||
drwxrwxr-x 2 jalcorn jalcorn 4096 Feb 27 08:29 .
|
||||
drwxr-xr-x 12 jalcorn jalcorn 4096 Dec 12 14:13 ..
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 32 Oct 27 2016 son1.ics -> /home/jalcorn/calendars/son1.ics
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 0 Nov 7 2016 Daily
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 34 Oct 27 2016 family.ics -> /home/jalcorn/calendars/family.ics
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 37320 Mar 3 06:10 ical2rem
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 34 Oct 27 2016 justin.ics -> /home/jalcorn/calendars/justin.ics
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 24 Nov 7 2016 reminders -> /home/jalcorn/.reminders
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 34 Oct 27 2016 vmd.ics -> /home/jalcorn/calendars/vmd.ics
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 0 Oct 27 2016 Test
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 0 Nov 7 2016 Weekly
|
||||
````
|
||||
- bin/getgooglecals.sh runs out of crontab and downloads whatever calendars I want. Note that we can also download organization calendars, I've included a public one here (Cleveland Heights Vocal Music Department calendar).
|
||||
- dailyreminders.sh is linked to weeklyreminders.sh and testreminders.sh so I can run it in different modes. The concatenate the various calendar outputs as a single remind file then send the reminders via email.
|
||||
### Example: .rem/son1/reminders file:
|
||||
````
|
||||
INCLUDE /home/jalcorn/.rem/defs.rem
|
||||
INCLUDE /home/jalcorn/.rem/float
|
||||
INCLUDE /home/jalcorn/.rem/son1/ical2rem
|
||||
fset _weeks() coerce("STRING", (trigdate()-today())/7) + plural((trigdate()-today())/7, " week")
|
||||
FSET _sfun(x) choose(x, -60, 30, 5, 0)
|
||||
FSET oldfloat(y,m,d) trigger(MAX(realtoday(), date(y,m,d)))
|
||||
FSET due(y,m,d) "(" + (date(y,m,d)-trigdate()) + ")"
|
||||
SET fullmoon moondate(2)
|
||||
REM [trigger(realtoday())] SPECIAL SHADE 145 70 100 %
|
||||
REM [float(2019,4,15,105)] MSG File tax return [due(2017,4,15)]%
|
||||
REM PRIORITY 9999 MSG %"%"%
|
||||
INCLUDE /home/jalcorn/.rem/bdays
|
||||
SET $LongDeg 81
|
||||
SET $LongMin 11
|
||||
SET $LongSec 11
|
||||
SET $LatDeg 41
|
||||
SET $LatMin 11
|
||||
SET $LatSec 11
|
||||
REM [trigger(moondate(2))] +1 MSG %"Full Moon%" %b%
|
||||
fset _srtd() coerce("STRING", _no_lz(_am_pm(sunrise(today()))))
|
||||
fset _sstd() coerce("STRING", _no_lz(_am_pm(sunset(today()))))
|
||||
MSG Sun is up today from [_srtd()] to [_sstd()].%"%"%
|
||||
````
|
||||
## Revision History
|
||||
### Version 0.7 2024-09-04
|
||||
- ISSUE 8: New version of remind complains if _sfun isn't defined. Output a header
|
||||
to define a function that does nothing if the function doesn't exist.
|
||||
### Version 0.6 2019-03-01
|
||||
- Publish on GitHub and change license to MIT License
|
||||
- Add supporting files and explanation of how I use it
|
||||
### version 0.5.2 2007-03-23
|
||||
- BUG: leadtime for recurring events had a max of 4 instead of DEFAULT_LEAD_TIME
|
||||
- remove project-lead-time, since Category was a non-standard attribute
|
||||
- NOTE: There is a bug in iCal::Parser v1.14 that causes multiple calendars to
|
||||
fail if a calendar with recurring events is followed by a calendar with no
|
||||
recurring events. This has been reported to the iCal::Parser author.
|
||||
### version 0.5.1 2007-03-21
|
||||
- BUG: Handle multiple calendars on STDIN
|
||||
- add --heading option for priority on section headers
|
||||
### version 0.5 2007-03-21
|
||||
- Add more help options
|
||||
- --project-lead-time option
|
||||
- Supress printing of heading if there are no todos to print
|
||||
### version 0.4
|
||||
- Version 0.4 changes all written or inspired by, and thanks to Mark Stosberg
|
||||
- Change to GetOptions
|
||||
- Change to pipe
|
||||
- Add --label, --help options
|
||||
- Add Help Text
|
||||
- Change to subroutines
|
||||
- Efficiency and Cleanup
|
||||
### version 0.3
|
||||
- Convert to GPL (Thanks to Mark Stosberg)
|
||||
- Add usage
|
||||
### version 0.2
|
||||
- add command line switches
|
||||
- add debug code
|
||||
- add SCHED _sfun keyword
|
||||
- fix typos
|
||||
### version 0.1 - ALPHA CODE.
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# cal_futureonly.pl -
|
||||
# Reads iCal files and outputs events between 1 month ago and 1 year from now.
|
||||
# Copyright (c) 2005, 2007, 2019 Justin B. Alcorn
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
cal_futureonly.pl --file=filname.ics > output.ics
|
||||
|
||||
--help Usage
|
||||
--man Complete man page
|
||||
--infile (REQUIRED) name of input calendar file
|
||||
--file (REQUIRED) name of output calendar file
|
||||
|
||||
Expects an ICAL stream on STDIN. Converts it to the format
|
||||
used by the C<remind> script and prints it to STDOUT.
|
||||
|
||||
=head2 --infile
|
||||
|
||||
Input file
|
||||
|
||||
=head2 --file
|
||||
|
||||
Output File
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Data::ICal;
|
||||
use Data::ICal::Entry;
|
||||
use DateTime::Span;
|
||||
use Data::ICal::DateTime;
|
||||
use DateTime;
|
||||
use Getopt::Long 2.24 qw':config auto_help';
|
||||
use Pod::Usage;
|
||||
use Data::Dumper;
|
||||
use vars '$VERSION';
|
||||
$VERSION = "0.1";
|
||||
|
||||
my $help;
|
||||
my $man;
|
||||
my $infile;
|
||||
my $file;
|
||||
my $debug = 0;
|
||||
|
||||
GetOptions (
|
||||
"help|?" => \$help,
|
||||
"man" => \$man,
|
||||
"debug" => \$debug,
|
||||
"infile=s" => \$infile,
|
||||
"file=s" => \$file
|
||||
);
|
||||
pod2usage(1) if $help;
|
||||
pod2usage(1) if (! $file);
|
||||
pod2usage(-verbose => 2) if $man;
|
||||
|
||||
my $limit = DateTime->now();
|
||||
$limit->subtract( months => 1);
|
||||
my $endlimit = DateTime->now()->add(years =>1);
|
||||
print STDERR "including events from: ",$limit->ymd," to: ".$endlimit->ymd,"\n" if $debug;
|
||||
my $span = DateTime::Span->from_datetimes( start => $limit, end => $endlimit );
|
||||
print STDERR "Parsing $infile\n" if $debug;
|
||||
my $cal = Data::ICal->new(filename => $infile);
|
||||
if (! $cal) {
|
||||
die "Died Trying to read $infile :".$cal->error_message;
|
||||
}
|
||||
#my $archive = Data::ICal->new(filename => 'archive.ics');
|
||||
print "Output = $file\n" if $debug;
|
||||
my $new = Data::ICal->new();
|
||||
if (! $new) {
|
||||
die $new->error_message;
|
||||
}
|
||||
|
||||
my @events = $cal->events($span);
|
||||
$new->add_entries(@events);
|
||||
|
||||
open(NEW, ">$file");
|
||||
print NEW $new->as_string;
|
||||
close NEW;
|
||||
exit 0;
|
||||
#:vim set ft=perl ts=4 sts=4 expandtab :
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
|
||||
r=`basename $0`
|
||||
|
||||
if [ $r == 'weeklyreminders.sh' ];
|
||||
then
|
||||
t=14;
|
||||
w=Weekly;
|
||||
elif [ $r == 'dailyreminders.sh' ];
|
||||
then
|
||||
t=3;
|
||||
w=Daily;
|
||||
else
|
||||
t=5
|
||||
w=Test;
|
||||
fi
|
||||
|
||||
cd .rem
|
||||
for d in * ;
|
||||
do
|
||||
if [ "$( ls -A $d/$w 2>/dev/null )" ];
|
||||
then
|
||||
echo "Sending a $w reminder to $d"
|
||||
ft=/tmp/$d-t-$$.txt
|
||||
f=/tmp/$d-$$.txt
|
||||
echo "Reminders for next $t days:" >> $f
|
||||
cat /dev/null > $d/ical2rem
|
||||
for c in $d/*.ics
|
||||
do
|
||||
calname=`basename $c .ics | tr a-z A-Z`
|
||||
cat $c 2>/dev/null | sed -e "s/^SUMMARY:/SUMMARY: {${calname}} /" \
|
||||
| sed -e 's/DT\([A-Z]*\);TZID=UTC:\([0-9T]*\)/DT\1:\2Z/' >> $ft
|
||||
done
|
||||
cat $ft | ~/bin/ical2rem.pl --label "Online Calendar" --heading "PRIORITY 9999" --lead-time $t >> $d/ical2rem
|
||||
if [ -e $d/reminders ];then r="${d}/reminders"; else r="${d}/ical2rem";fi
|
||||
/usr/bin/remind -q -iplain=1 $r >> $f
|
||||
echo "
|
||||
All calendars can be accessed by logging into https://calendar.google.com/ as $d@jalcorn.net
|
||||
" >> $f
|
||||
cat $f | mail -s "$w Reminders for $d" $d@jalcorn.net;
|
||||
cat $f
|
||||
rm $f
|
||||
rm $ft
|
||||
fi;
|
||||
done
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Get google calendars, fix issues caused by changes in Google calendars, and remove all past events.
|
||||
#
|
||||
# Obviously, I've removed the private hashes from private calendars.
|
||||
#
|
||||
cd ~/calendars
|
||||
wget -q -O full/justin.ics --no-check-certificate https://www.google.com/calendar/ical/jbalcorn\%40gmail.com/private-aaaaaaaaaaaaaaaaaaaaaaaaaa/basic.ics
|
||||
wget -q -O full/family.ics --no-check-certificate https://www.google.com/calendar/ical/jalcorn.net_aaaaaaaaaaaaaaaaaaaaaaaaaa\%40group.calendar.google.com/private-6c42a79dec0b3b3bb7b9b0ebf9776bc1/basic.ics
|
||||
wget -q -O full/son1.ics --no-check-certificate https://www.google.com/calendar/ical/son1\%40jalcorn.net/private-aaaaaaaaaaaaaaaaaaaaaaaaaa/basic.ics
|
||||
wget -q -O full/vmd.ics --no-check-certificate https://calendar.google.com/calendar/ical/chuh.org_0pmkefjkiqc4snoel7occlslh8%40group.calendar.google.com/public/basic.ics
|
||||
|
||||
for i in full/*.ics;do
|
||||
cat $i 2>/dev/null | sed -e 's/DT\([A-Z]*\);TZID=UTC:\([0-9T]*\)/DT\1:\2Z/' > /tmp/temp.ics
|
||||
cp /tmp/temp.ics $i
|
||||
done
|
||||
|
||||
~/bin/cal_futureonly.pl --infile=full/justin.ics --file=justin.ics
|
||||
~/bin/cal_futureonly.pl --infile=full/family.ics --file=family.ics
|
||||
~/bin/cal_futureonly.pl --infile=full/son1.ics --file=son1.ics
|
||||
~/bin/cal_futureonly.pl --infile=full/vmd.ics --file=vmd.ics
|
||||
@@ -19,7 +19,8 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
# version 0.6 2019-03-01
|
||||
# - Updates to put on GitHub
|
||||
# version 0.5.2 2007-03-23
|
||||
# - BUG: leadtime for recurring events had a max of 4 instead of DEFAULT_LEAD_TIME
|
||||
# - remove project-lead-time, since Category was a non-standard attribute
|
||||
@@ -32,7 +33,7 @@
|
||||
# version 0.5 2007-03-21
|
||||
# - Add more help options
|
||||
# - --project-lead-time option
|
||||
# - Suppress printing of heading if there are no todos to print
|
||||
# - Supress printing of heading if there are no todos to print
|
||||
# version 0.4
|
||||
# - Version 0.4 changes all written or inspired by, and thanks to Mark Stosberg
|
||||
# - Change to GetOptions
|
||||
@@ -56,12 +57,19 @@
|
||||
cat /path/to/file*.ics | ical2rem.pl > ~/.ical2rem
|
||||
|
||||
All options have reasonable defaults:
|
||||
--label Calendar name (Default: Calendar)
|
||||
--label Calendar name (Default: Calendar)
|
||||
--start Start of time period to parse (parsed by str2time)
|
||||
--end End of time period to parse
|
||||
--lead-time Advance days to start reminders (Default: 3)
|
||||
--todos, --no-todos Process Todos? (Default: Yes)
|
||||
--heading Define a priority for static entries
|
||||
--help Usage
|
||||
--man Complete man page
|
||||
--iso8601 Use YYYY-MM-DD date format
|
||||
--locations, --no-locations Include location? (Default: Yes)
|
||||
--end-times, --no-end-times Include event end times in reminder text
|
||||
(Default: No)
|
||||
--heading Define a priority for static entries
|
||||
--help Usage
|
||||
--debug Enable debug output
|
||||
--man Complete man page
|
||||
|
||||
Expects an ICAL stream on STDIN. Converts it to the format
|
||||
used by the C<remind> script and prints it to STDOUT.
|
||||
@@ -74,6 +82,14 @@ The syntax generated includes a label for the calendar parsed.
|
||||
By default this is "Calendar". You can customize this with
|
||||
the "--label" option.
|
||||
|
||||
=head2 --iso8601
|
||||
|
||||
Use YYYY-MM-DD date format in output instead of Mmm DD YYYY
|
||||
|
||||
=head2 --locations, --no-locations
|
||||
|
||||
Whether or not to include locations in events
|
||||
|
||||
=head2 --lead-time
|
||||
|
||||
ical2rem.pl --lead-time 3
|
||||
@@ -84,7 +100,7 @@ How may days in advance to start getting reminders about the events. Defaults to
|
||||
|
||||
ical2rem.pl --no-todos
|
||||
|
||||
If you don't care about the ToDos the calendar, this will suppress
|
||||
If you don't care about the ToDos the calendar, this will surpress
|
||||
printing of the ToDo heading, as well as skipping ToDo processing.
|
||||
|
||||
=head2 --heading
|
||||
@@ -98,6 +114,7 @@ the calendar entries. See the file defs.rem from the remind distribution for mo
|
||||
|
||||
use strict;
|
||||
use iCal::Parser;
|
||||
use Date::Parse;
|
||||
use DateTime;
|
||||
use Getopt::Long 2.24 qw':config auto_help';
|
||||
use Pod::Usage;
|
||||
@@ -108,19 +125,31 @@ $VERSION = "0.5.2";
|
||||
# Declare how many days in advance to remind
|
||||
my $DEFAULT_LEAD_TIME = 3;
|
||||
my $PROCESS_TODOS = 1;
|
||||
my $HEADING = "";
|
||||
my $HEADING = "";
|
||||
my $help;
|
||||
my $debug;
|
||||
my $man;
|
||||
my $iso8601;
|
||||
my $do_location = 1;
|
||||
my $do_end_times;
|
||||
my $start;
|
||||
my $end;
|
||||
|
||||
my $label = 'Calendar';
|
||||
GetOptions (
|
||||
"label=s" => \$label,
|
||||
"start=s" => \$start,
|
||||
"end=s" => \$end,
|
||||
"lead-time=i" => \$DEFAULT_LEAD_TIME,
|
||||
"todos!" => \$PROCESS_TODOS,
|
||||
"iso8601!" => \$iso8601,
|
||||
"locations!" => \$do_location,
|
||||
"end-times!" => \$do_end_times,
|
||||
"heading=s" => \$HEADING,
|
||||
"help|?" => \$help,
|
||||
"debug" => \$debug,
|
||||
"man" => \$man
|
||||
);
|
||||
) or pod2usage(1);
|
||||
pod2usage(1) if $help;
|
||||
pod2usage(-verbose => 2) if $man;
|
||||
|
||||
@@ -136,8 +165,22 @@ while (<>) {
|
||||
$in = "";
|
||||
}
|
||||
}
|
||||
my $parser = iCal::Parser->new();
|
||||
print STDERR "Read all calendars\n" if $debug;
|
||||
my(%parser_opts) = ("debug" => $debug);
|
||||
if ($start) {
|
||||
my $t = str2time($start);
|
||||
die "Invalid time $start\n" if (! $t);
|
||||
$parser_opts{'start'} = DateTime->from_epoch(epoch => $t);
|
||||
}
|
||||
if ($end) {
|
||||
my $t = str2time($end);
|
||||
die "Invalid time $end\n" if (! $t);
|
||||
$parser_opts{'end'} = DateTime->from_epoch(epoch => $t);
|
||||
}
|
||||
print STDERR "About to parse calendars\n" if $debug;
|
||||
my $parser = iCal::Parser->new(%parser_opts);
|
||||
my $hash = $parser->parse_strings(@calendars);
|
||||
print STDERR "Calendars parsed\n" if $debug;
|
||||
|
||||
##############################################################
|
||||
#
|
||||
@@ -209,6 +252,13 @@ sub _process_todos {
|
||||
#
|
||||
######################################################################
|
||||
|
||||
# Issue 8 https://github.com/jbalcorn/ical2rem/issues/8
|
||||
# Make sure there is a _sfun function declared in the reminder file. We'll just make it do nothing here.
|
||||
print 'IF args("_sfun") < 1
|
||||
FSET _sfun(x) choose(x,0)
|
||||
ENDIF
|
||||
';
|
||||
|
||||
print _process_todos($hash->{'todos'}) if $PROCESS_TODOS;
|
||||
|
||||
my ($leadtime, $yearkey, $monkey, $daykey,$uid,%eventsbyuid);
|
||||
@@ -260,20 +310,67 @@ foreach $yearkey (sort keys %{$events} ) {
|
||||
$leadtime = "+".$DEFAULT_LEAD_TIME;
|
||||
}
|
||||
my $start = $event->{'DTSTART'};
|
||||
print "REM ".$start->month_abbr." ".$start->day." ".$start->year." $leadtime ";
|
||||
if ($start->hour > 0) {
|
||||
print " AT ";
|
||||
print $start->strftime("%H:%M");
|
||||
print " +15 MSG %a %2 ";
|
||||
} else {
|
||||
print " MSG %a ";
|
||||
my $end = $event->{'DTEND'};
|
||||
my $duration = "";
|
||||
if ($end and ($start->hour or $start->minute or $end->hour or $end->minute)) {
|
||||
# We need both an HH:MM version of the delta, to put in the
|
||||
# DURATION specifier, and a human-readable version of the
|
||||
# delta, to put in the message if the user requested it.
|
||||
my $seconds = $end->epoch - $start->epoch;
|
||||
my $minutes = int($seconds / 60);
|
||||
my $hours = int($minutes / 60);
|
||||
$minutes -= $hours * 60;
|
||||
$duration = sprintf("DURATION %d:%02d ", $hours, $minutes);
|
||||
}
|
||||
print "%\"$event->{'SUMMARY'}";
|
||||
print " at $event->{'LOCATION'}" if $event->{'LOCATION'};
|
||||
print "\%\"%\n";
|
||||
print "REM ";
|
||||
if ($iso8601) {
|
||||
print $start->strftime("%F ");
|
||||
} else {
|
||||
print $start->month_abbr." ".$start->day." ".$start->year." ";
|
||||
}
|
||||
print "$leadtime ";
|
||||
if ($duration or $start->hour > 0 or $start->minute > 0) {
|
||||
print "AT ";
|
||||
print $start->strftime("%H:%M");
|
||||
print " SCHED _sfun ${duration}MSG %a %2 ";
|
||||
} else {
|
||||
print "MSG %a ";
|
||||
}
|
||||
print "%\"", "e($event->{'SUMMARY'});
|
||||
print(" at ", "e($event->{'LOCATION'}))
|
||||
if ($do_location and $event->{'LOCATION'});
|
||||
print "\%\"";
|
||||
if ($do_end_times and ($start->hour or $start->minute or
|
||||
$end->hour or $end->minute)) {
|
||||
my $start_date = $start->strftime("%F");
|
||||
my $start_time = $start->strftime("%k:%M");
|
||||
my $end_date = $end->strftime("%F");
|
||||
my $end_time = $end->strftime("%k:%M");
|
||||
# We don't want leading whitespace; some strftime's support
|
||||
# disabling the pdding in the format string, but not all,
|
||||
# so for maximum portability we do it ourselves.
|
||||
$start_time =~ s/^\s+//;
|
||||
$end_time =~ s/^\s+//;
|
||||
my(@pieces);
|
||||
if ($start_date ne $end_date) {
|
||||
push(@pieces, $end_date);
|
||||
}
|
||||
if ($start_time ne $end_time) {
|
||||
push(@pieces, $end_time);
|
||||
}
|
||||
print " (-", join(" ", @pieces), ")";
|
||||
}
|
||||
print "%\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub quote {
|
||||
local($_) = @_;
|
||||
s/\[/["["]/g;
|
||||
return $_;
|
||||
}
|
||||
|
||||
exit 0;
|
||||
#:vim set ft=perl ts=4 sts=4 expandtab :
|
||||
@@ -109,18 +109,15 @@
|
||||
|
||||
(defconst remind-keywords
|
||||
(sort
|
||||
(list "ADDOMIT" "AFTER" "AT" "BANNER" "BEFORE"
|
||||
"CAL" "CLEAR-OMIT-CONTEXT" "DEBUG" "DO" "DUMPVARS"
|
||||
"DURATION" "ELSE" "ENDIF" "ERRMSG" "EXIT" "FIRST"
|
||||
"FLUSH" "FOURTH" "FROM" "FSET" "IF" "IFTRIG" "IN"
|
||||
"INCLUDE" "INCLUDECMD" "LAST" "LASTDAY"
|
||||
"LASTWORKDAY" "MAYBE-UNCOMPUTABLE" "MSF"
|
||||
"MSG" "OMIT" "OMITFUNC" "ONCE"
|
||||
"POP-OMIT-CONTEXT" "PRESERVE" "PRIORITY" "PS" "PSFILE"
|
||||
"PUSH-OMIT-CONTEXT" "REM" "RUN" "SATISFY" "SCANFROM"
|
||||
"SCHED" "SECOND" "SET" "SKIP" "SPECIAL"
|
||||
"TAG" "THIRD" "THROUGH" "UNSET" "UNTIL"
|
||||
"WARN")
|
||||
(list "ADDOMIT" "AFTER" "AT" "BAN" "BANNER" "BEFORE" "CAL" "CLEAR"
|
||||
"CLEAR-OMIT-CONTEXT" "DEBUG" "DO" "DUMP" "DUMPVARS" "DURATION" "ELSE"
|
||||
"ENDIF" "ERRMSG" "EXIT" "EXPR" "FIRST" "FLUSH" "FOURTH" "FROM" "FSET"
|
||||
"FUNSET" "IF" "IFTRIG" "IN" "INC" "INCLUDE" "INCLUDECMD" "LAST"
|
||||
"LASTDAY" "LASTWORKDAY" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF" "MSG"
|
||||
"NOQUEUE" "OMIT" "OMITFUNC" "ONCE" "POP" "POP-OMIT-CONTEXT" "PRESERVE"
|
||||
"PRIORITY" "PS" "PSFILE" "PUSH" "PUSH-OMIT-CONTEXT" "REM" "RUN"
|
||||
"SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET" "SKIP" "SPECIAL"
|
||||
"TAG" "THIRD" "THROUGH" "UNSET" "UNTIL" "WARN")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
@@ -131,50 +128,57 @@
|
||||
|
||||
(defconst remind-builtin-variables
|
||||
(sort
|
||||
(list "$Ago" "$Am" "$And" "$April" "$At" "$August" "$CalcUTC" "$CalMode" "$Daemon" "$DateSep"
|
||||
"$DateTimeSep" "$December" "$DefaultColor" "$DefaultPrio"
|
||||
"$DefaultTDelta" "$DeltaOffset" "$DontFork" "$DontQueue"
|
||||
"$DontTrigAts" "$EndSent" "$EndSentIg" "$February" "$FirstIndent"
|
||||
"$FoldYear" "$FormWidth" "$Friday" "$Fromnow" "$Hour" "$Hplu" "$HushMode" "$IgnoreOnce"
|
||||
"$InfDelta" "$IntMax" "$IntMin" "$Is" "$January" "$July" "$June" "$LatDeg"
|
||||
"$Latitude" "$LatMin" "$LatSec" "$Location" "$LongDeg" "$Longitude"
|
||||
"$LongMin" "$LongSec" "$March" "$MaxSatIter" "$MaxStringLen" "$May"
|
||||
"$MinsFromUTC" "$Minute" "$Monday" "$Mplu" "$NextMode" "$November" "$Now" "$NumQueued"
|
||||
"$NumTrig" "$October" "$On" "$Pm" "$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday"
|
||||
"$September" "$SimpleCal" "$SortByDate" "$SortByPrio" "$SortByTime"
|
||||
"$SubsIndent" "$Sunday" "$SysInclude" "$T" "$Td" "$Thursday" "$TimeSep" "$Tm"
|
||||
"$Today" "$Tomorrow" "$Tuesday" "$Tw" "$Ty" "$U" "$Ud" "$Um" "$UntimedFirst" "$Uw" "$Uy"
|
||||
"$Was" "$Wednesday")
|
||||
(list "$AddBlankLines" "$Ago" "$Am" "$And" "$April" "$At" "$August"
|
||||
"$CalcUTC" "$CalMode" "$Daemon" "$DateSep" "$DateTimeSep" "$December"
|
||||
"$DefaultColor" "$DefaultPrio" "$DefaultTDelta" "$DeltaOverride"
|
||||
"$DontFork" "$DontQueue" "$DontTrigAts" "$EndSent" "$EndSentIg"
|
||||
"$ExpressionTimeLimit" "$February" "$FirstIndent" "$FoldYear"
|
||||
"$FormWidth" "$Friday" "$Fromnow" "$Hour" "$Hplu" "$HushMode"
|
||||
"$IgnoreOnce" "$InfDelta" "$IntMax" "$IntMin" "$Is" "$January" "$July"
|
||||
"$June" "$LatDeg" "$Latitude" "$LatMin" "$LatSec" "$Location"
|
||||
"$LongDeg" "$Longitude" "$LongMin" "$LongSec" "$March" "$MaxFullOmits"
|
||||
"$MaxLateMinutes" "$MaxPartialOmits" "$MaxSatIter" "$MaxStringLen"
|
||||
"$May" "$MinsFromUTC" "$Minute" "$Monday" "$Mplu" "$NextMode"
|
||||
"$November" "$Now" "$NumFullOmits" "$NumPartialOmits" "$NumQueued"
|
||||
"$NumTrig" "$October" "$On" "$OnceFile" "$ParseUntriggered" "$Pm"
|
||||
"$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday" "$September"
|
||||
"$SimpleCal" "$SortByDate" "$SortByPrio" "$SortByTime" "$SubsIndent"
|
||||
"$Sunday" "$SuppressImplicitWarnings" "$SuppressLRM" "$SysInclude" "$T" "$Td"
|
||||
"$TerminalBackground" "$Thursday" "$TimeSep" "$Tm" "$Today"
|
||||
"$Tomorrow" "$Tt" "$Tuesday" "$Tw" "$Ty" "$U" "$Ud" "$Um"
|
||||
"$UntimedFirst" "$Use256Colors" "$UseBGVTColors" "$UseTrueColors"
|
||||
"$UseVTColors" "$Uw" "$Uy" "$Was" "$Wednesday")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
(defconst remind-time-words
|
||||
(sort
|
||||
(list "Jan" "January" "Feb" "Mar" "Apr" "Jun" "Jul" "Aug" "Sept" "Sep" "Oct" "Nov" "Dec"
|
||||
"February" "March" "April" "May" "June" "July" "August" "September" "October"
|
||||
"November" "December" "Mon" "Monday" "Tue" "Tues" "Tuesday" "Wed" "Wednesday"
|
||||
"Thu" "Thursday" "Thurs" "Fri" "Friday" "Saturday" "Sat" "Sun" "Sunday")
|
||||
(list "Apr" "April" "Aug" "August" "Dec" "December" "Feb" "February"
|
||||
"Jan" "January" "Jul" "July" "Jun" "June" "Mar" "March" "May"
|
||||
"Nov" "November" "Oct" "October" "Sep" "September" "Fri"
|
||||
"Friday" "Mon" "Monday" "Sat" "Saturday" "Sun" "Sunday" "Thu"
|
||||
"Thursday" "Tue" "Tuesday" "Wed" "Wednesday")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
(defconst remind-builtin-functions
|
||||
(sort
|
||||
(list "abs" "access" "adawn" "adusk" "ampm" "args" "asc" "baseyr" "char"
|
||||
"choose" "coerce" "current" "date" "datepart" "datetime" "dawn" "day"
|
||||
"daysinmon" "defined" "dosubst" "dusk" "easterdate" "evaltrig"
|
||||
"filedate" "filedatetime" "filedir" "filename" "getenv" "hebdate"
|
||||
"hebday" "hebmon" "hebyear" "hour" "iif" "index" "isany" "isdst"
|
||||
"isleap" "isomitted" "language" "lower" "max" "min" "minsfromutc"
|
||||
(list "abs" "access" "adawn" "adusk" "ampm" "ansicolor" "args" "asc"
|
||||
"baseyr" "char" "choose" "coerce" "columns" "current" "date"
|
||||
"datepart" "datetime" "dawn" "day" "daysinmon" "defined" "dosubst"
|
||||
"dusk" "easterdate" "evaltrig" "filedate" "filedatetime" "filedir"
|
||||
"filename" "getenv" "hebdate" "hebday" "hebmon" "hebyear" "hour"
|
||||
"htmlescape" "htmlstriptags" "iif" "index" "isany" "isdst" "isleap"
|
||||
"isomitted" "language" "localtoutc" "lower" "max" "min" "minsfromutc"
|
||||
"minute" "mon" "monnum" "moondate" "moondatetime" "moonphase"
|
||||
"moontime" "ndawn" "ndusk" "nonomitted" "now" "ord" "ostype" "pad" "plural"
|
||||
"psmoon" "psshade" "realcurrent" "realnow" "realtoday" "sgn" "shell"
|
||||
"shellescape" "slide" "strlen" "substr" "sunrise" "sunset" "time"
|
||||
"timepart" "today" "trig" "trigback" "trigdate" "trigdatetime"
|
||||
"trigdelta" "trigduration" "trigeventduration" "trigeventstart"
|
||||
"trigfrom" "trigger" "trigpriority" "trigrep" "trigscanfrom"
|
||||
"trigtime" "trigtimedelta" "trigtimerep" "triguntil" "trigvalid"
|
||||
"typeof" "tzconvert" "upper" "value" "version" "weekno" "wkday"
|
||||
"wkdaynum" "year")
|
||||
"moontime" "multitrig" "ndawn" "ndusk" "nonomitted" "now" "ord"
|
||||
"orthodoxeaster" "ostype" "pad" "plural" "psmoon" "psshade"
|
||||
"realcurrent" "realnow" "realtoday" "rows" "sgn" "shell" "shellescape"
|
||||
"slide" "soleq" "stdout" "strlen" "substr" "sunrise" "sunset" "time"
|
||||
"timepart" "timezone" "today" "trig" "trigback" "trigdate"
|
||||
"trigdatetime" "trigdelta" "trigduration" "trigeventduration"
|
||||
"trigeventstart" "trigfrom" "trigger" "trigpriority" "trigrep"
|
||||
"trigscanfrom" "trigtags" "trigtime" "trigtimedelta" "trigtimerep"
|
||||
"triguntil" "trigvalid" "typeof" "tzconvert" "upper" "utctolocal"
|
||||
"value" "version" "weekno" "wkday" "wkdaynum" "year")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
;;; faces
|
||||
@@ -290,7 +294,7 @@
|
||||
|
||||
(defconst remind-conf-font-lock-keywords-1
|
||||
(list
|
||||
'("^[\;\#]\\s-+.*$" . remind-comment-face)
|
||||
'("^\s*[\;\#].*$" . remind-comment-face)
|
||||
'(remind-keywords-matcher . remind-conf-keyword-face)
|
||||
'("%[\"_]" . font-lock-warning-face)
|
||||
'("\\(%[a-mops-w]\\)" . remind-conf-substitutes-face)
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ RUN OFF
|
||||
# Ensure required version of remind is used... #
|
||||
################################################
|
||||
IF version() < "03.04.02"
|
||||
ERRMSG This file requires at least version 03.01.10 of Remind.%
|
||||
ERRMSG This file requires at least version 03.04.02 of Remind.%
|
||||
ERRMSG This version is version [version()].
|
||||
EXIT
|
||||
ENDIF
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
REM 1 Feb 2022 MSG Chinese New Year (Tiger)
|
||||
REM 22 Jan 2023 MSG Chinese New Year (Rabbit)
|
||||
REM 10 Feb 2024 MSG Chinese New Year (Dragon)
|
||||
REM 29 Jan 2025 MSG Chinese New Year (Snake)
|
||||
REM 17 Feb 2026 MSG Chinese New Year (Horse)
|
||||
REM 6 Feb 2027 MSG Chinese New Year (Goat)
|
||||
REM 26 Jan 2028 MSG Chinese New Year (Monkey)
|
||||
REM 13 Feb 2029 MSG Chinese New Year (Rooster)
|
||||
REM 3 Feb 2030 MSG Chinese New Year (Dog)
|
||||
REM 23 Jan 2031 MSG Chinese New Year (Pig)
|
||||
REM 11 Feb 2032 MSG Chinese New Year (Rat)
|
||||
REM 31 Jan 2033 MSG Chinese New Year (Ox)
|
||||
REM 19 Feb 2034 MSG Chinese New Year (Tiger)
|
||||
REM 8 Feb 2035 MSG Chinese New Year (Rabbit)
|
||||
REM 28 Jan 2036 MSG Chinese New Year (Dragon)
|
||||
REM 15 Feb 2037 MSG Chinese New Year (Snake)
|
||||
REM 4 Feb 2038 MSG Chinese New Year (Horse)
|
||||
REM 24 Jan 2039 MSG Chinese New Year (Goat)
|
||||
REM 12 Feb 2040 MSG Chinese New Year (Monkey)
|
||||
REM 1 Feb 2041 MSG Chinese New Year (Rooster)
|
||||
REM 22 Jan 2042 MSG Chinese New Year (Dog)
|
||||
REM 10 Feb 2043 MSG Chinese New Year (Pig)
|
||||
REM 30 Jan 2044 MSG Chinese New Year (Rat)
|
||||
REM 17 Feb 2045 MSG Chinese New Year (Ox)
|
||||
REM 6 Feb 2046 MSG Chinese New Year (Tiger)
|
||||
REM 26 Jan 2047 MSG Chinese New Year (Rabbit)
|
||||
REM 14 Feb 2048 MSG Chinese New Year (Dragon)
|
||||
REM 2 Feb 2049 MSG Chinese New Year (Snake)
|
||||
REM 23 Jan 2050 MSG Chinese New Year (Horse)
|
||||
+21
-5
@@ -468,6 +468,14 @@ case-sensitive:
|
||||
The \fB\-\-version\fR option causes \fBRemind\fR to print its version number
|
||||
to standard output and then exit.
|
||||
.TP
|
||||
.B \-\-print-tokens
|
||||
The \fB\-\-print-tokens\fR option causes \fBRemind\fR to print the tokens
|
||||
used by the parser, built-in function names, and system variable names
|
||||
to standard output and then exit. This output is designed to make it easy
|
||||
to create a syntax-highlighting file for various text editors. The output
|
||||
can be modified by hand or by a script into a syntax-highlighting file
|
||||
with relative ease.
|
||||
.TP
|
||||
.B \-\-max-execution-time\fR=\fIn\fR
|
||||
Limit the total execution time (as measured by the wall clock) to
|
||||
\fIn\fR seconds. This is useful if \fBRemind\fR is invoked on
|
||||
@@ -2181,6 +2189,11 @@ If the \fBTIME\fR is used where \fBRemind\fR expects a time-of-day
|
||||
\fIpm\fR suffix and the hour can be as large as you want, so long
|
||||
as the total number of minutes in the duration fits in a signed integer
|
||||
variable.
|
||||
.PP
|
||||
For convenience, a \fBTIME\fR constant may be surrounded by single
|
||||
quotes to match \fBDATE\fR and \fBDATETIME\fR constants, but these
|
||||
quotes are optional. That is, 12:56 and '12:56' represent the same
|
||||
\fBTIME\fR constant.
|
||||
.RE
|
||||
.TP
|
||||
.B DATE constants
|
||||
@@ -2812,8 +2825,15 @@ order, or 2 if sorting by time in descending order.
|
||||
The number of spaces by which all lines (except the first) of an
|
||||
\fBMSF\fR-type reminder should be indented. The default is 0.
|
||||
.TP
|
||||
.B $SuppressImplicitWarnings
|
||||
Normally, \fBRemind\fR issues a warning if a line begins with an unknown
|
||||
token and is treated as a \fBREM\fR command, or if a \fBREM\fR command
|
||||
is missing a type and is treated as a \fBMSG\fR-type reminder. Setting
|
||||
\fB$SuppressImplicitWarnings\fR to 1 suppresses these warnings. The default
|
||||
is 0 and we do not recommend disabling the warnings.
|
||||
.TP
|
||||
.B $SuppressLRM
|
||||
Normally, when Remind is run with the \fB\-c\fR option in a UTF-8 locale,
|
||||
Normally, when \fBRemind\fR is run with the \fB\-c\fR option in a UTF-8 locale,
|
||||
it emits a left-to-right mark sequence after printing day names or
|
||||
reminders. Some terminals render this incorrectly, so you can use:
|
||||
.RS
|
||||
@@ -5837,10 +5857,6 @@ after the WEEK keyword.
|
||||
The following tokens can be abbreviated:
|
||||
.TP
|
||||
o
|
||||
\fBREM\fR can be omitted - it is implied if no other valid command
|
||||
is present.
|
||||
.TP
|
||||
o
|
||||
\fBCLEAR-OMIT-CONTEXT\fR --> \fBCLEAR\fR
|
||||
.TP
|
||||
o
|
||||
|
||||
+34
-10
@@ -281,6 +281,7 @@ static void ColorizeEntry(CalEntry const *e, int clamp);
|
||||
static void SortCol (CalEntry **col);
|
||||
static void DoCalendarOneWeek (int nleft);
|
||||
static void DoCalendarOneMonth (void);
|
||||
static void DoSimpleCalendarOneMonth (void);
|
||||
static int WriteCalendarRow (void);
|
||||
static void WriteWeekHeaderLine (void);
|
||||
static void WritePostHeaderLine (void);
|
||||
@@ -967,21 +968,20 @@ static void DoCalendarOneWeek(int nleft)
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoCalendarOneMonth */
|
||||
/* DoSimpleCalendarOneMonth */
|
||||
/* */
|
||||
/* Produce a calendar for the current month. */
|
||||
/* Produce a "simple" calendar for the current month. */
|
||||
/* */
|
||||
/* A simple calendar is produced if the -s or -p option */
|
||||
/* was used. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void DoCalendarOneMonth(void)
|
||||
static void DoSimpleCalendarOneMonth(void)
|
||||
{
|
||||
int y, m, d, mm, yy, i, j;
|
||||
|
||||
InitMoonsAndShades();
|
||||
|
||||
if (!DoSimpleCalendar) WriteCalHeader();
|
||||
|
||||
DidADay = 0;
|
||||
|
||||
if (PsCal) {
|
||||
FromDSE(DSEToday, &y, &m, &d);
|
||||
if (PsCal == PSCAL_LEVEL1) {
|
||||
@@ -1054,7 +1054,29 @@ static void DoCalendarOneMonth(void)
|
||||
}
|
||||
printf("]\n}");
|
||||
}
|
||||
if (!DoSimpleCalendar) WriteCalTrailer();
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoCalendarOneMonth */
|
||||
/* */
|
||||
/* Produce a calendar for the current month. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void DoCalendarOneMonth(void)
|
||||
{
|
||||
InitMoonsAndShades();
|
||||
|
||||
if (DoSimpleCalendar) {
|
||||
DoSimpleCalendarOneMonth();
|
||||
return;
|
||||
}
|
||||
|
||||
WriteCalHeader();
|
||||
|
||||
while (WriteCalendarRow()) /* continue */;
|
||||
|
||||
WriteCalTrailer();
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1702,8 +1724,10 @@ static void GenerateCalEntries(int col)
|
||||
/* need to destroy it here. */
|
||||
|
||||
default:
|
||||
Wprint("Unrecognized command; interpreting as REM");
|
||||
WarnedAboutImplicit = 1;
|
||||
if (!SuppressImplicitRemWarnings) {
|
||||
Wprint("Unrecognized command; interpreting as REM");
|
||||
WarnedAboutImplicit = 1;
|
||||
}
|
||||
CreateParser(CurLine, &p);
|
||||
r=DoCalRem(&p, col);
|
||||
break;
|
||||
|
||||
+39
-6
@@ -208,7 +208,7 @@ int DoRem(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) {
|
||||
if ( (r=ParseRem(p, &trig, &tim)) != OK ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
@@ -437,10 +437,17 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
||||
if (trig->m != NO_MON) return E_MON_TWICE;
|
||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||
DBufFree(&buf);
|
||||
if (trig->d != NO_DAY) {
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
if (trig->m != NO_MON) {
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
if (trig->y != NO_YR) {
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
|
||||
FromDSE(tok.val, &y, &m, &d);
|
||||
trig->y = y;
|
||||
trig->m = m;
|
||||
@@ -542,6 +549,12 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case T_Number:
|
||||
DBufFree(&buf);
|
||||
Eprint("`%d' is not recognized as a year (%d-%d) or a day number (1-31)",
|
||||
tok.val, BASE, BASE+YR_RANGE);
|
||||
return E_PARSE_ERR;
|
||||
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||
@@ -682,11 +695,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
trig->typ = MSG_TYPE;
|
||||
if (s->isnested) return E_CANT_NEST_RTYPE;
|
||||
if (!WarnedAboutImplicit) {
|
||||
if (!WarnedAboutImplicit && !SuppressImplicitRemWarnings) {
|
||||
Wprint("Missing REM type; assuming MSG");
|
||||
WarnedAboutImplicit = 1;
|
||||
}
|
||||
@@ -787,6 +805,11 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
|
||||
|
||||
PushToken(DBufValue(&buf), s);
|
||||
@@ -904,6 +927,11 @@ static int ParseUntil(ParsePtr s, Trigger *t, int type)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("%s: %s", which, ErrMsg[E_INCOMPLETE]);
|
||||
DBufFree(&buf);
|
||||
@@ -1023,6 +1051,11 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]);
|
||||
DBufFree(&buf);
|
||||
|
||||
@@ -152,7 +152,6 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
|
||||
/* Try reading the first few bytes right into the buffer --
|
||||
we can usually save some unnecessary copying */
|
||||
|
||||
*(dbuf->buffer) = 0;
|
||||
if (fgets(dbuf->buffer, dbuf->allocatedLen, fp) == NULL) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
+51
-29
@@ -685,16 +685,12 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
/* Add a call to the call stack for better error messages */
|
||||
pushed = push_call(f->filename, f->name, f->lineno);
|
||||
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
debug_enter_userfunc(node, new_locals, f->nargs);
|
||||
}
|
||||
DBG(debug_enter_userfunc(node, new_locals, f->nargs));
|
||||
|
||||
/* Evaluate the function's expr_node tree */
|
||||
r = evaluate_expr_node(f->node, new_locals, ans, nonconst);
|
||||
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
debug_exit_userfunc(node, ans, r, new_locals, f->nargs);
|
||||
}
|
||||
DBG(debug_exit_userfunc(node, ans, r, new_locals, f->nargs));
|
||||
|
||||
if (r != OK) {
|
||||
/* We print the error here in order to get the call stack trace */
|
||||
@@ -1506,18 +1502,7 @@ static int logical_and(expr_node *node, Value *locals, Value *ans, int *nonconst
|
||||
/* Read a token. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int parse_expr_token_aux(DynamicBuffer *buf, char const **in);
|
||||
static int parse_expr_token(DynamicBuffer *buf, char const **in)
|
||||
{
|
||||
int r = parse_expr_token_aux(buf, in);
|
||||
|
||||
/* Munch any following whitespace */
|
||||
while (**in && isempty(**in)) (*in)++;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int parse_expr_token_aux(DynamicBuffer *buf, char const **in)
|
||||
{
|
||||
|
||||
char c;
|
||||
@@ -1556,6 +1541,7 @@ static int parse_expr_token_aux(DynamicBuffer *buf, char const **in)
|
||||
}
|
||||
(*in)++;
|
||||
} else {
|
||||
Eprint("%s `%c' (did you mean `%c%c'?)", ErrMsg[E_PARSE_ERR], c, c, c);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
return OK;
|
||||
@@ -1699,7 +1685,7 @@ static int parse_expr_token_aux(DynamicBuffer *buf, char const **in)
|
||||
/***************************************************************/
|
||||
static int peek_expr_token(DynamicBuffer *buf, char const *in)
|
||||
{
|
||||
return parse_expr_token_aux(buf, &in);
|
||||
return parse_expr_token(buf, &in);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1918,11 +1904,25 @@ static int set_constant_value(expr_node *atom)
|
||||
return OK;
|
||||
} else if (*s == '\'') { /* It's a literal date */
|
||||
s++;
|
||||
if ((r=ParseLiteralDate(&s, &dse, &tim)) != 0) return r;
|
||||
if (*s != '\'') return E_BAD_DATE;
|
||||
if ((r=ParseLiteralDateOrTime(&s, &dse, &tim)) != 0) {
|
||||
Eprint("%s: %s", ErrMsg[r], DBufValue(&ExprBuf));
|
||||
return r;
|
||||
}
|
||||
if (*s != '\'') {
|
||||
if (dse != NO_DATE) {
|
||||
Eprint("%s: %s", ErrMsg[E_BAD_DATE], DBufValue(&ExprBuf));
|
||||
return E_BAD_DATE;
|
||||
} else {
|
||||
Eprint("%s: %s", ErrMsg[E_BAD_TIME], DBufValue(&ExprBuf));
|
||||
return E_BAD_TIME;
|
||||
}
|
||||
}
|
||||
if (tim == NO_TIME) {
|
||||
atom->u.value.type = DATE_TYPE;
|
||||
atom->u.value.v.val = dse;
|
||||
} else if (dse == NO_DATE) {
|
||||
atom->u.value.type = TIME_TYPE;
|
||||
atom->u.value.v.val = tim;
|
||||
} else {
|
||||
atom->u.value.type = DATETIME_TYPE;
|
||||
atom->u.value.v.val = (dse * MINUTES_PER_DAY) + tim;
|
||||
@@ -1943,7 +1943,10 @@ static int set_constant_value(expr_node *atom)
|
||||
}
|
||||
if (*s == ':' || *s == '.' || *s == TimeSep) { /* Must be a literal time */
|
||||
s++;
|
||||
if (!isdigit(*s)) return E_BAD_TIME;
|
||||
if (!isdigit(*s)) {
|
||||
Eprint("%s: `%s'", ErrMsg[E_BAD_TIME], DBufValue(&ExprBuf));
|
||||
return E_BAD_TIME;
|
||||
}
|
||||
h = val;
|
||||
m = 0;
|
||||
while (isdigit(*s)) {
|
||||
@@ -1959,9 +1962,15 @@ static int set_constant_value(expr_node *atom)
|
||||
s++;
|
||||
}
|
||||
}
|
||||
if (*s || h>23 || m>59) return E_BAD_TIME;
|
||||
if (*s || h>23 || m>59) {
|
||||
Eprint("%s: `%s'", ErrMsg[E_BAD_TIME], DBufValue(&ExprBuf));
|
||||
return E_BAD_TIME;
|
||||
}
|
||||
if (ampm) {
|
||||
if (h < 1 || h > 12) return E_BAD_TIME;
|
||||
if (h < 1 || h > 12) {
|
||||
Eprint("%s: `%s'", ErrMsg[E_BAD_TIME], DBufValue(&ExprBuf));
|
||||
return E_BAD_TIME;
|
||||
}
|
||||
if (ampm == 'a') {
|
||||
if (h == 12) {
|
||||
h = 0;
|
||||
@@ -1977,7 +1986,10 @@ static int set_constant_value(expr_node *atom)
|
||||
return OK;
|
||||
}
|
||||
/* Not a time - must be a number */
|
||||
if (*s) return E_BAD_NUMBER;
|
||||
if (*s) {
|
||||
Eprint("%s: `%s'", ErrMsg[E_BAD_NUMBER], DBufValue(&ExprBuf));
|
||||
return E_BAD_NUMBER;
|
||||
}
|
||||
atom->u.value.type = INT_TYPE;
|
||||
atom->u.value.v.val = val;
|
||||
return OK;
|
||||
@@ -2025,7 +2037,7 @@ static int make_atom(expr_node *atom, Var *locals)
|
||||
/* System Variable */
|
||||
if (*(s) == '$' && isalpha(*(s+1))) {
|
||||
if (!FindSysVar(s+1)) {
|
||||
Eprint("`%s': %s", s, ErrMsg[E_NOSUCH_VAR]);
|
||||
Eprint("%s: `%s'", ErrMsg[E_NOSUCH_VAR], s);
|
||||
return E_NOSUCH_VAR;
|
||||
}
|
||||
if (strlen(s+1) < SHORT_NAME_BUF) {
|
||||
@@ -2860,25 +2872,32 @@ int ParseLiteralTime(char const **s, int *tim)
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ParseLiteralDate */
|
||||
/* ParseLiteralDateOrTime */
|
||||
/* */
|
||||
/* Parse a literal date or datetime. Return result in dse */
|
||||
/* and tim; update s. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ParseLiteralDate(char const **s, int *dse, int *tim)
|
||||
int ParseLiteralDateOrTime(char const **s, int *dse, int *tim)
|
||||
{
|
||||
int y, m, d;
|
||||
int r;
|
||||
|
||||
char const *orig_s = *s;
|
||||
|
||||
y=0; m=0; d=0;
|
||||
|
||||
*tim = NO_TIME;
|
||||
*dse = NO_DATE;
|
||||
if (!isdigit(**s)) return E_BAD_DATE;
|
||||
while (isdigit(**s)) {
|
||||
y *= 10;
|
||||
y += *(*s)++ - '0';
|
||||
}
|
||||
if (**s == ':' || **s == '.' || **s == TimeSep) {
|
||||
*s = orig_s;
|
||||
return ParseLiteralTime(s, tim);
|
||||
}
|
||||
if (**s != '/' && **s != '-' && **s != DateSep) return E_BAD_DATE;
|
||||
(*s)++;
|
||||
if (!isdigit(**s)) return E_BAD_DATE;
|
||||
@@ -2934,7 +2953,8 @@ int DoCoerce(char type, Value *v)
|
||||
return OK;
|
||||
case STR_TYPE:
|
||||
s = v->v.str;
|
||||
if (ParseLiteralDate(&s, &i, &m)) return E_CANT_COERCE;
|
||||
if (ParseLiteralDateOrTime(&s, &i, &m)) return E_CANT_COERCE;
|
||||
if (i == NO_DATE) return E_CANT_COERCE;
|
||||
if (*s) return E_CANT_COERCE;
|
||||
v->type = DATETIME_TYPE;
|
||||
free(v->v.str);
|
||||
@@ -3016,7 +3036,8 @@ int DoCoerce(char type, Value *v)
|
||||
|
||||
case STR_TYPE:
|
||||
s = v->v.str;
|
||||
if (ParseLiteralDate(&s, &i, &m)) return E_CANT_COERCE;
|
||||
if (ParseLiteralDateOrTime(&s, &i, &m)) return E_CANT_COERCE;
|
||||
if (i == NO_DATE) return E_CANT_COERCE;
|
||||
if (*s) return E_CANT_COERCE;
|
||||
v->type = DATE_TYPE;
|
||||
free(v->v.str);
|
||||
@@ -3042,6 +3063,7 @@ int DoCoerce(char type, Value *v)
|
||||
|
||||
case STR_TYPE:
|
||||
s = v->v.str;
|
||||
i=0; /* Avoid compiler warning */
|
||||
if (ParseLiteralTime(&s, &i)) return E_CANT_COERCE;
|
||||
if (*s) return E_CANT_COERCE;
|
||||
v->type = TIME_TYPE;
|
||||
|
||||
+10
@@ -4005,3 +4005,13 @@ BuiltinFunc *FindBuiltinFunc(char const *name)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
print_builtinfunc_tokens(void)
|
||||
{
|
||||
int i;
|
||||
printf("\n# Built-in Functions\n\n");
|
||||
for (i=0; i<NumFuncs; i++) {
|
||||
printf("%s\n", Func[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +171,9 @@ EXTERN DynamicBuffer ExprBuf;
|
||||
/* User-func recursion level */
|
||||
EXTERN INIT( unsigned int FuncRecursionLevel, 0);
|
||||
|
||||
/* Suppress warnings about implicit REM and MSG */
|
||||
EXTERN INIT( int SuppressImplicitRemWarnings, 0);
|
||||
|
||||
extern int NumFullOmits, NumPartialOmits;
|
||||
|
||||
/* List of months */
|
||||
|
||||
+10
@@ -717,6 +717,10 @@ void InitRemind(int argc, char const *argv[])
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
fprintf(stderr, "%s: `%s'\n", ErrMsg[-tok.val], arg);
|
||||
Usage();
|
||||
}
|
||||
Usage();
|
||||
}
|
||||
}
|
||||
@@ -1067,6 +1071,12 @@ ProcessLongOption(char const *arg)
|
||||
printf("%s\n", VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
if (!strcmp(arg, "print-tokens")) {
|
||||
print_remind_tokens();
|
||||
print_builtinfunc_tokens();
|
||||
print_sysvar_tokens();
|
||||
exit(0);
|
||||
}
|
||||
if (sscanf(arg, "max-execution-time=%d", &t) == 1) {
|
||||
if (t < 0) {
|
||||
fprintf(ErrFp, "%s: --max-execution-time must be non-negative\n", ArgV[0]);
|
||||
|
||||
+4
-2
@@ -356,8 +356,10 @@ static void DoReminders(void)
|
||||
/* If we don't recognize the command, do a REM by default, but warn */
|
||||
|
||||
default:
|
||||
Wprint("Unrecognized command; interpreting as REM");
|
||||
WarnedAboutImplicit = 1;
|
||||
if (!SuppressImplicitRemWarnings) {
|
||||
Wprint("Unrecognized command; interpreting as REM");
|
||||
WarnedAboutImplicit = 1;
|
||||
}
|
||||
DestroyParser(&p);
|
||||
CreateParser(CurLine, &p);
|
||||
purge_handled = 1;
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ static double phase (double, double *, double *, double *, double *, double *, d
|
||||
/* */
|
||||
/* jdate */
|
||||
/* */
|
||||
/* Convert a date and time to DSE day and fraction. */
|
||||
/* Convert a date and time to Julian day and fraction. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static long jdate(int y, int mon, int day)
|
||||
|
||||
+5
-1
@@ -145,7 +145,9 @@ int PushOmitContext(ParsePtr p)
|
||||
context->partsave = malloc(NumPartialOmits * sizeof(int));
|
||||
if (NumPartialOmits && !context->partsave) {
|
||||
free(context->filename);
|
||||
free(context->fullsave);
|
||||
if (context->fullsave) {
|
||||
free(context->fullsave);
|
||||
}
|
||||
free(context);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
@@ -399,6 +401,8 @@ int DoOmit(ParsePtr p)
|
||||
default:
|
||||
if (tok.type == T_Until) {
|
||||
Eprint("OMIT: UNTIL not allowed; did you mean THROUGH?");
|
||||
} else if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
} else {
|
||||
Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN],
|
||||
DBufValue(&buf));
|
||||
|
||||
+6
-1
@@ -55,7 +55,7 @@ int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queu
|
||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int dse, int *err);
|
||||
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode);
|
||||
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int dse, int tim);
|
||||
int ParseLiteralDate (char const **s, int *dse, int *tim);
|
||||
int ParseLiteralDateOrTime (char const **s, int *dse, int *tim);
|
||||
int ParseLiteralTime (char const **s, int *tim);
|
||||
expr_node *parse_expression(char const **e, int *r, Var *locals);
|
||||
|
||||
@@ -242,3 +242,8 @@ void PutWideChar(wchar_t const wc, DynamicBuffer *output);
|
||||
extern int _private_mul_overflow(int a, int b);
|
||||
extern int _private_add_overflow(int a, int b);
|
||||
extern int _private_sub_overflow(int a, int b);
|
||||
|
||||
/* Utility functions for dumping tokens */
|
||||
void print_sysvar_tokens(void);
|
||||
void print_builtinfunc_tokens(void);
|
||||
void print_remind_tokens(void);
|
||||
|
||||
+137
-28
@@ -39,19 +39,19 @@ while (isdigit(*(string))) { \
|
||||
Token TokArray[] = {
|
||||
/* NAME MINLEN TYPE VALUE */
|
||||
{ "addomit", 7, T_AddOmit, 0 },
|
||||
{ "after", 3, T_Skip, AFTER_SKIP },
|
||||
{ "after", 5, T_Skip, AFTER_SKIP },
|
||||
{ "april", 3, T_Month, 3 },
|
||||
{ "at", 2, T_At, 0 },
|
||||
{ "august", 3, T_Month, 7 },
|
||||
{ "banner", 3, T_Banner, 0 },
|
||||
{ "before", 3, T_Skip, BEFORE_SKIP },
|
||||
{ "before", 6, T_Skip, BEFORE_SKIP },
|
||||
{ "cal", 3, T_RemType, CAL_TYPE },
|
||||
{ "clear-omit-context", 5, T_Clr, 0 },
|
||||
{ "debug", 5, T_Debug, 0 },
|
||||
{ "december", 3, T_Month, 11 },
|
||||
{ "do", 2, T_IncludeR, 0 },
|
||||
{ "dumpvars", 4, T_Dumpvars, 0 },
|
||||
{ "duration", 3, T_Duration, 0 },
|
||||
{ "duration", 8, T_Duration, 0 },
|
||||
{ "else", 4, T_Else, 0 },
|
||||
{ "endif", 5, T_EndIf, 0 },
|
||||
{ "errmsg", 6, T_ErrMsg, 0 },
|
||||
@@ -85,9 +85,9 @@ Token TokArray[] = {
|
||||
{ "noqueue", 7, T_NoQueue, 0 },
|
||||
{ "november", 3, T_Month, 10 },
|
||||
{ "october", 3, T_Month, 9 },
|
||||
{ "omit", 3, T_Omit, 0 },
|
||||
{ "omit", 4, T_Omit, 0 },
|
||||
{ "omitfunc", 8, T_OmitFunc, 0 },
|
||||
{ "once", 3, T_Once, 0 },
|
||||
{ "once", 4, T_Once, 0 },
|
||||
{ "pop-omit-context", 3, T_Pop, 0 },
|
||||
{ "preserve", 8, T_Preserve, 0 },
|
||||
{ "priority", 8, T_Priority, 0 },
|
||||
@@ -103,7 +103,7 @@ Token TokArray[] = {
|
||||
{ "second", 6, T_Ordinal, 1 },
|
||||
{ "september", 3, T_Month, 8 },
|
||||
{ "set", 3, T_Set, 0 },
|
||||
{ "skip", 3, T_Skip, SKIP_SKIP },
|
||||
{ "skip", 4, T_Skip, SKIP_SKIP },
|
||||
{ "special", 7, T_RemType, PASSTHRU_TYPE },
|
||||
{ "sunday", 3, T_WkDay, 6 },
|
||||
{ "tag", 3, T_Tag, 0 },
|
||||
@@ -112,13 +112,28 @@ Token TokArray[] = {
|
||||
{ "thursday", 3, T_WkDay, 3 },
|
||||
{ "tuesday", 3, T_WkDay, 1 },
|
||||
{ "unset", 5, T_UnSet, 0 },
|
||||
{ "until", 3, T_Until, 0 },
|
||||
{ "until", 5, T_Until, 0 },
|
||||
{ "warn", 4, T_Warn, 0 },
|
||||
{ "wednesday", 3, T_WkDay, 2 }
|
||||
};
|
||||
|
||||
static int TokStrCmp (Token const *t, char const *s);
|
||||
|
||||
static void
|
||||
init_token(Token *t)
|
||||
{
|
||||
t->name = NULL;
|
||||
t->type = T_Illegal;
|
||||
t->val = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
token_error(Token *t, int errcode)
|
||||
{
|
||||
t->type = T_Illegal;
|
||||
t->val = -errcode;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FindInitialToken */
|
||||
@@ -132,7 +147,7 @@ char const *FindInitialToken(Token *tok, char const *s)
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
tok->type = T_Illegal;
|
||||
init_token(tok);
|
||||
|
||||
while (isempty(*s)) s++;
|
||||
|
||||
@@ -159,7 +174,7 @@ void FindToken(char const *s, Token *tok)
|
||||
int top, bot, mid, r, max;
|
||||
int l;
|
||||
|
||||
tok->type = T_Illegal;
|
||||
init_token(tok);
|
||||
if (! *s) {
|
||||
tok->type = T_Empty;
|
||||
return;
|
||||
@@ -233,9 +248,9 @@ void FindNumericToken(char const *s, Token *t)
|
||||
int mult = 1, hour, min;
|
||||
char const *s_orig = s;
|
||||
int ampm = 0;
|
||||
int r;
|
||||
|
||||
t->type = T_Illegal;
|
||||
t->val = 0;
|
||||
init_token(t);
|
||||
if (isdigit(*s)) {
|
||||
PARSENUM(t->val, s);
|
||||
|
||||
@@ -243,22 +258,37 @@ void FindNumericToken(char const *s, Token *t)
|
||||
if (*s == '-' || *s == '/') {
|
||||
char const *p = s_orig;
|
||||
int dse, tim;
|
||||
if (ParseLiteralDate(&p, &dse, &tim) == OK) {
|
||||
if (*p) return;
|
||||
r = ParseLiteralDateOrTime(&p, &dse, &tim);
|
||||
if (r == OK) {
|
||||
if (*p) {
|
||||
if (tim == NO_TIME) {
|
||||
t->val = -E_BAD_DATE;
|
||||
} else {
|
||||
t->val = -E_BAD_TIME;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (tim == NO_TIME) {
|
||||
t->type = T_Date;
|
||||
t->val = dse;
|
||||
return;
|
||||
}
|
||||
if (dse == NO_DATE) {
|
||||
t->type = T_Time;
|
||||
t->val = tim;
|
||||
return;
|
||||
}
|
||||
t->type = T_DateTime;
|
||||
t->val = MINUTES_PER_DAY * dse + tim;
|
||||
}
|
||||
} else {
|
||||
token_error(t, r);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we hit a comma, swallow it. This allows stuff
|
||||
like Jan 6, 1998 */
|
||||
if (*s == ',') {
|
||||
if (*s == ',' && *(s+1) == 0) {
|
||||
/* Classify the number we've got */
|
||||
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;
|
||||
@@ -269,8 +299,16 @@ void FindNumericToken(char const *s, Token *t)
|
||||
if (*s == ':' || *s == '.' || *s == TimeSep) {
|
||||
s++;
|
||||
hour = t->val;
|
||||
if (!isdigit(*s)) {
|
||||
token_error(t, E_BAD_TIME);
|
||||
return;
|
||||
}
|
||||
PARSENUM(min, s);
|
||||
if (min > 59) return; /* Illegal time */
|
||||
if (min > 59) {
|
||||
/* Illegal time */
|
||||
token_error(t, E_BAD_TIME);
|
||||
return;
|
||||
}
|
||||
/* Check for p[m] or a[m] */
|
||||
if (*s == 'A' || *s == 'a' || *s == 'P' || *s == 'p') {
|
||||
ampm = tolower(*s);
|
||||
@@ -279,9 +317,15 @@ void FindNumericToken(char const *s, Token *t)
|
||||
s++;
|
||||
}
|
||||
}
|
||||
if (*s) return; /* Illegal time */
|
||||
if (*s) {
|
||||
token_error(t, E_BAD_TIME);
|
||||
return;
|
||||
}
|
||||
if (ampm) {
|
||||
if (hour < 1 || hour > 12) return;
|
||||
if (hour < 1 || hour > 12) {
|
||||
token_error(t, E_BAD_TIME);
|
||||
return;
|
||||
}
|
||||
if (ampm == 'a') {
|
||||
if (hour == 12) {
|
||||
hour = 0;
|
||||
@@ -303,45 +347,70 @@ void FindNumericToken(char const *s, Token *t)
|
||||
}
|
||||
|
||||
/* If we hit a non-digit, error! */
|
||||
if (*s) return;
|
||||
if (*s) {
|
||||
token_error(t, E_BAD_NUMBER);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Classify the number we've got */
|
||||
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 t->type = T_Number;
|
||||
return;
|
||||
} else if (*s == '*') {
|
||||
}
|
||||
|
||||
switch (*s) {
|
||||
case '*':
|
||||
s++;
|
||||
PARSENUM(t->val, s);
|
||||
if (*s) return; /* Illegal token if followed by non-numeric char */
|
||||
if (*s) {
|
||||
/* Illegal token if followed by non-numeric char */
|
||||
token_error(t, E_BAD_NUMBER);
|
||||
return;
|
||||
}
|
||||
t->type = T_Rep;
|
||||
return;
|
||||
} else if (*s == '+') {
|
||||
|
||||
case '+':
|
||||
s++;
|
||||
if (*s == '+') { mult = -1; s++; }
|
||||
PARSENUM(t->val, s);
|
||||
if (*s) return; /* Illegal token if followed by non-numeric char */
|
||||
if (*s) {
|
||||
/* Illegal token if followed by non-numeric char */
|
||||
token_error(t, E_BAD_NUMBER);
|
||||
return;
|
||||
}
|
||||
t->type = T_Delta;
|
||||
t->val *= mult;
|
||||
return;
|
||||
} else if (*s == '-') {
|
||||
case '-':
|
||||
s++;
|
||||
if (*s == '-') { mult = -1; s++; }
|
||||
PARSENUM(t->val, s);
|
||||
if (*s) return; /* Illegal token if followed by non-numeric char */
|
||||
if (*s) {
|
||||
/* Illegal token if followed by non-numeric char */
|
||||
token_error(t, E_BAD_NUMBER);
|
||||
return;
|
||||
}
|
||||
t->type = T_Back;
|
||||
t->val *= mult;
|
||||
return;
|
||||
} else if (*s == '~') {
|
||||
|
||||
case '~':
|
||||
s++;
|
||||
if (*s == '~') { mult = -1; s++; }
|
||||
PARSENUM(t->val, s);
|
||||
if (*s) return; /* Illegal token if followed by non-numeric char */
|
||||
if (*s) {
|
||||
/* Illegal token if followed by non-numeric char */
|
||||
token_error(t, E_BAD_NUMBER);
|
||||
return;
|
||||
}
|
||||
t->type = T_BackAdj;
|
||||
t->val *= mult;
|
||||
return;
|
||||
|
||||
default: return;
|
||||
}
|
||||
return; /* Unknown token type */
|
||||
}
|
||||
|
||||
|
||||
@@ -368,3 +437,43 @@ static int TokStrCmp(Token const *t, char const *s)
|
||||
if (!*s || (*s == ',' && !*(s+1))) return 0;
|
||||
return (*tk - tolower(*s));
|
||||
}
|
||||
|
||||
static void
|
||||
print_token(Token *tok)
|
||||
{
|
||||
if (tok->MinLen < (int) strlen(tok->name)) {
|
||||
printf("%.*s\n", tok->MinLen, tok->name);
|
||||
}
|
||||
printf("%s\n", tok->name);
|
||||
}
|
||||
|
||||
void
|
||||
print_remind_tokens(void)
|
||||
{
|
||||
int i;
|
||||
Token *tok;
|
||||
int num = (int) (sizeof(TokArray) / sizeof(TokArray[0]));
|
||||
printf("# Remind Tokens\n\n");
|
||||
for (i=0; i<num; i++) {
|
||||
tok = &TokArray[i];
|
||||
if (tok->type != T_Month && tok->type != T_WkDay) {
|
||||
print_token(tok);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n# Month Names\n\n");
|
||||
for (i=0; i<num; i++) {
|
||||
tok = &TokArray[i];
|
||||
if (tok->type == T_Month) {
|
||||
print_token(tok);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n# Weekdays\n\n");
|
||||
for (i=0; i<num; i++) {
|
||||
tok = &TokArray[i];
|
||||
if (tok->type == T_WkDay) {
|
||||
print_token(tok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,7 +572,7 @@ int GetVarValue(char const *str, Value *val)
|
||||
v=FindVar(str, 0);
|
||||
|
||||
if (!v) {
|
||||
Eprint("%s: %s", ErrMsg[E_NOSUCH_VAR], str);
|
||||
Eprint("%s: `%s'", ErrMsg[E_NOSUCH_VAR], str);
|
||||
return E_NOSUCH_VAR;
|
||||
}
|
||||
return CopyValue(val, &v->v);
|
||||
@@ -934,6 +934,7 @@ static SysVar SysVarArr[] = {
|
||||
{"SortByTime", 0, INT_TYPE, &SortByTime, 0, 0 },
|
||||
{"SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132 },
|
||||
{"Sunday", 1, STR_TYPE, &DynamicDayName[6], 0, 0 },
|
||||
{"SuppressImplicitWarnings", 1, INT_TYPE, &SuppressImplicitRemWarnings, 0, 1},
|
||||
{"SuppressLRM", 1, INT_TYPE, &SuppressLRM, 0, 1 },
|
||||
{"SysInclude", 0, STR_TYPE, &SysDir, 0, 0 },
|
||||
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0 },
|
||||
@@ -1119,7 +1120,7 @@ static void DumpSysVar(char const *name, const SysVar *v)
|
||||
return;
|
||||
}
|
||||
if (name) strcat(buffer, name); else strcat(buffer, v->name);
|
||||
fprintf(ErrFp, "%16s ", buffer);
|
||||
fprintf(ErrFp, "%25s ", buffer);
|
||||
if (v) {
|
||||
if (v->type == CONST_INT_TYPE) {
|
||||
fprintf(ErrFp, "%d\n", v->constval);
|
||||
@@ -1198,3 +1199,12 @@ set_components_from_lat_and_long(void)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_sysvar_tokens(void)
|
||||
{
|
||||
int i;
|
||||
printf("\n# System Variables\n\n");
|
||||
for (i=0; i< (int) NUMSYSVARS; i++) {
|
||||
printf("$%s\n", SysVarArr[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,6 +597,9 @@ if test $? = 0 ; then
|
||||
done
|
||||
fi
|
||||
|
||||
# Test --print-tokens long option
|
||||
../src/remind --print-tokens < /dev/null >> ../tests/test.out 2>&1
|
||||
|
||||
cmp -s ../tests/test.out ../tests/test.cmp
|
||||
if [ "$?" = "0" ]; then
|
||||
echo "Remind: Acceptance test PASSED"
|
||||
|
||||
+470
-122
@@ -1007,7 +1007,7 @@ a049 => 21
|
||||
substr(21, 2) => Type mismatch
|
||||
../tests/test.rem(326): substr(): Type mismatch
|
||||
set a051 substr(a050, 2, 6)
|
||||
../tests/test.rem(327): Undefined variable: a050
|
||||
../tests/test.rem(327): Undefined variable: `a050'
|
||||
a050 => Undefined variable
|
||||
set a052 time(1+2, 3+4)
|
||||
1 + 2 => 3
|
||||
@@ -1334,7 +1334,7 @@ trigduration() => -1
|
||||
# Test adding TIME+TIME and DATETIME+TIME
|
||||
set a126 11:00 + 3:00
|
||||
11:00 + 03:00 => 14:00
|
||||
set a127 23:00 + 5:30
|
||||
set a127 '23:00' + 5:30
|
||||
23:00 + 05:30 => 04:30
|
||||
set a128 '2018-02-03@10:00' + 6:45
|
||||
2018-02-03@10:00 + 06:45 => 2018-02-03@16:45
|
||||
@@ -2716,114 +2716,115 @@ a125 -1
|
||||
dump $
|
||||
Variable Value
|
||||
|
||||
$AddBlankLines 1 [0, 1]
|
||||
$Ago "ago"
|
||||
$Am "am"
|
||||
$And "and"
|
||||
$April "April"
|
||||
$At "at"
|
||||
$August "August"
|
||||
$CalcUTC 0 [0, 1]
|
||||
$CalMode 0
|
||||
$Daemon 0
|
||||
$DateSep "-"
|
||||
$DateTimeSep "@"
|
||||
$December "December"
|
||||
$DefaultColor "-1 -1 -1"
|
||||
$DefaultPrio 5000 [0, 9999]
|
||||
$DefaultTDelta 0 [0, 1440]
|
||||
$DeltaOverride 0
|
||||
$DontFork 0
|
||||
$DontQueue 1
|
||||
$DontTrigAts 0
|
||||
$EndSent ".?!"
|
||||
$EndSentIg "\"')]}>"
|
||||
$ExpressionTimeLimit 0
|
||||
$February "February"
|
||||
$FirstIndent 0 [0, 132]
|
||||
$FoldYear 0 [0, 1]
|
||||
$FormWidth 72 [20, 500]
|
||||
$Friday "Friday"
|
||||
$Fromnow "from now"
|
||||
$Hour "hour"
|
||||
$Hplu "s"
|
||||
$HushMode 0
|
||||
$IgnoreOnce 1
|
||||
$InfDelta 0
|
||||
$IntMax 2147483647
|
||||
$IntMin -2147483648
|
||||
$Is "is"
|
||||
$January "January"
|
||||
$July "July"
|
||||
$June "June"
|
||||
$LatDeg 30
|
||||
$Latitude "30.500000"
|
||||
$LatMin 30
|
||||
$LatSec 0
|
||||
$Location "Ottawa"
|
||||
$LongDeg -25
|
||||
$Longitude "24.750000"
|
||||
$LongMin 15
|
||||
$LongSec 0
|
||||
$March "March"
|
||||
$MaxFullOmits 1000
|
||||
$MaxLateMinutes 0 [0, 1440]
|
||||
$MaxPartialOmits 366
|
||||
$MaxSatIter 150 [10, Inf)
|
||||
$MaxStringLen 65535 [-1, Inf)
|
||||
$May "May"
|
||||
$MinsFromUTC -300 [-780, 780]
|
||||
$Minute "minute"
|
||||
$Monday "Monday"
|
||||
$Mplu "s"
|
||||
$NextMode 0
|
||||
$November "November"
|
||||
$Now "now"
|
||||
$NumFullOmits 1
|
||||
$NumPartialOmits 0
|
||||
$NumQueued 0
|
||||
$NumTrig 41
|
||||
$October "October"
|
||||
$On "on"
|
||||
$OnceFile ""
|
||||
$ParseUntriggered 1 [0, 1]
|
||||
$Pm "pm"
|
||||
$PrefixLineNo 0
|
||||
$PSCal 0
|
||||
$RunOff 0
|
||||
$Saturday "Saturday"
|
||||
$September "September"
|
||||
$SimpleCal 0
|
||||
$SortByDate 0
|
||||
$SortByPrio 0
|
||||
$SortByTime 0
|
||||
$SubsIndent 0 [0, 132]
|
||||
$Sunday "Sunday"
|
||||
$SuppressLRM 0 [0, 1]
|
||||
$T 0
|
||||
$Td -1
|
||||
$TerminalBackground -1
|
||||
$Thursday "Thursday"
|
||||
$TimeSep ":"
|
||||
$Tm -1
|
||||
$Today "today"
|
||||
$Tomorrow "tomorrow"
|
||||
$Tt 00:00
|
||||
$Tuesday "Tuesday"
|
||||
$Tw -1
|
||||
$Ty -1
|
||||
$U 1991-02-16
|
||||
$Ud 16
|
||||
$Um 2
|
||||
$UntimedFirst 0
|
||||
$Use256Colors 0
|
||||
$UseBGVTColors 0
|
||||
$UseTrueColors 0
|
||||
$UseVTColors 0
|
||||
$Uw 6
|
||||
$Uy 1991
|
||||
$Was "was"
|
||||
$Wednesday "Wednesday"
|
||||
$AddBlankLines 1 [0, 1]
|
||||
$Ago "ago"
|
||||
$Am "am"
|
||||
$And "and"
|
||||
$April "April"
|
||||
$At "at"
|
||||
$August "August"
|
||||
$CalcUTC 0 [0, 1]
|
||||
$CalMode 0
|
||||
$Daemon 0
|
||||
$DateSep "-"
|
||||
$DateTimeSep "@"
|
||||
$December "December"
|
||||
$DefaultColor "-1 -1 -1"
|
||||
$DefaultPrio 5000 [0, 9999]
|
||||
$DefaultTDelta 0 [0, 1440]
|
||||
$DeltaOverride 0
|
||||
$DontFork 0
|
||||
$DontQueue 1
|
||||
$DontTrigAts 0
|
||||
$EndSent ".?!"
|
||||
$EndSentIg "\"')]}>"
|
||||
$ExpressionTimeLimit 0
|
||||
$February "February"
|
||||
$FirstIndent 0 [0, 132]
|
||||
$FoldYear 0 [0, 1]
|
||||
$FormWidth 72 [20, 500]
|
||||
$Friday "Friday"
|
||||
$Fromnow "from now"
|
||||
$Hour "hour"
|
||||
$Hplu "s"
|
||||
$HushMode 0
|
||||
$IgnoreOnce 1
|
||||
$InfDelta 0
|
||||
$IntMax 2147483647
|
||||
$IntMin -2147483648
|
||||
$Is "is"
|
||||
$January "January"
|
||||
$July "July"
|
||||
$June "June"
|
||||
$LatDeg 30
|
||||
$Latitude "30.500000"
|
||||
$LatMin 30
|
||||
$LatSec 0
|
||||
$Location "Ottawa"
|
||||
$LongDeg -25
|
||||
$Longitude "24.750000"
|
||||
$LongMin 15
|
||||
$LongSec 0
|
||||
$March "March"
|
||||
$MaxFullOmits 1000
|
||||
$MaxLateMinutes 0 [0, 1440]
|
||||
$MaxPartialOmits 366
|
||||
$MaxSatIter 150 [10, Inf)
|
||||
$MaxStringLen 65535 [-1, Inf)
|
||||
$May "May"
|
||||
$MinsFromUTC -300 [-780, 780]
|
||||
$Minute "minute"
|
||||
$Monday "Monday"
|
||||
$Mplu "s"
|
||||
$NextMode 0
|
||||
$November "November"
|
||||
$Now "now"
|
||||
$NumFullOmits 1
|
||||
$NumPartialOmits 0
|
||||
$NumQueued 0
|
||||
$NumTrig 41
|
||||
$October "October"
|
||||
$On "on"
|
||||
$OnceFile ""
|
||||
$ParseUntriggered 1 [0, 1]
|
||||
$Pm "pm"
|
||||
$PrefixLineNo 0
|
||||
$PSCal 0
|
||||
$RunOff 0
|
||||
$Saturday "Saturday"
|
||||
$September "September"
|
||||
$SimpleCal 0
|
||||
$SortByDate 0
|
||||
$SortByPrio 0
|
||||
$SortByTime 0
|
||||
$SubsIndent 0 [0, 132]
|
||||
$Sunday "Sunday"
|
||||
$SuppressImplicitWarnings 0 [0, 1]
|
||||
$SuppressLRM 0 [0, 1]
|
||||
$T 0
|
||||
$Td -1
|
||||
$TerminalBackground -1
|
||||
$Thursday "Thursday"
|
||||
$TimeSep ":"
|
||||
$Tm -1
|
||||
$Today "today"
|
||||
$Tomorrow "tomorrow"
|
||||
$Tt 00:00
|
||||
$Tuesday "Tuesday"
|
||||
$Tw -1
|
||||
$Ty -1
|
||||
$U 1991-02-16
|
||||
$Ud 16
|
||||
$Um 2
|
||||
$UntimedFirst 0
|
||||
$Use256Colors 0
|
||||
$UseBGVTColors 0
|
||||
$UseTrueColors 0
|
||||
$UseVTColors 0
|
||||
$Uw 6
|
||||
$Uy 1991
|
||||
$Was "was"
|
||||
$Wednesday "Wednesday"
|
||||
msg [$April]%
|
||||
../tests/test.rem(478): Trig = Saturday, 16 February, 1991
|
||||
$April => "April"
|
||||
@@ -3380,7 +3381,7 @@ 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
|
||||
../tests/test.rem(595): Expecting time after AT
|
||||
../tests/test.rem(595): Ill-formed time: `0:00am'
|
||||
REM AT 1:00AM MSG foo 1a
|
||||
../tests/test.rem(596): Trig = Saturday, 16 February, 1991 AT 01:00
|
||||
foo 1a
|
||||
@@ -3430,9 +3431,9 @@ REM AT 12:00am MSG foo 12a
|
||||
foo 12a
|
||||
|
||||
REM AT 13:00AM MSG foo 13a
|
||||
../tests/test.rem(608): Expecting time after AT
|
||||
../tests/test.rem(608): Ill-formed time: `13:00AM'
|
||||
REM AT 0:00pm MSG foo 0p
|
||||
../tests/test.rem(609): Expecting time after AT
|
||||
../tests/test.rem(609): Ill-formed time: `0:00pm'
|
||||
REM AT 1:00PM MSG foo 1p
|
||||
../tests/test.rem(610): Trig = Saturday, 16 February, 1991 AT 13:00
|
||||
foo 1p
|
||||
@@ -3482,11 +3483,11 @@ REM AT 12:00pm MSG foo 12p
|
||||
foo 12p
|
||||
|
||||
REM AT 13:00PM MSG foo 13p
|
||||
../tests/test.rem(622): Expecting time after AT
|
||||
../tests/test.rem(622): Ill-formed time: `13:00PM'
|
||||
|
||||
DEBUG +x
|
||||
SET x 0:00am + 0
|
||||
../tests/test.rem(625): Ill-formed time
|
||||
../tests/test.rem(625): Ill-formed time: `0:00am'
|
||||
SET x 1:00AM + 0
|
||||
01:00 + 0 => 01:00
|
||||
SET x 2:00am + 0
|
||||
@@ -3512,10 +3513,10 @@ SET x 11:00AM + 0
|
||||
SET x 12:00am + 0
|
||||
00:00 + 0 => 00:00
|
||||
SET x 13:00AM + 0
|
||||
../tests/test.rem(638): Ill-formed time
|
||||
../tests/test.rem(638): Ill-formed time: `13:00AM'
|
||||
|
||||
SET x 0:00pm + 0
|
||||
../tests/test.rem(640): Ill-formed time
|
||||
../tests/test.rem(640): Ill-formed time: `0:00pm'
|
||||
SET x 1:00PM + 0
|
||||
13:00 + 0 => 13:00
|
||||
SET x 2:00pm + 0
|
||||
@@ -3541,10 +3542,10 @@ SET x 11:00PM + 0
|
||||
SET x 12:00pm + 0
|
||||
12:00 + 0 => 12:00
|
||||
SET x 13:00PM + 0
|
||||
../tests/test.rem(653): Ill-formed time
|
||||
../tests/test.rem(653): Ill-formed time: `13:00PM'
|
||||
|
||||
SET x '2015-02-03@0:00am' + 0
|
||||
../tests/test.rem(655): Ill-formed time
|
||||
../tests/test.rem(655): Ill-formed time: '2015-02-03@0:00am'
|
||||
SET x '2015-02-03@1:00AM' + 0
|
||||
2015-02-03@01:00 + 0 => 2015-02-03@01:00
|
||||
SET x '2015-02-03@2:00am' + 0
|
||||
@@ -3570,10 +3571,10 @@ SET x '2015-02-03@11:00AM' + 0
|
||||
SET x '2015-02-03@12:00am' + 0
|
||||
2015-02-03@00:00 + 0 => 2015-02-03@00:00
|
||||
SET x '2015-02-03@13:00AM' + 0
|
||||
../tests/test.rem(668): Ill-formed time
|
||||
../tests/test.rem(668): Ill-formed time: '2015-02-03@13:00AM'
|
||||
|
||||
SET x '2015-02-03@0:00pm' + 0
|
||||
../tests/test.rem(670): Ill-formed time
|
||||
../tests/test.rem(670): Ill-formed time: '2015-02-03@0:00pm'
|
||||
SET x '2015-02-03@1:00PM' + 0
|
||||
2015-02-03@13:00 + 0 => 2015-02-03@13:00
|
||||
SET x '2015-02-03@2:00pm' + 0
|
||||
@@ -3599,7 +3600,7 @@ SET x '2015-02-03@11:00PM' + 0
|
||||
SET x '2015-02-03@12:00pm' + 0
|
||||
2015-02-03@12:00 + 0 => 2015-02-03@12:00
|
||||
SET x '2015-02-03@13:00PM' + 0
|
||||
../tests/test.rem(683): Ill-formed time
|
||||
../tests/test.rem(683): Ill-formed time: '2015-02-03@13:00PM'
|
||||
|
||||
# Test the ampm function
|
||||
set x ampm(0:12) + ""
|
||||
@@ -5699,6 +5700,11 @@ set zxk dooby(1)
|
||||
Entering UserFN dooby(1)
|
||||
Leaving UserFN dooby(1) => 1
|
||||
|
||||
REM 1 Jan 1873 MSG This should fail
|
||||
../tests/test.rem(1122): `1873' is not recognized as a year (1990-5990) or a day number (1-31)
|
||||
REM 1873-12-11 MSG Also bad.
|
||||
../tests/test.rem(1123): Bad date specification: `1873-12-11'
|
||||
|
||||
# Don't want Remind to queue reminders
|
||||
EXIT
|
||||
|
||||
@@ -13235,3 +13241,345 @@ No reminders.
|
||||
| | | | | | | |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|
||||
# Remind Tokens
|
||||
|
||||
addomit
|
||||
after
|
||||
at
|
||||
ban
|
||||
banner
|
||||
before
|
||||
cal
|
||||
clear
|
||||
clear-omit-context
|
||||
debug
|
||||
do
|
||||
dump
|
||||
dumpvars
|
||||
duration
|
||||
else
|
||||
endif
|
||||
errmsg
|
||||
exit
|
||||
expr
|
||||
first
|
||||
flush
|
||||
fourth
|
||||
from
|
||||
fset
|
||||
funset
|
||||
if
|
||||
iftrig
|
||||
in
|
||||
inc
|
||||
include
|
||||
includecmd
|
||||
last
|
||||
lastday
|
||||
lastworkday
|
||||
maybe
|
||||
maybe-uncomputable
|
||||
msf
|
||||
msg
|
||||
noqueue
|
||||
omit
|
||||
omitfunc
|
||||
once
|
||||
pop
|
||||
pop-omit-context
|
||||
preserve
|
||||
priority
|
||||
ps
|
||||
psfile
|
||||
push
|
||||
push-omit-context
|
||||
rem
|
||||
run
|
||||
satisfy
|
||||
scan
|
||||
scanfrom
|
||||
sched
|
||||
second
|
||||
set
|
||||
skip
|
||||
special
|
||||
tag
|
||||
third
|
||||
through
|
||||
unset
|
||||
until
|
||||
warn
|
||||
|
||||
# Month Names
|
||||
|
||||
apr
|
||||
april
|
||||
aug
|
||||
august
|
||||
dec
|
||||
december
|
||||
feb
|
||||
february
|
||||
jan
|
||||
january
|
||||
jul
|
||||
july
|
||||
jun
|
||||
june
|
||||
mar
|
||||
march
|
||||
may
|
||||
nov
|
||||
november
|
||||
oct
|
||||
october
|
||||
sep
|
||||
september
|
||||
|
||||
# Weekdays
|
||||
|
||||
fri
|
||||
friday
|
||||
mon
|
||||
monday
|
||||
sat
|
||||
saturday
|
||||
sun
|
||||
sunday
|
||||
thu
|
||||
thursday
|
||||
tue
|
||||
tuesday
|
||||
wed
|
||||
wednesday
|
||||
|
||||
# Built-in Functions
|
||||
|
||||
abs
|
||||
access
|
||||
adawn
|
||||
adusk
|
||||
ampm
|
||||
ansicolor
|
||||
args
|
||||
asc
|
||||
baseyr
|
||||
char
|
||||
choose
|
||||
coerce
|
||||
columns
|
||||
current
|
||||
date
|
||||
datepart
|
||||
datetime
|
||||
dawn
|
||||
day
|
||||
daysinmon
|
||||
defined
|
||||
dosubst
|
||||
dusk
|
||||
easterdate
|
||||
evaltrig
|
||||
filedate
|
||||
filedatetime
|
||||
filedir
|
||||
filename
|
||||
getenv
|
||||
hebdate
|
||||
hebday
|
||||
hebmon
|
||||
hebyear
|
||||
hour
|
||||
htmlescape
|
||||
htmlstriptags
|
||||
iif
|
||||
index
|
||||
isany
|
||||
isdst
|
||||
isleap
|
||||
isomitted
|
||||
language
|
||||
localtoutc
|
||||
lower
|
||||
max
|
||||
min
|
||||
minsfromutc
|
||||
minute
|
||||
mon
|
||||
monnum
|
||||
moondate
|
||||
moondatetime
|
||||
moonphase
|
||||
moontime
|
||||
multitrig
|
||||
ndawn
|
||||
ndusk
|
||||
nonomitted
|
||||
now
|
||||
ord
|
||||
orthodoxeaster
|
||||
ostype
|
||||
pad
|
||||
plural
|
||||
psmoon
|
||||
psshade
|
||||
realcurrent
|
||||
realnow
|
||||
realtoday
|
||||
rows
|
||||
sgn
|
||||
shell
|
||||
shellescape
|
||||
slide
|
||||
soleq
|
||||
stdout
|
||||
strlen
|
||||
substr
|
||||
sunrise
|
||||
sunset
|
||||
time
|
||||
timepart
|
||||
timezone
|
||||
today
|
||||
trig
|
||||
trigback
|
||||
trigdate
|
||||
trigdatetime
|
||||
trigdelta
|
||||
trigduration
|
||||
trigeventduration
|
||||
trigeventstart
|
||||
trigfrom
|
||||
trigger
|
||||
trigpriority
|
||||
trigrep
|
||||
trigscanfrom
|
||||
trigtags
|
||||
trigtime
|
||||
trigtimedelta
|
||||
trigtimerep
|
||||
triguntil
|
||||
trigvalid
|
||||
typeof
|
||||
tzconvert
|
||||
upper
|
||||
utctolocal
|
||||
value
|
||||
version
|
||||
weekno
|
||||
wkday
|
||||
wkdaynum
|
||||
year
|
||||
|
||||
# System Variables
|
||||
|
||||
$AddBlankLines
|
||||
$Ago
|
||||
$Am
|
||||
$And
|
||||
$April
|
||||
$At
|
||||
$August
|
||||
$CalcUTC
|
||||
$CalMode
|
||||
$Daemon
|
||||
$DateSep
|
||||
$DateTimeSep
|
||||
$December
|
||||
$DefaultColor
|
||||
$DefaultPrio
|
||||
$DefaultTDelta
|
||||
$DeltaOverride
|
||||
$DontFork
|
||||
$DontQueue
|
||||
$DontTrigAts
|
||||
$EndSent
|
||||
$EndSentIg
|
||||
$ExpressionTimeLimit
|
||||
$February
|
||||
$FirstIndent
|
||||
$FoldYear
|
||||
$FormWidth
|
||||
$Friday
|
||||
$Fromnow
|
||||
$Hour
|
||||
$Hplu
|
||||
$HushMode
|
||||
$IgnoreOnce
|
||||
$InfDelta
|
||||
$IntMax
|
||||
$IntMin
|
||||
$Is
|
||||
$January
|
||||
$July
|
||||
$June
|
||||
$LatDeg
|
||||
$Latitude
|
||||
$LatMin
|
||||
$LatSec
|
||||
$Location
|
||||
$LongDeg
|
||||
$Longitude
|
||||
$LongMin
|
||||
$LongSec
|
||||
$March
|
||||
$MaxFullOmits
|
||||
$MaxLateMinutes
|
||||
$MaxPartialOmits
|
||||
$MaxSatIter
|
||||
$MaxStringLen
|
||||
$May
|
||||
$MinsFromUTC
|
||||
$Minute
|
||||
$Monday
|
||||
$Mplu
|
||||
$NextMode
|
||||
$November
|
||||
$Now
|
||||
$NumFullOmits
|
||||
$NumPartialOmits
|
||||
$NumQueued
|
||||
$NumTrig
|
||||
$October
|
||||
$On
|
||||
$OnceFile
|
||||
$ParseUntriggered
|
||||
$Pm
|
||||
$PrefixLineNo
|
||||
$PSCal
|
||||
$RunOff
|
||||
$Saturday
|
||||
$September
|
||||
$SimpleCal
|
||||
$SortByDate
|
||||
$SortByPrio
|
||||
$SortByTime
|
||||
$SubsIndent
|
||||
$Sunday
|
||||
$SuppressImplicitWarnings
|
||||
$SuppressLRM
|
||||
$SysInclude
|
||||
$T
|
||||
$Td
|
||||
$TerminalBackground
|
||||
$Thursday
|
||||
$TimeSep
|
||||
$Tm
|
||||
$Today
|
||||
$Tomorrow
|
||||
$Tt
|
||||
$Tuesday
|
||||
$Tw
|
||||
$Ty
|
||||
$U
|
||||
$Ud
|
||||
$Um
|
||||
$UntimedFirst
|
||||
$Use256Colors
|
||||
$UseBGVTColors
|
||||
$UseTrueColors
|
||||
$UseVTColors
|
||||
$Uw
|
||||
$Uy
|
||||
$Was
|
||||
$Wednesday
|
||||
|
||||
+4
-1
@@ -450,7 +450,7 @@ set a125 trigduration()
|
||||
|
||||
# Test adding TIME+TIME and DATETIME+TIME
|
||||
set a126 11:00 + 3:00
|
||||
set a127 23:00 + 5:30
|
||||
set a127 '23:00' + 5:30
|
||||
set a128 '2018-02-03@10:00' + 6:45
|
||||
set a129 23:30 + '2019-02-02@16:44'
|
||||
|
||||
@@ -1119,6 +1119,9 @@ set zxk dooby()
|
||||
set zxk dooby(1, 2)
|
||||
set zxk dooby(1)
|
||||
|
||||
REM 1 Jan 1873 MSG This should fail
|
||||
REM 1873-12-11 MSG Also bad.
|
||||
|
||||
# Don't want Remind to queue reminders
|
||||
EXIT
|
||||
|
||||
|
||||
Reference in New Issue
Block a user