AppleScript is back. The December tools update from Apple included the new AppleScript Studio. (Join the ADC; even free members get access to most updates.) At the Macworld Expo, in addition to the new iMac and iPhoto, Apple was pushing AppleScript.
Until recently, I did all of my coding in a text processor and used the Terminal to compile and run the code, and for running JUnit to make sure all of my tests worked. In this month's column, I'll work through an example that shows you how to use AppleScript to automate many of these tasks.
The final application is usable, but that's not really the point. You can push one button to compile, another to run, and a third to run your test suite. All we really end up with is a GUI front end on the Terminal. This is just a quick tutorial to get you to consider how AppleScript can help Java developers on the Mac. Sure, Ant would be a better solution, and I keep meaning to download and learn it. Maybe an AppleScript front end for Ant is the solution.
As always, you can send email to me at DSteinberg@core.com with the subject line "O'Reilly Mac"; I'm interested in your comments, as well as suggestions for future columns. This month's column came from a reader question about scripting the Terminal to run a Java application. As for me, lately I've been using a couple of IDEs that actually make my life easier. Next month, I'll review various IDEs available on Mac OS X. I've got my favorites; if you'd like to suggest yours, feel free to email me with the subject line "The IDEs of Mac".
Make sure you have the December 2001 release of the developer tools that includes AppleScript Studio. AppleScript Studio is a bit of a misnomer; it is really an enhancement to Project Builder. When you open up Project Builder, you can choose to create three different types of AppleScript projects. You can then use Interface Builder to create an Aqua GUI for your script. To make Java a first-class citizen on the Mac, it would be nice to have this Interface Builder functionality for Java projects as well.
You'll use Interface Builder to create an application that looks like this:
For the most part, Interface Builder behaves the same as other RAD (Rapid Application Design) tools that you may have used, so I won't spend a lot of time on this part. To create the rest of the interface, you'll drag and resize components from the Cocoa-Views window into the window you are designing.
You'll notice guides that appear to help you align the buttons. Your buttons should almost look like the buttons in the picture. The blue background for the Compile button indicates to users that if they use their Return key, they will select Compile. Click on the Compile button and look at the properties in the Show Info window. About halfway down is a field labeled Equiv. From the pull-down box, change the default value of "no key" to "Return" and your button will be appropriately highlighted.
All of the text in the window is created by modifying the component labeled System Font Text. Drag it into your window and double-click on it to change the text. The text fields are created by dragging the unlabeled text field in the top right of Cocoa-Views into your window, and placing and resizing it. Make sure that your fields are enabled, editable, and scrollable. To set off the headings Commands and Parameter Settings, choose a border for the text and center the text.
Now let's create a script for the Run button.
For this next part, you will need a compiled Java application that you can run from the command line. HelloWorld will do, or you can pick an application from a previous column if you don't have one handy. In this example, I'm using the application Old MacDonald. It is located in the directory /Users/dhs/projects/omd/, and the class containing the
main() method is called Main. To run this from the command line, I would change directories using:
Then I would run the application using:
In our script, we'll tell the Terminal to do these two actions. (Of course, you should change the information for the location and
main() for your application.) The script should look like this:
on clicked theObject if title of theObject = "Run" then tell application "Terminal" do script with command "cd /Users/dhs/projects/omd/; java Main" end tell end if end clicked
Like other scripting languages, AppleScript is difficult to debug. If you type in a syntactically correct statement and save it, AppleScript Studio will format it nicely and color the keywords appropriately. If you have a typo, it can be very difficult to run down.
In the script above, when a button is clicked, we first check that it was the Run button. If it is, we tell the Terminal application to open up a window and execute the given command. Notice the semicolon used to separate the two commands. It is the same as executing the
java commands on different lines, as shown above. Click the Run button and you will open up a Terminal window and run your application. Click the Run button again. You open up another Terminal window and again run your application. We may want to avoid having all of these Terminal windows open every time we Run, Test, or Compile. Also, we don't want the path and class name hard-wired into the application.
Let's start by eliminating the Terminal window. If you don't require console output for your application, you can replace the Terminal commands with a shell script like this:
on clicked theObject if title of theObject = "Run" then do shell script "cd /Users/dhs/projects/omd/; java Main" end if end clicked
The one advisory is that you are using a sh shell instead of the usual Mac OS X Terminal tcsh shell, and the commands may vary. What about warnings? If you type in the wrong path or class name, you usually see these messages in the Terminal window. If I remove omd/ from the classpath above and run the script, the following dialog box will pop up:
We'd like to be able to enter information into the text fields in our tool and run our Java application with the classpath that is passed in from the location of the class files. The script should be something like this. (Note that the third and fourth lines in this code listing should not be on separate lines.)
if title of theObject = "Run" then tell application "Terminal" do script with command "cd " & outputLocation & "; java -classpath " & classPath & ":. " & mainClass end tell end if
outputLocation should point to wherever the compiled files are. Since we begin by changing directories to this location,
classPath contains the classpath information other than the location of these class files, followed by the pointer to the current directory (:.).
|This is a good example of bringing two technologies together to work more efficiently. What comments do you have?|
mainClass variable is the name of the class containing
main(). Suppose that I compiled Old MacDonald into the classes subdirectory of /omd. Then
outputLocation would be /Users/dhs/projects/omd/classes/,
classPath wouldn't need to be set but could be :., and
mainClass would be
You'll need to read this information from the text fields, so go back to Interface Builder. You should provide a name for each text field. Click on each one in turn and view the AppleScript page of the Show Info window. Name them, from top to bottom: source, output, classPath, package, main, and test. You can now create variables to store the information you read-in whenever the user clicks on a button.
Here's the entire source code for the compiler, runner, tester tool:
-- Application.applescript property classPath : "." global mainClass, compilePath, testClass, sourceLocation, outputLocation on clicked theObject set mainClass to contents of text field "main" of window "O'Java" set classPath to contents of text field "classPath" of window "O'Java" set compilePath to contents of text field "package" of window "O'Java" set testClass to contents of text field "test" of window "O'Java" set sourceLocation to contents of text field "source" of window "O'Java" if the contents of text field "output" of window "O'Java" = "" then set outputLocation to contents of text field "source" of window "O'Java" else set outputLocation to contents of text field "output" of window "O'Java" end if if title of theObject = "Run" then tell application "Terminal" do script with command "cd " & outputLocation & "; java -classpath " & classPath & ":. " & mainClass end tell else if title of theObject = "Compile" then do shell script "cd " & sourceLocation & "; javac -classpath " & classPath & " -d " & outputLocation & " " & compilePath & "*.java" else if title of theObject = "Test" then do shell script "java -classpath " & classPath & ":" & outputLocation & " " & "junit.swingui.TestRunner " & testClass end if end clicked
You can download the complete application here.
Even with my obviously limited AppleScript knowledge, we've ended up with a simple application that can be used to run, compile, and test our code while we develop from a simple text editor. Here are my settings for the Old MacDonald Java application:
Also in Java Programming on a Mac
The compiler and test runner are running in the shell with the command
do shell script. Because my version of Old MacDonald prints the output to the console, I'm stuck using the Terminal application. If you only run GUI applications, you can modify that command.
You can easily extend this application to your own needs. You may want to add a button that only compiles a single class. You may also want to add components other than text fields for setting your parameters. Or you may just want to provide a GUI front end for ANT. As always, please share your additions by posting in the TalkBack below.
The most important extension you may want to provide is persistence for your variables. This tool allows you to enter the information once each session, but you may want to save the settings between settings. You can't save properties in a generated app. the way you could in the past with a script.
AppleScript cult hero Sal Soghoian (although that isn't Apple's official title for him) posted routines on the January 28 applescript-studio mailing list. You can find this and other AppleScript lists at http://lists.apple.com/. You can find documentation and information about AppleScript at http://www.apple.com/applescript/ and Mac OS X-specific information at http://www.apple.com/applescript/macosx/.
Daniel H. Steinberg is the editor for the new series of Mac Developer titles for the Pragmatic Programmers. He writes feature articles for Apple's ADC web site and is a regular contributor to Mac Devcenter. He has presented at Apple's Worldwide Developer Conference, MacWorld, MacHack and other Mac developer conferences.
Return to the Mac DevCenter.
Copyright © 2009 O'Reilly Media, Inc.