Sometimes it's all about the aesthetics.

10/21/2007

Shell Script in An OSX Bundle And More

Dr. Ping Yeh brought up a question about how to put a shell script in the Dock of Mac OS X. My original thought about this question is to solve it with a shell script with a file extension/type *.command and it can be run by double clicking it. Open the *.command files and the Terminal.app will launch the shell to run it. But the problem becomes the limitation of the left side of the Dock, a item has to be an "application" to sit in the left side of the Dock. (At the time we didn't work it thoroughly and forgot the right side the Dock... The thing is, you can just put the *.command file in the right side of the separator and click to launch it.)
filedock

Just put it in the right side of the Dock.

You have to wrap your shell script into an application if you want it to stay in the left side of the Dock. Luckily we can follow the procedure in this document by Artem Fishman (via google search).
Basically the bundle structure looks like this:
MyBundle.app
MyBundle.app/Contents
MyBundle.app/Contents/Info.plist
MyBundle.app/Contents/MacOS
MyBundle.app/Contents/MacOS/MyBundle
MyBundle.app/Contents/MacOS/startup.command
MyBundle.app/Contents/Resources
MyBundle.app/Contents/Resources/MyIcons.icns
(The name "MyIcons" is defined in Info.plist file.)
MyBundle

MyBundle.app in my Dock.

However that document only helps you run the script silently. It's not enough if you want to be able to read the output of the shell script or even interact with the shell script. A better way to do it is just simply writing your main script in a command file inside the bundle and "open" the command like this:
#!/bin/sh
#File:  MyBundle.app/Contents/MacOS/MyBundle
mypath=`dirname "$0"`
open $mypath/starup.command
With this command file:
#!/bin/sh
#File:  MyBundle.app/Contents/MacOS/startup.command
echo "this is a test"
/bin/sleep 5
This will give a terminal window with the output of "this is a test" and 5 seconds delay. Now you have a working application that can be put on the dock and also give you an opportunity to read the output!
Completed Command

After the command is completed, the terminal leaves a dummy window.


vmd

VMD in action, you can see there is a console window utilizing Terminal.app.

Unfortunately this new application doesn't close the terminal window automatically. You got a "Completed Command" window after the application finished and it requires you to close it manually. This had been my major quest since the first time I knew about the *.command files. I always want to improve a program called VMD, a program that shells-out a console window but leaves that window half dead after finished all the task. This time I decided to finish this quest. I started with closing the window in the front or idle window with Applescript but the side-effects are bad --- either logically bad or bugs on Terminal.app . Later I have to abandon the idea of using "open" command asking Terminal.app to open the script.
Yay! Eventually I did it.
#!/bin/sh
#File:  MyBundle.app/Contents/MacOS/MyBundle
mypath=`dirname "$0"`
osascript << EOT
tell application "System Events" to set terminalOn to (exists process "Terminal")
tell application "Terminal"
   if (terminalOn) then
        activate
        do script "\"$mypath/startup.command\"; exit"
   else
        do script "\"$mypath/startup.command\"; exit" in front window
   end if
end tell
EOT
exit 0
Time to fix the VMD.
(Update: This demo bundle is now available for download.)
(Update: It turns out that if you already have Terminal.app running, clicking the command files on right side of the dock might not be working.)
(Update: In order to make the trick work, you still need to set your terminal.app's shell preference to "close only if the shell exited cleanly".)
(Update: For processing arguments and drop actions, use the DropScript by Wilfredo Sánchez, updated source can be found through SVN repository. Also checkout his introduction.)
(Update: Some shell scripts are suitable for contextual menu items. Check the website out.)

2 comments:

Tsu-Fan said...

Hi MJ,
how are you guys? Have you tried to put freebsd on an intel-mac?

regards,

TFC

mjhsieh said...

Why would I do this kind of thing? No, I probably won't try that. If I ever want to try it, I would run it on vmware.