Scripting Cocoa with F-Scriptby Philippe Mougin
Editor's Note -- We're seeing lots of activity in the open-source community around Mac OS X. One of the projects that has caught my eye is F-Script by Philippe Mougin. This lightweight object-oriented scripting layer provides interactive access to Cocoa frameworks and custom objects. I'm presenting this tutorial to you as part of our exploration into Cocoa and its related tools. After you've had a chance to read the text and play with the code, let us know what you think via the TalkBack function. If you find F-Script interesting, we'll publish a couple more articles in this series. Please enjoy! -- Derrick Story, managing editor
Thanks to Objective-C, Cocoa is built on a highly dynamic, reflexive, and open object model. Among other things, this makes it possible to build visual object graph editors like Interface Builder, runtime monitoring tools, object browsers, and numerous other programs making use of the capabilities of the Cocoa runtime.
In this article, I want to give you a taste of Cocoa scripting, and show you the level of integration you can expect. We will use F-Script, an open-source scripting language for Cocoa, to build a graphical application. Using F-Script, we'll directly program against the Application Kit, which is the Cocoa object framework for graphical user interfaces.
Note that one can build this kind of application using Interface Builder, but in this article, we will use the Application Kit programmatically, in order to illustrate Cocoa scripting.
Hey, another currency converter
Our application is a currency converter, similar to the one found in Apple tutorials (see: /Developer/Documentation/Cocoa/ObjCTutorial/CurrencyConverterTutorial.pdf).
Fig. 1. The currency converter we will build using F-Script and Cocoa.
You can obtain F-Script at fscript.org. In this article, we use F-Script 1.1 on Mac OS X.
F-Script is a pure object-oriented scripting language with Smalltalk-like syntax and concepts. You can interact with F-Script through the "fs" application, which gives you an interactive shell into which you can type instructions.
Some pointers on the F-Script syntax:
- Instructions are separated by "."
- ":=" denotes an assignment.
- Strings use simple quotes: 'A string'.
- Comments use double quotes: "A comment"
The currency converter script, version 1
The following script can be entered into the F-Script shell using a simple copy/paste. You can also enter the instructions step by step: You'll then see the currency converter interface appearing bit by bit. Of course, you can change the values of arguments used in the script or omit some instructions in order to see what happens. You can even interact with the objects after you have built the currency converter.
F-SCRIPT CURRENCY CONVERTER (version 1)
"Instantiate and configure a window" window := NSWindow alloc initWithContentRect:(125<>513 extent:400<>200) styleMask:NSTitledWindowMask + NSClosableWindowMask + NSMiniaturizableWindowMask + NSResizableWindowMask backing:NSBackingStoreBuffered defer:NO. "Put the window onscreen" window orderFront:nil. "Give a title to the window" window setTitle:'Currency Converter'. "Instantiate a form object" form := NSForm alloc initWithFrame:(60<>90 extent:320<>85). "Put the form into the window" window contentView addSubview:form. "Configure the form" form addEntry:'Exchange Rate per $1'. form addEntry:'Dollars to Convert'. form addEntry:'Amount in Other Currency'. form setAutosizesCells:YES. "Instantiate a decorative line and put it in the window" line := NSBox alloc initWithFrame:(15<>70 extent:370<>2). window contentView addSubview:line. "Instantiate a button, put it in the window and configure it" button := NSButton alloc initWithFrame:(250<>20 extent:90<>30). window contentView addSubview:button. button setBezelStyle:NSRoundedBezelStyle. button setTitle:'Convert'. "Instantiate the script that will compute the currency conversion" conversionScript := [(form cellAtIndex:2) setStringValue:(form cellAtIndex:0) floatValue * (form cellAtIndex:1) floatValue. form selectTextAtIndex:0]. "Make the script the target of the form" "The script will be evaluated when the user presses Return" form setTarget:conversionScript. form setAction:#value. "Make the script the target of the button" "The script will be evaluated when the user presses the button" button setTarget:conversionScript. button setAction:#value.
We note several interesting things straight away:
- We directly reference the Cocoa classes in the code:
NSButtonNSBox are Cocoa classes.
- We directly reference Cocoa constants: Constants such as
NSRoundedBezelStyleare symbolic names defined by Cocoa.
- We directly use the Cocoa API. Methods such as
setTitle:, and so on are part of the Cocoa frameworks.
- The syntax for sending messages to objects is similar to the Objective-C syntax, except that we don't use
]to mark the beginning and end of a message send. This similarity doesn't come as a surprise because Objective-C syntax for message sending is borrowed from Smalltalk.
- We can pass F-Script objects as arguments to Cocoa methods. Alternatively, we can get Cocoa objects from these calls and further use them from F-Script. As you may know, providing this kind of integration often requires the use of somewhat delicate bridging techniques. With F-Script, things are much simpler in this respect because there is nothing to bridge: The F-Script object model is the Cocoa object model.
The actual currency conversion is computed by an object created using the following instruction:
conversionScript := [(form cellAtIndex:2) setStringValue:(form cellAtIndex:0) floatValue * (form cellAtIndex:1) floatValue. form selectTextAtIndex:0].
] notation creates an object of class
Block which represents a block of code that can be executed later (
Block is an Objective-C class provided by the F-Script framework). In our block, we simply get the values of the fields in the user-interface objects, perform the computation (simply involves multiplication) and put the result in a UI element. Once it's done, we select the text in the first field of the form to mimic the Apple currency converter behavior.
Further on in the code, our block object becomes the target of the
button objects. Thus, it is evaluated when the user hits Return or clicks on the button.
Pages: 1, 2