Use LaunchBar to execute, in the "background," commands via a shell

August 09, 2009

Early this year I migrated from Quicksilver to LaunchBar and haven't looked back. These days I use LaunchBar for just about everything, even to a greater extent than I did with Quicksilver (and I was a Quicksilver nut). It's just great software, if a tad bit expensive (~$35). (There was nothing wrong per se with Quicksilver, but core development kind of stopped (it was open-sourced) when the software's creator headed to Google to run its Quick Search Box for Mac project, and even he was recommending that users jump ship and try LaunchBar.)

In any event, I came up with these AppleScripts in order to solve an annoying problem that presents itself at the end of the following sequence: 1) plug closed MacBook Pro into a 24" Apple LED Cinema Display and use only that monitor; 2) disconnect the display from the computer and sleep the computer; and 3) wake the computer and use only its built-in display. About 75% of the time, certain elements of the OS don't appreciate that the screen resolution has changed (i.e., that the working resolution is now much lower), and so things like Expose and Spaces — which I've mapped to corners of the screen — can't be triggered. The only solution I've found is to execute "killall Dock" from a terminal (thanks Richard), which kind of resets everything.

Instead of bringing a terminal emulator into focus and then executing the command, I thought it would be more efficient (and the sequence more easily assignable to muscle-memory) to use LaunchBar to run the command. To this end I coded up two separate AppleScripts, each of which solves the problem in a slightly different way.

The first relies on iTerm, which, for the past few years has been my Mac OS X terminal emulator of choice, and, as luck would have it, is AppleScript-able. The script assumes iTerm is running; in my case, if the computer is on, iTerm is open. (Obviously with a few simple tweaks you can have the script check to see if iTerm is open, and then either activate or launch, depending.)

The iTerm-centric script opens a new session (i.e., a new tab) within the first open terminal window (I'm assuming most people use a single window with multiple tabs) so as not to disrupt whatever you currently may be doing within iTerm, executes the shell command you gave LaunchBar, closes the session/tab and returns the window focus to whatever application you were using before you invoked LaunchBar.

To get the script working, simply paste the below code into a new file from within Script Editor, and save the file to: ~/Library/Application Support/LaunchBar/Actions/.

on handle_string(command)
    tell application "iTerm"
        activate
        tell the first terminal to launch session "Default"
        tell the last session of the first terminal to write text command
        terminate the last session of the first terminal
    end tell
    tell application "System Events"
        keystroke tab using (command down)
        keystroke tab using (command down)
        keystroke tab using (command down)
    end tell
end handle_string

You can name the script whatever you want, but keep in mind that this name will be the alias used to launch it from within LaunchBar. For example, I named my script "shell.scpt," and so to set it in motion I type (or start to type) "shell" from within LaunchBar, and then hit the space bar (so that I can enter the command) when I see that "shell" is the highlighted action.

The second AppleScript I whipped up uses Mac OS X's native terminal emulator, Terminal. It launches Terminal, routes your shell command through it, and then closes the application (thus bringing the window focus back to the app you were using previously).

on handle_string(command)
    tell application "Terminal"
        launch
        do script command
    end tell
    tell application "Terminal" to quit saving no
end handle_string

Update: Soon after posting this, Cameron Hunt wrote me to let me know that this actually can be done via LaunchBar without having to invoke a terminal emulator (see the script below, which is a slight modification of the second script above).

on handle_string(command)
    do shell script command
end handle_string

If you don't have a preference, I definitely recommend the second third of these AppleScripts because it's so much faster than the first two, despite it having to launch Terminal, and obviously would be faster still if you always kept Terminal open (and then used activate instead of launch).

I should mention that if you've a specific terminal command you want to execute (instead of the ability to run any command, as described above), I think you probably can just create a simple shell script consisting of nothing but the shebang, your interpreter of choice and the terminal command. Place the script in the same directory mentioned above and you should be good to go.

You should follow me on Twitter here