For something to be widely portable, it should be written in sh or csh.
Though csh is clearly brain-dead, I switched to it long ago because sh used
to have some serious deficiencies, like no built-in echo.
Below is a C-shell script I find handy... Hope some of you will too. It
displays three calendars side by side, showing the previous, current, and
following month in a convenient form. It is possible to select the month
and/or year that is displayed in the center.
Curt McDowell
IBM T. J. Watson Research Center
----------------------------------------------------------------------------
#!/bin/csh -f
#
# cal3 by Curt McDowell
#
# Print out three calendars side by side: the previous month,
# the current month, and the next month. It is also possible to
# specify the month and/or year of the middle calendar.
#
set excode=1
if ( $#argv > 0 ) @ month=$1 # Strips leading zeroes
if ( $#argv > 1 ) @ year=$2
if ( $#argv > 2 ) echo "Usage: cal3 [ month [ year ] ]"
if ( $#argv > 2 ) exit 1
if ( ! $?year ) then
set now=`date`
set year=$now[6]
if ( ! $?month ) then
set month=`date +%m`
endif
endif
if ( $year < 70 ) @ year += 2000
if ( $year < 100 ) @ year += 1900
if ( $month == 1 ) @ prevyear = $year - 1
if ( $month == 1 ) @ prevmonth = 12
if ( $month != 1 ) @ prevyear = $year
if ( $month != 1 ) @ prevmonth = $month - 1
if ( $month == 12 ) @ nextyear = $year + 1
if ( $month == 12 ) @ nextmonth = 1
if ( $month != 12 ) @ nextyear = $year
if ( $month != 12 ) @ nextmonth = $month + 1
set TMP1=/tmp/c3_a$$
set TMP2=/tmp/c3_b$$
set TMP3=/tmp/c3_c$$
if ( $month < 1 || $month > 12 ) then
/bin/sh -c "echo 'cal3: Bad parameter.' 1>&2"
goto end
endif
onintr end
/usr/bin/cal $prevmonth $prevyear > $TMP1
/usr/bin/cal $month $year > $TMP2
/usr/bin/cal $nextmonth $nextyear > $TMP3
# /usr/ucb/head is required for some versions of pr (SunOS)
/bin/pr -m -t $TMP1 $TMP2 $TMP3 | /usr/ucb/head -8
set excode=0
end:
/bin/rm -f $TMP1 $TMP2 $TMP3
exit $excode
No, it takes less code. You're using the wrong language.
If these two lines don't send up a red flag in your head, you're
color-blind:
/bin/sh -c "echo 'cal3: Bad parameter.' 1>&2"
goto end
You really ought to consider whether it's time to quit beating your head
against the wall before you incur permanent and incurable brain-damage --
just like the shell you're using. You'd find that it feels really good
when you stop.
The following program is smaller (and thus easier to read and understand),
faster, uses no tempfiles, and gives you today in vt100-style inverse
video. Adding termcap support or command line parsing would be trivial.
--tom
#!/usr/bin/perl
#
# today - print out last month, this month, and next month from
# cal program, with today in reverse video (vt100 hardcoded)
$SO = "\033[7m"; # should really use termcap
$SE = "\033[m";
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$mon++; # 0-based
$year += 1900; # 1900-based
# select next year and prev year "wrapping" at 12 months
$nmon = $mon + 1; $nyear = $year; if ( $nmon == 13 ) { $nmon = 1; $nyear++; }
$pmon = $mon - 1; $pyear = $year; if ( $pmon == 0 ) { $pmon = 12; $pyear--; }
open (prev, "cal $pmon $pyear |");
open (cur, "cal $mon $year |");
open (foll, "cal $nmon $nyear |");
until (eof(prev) && eof(cur) && eof(foll)) {
chop($prev = <prev>); chop($foll = <foll>); chop($cur = <cur>);
$len = 22;
$cur =~ s/\b$mday\b/$SO$mday$SE/ && $len += 7;
printf (sprintf("%%-20s %%-%ds %%-20s\n", $len), $prev, $cur, $foll);
}
>Though csh is clearly brain-dead, I switched to it long ago because sh used
>to have some serious deficiencies, like no built-in echo.
Later, in the csh script:
> /bin/sh -c "echo 'cal3: Bad parameter.' 1>&2"
Doncha just love it?
--
Kenneth Herron khe...@ms.uky.edu
University of Kentucky +1 606 257 2975
Department of Mathematics "Robin Hood was a brave hero, and he wore
the finest green leotards (but we'll forgive him)."
########
# cal3 - 3-month calendar printer
########
case $# in
0|1) eval `date "+M=${1:-%m} Y=19${2:-%y}"`;;
2) M=$1 Y=$2;;
*) echo "Usage: $0 [month [year]]" >&2; exit 2;;
esac
bc <<! | xargs -n2 cal | pr -3 -t -l8
m=$M; y=$Y
if (m>1) {m-1; y}; if (m==1) {12; y-1} /* prev month */
m; y /* this month */
if (m<12) {m+1; y}; if (m==12) {1; y+1} /* next month */
!
exit 0
So, csh is clearly brain-dead. And this is just about all /bin/sh is worth!
>########
># cal3 - 3-month calendar printer
>########
>...
Actually, Joe's sh script works very well, esp. if # is not the first char
in the file, and it's much faster than the csh script.
>The following program is smaller (and thus easier to read and understand),
>faster, uses no tempfiles, and gives you today in vt100-style inverse
>video. Adding termcap support or command line parsing would be trivial.
>--tom
This stuff is so simple that there's hardly any readability problem to
begin with... and Joe's is the smallest and probably the least readable.
And you guys keep throwing out the error checking.
Hmmm... It seems that perl comes with IBM AIX 3.2. There may be some real
hope for perl! That being the case, I started fiddling with your script and,
seeing as this is alt.sources and not alt.sources.d, I feel obligated to post
the result :-). You shouldn't gripe about how big it's gotten... everything
has a purpose... it always does the Right Thing.
Shall we put this one to rest?
O O
Curt McDowell >
IBM T. J. Watson Research Center \_/
----------------------------------------------------------------------------
#!/usr/bin/perl
#
# cal3 - print out last month, this month, and next month from
# cal program, with today in reverse video (vt100 hardcoded)
#
# If you have tput, change the following variable to the correct path.
# Tput is available from comp.sources.unix archives (ftp.uu.net,
# j.cc.purdue.edu, etc.) as v07i072.
$tput = "/usr/5bin/tput"; # Set for local environment
$width = 24;
if ( -x $tput ) {
open(smso, $tput." smso; echo |"); chop($SO = <smso>);
open(rmso, $tput." rmso; echo |"); chop($SE = <rmso>);
} else {
$SO = "\033[7m"; # Default to vt100
$SE = "\033[m";
}
($sec,$min,$hour,$mday,$curmon,$curyear,$wday,$yday,$isdst) = localtime(time);
$curmon++;
$mon = $curmon; $year = $curyear;
if ( $#ARGV >= 0 ) { $mon = $ARGV[0]; }
if ( $#ARGV >= 1 ) { $year = $ARGV[1]; }
# Allow omission of century up to the year 2069.
if ( $curyear < 70 ) { $curyear += 2000; }
if ( $curyear < 100 ) { $curyear += 1900; }
if ( $year < 70 ) { $year += 2000; }
if ( $year < 100 ) { $year += 1900; }
if ( $mon < 1 || $mon > 12 || $year < 1 || $year > 9999 ) {
printf(<STDERR>, "cal3: Illegal parameter.\n");
exit(1);
}
# Select next year and prev year "wrapping" at 12 months.
$nmon = $mon + 1; $nyear = $year; if ( $nmon == 13 ) { $nmon = 1; $nyear++; }
$pmon = $mon - 1; $pyear = $year; if ( $pmon == 0 ) { $pmon = 12; $pyear--; }
open (prev, "cal $pmon $pyear |");
open (cur, "cal $mon $year |" );
open (foll, "cal $nmon $nyear |");
# Determine which month, if any, will contain a highlighted day.
$hiprev = ( $pmon == $curmon && $pyear == $curyear );
$hicur = ( $mon == $curmon && $year == $curyear );
$hifoll = ( $nmon == $curmon && $nyear == $curyear );
until (eof(prev) && eof(cur) && eof(foll)) {
chop($prev = <prev>); $lenprev = length($prev);
chop($cur = <cur> ); $lencur = length($cur);
chop($foll = <foll>); $lenfoll = length($foll);
if ( $hiprev ) { $prev =~ s/\b$mday\b/$SO$mday$SE/; };
if ( $hicur ) { $cur =~ s/\b$mday\b/$SO$mday$SE/; };
if ( $hifoll ) { $foll =~ s/\b$mday\b/$SO$mday$SE/; };
printf (sprintf ("%%-%ds%%-%ds%%-%ds\n",
$width + length($prev) - $lenprev,
$width + length($cur ) - $lencur,
$width + length($foll) - $lenfoll), $prev, $cur, $foll);
}
Excuse me while I laugh.