24

This geeklet requires MacRuby. There is a package installer on macruby.org for 10.6

MacRuby package installer

This script accesses the shared system events calendar (the one iCal uses) directly, making the events in a given range of dates available directly in the script as objects. The output can be customized as much as is possible with ruby. The included output and formatting is very basic, and could be extended greatly.

For information on the attributes that are available on the event objects, see the Apple reference pages below:

The first contains properties like title, notes, and the even UID, the second describes properties for the time and recurrence.

#!/usr/local/bin/macruby
framework 'calendarstore'

    # This required MacRuby to be installed.
# A package installer for 10.6+ is available at http://www.macruby.org/

    # Period is the number of days (including today) to include in the list.
# The default is three days.
period = (3 * 3600 * 24)
range = Time.local(Time.now.year, Time.now.mon, Time.now.day)..(Time.local(Time.now.year, Time.now.mon, Time.now.day) + period)

    predicate = CalCalendarStore.eventPredicateWithStartDate(NSDate.dateWithString(range.begin.to_s), endDate:NSDate.dateWithString(range.end.to_s), calendars:CalCalendarStore.defaultCalendarStore.calendars)
day_cache = nil

    # All formatting done here is intended to be RIGHT JUSTIFIED.
# Inside the block everything except #timeIntervalSince1970 is normal ruby,
# so it should be pretty easy for many people to change around.
CalCalendarStore.defaultCalendarStore.eventsWithPredicate(predicate).each do |event|
  started_at = Time.at(event.startDate.timeIntervalSince1970)

      print "n" + started_at.strftime("%A %B %d").upcase + "n" if started_at.day != day_cache

      print "→" if started_at < Time.now
  print "⚠ " if (Time.now - started_at < (3600 * 5)) && (Time.now - started_at > 0)
  print event.title
  print " (#{event.location})" if event.location
  print (event.isAllDay ? "        ∞" : started_at.strftime(" %R")) 

      print "n"
  day_cache = started_at.day
end

I will almost definitely be updating this as I think of better ideas, so watch the comments for updates or a more permanent place to track changes.</p>

Geeklet files to download

Comments

User Avatar
holdir 1288 days ago
Today I downloaded your geeklet and I must say it works perfectly for me.

I made a slighly modification of the code, line 33:

original: print " (#{event.location})" if event.location

modified: print " (#{event.location})" if event.location != ""

I modified that because if you have events with no location, with your code, after the event's name it prints "()". I know that's a little thing but it just annoys me xD

Good work!
User Avatar
farski 1285 days ago
@holdir, Glad it worked for you. Strange that you were getting blank parentheses; it's been my experience that if an event doesn't have a location the Calendar object doesn't returned nil for #location, not an empty string. I did a bit of refactoring on this whole script today anyway, so took the chance to that situation anyway, albeit in a different way.

**Here's my current working version**. Sorry, no comments; I forgot!

#!/usr/local/bin/macruby

framework 'calendarstore'



range = Time.local(Time.now.year, Time.now.mon, Time.now.day)..(Time.local(Time.now.year, Time.now.mon, Time.now.day) + (31 * 3600 * 24))

events = CalCalendarStore.defaultCalendarStore.eventsWithPredicate(CalCalendarStore.eventPredicateWithStartDate(NSDate.dateWithString(range.begin.to_s), endDate:NSDate.dateWithString(range.end.to_s), calendars:CalCalendarStore.defaultCalendarStore.calendars))[0,7]



events.each_with_index do |event, i|

event.startDate, output = Time.at(event.startDate.timeIntervalSince1970), Array.new



if (!events[i-1] || (event.startDate.day != Time.at(events[i-1].startDate.timeIntervalSince1970).day))

output
User Avatar
sfr234 1284 days ago
Hey there, for some reason the geeklet is not working for me. I tried to delete it but I still have an empty box when editing geeklets on GeekTool. Any ideas on how I can remove these empty windows? Thanks in advance.
User Avatar
matt 1284 days ago
Click the X in the corner of the empty box.
User Avatar
sfr234 1284 days ago
Tried that but it won't work.
User Avatar
elel 1284 days ago
same^.

i got macruby. and downloaded the geeklet. the geeklet asks for permission to run i say yes. nothing happens.
User Avatar
farski 1282 days ago
Hm, I wouldn't think anything would need permission to run for this. What happens if you just start a new geeklet and paste the script in?

Also, there was an error in my last post, so here's a minor update

#!/usr/local/bin/macruby

framework 'calendarstore'



range = Time.local(Time.now.year, Time.now.mon, Time.now.day)..(Time.local(Time.now.year, Time.now.mon, Time.now.day) + (31 * 3600 * 24))

events = CalCalendarStore.defaultCalendarStore.eventsWithPredicate(CalCalendarStore.eventPredicateWithStartDate(NSDate.dateWithString(range.begin.to_s), endDate:NSDate.dateWithString(range.end.to_s), calendars:CalCalendarStore.defaultCalendarStore.calendars))[0,7]



events.each_with_index do |event, i|

event.startDate, output = Time.at(event.startDate.timeIntervalSince1970), Array.new



if (!events[i-1] || (event.startDate.day != Time.at(events[i-1].startDate.timeIntervalSince1970).day))

output
User Avatar
tig82 1271 days ago
I've got the same problem as above. Any help?

I tried to run the script but it doesn't work and now I can't delete the empty box.

Any help would be great...

&nbsp;
User Avatar
njacobson 1270 days ago
I ran the script but am unable to edit it, when in the Geektool Preference pane this customization as well as previously created ones do not populate, and are in fixed positions. &nbsp;

Any suggestions? &nbsp;Really this is annoying.
User Avatar
busyscott 1263 days ago
Got it to work. However all of my calendars are delegations from Gmail, how do I get these to display???
User Avatar
jordanof83 1254 days ago
i was having same issue as sfr234 but now it's worse.&nbsp;

i did copy and paste the code into the text editor and closed it in order to save changes. when i say yes or no (to save changes) it does nothing. not sure if it's a geektool issue or issue with this specific script. either way, it's still not working for me. i'm pretty much a noob when it comes to scripts or coding at all. so, what am i missing?

any help is greatly appreciated.&nbsp;
User Avatar
Arlefreak 1249 days ago
I have the same problem didn't show a thing and when I tried to close it didn't worked editing the skript also didn't work ... i restart my computer and i could errase them it was the only way... why ?!
User Avatar
dii 1249 days ago
Works great thanks! I can't figure out how to change the time from 24hr to 12hr. Can someone please help? Thank you! 
User Avatar
thcousins 1247 days ago
Thanks farski, love it...

Thought I'd share my slightly customized version with you all

CHANGES:

1. This version is left formatted.

2. It shows start and end times.

3. It shows past events (with ticks next to them).

4. Current events are highlighted with a star.

SCREENSHOT:

[![Screenshot](http://dl.dropbox.com/u/4895699/Screen%20shot%202011-04-21%20at%2011.44.14.png)](http://dl.dropbox.com/u/4895699/Screen%20shot%202011-04-21%20at%2011.44.14.png)

CODE:

#!/usr/local/bin/macruby

framework 'calendarstore'



# Original code by farski found at http://www.macosxtips.co.uk/geeklets

# This required MacRuby to be installed.

# A package installer for 10.6+ is available at http://www.macruby.org/



# Period is the number of days (including today) to include in the list.

# The default is three days.



before = (3 * 3600 * 24)

after = (7 * 3600 * 24)



range = (Time.local(Time.now.year, Time.now.mon, Time.now.day) - before)..(Time.local(Time.now.year, Time.now.mon, Time.now.day) + after)



print "\n"



predicate = CalCalendarStore.eventPredicateWithStartDate(NSDate.dateWithString(range.begin.to_s), endDate:NSDate.dateWithString(range.end.to_s), calendars:CalCalendarStore.defaultCalendarStore.calendars)

day_cache = nil



# Inside the block everything except #timeIntervalSince1970 is normal ruby, so it should be pretty easy for many people to change around.



CalCalendarStore.defaultCalendarStore.eventsWithPredicate(predicate).each do |event|

started_at = Time.at(event.startDate.timeIntervalSince1970)

ends_at = Time.at(event.endDate.timeIntervalSince1970)



#Display DAY MONTH and DATE then each event

print "\n" if day_cache != nil && started_at.day != day_cache



print started_at.strftime("- %A %B %d").upcase + "\n" if started_at.day != day_cache



#Display an arrow if event has started

print " ✓" if ends_at < Time.now



#Display a star if event is current

print " ☆" if started_at < Time.now && ends_at > Time.now



print "\t" + (event.isAllDay ? "" : started_at.strftime("%R") + "-" + ends_at.strftime("%R") + " - ")

print event.title

#print "(#{event.location})" if event.location != ""

print "\n"

day_cache = started_at.day

end

UPDATE:

2011/05/12 - Corrected missing backslashes from the code.
User Avatar
hhernandez 1240 days ago
I have multiple calendars. I just want to show my main work calendar? Also I want to show a subscription calendar from ical merge with the main one. Thoughts?
User Avatar
jamalj 1239 days ago
I'm receiving this error from a direct copy / paste of the last posted script:

[04:08 PM] ~: ruby /Users/jamal/Scripts/Geektool-iCal-Events.rb



/Users/jamal/Scripts/Geektool-iCal-Events.rb:19: syntax error, unexpected tSYMBEG, expecting kDO or '{' or '('



...ng(range.end.to_s), calendars:CalCalendarStore.defaultCalend...



                              ^



/Users/jamal/Scripts/Geektool-iCal-Events.rb:19: syntax error, unexpected ')', expecting $end

Any suggestions?
User Avatar
thcousins 1223 days ago
jamalj,

Did you get it to work?

There were some backslashed missing from the script, but I have corrected now.
User Avatar
djjenks 1233 days ago
I'm having the same issue as hhernandez with the multiple calendars....anyone have ideas?
User Avatar
lexlimo 1224 days ago
I had the same problem with multiple calendars.  Instead of calling defaultCalendarStore.calendars, I used defaultCalendarStore.calendarWithUID.  I got the UID for the calendar I wanted by doing:

CalCalendarStore.defaultCalendarStore.calendars.each do |calendar|

print "n" + calendar.uid + " " + calendar.title

end

That printed out all the calendar UIDs and their titles.  I later clued in that I could look in:

/Users/[username]/Library/Calendars



Then into the .caldav folder, then check the info.plist inside each of the contained .calendar folders and figure out which one was the correct calendar and grab the (note the name of the .calendar folder is the UID)

Then I just modified the glet code with this:

cal = CalCalendarStore.defaultCalendarStore.calendarWithUID("XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")

predicate = CalCalendarStore.eventPredicateWithStartDate(NSDate.dateWithString(range.begin.to_s), endDate:NSDate.dateWithString(range.end.to_s), calendars:[cal])

day_cache = nil

Obviously the XXXXs represent the calendar UID.  Note that the [cal] variable is in [] brackets, that's because eventPredicateWithStartDate wants an array there.  So I assume you could grab multiple calendars this way and build that array manually.

I had only minor exposure to ruby or objc so this is all total hacking around stuff, but the results are what I wanted.  

Hope that helps.
User Avatar
dna1977 1222 days ago
This is ridiculous... This doesn't work at all. Worst thing is that I can't even delete it. I have tried deleting Geektool but I'm stuck with this stupid script, I can't even delete Geektool as it says that it is running.

I've tried clicking on the "cross"... I've tried unchecking "default group" but nothing happens. If I re-install Geektool, the stupid shell re-appears.

Any cure????? Anyone?? I don't want to fix it.. I want to get rid of it, please.
User Avatar
mludd 1212 days ago
So yeah, I'm having the same problem as everyone else.

Installed it, asked for permission for install.

After install it's not working and I'm seeing the box that can't be closed.

I don't want to nuke my existing setup so it'd be really really nice with a solution (Solution = fix the problem or a "how to remove it").
User Avatar
mludd 1212 days ago
Update: I just tried to edit the script of one of the boxes I managed to create.

Result? I can't save it. I can't click No or Yes.

This is bugged and broken.

Please find a solution.
User Avatar
mludd 1212 days ago
Ah, solution.

Use the property list editor on the geektools files there and remove all references to this geeklet.

Kill geektools, restart it, done.
User Avatar
fromanphotos 1211 days ago
Where does the script exist to make the changes described above? Thanks
User Avatar
lane-a-tic 1206 days ago
Thanks thcousins and farski -

Love this! I had similar troubles as the group above, with frozen GeekTools, etc. But a little restart and I am good to go!

Thank you, clever people!
User Avatar
mdsnyderjr 1192 days ago
I'd prefer to not have to use military time.&nbsp; Anybody know how to fix that?

thanks!
User Avatar
ChrisM 1171 days ago
In the line:

print (event.isAllDay ? " ∞" : started_at.strftime(" %R"))

Change the uppercase 'R' near the end to a lowercase one.
User Avatar
ChrisM 1171 days ago
What language is the code in?

I'm trying to figure out how to simply **grey** **out** past events instead of putting that arrow by it.

I have the arrow now so:

ended_at = Time.at(event.endDate.timeIntervalSince1970) #new variable declaration

print "→" if (started_at < Time.now) && (Time.now < ended_at)



Can anyone help me achieve my desire for a coloured font? =)
User Avatar
jll 1171 days ago
How can I get day and month names in another language? I use Spanish as system language in MacOSX but Ruby uses english to print day and month...

Thanks!
User Avatar
done84 493 days ago
I want to change language too, have you found a solution?
User Avatar
maayala 1170 days ago
Solution: also had the same problem, it locks the window in geek, the solution is to install the program macruby, without this program do not close sales geek.I hope it will be useful
User Avatar
hzlnt 1147 days ago
Thcousins,

I love your script, but for some reason it disappears for intervals of time. Does anyone know how to fix this?
User Avatar
Nob0dy 1140 days ago
I want to uninstall that sh*t,how I can do that ?!

(Without MacRuby)
User Avatar
mrantonyyu 1131 days ago
How can I include multiple calendars? it works on my default calendar, but i also have multiple calendars. They are linked through caldav and google calendars.
User Avatar
bepeacock 1115 days ago
This is awesome! I ended up using @thcousins' code and modified a couple of spots:

I set `before = (0 * 3600 * 24)

after = (10 * 3600 * 24)`so that past events would not show.



I also changed the time code at the end to be `print "\t" + (event.isAllDay ? "" : started_at.strftime("%l:%M %p") + "-" + ends_at.strftime("%l:%M %p") + " - ")` which will show the 12-hour time, (like %r) but gets rid of seconds and adds the AM/PM.
User Avatar
zndr 1114 days ago
would post code but shitty large code inserts suck on this side, see link: [Zndr's Calendar](http://pastebin.com/91yArvwc)

Same formatting as Farksi

updated with theCousins previous events and completed events check list

Added a matrix to use specific calendars based off lexlimo's post.
User Avatar
dwinglis 1113 days ago
I've noticed that all day events that are longer than one day don't show... any ideas?
User Avatar
bepeacock 1113 days ago
@zndr to make your code appear in the grey box, you have to lead and end with '

Check out the "Formatting help" link below the submit a comment box.
User Avatar
zndr 1109 days ago
I tried, it didn't end up working, I'll try again Bepeacock

yea nope doesn't work, if I wanted to do a single line of code sure, but that's not the case...shitty formatting guides are shitty.
User Avatar
descoperi 1109 days ago
Is it possible for me to have two separate shells for this? One containing the current day's list of events and the other containing the next days' events.

Help, please?

Thanks!
User Avatar
britainyk 1109 days ago
Love it! once I got it to work. Took a minute, but I prevailed!!

thanks!
User Avatar
montrealex 1104 days ago
Thcousins, I like your tweaks with stars etc.... Use your script and love it :-) thanks. Of course, thanks to Farski without whom I would not have tried this geeklet and discover Ruby etc.... :-))
User Avatar
mike 1091 days ago
I'm having the same problem as others up top about 120 days ago. I tried to install this, I answered yes to run the scripts. It never worked for me, and now their are two windows stuck in one of my collections. I've restarted geek tools, I've rebooted my computer twice, and, yes, I've hit the X btw in the top right SEVERAL times. I don't want to fix this geeklet, I would just like to get rid it along with the windows that are stuck, which are also screwing up one of my collections. Can anyone help with this??

Mludd said he found the solution up above, but I don't understand what he meant by "Use the property list editor on the geektools files there and remove all references to this geeklet."

Also, I would like to be able to remove this without having to install MacRuby, but if that's the only way, then I'll do it. PLEASE HELP!!
User Avatar
mike 1091 days ago
After writing this, I tried one last thing, and it seemed to have worked, so I wanted to let others know in case they are dealing with the same issue. I use AppCleaner for all of my uninstalling needs. Event if you downloaded the program from the App Store, just uninstall Geektools with AppCleaner, then reinstall it. When you open up Geektools, the windows from this geeklet should still be there, but they should also be deletable. At first I was worried that they were still stuck, but then I tried to delete them with the X btw in the top right, and, thankfully, they went away. I have no idea what the problem was, but deleting and reinstalling with AppCleaner worked.
User Avatar
farski 1051 days ago
Sorry I didn't reply to any of the comments. Once I started doing development in Lion several months ago I never got around to setting up geektools again. I'm going to try to get all my widgets back in the next few days, so I will see how things go with this one.
User Avatar
barndoor0311 959 days ago
Thank you for the nice addition to my desktop!
User Avatar
eypuff 959 days ago
does anyone know how to bold just the days?

For Example:

[bold]Thursday, February 02[/bold]

- Blah BLah

- Blah BLha

[bold]Friday, February 03[/bold]

- Blah blh

- Blahsld BLha
User Avatar
shaunamcc 886 days ago
hey, just started using geektool and wanted this code to appear as a sentence to match the rest of my geektools. i.e., on sunday april 15th, lunch with captain kirk at 12:00 in case there are any other newbies out there, here is the code I used:

#!/usr/local/bin/macruby

framework 'calendarstore'

# This required MacRuby to be installed.

# A package installer for 10.6+ is available at http://www.macruby.org/

# Period is the number of days (including today) to include in the list.

# The default is three days.

period = (3 * 3600 * 24)

range = Time.local(Time.now.year, Time.now.mon, Time.now.day)..(Time.local(Time.now.year, Time.now.mon, Time.now.day) + period)

predicate = CalCalendarStore.eventPredicateWithStartDate(NSDate.dateWithString(range.begin.to_s), endDate:NSDate.dateWithString(range.end.to_s), calendars:CalCalendarStore.defaultCalendarStore.calendars)

day_cache = nil

# All formatting done here is intended to be RIGHT JUSTIFIED.

# Inside the block everything except #timeIntervalSince1970 is normal ruby,

# so it should be pretty easy for many people to change around.

CalCalendarStore.defaultCalendarStore.eventsWithPredicate(predicate).each do |event|

started_at = Time.at(event.startDate.timeIntervalSince1970)

print "On " + started_at.strftime("%A %B %d").downcase + ", " if started_at.day != day_cache

print "→" if started_at < Time.now

print "⚠ " if (Time.now - started_at < (3600 * 5)) && (Time.now - started_at > 0)

print event.title

print " at "

print (event.isAllDay ? " ∞" : started_at.strftime(" %R"))

print "\n"

day_cache = started_at.day

end
User Avatar
nestor 741 days ago
Hi,

very nice work! Don't know ruby but wondering if it's possible to localize the names of the days and of the months

Nestor
User Avatar
done84 493 days ago
Is there a way to change LANGUAGE for the week days and months?
User Avatar
marcoie 379 days ago
To Uninstall in case THIS DON´t work go in finder to folder:

/Users//Library/Preferences/

And edit removing all references to his gee let

/Users//Library/Preferences/org.tynsoe.GeekTool.plist

/Users//Library/Preferences/org.tynsoe.geektool3.plist

It will be all back to normnal.
User Avatar
smenzer 352 days ago
So I've been using this for years now and love it! However, looks like an update to OSX 10.8 broke it -- framework 'calendarstore' is no longer valid and documentation points to using EKCalednar Class now (https://developer.apple.com/library/mac/documentation/DataManagement/Reference/EKCalendarClassRef/Reference/Reference.html#//apple_ref/doc/uid/TP40009564). Any chance you're planning to update this article with the new code?

Thanks!

Log in to comment or register here.