14,000 hints and counting!

The following comments are owned by whoever posted them. This site is not responsible for what they say.
The ultimate 3-column calendar
Authored by: wallybear on Jul 08, '04 08:05:14AM
I found the problem in the three column display and I also analyzed the code made by redclawx and found some bad problems.
1. In reassembling my code he forgot to declare the variable fill
2. The code for computation of previous and next month around year boundaries is wrong: for example, if current month is Dec 2004 you will get displayed Nov 2005 / Dec 2004 / Jan 2005; if current month is Jan 2005 you will get Dec 2004 / Jan 2005 / Feb 2004.
3. Parts of my code were superfluous for a US calendar.
So I rewrote the code, added the side-by-side three column display and the possibility to choose the months to be displayed, and made it more modular. Here is the result of my efforts (and, hopefully, the end of this quest):
``````
#!/bin/sh

month=`date +%m`
year=`date +%Y`
currDay=`date "+%d"`

getDate()
{
# syntax: getDate monthGap
themonth=\$((\$month+\$1))
theyear=\$year
if [[ \$themonth -gt 12 ]]
then
themonth=\$((\$themonth-12))
theyear=\$((\$theyear+1))
fi
if [[ \$themonth -lt 1 ]]
then
themonth=\$((12-\$themonth))
theyear=\$((\$theyear-1))
fi
echo \$themonth " " \$theyear
}

MarkToday()
{
awk -v cday=\$currDay '{ fill=(int(cday)>9?"":" "); a=\$0; sub(" "fill int(cday)" ","["fill int(cday)"]",a); print  a }'
}

doCalUS()
{
cal \$(getDate -1)
echo
cal \$month \$year | awk '{ print " " \$0 " " }' | MarkToday
echo
cal \$(getDate 1)
}

doCalUS | pr -3 -t -i100 | colrm 22 23
``````
You can paste this code directly in GeekTool. The code above is for US-kind calendars, and this is the result:
``````
June 2004              July 2004             August 2004
S  M Tu  W Th  F  S    S  M Tu  W Th  F  S    S  M Tu  W Th  F  S
1  2  3  4  5                1  2  3    1  2  3  4  5  6  7
6  7  8  9 10 11 12    4  5  6  7[ 8] 9 10    8  9 10 11 12 13 14
13 14 15 16 17 18 19   11 12 13 14 15 16 17   15 16 17 18 19 20 21
20 21 22 23 24 25 26   18 19 20 21 22 23 24   22 23 24 25 26 27 28
27 28 29 30            25 26 27 28 29 30 31   29 30 31
``````
You can get a slightly narrower calendar replacing the last line with this one:
``doCalUS | pr -3 -t -i100 | colrm 22 24 | colrm 44 44``
If you want an italian calendar, replace the lines from doCalUs() (included) to the end of script with the following:
``````
ItaHdr()
{
echo \$1/\$2 | awk '{ split("Gennaio/Febbraio/Marzo/Aprile/Maggio/Giugno/Luglio/Agosto/Settembre/Ottobre/Novembre/Dicembre",arr,"/"); \
split(\$0,arg,"/"); a=arr[int(arg[1])] " " arg[2]; print substr("          ",1,(21-length(a))/2) a; }'
echo " Lu Ma Me Gi Ve Sa Do"
}

MoIsFirstDay()
{
awk '{nl=0; getline; getline; if (substr(\$0,1,2) == " 1")  {print "                    1 "; nl=1; } \
do { prevline=\$0; if (getline == 0) { if (nl == 0) print ; exit;} print " " substr(prevline,4,17) " " substr(\$0,1,2) " "; } while (1); }'
}

doCalIta()
{
ItaHdr \$(getDate -1); cal \$(getDate -1) | MoIsFirstDay
ItaHdr \$month \$year ; cal \$month \$year  | MoIsFirstDay | MarkToday
ItaHdr \$(getDate 1) ; cal \$(getDate  1) | MoIsFirstDay
}

doCalIta | pr -3 -t -i100 | colrm 22 22 | colrm 46 46
``````
And here is the result:
``````
Giugno 2004           Luglio 2004           Agosto 2004
Lu Ma Me Gi Ve Sa Do  Lu Ma Me Gi Ve Sa Do  Lu Ma Me Gi Ve Sa Do
1  2  3  4  5  6            1  2  3  4                     1
7  8  9 10 11 12 13   5  6  7[ 8] 9 10 11   2  3  4  5  6  7  8
14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15
21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22
28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29
30 31
``````
Also in this case, you ca get a narrower display replacing the last line with this one:
``doCalIta  | pr -3 -t -i100 | colrm 22 23 | colrm 46 47``
The shell commands used in this script are pr (for columnize output) and colrm (to remove some blank column in eccess).
As you can see the code is modular, so you can easily modify for other localizations.
The function getDate() gets called for displaying of months; it allows you to choose which months to consider: getDate 1 means one month after current, getDate -3 means the third month before the current, and so on. So, if you prefer (ennisdb? are you reading this?) to display the current month and the next two instead of the default setting, you simply have to change the doCalUs funtion to look like this one:
``````
doCalUS()
{
cal \$month \$year | awk '{ print " " \$0 " " }' | MarkToday
echo
cal \$(getDate 1)
echo
cal \$(getDate 2)
}
``````
and here is the result:
``````
July 2004             August 2004           September 2004
S  M Tu  W Th  F  S    S  M Tu  W Th  F  S    S  M Tu  W Th  F  S
1  2  3    1  2  3  4  5  6  7             1  2  3  4
4  5  6  7[ 8] 9 10    8  9 10 11 12 13 14    5  6  7  8  9 10 11
11 12 13 14 15 16 17   15 16 17 18 19 20 21   12 13 14 15 16 17 18
18 19 20 21 22 23 24   22 23 24 25 26 27 28   19 20 21 22 23 24 25
25 26 27 28 29 30 31   29 30 31               26 27 28 29 30
``````
This should satisfy ennisdb. : )
(Note: getDate has a range of +/- 12 months max around the current date)

Happy GeekTooling !
The ultimate 3-column calendar
Authored by: redclawx on Jul 08, '04 06:22:07PM

wallybear,
This is why I'm not a programer. :P fill is a variable? Missed that one, I thought it was a unix command. Once I get home I'll have to update my code in GeekTool. Thanks for the effort you (and everyone) has put into this.

The ultimate 3-column calendar
Authored by: wallybear on Jul 09, '04 05:32:25AM

Not a programmer? You did a good work anyway... Just a little too much cut and paste. :)
I'm not a programmer too (for CLI, at least, I work in Cocoa and 4D), but man pages and online Linux-oriented sites are really plenty of infos.
CLI programming is really fun.

The ultimate 3-column calendar
Authored by: Sigma on Jul 25, '04 08:16:35PM

This is really useful... I've been tinkering with it for a while and I can't seem to get what I want. I want all 12 months of the current year with the current date highlighted. And I wanted them to be horizontal. The clocest I have gotten is having the full year in the usual cal style... any suggestions?

The ultimate 3-column calendar
Authored by: icerabbit on Aug 02, '04 11:31:26AM

The only odd thing is, with a copy/paste into GeekTool, I get the month August three times. Not July - August - September

The ultimate 3-column calendar
Authored by: gent99 on Aug 03, '04 05:48:03AM

Strange things happen in August:

This little Script displays an error only in August:

#!/bin/sh
month=`date +%m`
themonth=\$((\$month+\$1))
echo \$themonth

Error: 08: value too great for base (error token is "08")

Every other month works fine.

Any U++x freak who can help us?

The ultimate 3-column calendar
Authored by: icerabbit on Aug 03, '04 08:39:36AM

I have the same error line.
Will see if there's a way to contact Wallybear.

The ultimate 3-column calendar
Authored by: Herbo on Aug 03, '04 01:06:16PM

The problem seems to be how bash handles leading zeros, it treats the number as octal rather than base 10. Hence 8 is an invalid octal number (valid range being 0 to 7).

Try removing the leading zero from the month by changing the month assignment line to:

month=`date +%m | sed -e 's/^0//'`

-Herbo

The ultimate 3-column calendar
Authored by: icerabbit on Aug 03, '04 06:25:42PM

By Joe,
That works!
Thanks Herbo :)

The ultimate 3-column calendar
Authored by: gent99 on Aug 04, '04 03:30:58AM

Actually this is a bug in bash. look here:

http://lists.debian.org/debian-boot/2000/05/msg00287.html

i managed to fix it with the following code:

month=`expr \$month + 0`

this is working too.

August bug - A solution to that nasty bash bug
Authored by: wallybear on Sep 06, '04 05:52:28AM

The problem is due to a bug of bash. it treats '08' as an octal, because of the leading zero.
The only available token of the date command to get the month's number gives a number with a leading zero for the range 1..9 (01..09).
A simple solution (btw I hope that a simpler one exists) is to replace the following line at the beginning of the script:

month=`date +%m`

with this one:

month=`date +%m | awk '{print int(\$0)}'`

this will strip the leading zero if present and fix the bug.
The bug does not show with the day's number as in this case the leading zero is stripped by the appropriate 'date' token.

Happy geektooling...

The ultimate 3-column calendar
Authored by: theupperhand on Mar 24, '09 06:47:48PM

i really like this, though i would like to have the full year. i've been tinkering and know how to make previous and future months display, but can't figure out to make it display properly except in 1 column. and having the previous and future months doesn't give me the whole year either. any help is appreciated.

The ultimate 3-column calendar
Authored by: theupperhand on Apr 02, '09 08:40:19AM

i think i figured it out. i tried:

cal -y | awk -v cday=`date "+%d"` '{ fill=(int(cday)>9?"":" "); \
a=\$0; sub(" "fill int(cday)" ","["fill int(cday)"]",a); print a }'\

and it appears to work, it shows the full year with the current day between square brackets.

The ultimate 3-column calendar
Authored by: theupperhand on Apr 02, '09 08:50:05AM

nevermind, this still doesn't work right. i noticed that other days are highlighted too, but only in 4 other months.