Scripting Safari

I am new to Mac programming.  I have downloaded Xcode and MacRuby and have some familiarity with Objective-C and common Unix tools.  I had thought that I might stick to MacRuby for any immediate projects so that I could get the “feel” of the system quickly.

I was not sure what I wanted to tackle as a first project.  I wrote a traditional “Hello, world!” application and ran it.


puts "Hello, world!"
puts "Testing."

I opted to edit the code in vi.  I soon found that vi on the Mac is actually vim.  Cool!

I searched through a few sites and found an interesting Ars Technica article on using the Scripting Bridge via MacRuby to eliminate the need to use AppleScript to control other applications:

One of the scripts in the article lists the names of the sites in all of the tabs for a running instance of Safari.  I thought it would be nice to try to write a script that would invoke Safari and open various tabs for a handful of sites that I visit regularly.  I’d like to have tabs open for Google, Twitter,YCombinator / HackerNews, and GMail.

I soon found that in order to familiarize myself with the scriptable objects in Safari, I’d have to use the AppleScript Editor.  I invoked the editor, and opened the dictionary entry for Safari:

Unfortunately, the object reference seems to be geared toward AppleScript.  I couldn’t figure out how to invoke the chain of expressions in MacRuby to do what the AppleScript I had ended up finding on the web could accomplish.  I tried to simply call the Safari.application object’s open() method with a URL:


framework "ScriptingBridge"

safari=SBApplication.applicationWithBundleIdentifier("") ""

Arrrgh! Safari then tried to open a file on the filesystem itself with the argument that I had specified, prefixed with the “file://” protocol:

I experimented with the Do JavaScript directive in AppleScript to see if I could use a call from JavaScript to open new tabs.  When I couldn’t exactly figure out the syntax for that in MacRuby, I wondered, “What if I just open a local HTML file that has a JS payload that can open these tabs?”

I created this HTML file:

<html><head /><body>
<script type="text/javascript">
   var sites=[
    ] ;
   function openMore() {
      var i;
      for(i in sites) {[i]);
Loading...please wait.

After a lot of experimentation, I found that I just wasn’t going to figure out enough about how to properly script Safari in MacRuby at this juncture.  So, my pet project changed slightly into something different.  I decided to use a simple Bash script as a wrapper for a small AppleScript script.

After a quick Google search, I found that Bash supports arrays.  Good.  I wanted to be able to specify a list of URL’s at the top of the script.  I would then add code to iterate through the list and open each URL in a tab of its own.

As luck would have it, I couldn’t get any of the array samples that I found to work.  Why? I suspect that the default Bash implementation on OS/X (Lion) is a bit old:

$ bash --version

GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
Copyright (C) 2007 Free Software Foundation, Inc.

Hmmm.  Copyright 2007.  Okay, maybe it was a lofty goal to expect to be able to use a list of strings from the stock version of Bash.  I wrote a function called saf() that will pass a URL to an AppleScript file.

function saf {
 osascript $HOME/Progs/mysafari.scpt $1

open -a safari ""


I first invoke Safari via the open command and direct it to Google.  This gives me a running instance for use within the AppleScript code:


on run argv
   tell front window of application "Safari"
      set newTab to make new tab
      set the URL of newTab to item 1 of argv
      set the current tab to newTab
   end tell
end run

Now, I can invoke the script from a terminal prompt by typing


…which yields my desired Safari session:

I also toyed with the idea of specifying the entire script in the osascript command-line and I toyed with the idea of compiling the AppleScript code.

I think that I may still revisit this subject later, perhaps using MacRuby to put a decent UI on top of the script so that I can edit the URL list more easily.

( Please see comments for a contributed MacRuby solution…)


About Jim Lawless

I've been programming computers for about 36 years ... 30 of that professionally. I've been a teacher, I've worked as a consultant, and have written articles here and there for publications like Dr. Dobbs Journal, The C/C++ Users Journal, Nuts and Volts, and others.
This entry was posted in Technology and tagged , , , , . Bookmark the permalink.

2 Responses to Scripting Safari

  1. Mateus says:

    hi Jim, you can solve it with MacRuby like this:

    #!/usr/bin/env macruby -wKU
    framework “ScriptingBridge”

    safari = SBApplication.applicationWithBundleIdentifier(“”)
    new_window = SafariDocument.alloc.init # create a new window < site}) # create a new tab << new_tab # add the tab to the window

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s