applescript

AppleScript tricks: What to Do When the Frontmost Window Isn't Frontmost

The Problem: Scripts often target the current document window of an application. This is usually easily handled with something like...


Tell application "Finder" to get window 1

The problem with this approach is that it returns a useless window if the wrong kind of window is in front. In the Finder, this will often be a Get Info window, folder options window, or preferences. Some applications have special classes of windows to make this easier, but many do not. To find the frontmost window of these applications, you need to do this manually.

To make this work, you need to loop through your windows until you find one of the right type. You could do this by the name of the window (e.g. find Finder windows whose names don't contain "Finder Preferences"), but that requires you to catalog the names of every non-standard window, and can cause problems if, for example, you have a folder named "Finder Preferences."

A better approach is to identify a property that only the right kind of windows contain. So, for Finder windows, you can look for the folder of the window, as in...

Tell application "Finder"
set theFolder to (path to desktop folder as alias)
repeat with i from 0 to (count of windows)
try
get folder of window i
set theFolder to result as alias
exit repeat
end try
end repeat
end tell

In this code, the "try" handler gracefully handles windows without the "folder" property. Likewise, by setting theFolder to the Desktop to begin with, it also handles the situation where there are no open windows.

Using this technique, the following script will open the current Finder window in a new tab in the frontmost Terminal window. If there isn't a terminal window available, it opens a new window. The code gets pretty involved for the Terminal (including having to go to UI scripting to make a new tab), but it avoids the pitfalls of multiple open windows in each application, not all of which are useful folder or terminal windows.

on run
get quoted form of POSIX path of my getCurrentFolder()
my termScriptInNewTab("cd " & result)
end run

on termScriptInNewTab(cmd)
tell application "Terminal"
activate
set termWins to count of windows
set frontWin to 0
repeat with i from 1 to (count of windows)
try
set tabCount to count of tabs of window i
set frontWin to i
exit repeat
end try
end repeat
if frontWin is 0 then
do script cmd
else
set frontmost of window frontWin to true
tell application "System Events" to tell (first application process whose name is "Terminal") to keystroke "t" using {command down}
set xi to 0
repeat until (count of tabs of window 1) is (tabCount + 1)
if xi ≤ 4 then -- don't wait more than one second
delay 0.25
else
set xi to -1
exit repeat
end if
end repeat
if xi is not -1 then
do script cmd in (last tab of window 1)
else
do script cmd
end if
end if
end tell
end termScriptInNewTab

on getCurrentFolder()
tell application "Finder"
set theFolder to (path to desktop folder as alias)
repeat with i from 0 to (count of windows)
try
get folder of window i
set theFolder to result
exit repeat
end try
end repeat
return theFolder as alias
end tell
end getCurrentFolder

Extra credit: How can you adapt the termScriptInNewTab handler to run the command in the first tab that isn't busy, rather than a new tab?

Ubiquitious Mac Automation

I often find myself wanting to make my Mac do something even when I’m not there. It could be something as simple as “reboot” or something more complex, like, “Add this task to OmniFocus”. Unfortunately, unless my Mac is up and running and accepting remote connections, there’s no way I can do this.

Or is there?

One obvious answer is to set up mail rules that shoot off AppleScripts. When an appropriately formatted messages comes in from the right sender(s), the script runs, and you’re all set to go. This approach has the advantage of being either close to real time (if Mail’s up and running, it works) or asynchronous if Mail’s off – the actions will fire off when you next check email, if your computer happens to be off.

Another option is to monitor various internet feeds to create similar results. I’ve written about Proxi before, and it remains one of my favorite tools for automating my Mac. One thing it can do is monitor network resources, such as RSS feeds, Twitter accounts, Mail, Skype, iChat, etc. This, it turns out, is the key to handling this need for remote automation.

By monitoring an RSS feed, you can set it up to check Gmail (which publishes an ATOM feed of your mail), a blog, or anything else, and have it fire off a script with some or all of the values passed by the feed. One very cool use of this ability is to set up script-firing Gmail rules by just having Proxi parse the ATOM feed and then activate scripts when certain conditions are met. This gives you the best of both worlds: Gmail’s powerful web-based interface, and the integrated goodness of Apple’s Mail program.

Another great tool is Twitter. Twitter’s main purpose is to share little snippets about what you’re up to with the rest of the world. But Twitter can also be used as simply an online notepad. It integrates with both SMS and IM clients, so it’s easy to contact, and you can even use a service like Jott with it, so you can phone in a “tweet” to your Twitter account.

Proxi has a Twitter monitor, so if you set up an appropriate Twitter account, you can have Proxi take action on incoming tweets, just like it can with GMail’s RSS feed.

Lastly, Proxi can monitor iChat and Skype and fire off scripts based on behavior in those apps. (iChat also has some of these capabilities built in if you’ve upgraded to Leopard) This can be an excellent way to have instant access to your computer from a remote machine.

What have I done with this? Well, I set up a Twitter account that feeds directly into OmniFocus so that I can capture a new task anywhere (via the web, SMS, IM, or the phone – thanks to Jott) and rest assured that when I next turn on my Mac, Proxi will pick them up and dump them into my electronic inbox.

Great RubyOSA tutorial

Here’s a fantastic tutorial from MacZealots to get you started on automating your Mac using Ruby (instead of, say, AppleScript). If AppleScript is too hinky and irregular for you programmer types, this might be just the ticket.

What would a weekly review script actually do?

A couple folks have asked that I build a “weekly review” script for Entourage. I have just one question, what would it do?

I can easily see that it might build a list of projects without next actions, overdue tasks, maybe even upcoming events from your calendar. But all that is really at your fingertips anyhow, isn’t it?

Let me know what a review type script or application would do for you. Sound off in the comments!

* is at your service with ThisService

ThisService promises to turn any AppleScript or shell script into a live, working, entry in the much-ignored Services menu. And yes, it will take input text and do something with it, so your hopes of turning random selected text into, say, a note in KGTD (or something purple) can now come true.

It’s a perfect Halloween gift for the compulsive scripter in your family.

Pages

Subscribe to RSS - applescript