"Don't Use Manual Procedures"
I always wanted to follow the advice "Don't Use Manual Procedures" - tip 61 in the excellent book "Pragmatic Programmer".
But I always thought that I didn't have the right tools to make it simple to automate stuff. I used to be a windows user, but was so frustrated. Even the simplest things, like zipping a bunch of files and naming them with a suffix of todays date, was really hard work using the poor "bat"-scripts.
Andreas Automation v. 0.1 (Windows/Cygwin)
So I used to use cygwin, and store small snippets of bash-scripts for my most repetitive jobs. I also did use some perl and ANT-scripting for simple automation.
Andreas Automation v. 0.2 (learning Ruby)
For about two years ago I found out about ruby, and thought that often ruby was simpler to use than shell-scripts (and perl, and definitely better than ANT for the same tasks). So I started to collect small snippets of ruby code to do my repetitive stuff.
But I could not use it to interact with my regular desktop-apps (I guess you can use some-kind of VB-scripting to do some work with Microsoft programs, but I did not want to go that way...)
Andreas Automation v. 0.3 (Learning Mac...)
This year I switched to use a Mac for work, and I saw the promise of using some-kind of blend of "Quicksilver-AppleScript" to automate stuff with my desktop apps. Quicksilver is an amazing piece of software, but after a while I found myself using it mostly for finding stuff (applications and files) fast. And I didn't really like the approach of AppleScript (I wanted the power of Ruby...). So what is the solution?
Andreas Automation v. 0.4 (July 2007...)
I have found a new way to be truly productive (At least I hope so, this approach is really new to me, and I haven't figured out what is possible yet...
So what is the solution? During the last weeks I have found out about two different ruby gems that seems to solve my problem, "RubyOSA" and "Sake".
What these two techniques combined let me do is:
- RubyOSA: Interact with Mac applications from Ruby
- Sake: Have a repository for categorized scripts and a simple way to use them
RubyOSA
RubyOSA is a bridge from the Ruby language to the Apple Event Manager. What that means is basically that what you can do with AppleScript you can now do with Ruby (!). RubyOSA was developed by Apple and published under the BSD-license, see RubyForge.
Super-short-tutorial
$ sudo gem install rubyosa
Create a file: "on_itunes.rb"
require 'rubygems'
require 'rbosa'
app = OSA.app('iTunes')
puts "'#{app.current_track.name}' by '#{app.current_track.artist}'"
What that let's me do is:
$ ./on_itunes.rb
--> 'Palace & Main' by 'Kent'
To impress colleagues and friends, it is even cooler to use irb. Start by opening irb, and paste in the code from "on_itunes.rb".
Then type: app.next_track (and hear how iTunes starts playing the next song in your playlist). Did, I hear a "Wow!" ?
Changing songs in itunes from the command line is maybe not the most useful thing you can do, but it was mostly to illustrate the point.
Another example then:
Sometimes I want to work without being interrupted by emails, im-clients etc. Particularly when I am doing a presentation with a projector, or when pair-programming. What I want then is a script to just say "World - don't interrupt me now!" and expect Skype, Icq, Msn, Mail-client (whatever) to just "shut-up". So this is the start of such a script (it only interacts with Skype and Adium right now).
require 'rubygems'
require 'rbosa'
mess= ARGV[0]
skype = OSA.app('Skype')
skype.send2("SET PROFILE MOOD_TEXT #{mess}", "send script")
skype.send2("SET USERSTATUS OFFLINE", "send script")
adium = OSA.app('Adium')
adium.adium_controller.my_status_message = mess
adium.adium_controller.my_status_type = OSA::Adium::ASST::OFFLINE
For more info, see Maczealot's more complete tutorial (that's how I found out about it)
Sake
Sake is a "system-wide Rake". (If you don't know what Rake is, it's a build system for Ruby (similar to make or ANT etc.) that can be used for a lot more than builds. More info about Rake
How to install sake? Simple, just:
$ sudo gem install sake
So why would that be useful? For instance by wrapping my "on_itunes.rb" in a Rakefile like:
namespace :itunes do
desc "Displays the current chosen song in itunes"
task :current_song do
require 'rubygems'
require 'rbosa'
app = OSA.app('iTunes')
puts app.current_track.name
end
desc "Play next song in iTunes playlist"
task :go_next do
require 'rubygems'
require 'rbosa'
app = OSA.app('iTunes')
app.next_track
p "Now playing: #{app.current_track.name}"
app.play
end
end
I can now install tasks from my rake file into the "system-wide repository of useful scripts" :
$ sake -i rubyosa.rake itunes:go_next
$ sake -i rubyosa.rake itunes:current_song
$ sake -T itunes
Displays the following:
sake itunes:current_song # Displays the current choosen song in itunes
sake itunes:go_next # Change to next song in itunes playlist (and play it)
What's next?
One thing I really like to automate is blog posts, like this one, with code examples that I like to be syntax highlighted.
So this post is done using a plain text markdown-file. With a few lines of ruby code I first identify code-fragments, then syntax highlight those rows using the excellent ultraviolet-gem which highlight files based on TextMate-themes, and then the whole markdown-file is transformed using the normal "bluecloth"- API.
To create this post I did:
$ sake blogger:preview automate_everything.markdown
I still have to log in to blogger and paste the html created, so this is not good enough...
I'm working on the "sake blogger:post"-command that will use the blogger REST-API to add blog posts.
To be continued... (Andreas Automation v. 0.5...)