Confessions of the Unix-Deficient
Okay, fine, I'll admit it... When it comes to shell scripting, I don't know my Bash from my Tsch. My command line abilities reached an all time high when I figured out how to pipe lines into 'grep'. I still hold my breath any time I use 'cat' and I say a quick prayer before firing up 'vim'. I must have suffered some head trauma because I can't remember a thing I learned from my 'Unix for Macs' book.
Despite these deficiencies, however, I've still wanted to get into shell scripting for one reason - automation. Rails and Textmate have helped to DRY up my day significantly, but I still waste time and, more importantly, attention on simple, routine tasks. I knew that I wanted my first task to be automating the process of opening up all the programs and windows I need for a project. I wanted to be able to simply type 'fire_up my_project' into iTerm and have it open a tab for the server, a tab for the console and a tab for the project directory. I wanted it to then open the project in TextMate (without the pesky directories like /doc and /log) and then open the site in Firefox.
I knew this was all possible, but how much Unix wizardry was I going to have to learn?
Ruby to the Rescue
Thankfully, it didn't take me long to realize that shell scripts don't have to be written in Bash, they can also be written in Ruby! All it took was a little setup and I was ready to automate.
First, I needed a place to put my new commands. I decided to create a /bin directory in my home directory (ie ~/bin). I then needed to add this to my $PATH by inserting the following at the bottom of my bash_profile (to access this file, use mate ~/.bash_profile in the console).
Now any file in this directory can be accessed as a command from the command line. I created a file in /bin called 'fire_up' (no file type suffix) and set its permissions to be executable by typing this in the command line:
chmod 755 ~/bin/fire_up
In order to be able to use Ruby in this script, the Ruby shebang needs to be the first line in the script:
Once that's in there you can use all the Ruby you want. Arguments passed into the script from the command line are stored in the ARGV array.
Bringing iTerm to Life
Small Print: I should mention that the following solution is only going to work for the iTerm console (pick it up at http://iterm.sourceforge.net/index.shtml), it will not work with Apple's Terminal program.
Though I now had the flexibility and power of Ruby at my disposal, I still wasn't sure how I could use it to control iTerm. After a little poking around, I found that iTerm supports Applescript. Using Applescript I would be able to fully control iTerm's windows, tabs, colors, the works. After a bit of work, I was able to wrap these Applescript commands into an easy to use, fully Ruby library I call ItermWindow. The class is used like this:
# EXAMPLE - Use the current iTerm window, cd to a project # and open in TextMate, launch the server and the console # and title them ItermWindow.current do |window| window.open_tab :project_dir do |tab| tab.write "cd ~/projects/my_project/trunk" tab.write "mate ./" tab.title = "MyProject Dir" end window.open_tab :server do |tab| tab.write "cd ~/projects/my_project/trunk" tab.write "script/server -p 3005" tab.title = "MyProject Server" end window.open_tab :console do |tab| tab.write "cd ~/projects/my_project/trunk" tab.write "script/console" tab.title = "MyProject Console" end end
Full documentation on the rest of the ItermWindow functionality is located within the class file.
So feel free to make your own implementations with the ItermWindow library, hopefully it will be a valuable tool in removing the routine tasks from your day.