If you type the command calendar, you'll see lines with "to-do" items for today and tomorrow from a file named calendar in your current directory. If you put that file in your home directory, your system administrator can run the command calendar-to mail (1.33) everyones' "to-do" items to them. You can also automate your personal calendar setup by running calendar yourself - the calendar can be mailed to you, sent to the printer, and so on, first thing each morning. See below for an example calendar file and more information.
calendar builds a complicated egrep (27.5) expression to search your calendar file. You can see that expression yourself if you want to.
Let's start by showing a few lines of a sample calendar file. (Yours can be much longer.) Then I'll run calendar to show what lines it picks:
%cat calendar
-- WORK -- 12/28 Project report due tomorrow! -- PERSONAL -- * 8 rub Lisa's feet Take Lisa out to dinner on December 8 dec 9 buy Lisa lunch On 12/10, Lisa will be hungry for ice cream -- BIRTHDAYS -- 1/1 Mom's birthday - make dinner reservations by 12/20! %date
Tue Dec 8 08:43:40 PST 1992 %calendar
* 8 rub Lisa's feet Take Lisa out to dinner on December 8 dec 9 buy Lisa lunch
Today is December 8.
The calendar utility found lines in my calendar file for
today and tomorrow.
calendar understands lots of date formats.
The date can be anywhere on a line.
If you leave a line in your file for more than one year (like Mom's
birthday) calendar will show it every year.
If a line has more than one date, you'll see the line on both of those
dates (I'll be reminded before Mom's birthday and also in time to make a
dinner reservation).
An asterisk (*
) in place of a month means "all months."
Many versions of calendar utility run your calendar file
through the C language preprocessor, cpp.
Among other things, this lets you include
several calendar files in your own calendar file.
Lines that start with a hash mark (#
) in column 1 are read by the
preprocessor.
For instance, this line in your calendar file would include all
the contents of the file /usr/local/lib/office.calendar
just as if you'd typed them into your own file:
#include "/usr/local/lib/office.calendar"
Someone (the office secretary) can maintain the office.calendar file.
People in the office who want reminders from it can put the
#include
line in their own calendar files.
By the way, if you start a line with #
and it's not for the
preprocessor, you'll get a mysterious error like
calendar:
1:
undefined
control
.
That means line 1 of the file had something the preprocessor couldn't
understand.
How can calendar find dates in all the formats it accepts - and
only for today and tomorrow?
It runs a system program, usually named /usr/lib/calendar,
that generates an expression for
egrep -f (27.7).
The expression searches for the dates of today and tomorrow; if
today is a Friday, the expression includes dates on Saturday, Sunday, and
Monday.
Here's the expression I got by running /usr/lib/calendar
on Tuesday, December 8.
TAB characters are shown as T
; spaces are shown as .
%/usr/lib/calendar
(^|[T(,;])((([Dd]ec[^T]*|\*)[T]*|(012|12|\*)/)0*8)([^0123456789]|$) (^|[T(,;])((([Dd]ec[^T]*|\*)[T]*|(012|12|\*)/)0*9)([^0123456789]|$)
I'll turn the first line of that into English.
I'm not writing this just for egrep fanatics :-)
; this is
also useful for understanding what kinds of dates calendar will
recognize.
I'm going to skip some not-so-subtle things like the nesting of the parentheses
and just give an overview.
If you haven't seen extended regular expressions before, see article
26.4.
The expression finds lines in your calendar file that meet these
conditions, in order from left to right across the line:
(^|[T(,;])
This matches whatever comes before the date.
Match at the beginning of a line (^
) or (|
) match
a space, TAB, opening parenthesis, comma, or semicolon
([T(,;]
).
This keeps egrep from matching other words that start with or
contain the month abbreviation [Dd]ec
.
((([Dd]ec[^T]*|\*)[T]*|(012|12|\*)/)0*8)
This matches the date.
Match Dec or dec with zero or more of any character besides
space or TAB after
that ([Dd]ec[^T]*
)-or (|
) have a literal asterisk
(\*
), which means "match this on any month of the year."
Or (|
) match a numeric month like 012 or 12 or a literal
asterisk ((012|12|\*)
)-followed by a slash (/
).
Finally, you need today's date: it starts with any number of
zeros and ends with 8 ()0*8)
).
([^0123456789]|$)
The end of the expression matches lines anything except a digit - or matches the end of the line. This keeps egrep from matching non-dates like 8.75.
Whew. That expression is repeated for every other day that needs to be matched. On Fridays, the output of /usr/lib/calendar has four lines - one each for Friday, Saturday, Sunday, and Monday.
If you want a calendar every weekday, put a line like the following into your personal crontab file (40.12). We've split this onto two lines for printing, but you should type it all on one line:
$USER && < | 6 6 * * 1-5 tf=/tmp/cal.$USER; umask 077; /bin/calendar > $tf; test -s $tf && mail -s 'Calendar for today' $USER < $tf; rm -f $tf |
---|
That runs calendar from my home directory at
6:06 a.m. (40.5)
every weekday morning.
It sets a
Bourne shell variable (6.8)
named tf with the name of a temporary file in the
/tmp directory (21.3),
and sets a
umask (22.4)
to make the file private.
Then it runs calendar and saves the output in the temporary file.
If there's a calendar for today, the mail command sends the file
to me.
(The -s option on our mail command adds the Subject:
line Calendar for today to the message.
It isn't required.)
Finally, the temporary file is removed.
If you don't have personal crontabs, you can use a self-restarting at job (40.8) and the nextweekday script (40.10) instead.
-