04 December 2006

No Vista Service Packs...

Ballmer: Vista to Spur 'Wave of Innovation'
Asked about the timeline for Vista service packs, Ballmer quipped that as it is the highest-quality, most secure and reliable Windows operating system ever, there should be no need for a service pack.

I'll be back when I catch my breath again... seriously.

17 November 2006

Google Earth KML Date Formatting

I am just building stuff using Google Earth, especially the new time stamped stuff. Very nice, really.

However GE expects dates in the format 2006-11-17 which isn't so bad in itself. It's AppleScript's fault that it is a pain to format dates other than the system's preset. You just do a

set dateString to (year of theDate) & "-" & (month of theDate as number) & "-" & (day of theDate)

and there you go. Nevertheless GE still choked on my formatted dates: 2006-9-5 can't be parsed by Google Earth. The leading 0 is mandatory!? WTF!?

Well here is the solution:
on format_date(theDate)
tell theDate
set y to year as string
set m to (month of theDate as number) as string
if (count of m) is 1 then set m to "0" & m
set d to day as string
if (count of d) is 1 then set d to "0" & d
end tell
return y & "-" & m & "-" & d
end format_date

Script Friday: Keynote Slide Sets

I do a lot of presentations. I put together various slide decks on the different topics and then depending on the event, customer and time available I skip and reveal a different subset of slides. If I want to keep track of which slides I showed where then all I can do is have multiple copies of the same Keynote Presentation. Which is a pain, because say I want to change the content of one slide from say "October 2006" to "November 2006" then I have to remember which copy is the most current or do the change in all copies.

Wouldn't it be great if I could store multiple slide sets in one Keynote Presentation?

Keynote 3 introduced AppleScript support. Though the implementation is... er... special, it is surprisingly adept to this task.

Use the notes area of the slide to store the skipped/shown status of a slide. Decide on a name for your slide set. For Slides that should be shown in this Slide Set add a line with <Slide Set Name> to the notes. For slides that should be skipped add <Slide Set Name skip>. Obviously if your name ends in "skip", you're in deep trouble. I used the <> as markers, change the scripts if that bothers you. If a slide has neither in its notes the script will leave it unchanged. This way you can have different slide sets for different topics and the won't affect each other.

Then show all slides (or change the skip/hide setting of slides in some weird way) run this script, enter the name of the set and enjoy.

Restore Slide Set

Ok, so this manually setting the markers in slides will get tiresome really quickly. So I wrote a script to store the current slide set, run it, give a name for your slide set... wonderful.

WARNING: the way AppleScript (or specifically Keynote's implementation) handles the notes field means that when the script has to change the notes field ALL rich text formatting will be lost... :( If you don't like that, you will have to add the markers manually.

Save Slide Set

If you are bored of a certain Slide Set, you can remove the markers again:

Remove Slide Set Tags

This opens up a whole bunch of possibilities. You could have one Slide Deck with three slide sets, one for 25 minutes, one for 50 minutes and one for 100 minutes. Let's call them "Hurry Up!", "Standard" and "Detailed". Now before a presentation you could choose the proper slide set and go. However we all know how these things go. Sometimes you get a lot of questions on a certain topic and you would actually like to be able to dig deeper into this. So you could drop out of presentation mode, change the slide set to detailed and continue. Then after you are done with this topic you switch to the "Hurry Up!" set to make up for lost time. To make this easier, use "pre-canned" scripts with the marker name built-in.

Standard Set

I use Salling Clicker to switch on-the-fly, in presentation mode using the cell to execute these scripts. Unfortunately Keynote doesn't allow you to modify slides in the background using AppleScript, so the scripts will actually drop presentation mode, do their stuff, then resume presentation mode. It is a brief but ugly flash of your desktop on the screen. However I think the pay off is worth it. You should be able to assign these scripts to a HotKey Manager or other way of executing them, I leave that as an exercise for the reader.

Please let me know how you use these.

15 November 2006

Xserves!

This is important to me, mainly for business. Still: YAY!

(Late) Script Friday: Fading Terminal Windows

This script was inspired by the scripts of Erik Barzeski and Daniel Jalkut.

What the script does is watch your Terminal Windows and if they are busy doing some important process it will slowly fade them into the background (increase the transparency). Once the process is complete (or if you quit the watcher), it will set the transparency back to normal.

Note: there seems to be a bug in Terminal scripting, so that changes in transparency only register when there already is a transparency set in the background color, so you have to set at least a minimal transparency for your default windows. (Move the slider in the Windows Preferences just a tick or two, you won't see it but then everything works fine.)

Some people (like my wife, believe it or not, she uses Terminal) might find all that fading and transparency is distracting. So especially for you (well, her, actually) I wrote a version that will minimize the window instead. (I find that all those windows zipping about are worse than fading windows, but she is a biologist and the stuff she invokes from the command line usually runs for a long long time, so I guess that "ghost letters" on the desktop might be distracting.)

Download the scripts here.

Swamped

I'm still here... around... somewhere....

Very busy lots of work. Be back Friday with a neat script.

02 November 2006

Perceived security

The Boarding Pass Brouhaha is a great summary of the recent fall-out concerning boarding passes. So many of the security measure introduced since 9/11 are just give you the perception of security.

One solution to this particular problem would also be to not give the passenger the option of printing the boarding pass at home. You could still check-in early, securing your seat, but not print the boarding pass. Once you are at the airport, you can print the boarding pass at the machines at the airport. I already do that when I'm on the road and can't print. If TSA only accepted the machine boarding passes, easily recognized by the paper, then it would be much more difficult to forge a boarding pass. Still not impossible, but right now the authenticity of the boarding passes is laughable.

29 October 2006

How to check for UI scripting

How embarrassing. This blog gets a link from MacDevCenter and I have a (minor) bug in the script. I have had UI Scripting enabled for son long that I always forget to check for it in the script. Obviously if somebody else runs the script, nothing happens.

To enable UI scripting go to the Universal Access Preference Pane and enable the checkbox at the bottom of the screen. However good script should check for this and give you a dialog, prompting you to enable it. Here is the code:

(Works with Tiger and up.)

tell application "System Events"
if not UI elements enabled then
display dialog "GUI Scripting is not enabled. This script requires GUI scripting, click \"OK\" to enable."
set UI elements enabled to true
end if
end tell


Note to self: paste this in front of every script that uses UI scripting.

27 October 2006

Script Friday: Birthday Address Book Plug-ins

Two quick and fun Address Book Plug-ins, download the archive, put the scripts into ~/Library/Address Book Plug-Ins (create folder if necessary).

Both don't actually do anything but one will display the age and the other the zodiac when you click on the birthday label in Address Book.

25 October 2006

.Mac site feed

If you start a blog in iWeb then you will get an RSS feed, that part is simple. however some people don't want to open a blog, but just post individual pages. if you want to keep track of what they are doing there is a RSS feed for the entire site. Just enter:

http://rss.mac.com/username/iWeb/Sites.rss

into your favorite feedreader.

21 October 2006

Rock Star Developers

This movie on 37Signals on the Apple Page (why is it in the Higher Education section?) is just one more proof of the fact that the Mac community treats their developers like Rock Stars. Don't get me wrong. Jason and David and all of 37signals deserve all the attention. The stuff they make is awesome, not to mention Ruby on Rails.

Maybe it is not so much the fact that Mac users want to treat the developers differently, but that the Mac as a platform attracts a different breed of developers, who act like Rock Stars and then get treated the same way.

20 October 2006

Script Friday: SubEthaEdit Server

SubEthaEdit is a great tool to share and collaborate on text documents. However to share a document you need a machine that is available to the internet (not behind a NAT or firewall) and has to be on, not very friendly for laptop users.

Use this script to turn your home server into a SubEthaEdit Server. On how to setup your home server, dyndns and the router I will leave that as a exercise for the attentive reader. SubEthaEdit 2 uses a port range of 6942-6951.

This script will open all the documents in ~/Documents/SubEthaEdit Server Documents/ and turn the sharing on. Then it will periodically save all open documents. You can use SubEthaEdit from your client to connect. Try my SubEthaEdit Server!

You can actually get the code for the script there. I was tempted to have that be the only place but eventually I will turn that off again so I will also put it this article so it ends up in the archive. This however a wonderful chance to directly put feedback in to the code. Much more interactive than comments!

SubEthaEdit Server (click link to open script in Script Editor)

Save as application and check the "Stay open" option. Then set the script as a login item and set that user to automatically login. This is generally a bad idea on a server but SubEthaEdit has no background deamon to do the serving so we have to use the GUI app. Please give the Codingmonkeys lots of feedback that we want this feature!

17 October 2006

Set Boot Volume in the command line

I haven't found this anywhere, so I will throw it out to the Googlesphere here.

Say you want to restart a Mac and boot from CD. Say it doesn't have a display and keyboard attached and you don't have Remote Desktop around (you should though).

You can always ssh in and do the following: Insert the CD. Run diskutil list to see wether the CD mounted and note the partition number (something like /dev/disk1s2 though the numbers will vary. Then to actually set the next boot drive use:

sudo bless --device /dev/disk1s2 --setBoot

and do a sudo reboot to restart. There is also a --mount option which will take the mount point, e.g. "/Volumes/Mac OS X Server Install/". To do a Netboot do:

sudo bless --netboot --server bsdp://255.255.255.255

You can replace the 255's with the NetBoot server's IP address if you want to boot off a specific server.

The bless command has another option --nextonly which will only remember the setting for one boot. Read the bless man page for more details.

16 October 2006

Steve Jobs Interview on MSNBC.com

There is new Steve Jobs Interview on (ironically) MSNBC.com. My favorite quote:
Microsoft has announced its new iPod competitor, Zune. It says that this device is all about building communities. Are you worried?
In a word, no. I've seen the demonstrations on the Internet about how you can find another person using a Zune and give them a song they can play three times. It takes forever. By the time you've gone through all that, the girl's got up and left! You're much better off to take one of your earbuds out and put it in her ear. Then you're connected with about two feet of headphone cable.

Which just goes to prove that geeks aren't good product designers. They never think of the human interaction associated with a product.
(Via Gruber's Linked List)

13 October 2006

Daring Fireball: Processing Processes

Comparing Shell scripts to AppleScript seems fairly common these days. John Gruber over at Daring Fireball has a nice and (as usual) longish article on Processing Processes.

Script Friday: Build Similar Tracks Playlist in iTunes

Use this script on the currently playing track or selection in iTunes to build a list of similar tracks. It will generate a new playlist and start with the current track (iTunes will "hiccup" briefly while switching playlists, sorry).

Similar Artist information is gained by accessing the Audioscrobbler Web Service. I am in no way affiliated with last.fm/audioscrobbler but any company that opens their APIs for scripters does get bonus points from me.

This script is very sensitive to the naming of the artists in your library, if your naming does not match the naming in audioscrobbler then you are out of luck. Take a look at the event log to track down problems.

Use the following parameters to adjust to your preferences (you will find them in the first few lines of the script as properties):

includePlaylist : "Library" -- pick only songs from this playlist, use "Library" for all your songs, podcasts and songs which are marked 'Skip when shuffling' are ignored by default
numberOfTracks : 12 -- how many tracks should be added to the new playlist
minimumRating : 20 -- only choose tracks with a rating higher or equal to this, note: 1 star in iTunes equals a rating of 20 (5 stars = 100)
minimumMatch : 40 -- Audioscrobbler has a 'match' index for the artists from 100 downwards, describing how similar two artists are rated. ignore artists with a match rating lower than this.
namePrefix : "Similar Tracks starting with " -- the new playlist will start with this string followed by the name of the artist

So without much further ado:

Build Similar Tracks Playlist

12 October 2006

More on find...

Funny that I write about find yesterday and then I find this:

Harnessing The Über-Powerful find Command (+xargs)

Go there and read on the xargs thing I teased you with yesterday.

11 October 2006

Shell vs. AppleScript: 1-0

I added Google Analytics to his blog, just because I'm really curious and it really beats a boring hit counter (left handed and twice on any week-day). Aside from the fact that I am totally enslaving myself and my online publications to Google (and happily doing that, which is weird) it was really easy, you just have to insert a few lines of javascript into every page. Of course using a template based blogging system makes that really simple. But then I wondered about wether I could get Google to analyse my iWeb Blog?

Of course I could try to change the internal iWeb templates but that would be painful and I'd probably have to re-do that every time iWeb gets an update. It would be nicer to work on the published pages. If you go to your iDisk then you will see a "Sites" and a "Web" folder. The Sites folder was (is) used by the old web-based ".Mac HomePage" or can be used to publish self made pages. And if you look into the "Web" folder, then you see the code that iWeb generates. You can view and even modify the code there, and it will retain you modifications until you re-publish the site in iWeb.

So the problem is easy, open every html file, insert a code snippet before the </body> tag. Sounds like a job for a script. Fortunately AppleScript has this great support for filtering and you can do that recursively through folders , too. Should be as simple as

get every file of entire contents of iWebBaseFolder where name ends with ".html"

It should be. Try this with any decently sized iWeb page and you will get a timeout error. Of course you can increase the timeout, but it seems wrong that AppleScript chokes on this. Note: I have mounted my iDisk the standard way, so it is using WebDAV und you can tell by the delays this causes in Finder, if you have set your iDisk to synchronize with a local mirror, then this might actually work.

Of course finding the files is only the first part, then you have to open the text parse it for the </body> tag and insert the code and save the file again. All of this is very painful in AppleScript.

Wait, isn't this what Unix is supposed to be good at? Let's try. The find part is easy

find /Volumes/idiskname/Web/Sites -name '*.html'

You can still see the names appearing but it is much better than the AppleScript solution. So how do we go about the text manipulation? The answer is sed (stream editor) which takes a stream of characters and somehow manipulates this using the magic incantations of regular expressions and things that the sed man pages calls "functions" but which are basically single letters which are meaningful to the initiated and completely illegible to laypersons. Thankfully you can enter and nice search in Google (there it is again, I have no idea how I was able to learn programming entirely without Google) and find some examples:

# substitute "foo" with "bar" EXCEPT for lines which contain "baz"
sed '/baz/!s/foo/bar/g'

If the script already inserted the snippet then we won't need to insert it again. So some experimenting and much confusion lead to:

sed -i .bak -e "/$textToInsert/!s/$textToReplace/$textToInsert&/g" filename

Where the $ prefix denotes variables I defined earlier in the script to turn it into something close to legible. What this command does is: if a line does not (!) contain $textToInsert then substitute (s) $textToReplace with $textToInsert and append the text we orginally searched for ($textToReplace, &) globally across the document (g) filename and then write that into the file, keeping a copy with a .bak extension around in case all this gibberish happens out to pruduce... well gibberish.

Combine that with the find command form earlier and a nice -exec extension and you get the entire script:

#!/bin/bash

googleAnalyticsCode='enter your Google Analytics code number here'
textToInsert="<script src=\"http:\/\/www.google-analytics.com\/urchin.js\" type=\"text\/javascript\"><\/script><script type=\"text\/javascript\">_uacct = \"$googleAnalyticsCode\";urchinTracker();<\/script>"
textToReplace="<\/[Bb][Oo][Dd][Yy]>"
iWebBasePath='/Volumes/idiskname/Web/Sites'

# this is where the actual work happens
find $iWebBasePath -iname '*.html' -exec sed -i .bak -e "/$textToInsert/!s/$textToReplace/$textToInsert&/g" {} \; -print


Basically a one liner. I added the -print at the end of the command so I can see which files the script is working on. Otherwise you would get no feedback at all.

Admittedly very powerful. Armed with this new knowledge we can go ahead a write a script that removes the Google Analytic snippet again:

#!/bin/bash

googleAnalyticsCode='enter your Google Analytics code number here'
textToRemove="<script src=\"http:\/\/www.google-analytics.com\/urchin.js\" type=\"text\/javascript\"><\/script><script type=\"text\/javascript\">_uacct = \"$googleAnalyticsCode\";urchinTracker();<\/script>"
iWebBasePath='/Volumes/idiskname/Web/Sites'

# this is where the actual work happens
find $iWebBasePath -iname '*.html' -exec sed -i .bak -e "s/$textToRemove//g" {} \; -print

and (I bet you waited fro this) a one liner to remove all those pesky .bak files (after testing of course):

find /Volumes/arminb/Web/Sites -iname '*.bak' -exec rm {} \; -print

(again the print is for the sole purpose of having something to watch) And I know some smart guy will chime in here and say that xargs would be so much more efficient than -exec and that is true but I will leave that for another day.

I love AppleScript very much but in this case the command line tools are way more efficient (though painful to learn). I guess the resume here should be: "Know your tools!"

10 October 2006

Automator Actions

Shameless plug, but still. I wanted to point out, that I have a small site with a few useful Automator actions. They are up there including the code!

Armin's Automator Actions

Address Book Plug-In: Show Emails from or to

One of the recurring topics int he old blog were short AppleScripts to optimize the workflow. Here is a new one.

Show Emails From

Click on the link above and save the script that is opened in Script Editor in ~/Library/Address Book Plug-Ins/ as Show Email From. Create the folder if necessary. Then (re-)start Address Book and click and hold on the label next to an email address. You can now select the Show Emails from option, which will open a new message browser window in Mail and fill out the search field to show emails from this email address only.

Then go back in to Script Editor and change the lines
   return "Show emails from " & theName

to
   return "Show emails to " & theName

and
   click button "From" of window 1 

to
   click button "To" of window 1 

or click here for the entire script and save this as Show Email To in the same folder. Restart Address Book.

BTW: Opening new Mail viewer windows (File Menu > New Viewer Window) is one of the 'unsung' features in Mail which really increases my productivity. If you aren't using that yet, then start remembering the keyboard shortcut (command-option-N) to your repertoire.

Welcome (Back)!

It's been a while since I had a technical blog. While my personal life is nicely covered, I was still missing a venue for some of the technical stuff I've been doing recently.

As before, my plan is to blog mac-centric tips, tricks and scripts on how to use your Mac more efficiently. This time I took the chicken way out and registered with Blogger. I don't want the hassle of managing my own server, the service is free and there is the slight hope of getting some revenue through AdSense.

Welcome back! And don't forget to please reply!

Armin