REALbasic University Resources:

RBU: Glossary Defines common REALbasic programming terms
  Archives Previously published columns
Translations: Dutch Courtesy of Floris van Sandwijk
  Japanese Courtesy of Kazuo Ishizuka
  Chinese Courtesy of Dong Li
  RBU Translation Guide Information on Translating RBU into other languages
Books: Matt's Book (2nd Edition!) Ideal for experienced programmers
  Erick's Book Best for beginning programmers
Websites: Mother Ship The publisher of REALbasic
  RB Webring Links to hundreds of REALbasic websites
  RESExcellence Another REALbasic programming column
  REALbasic Developer Magazine The premiere source for REALbasic instruction.

REALbasic University is Sponsored by

Make your Mac do what YOU want it to. Create games, utilities, cool Mac OS X tricks. Download REALbasic now and create your own software.


Print This Article

REALbasic University: Column 073

DoRbScript: Part III

Last time I outlined the steps we'd take to create DoRbScript, an AppleScriptable program for remotely running RbScripts. The steps were:

  1. Create the AppleScript "dictionary" for our app
  2. Create the app and handle the Apple Events sent to it
  3. Create an AppleScript to test the program

We did the first one last time, so today we'll do the second.

Creating the DoRbScript Application

First, start a new REALbasic project. From the tool palette drag on an RBScript icon onto Window1.

Next, add a new class (File, "New Class") and call it app. Give it a super of "application". You must do this because only the application class receives Apple Events: without an application class your program won't notice any Apple Event messages sent to it.

Now let's add a couple properties to our app object (open app and choose "New Property" from the Edit menu). Add:

  
error as integer
theResult as string

We'll use these to store information about the running script (i.e. an error message or whatever the result was).

Now let's open up RBScript1 and you'll see it contains several events. These are things that happen while your script is running. The first is CompilerError. Since it's possible the script passed might contain an error, we want to report that error. So let's save that error info like this:

  
app.theResult = errorMsg
app.error = errorNumber

You'll notice we're storing these inside the properties we added to the app object (that's why we preceed them with "app." so that RB knows where the properties are located).

Next, we have the print event. The code for it looks like this:

 app.theResult = msg 

To get data out of your RBScript, you use the "print" command. Whatever is "printed" shows up in the msg property sent to this event. All this does is store the result in our string property.

Finally, go to the RuntimeError event and put in this:

 app.error = 0 

This is just an arbitrary error number I made up. For the purposes of our program, a -1 means no error, a 0 means a runtime error, and any positive number would be the error code reported in RB's online help (under RBScript).

Now that we've done that, we're almost done. We next have to add the code to handle the Apple Event sent. We do this inside the app object, inside the HandleAppleEvent event:

  
if not (eventClass = "misc" and eventID = "dorb") then
error = -1
window1.rbScript1.source = event.StringParam("----")
window1.rbScript1.run

while window1.rbScript1.state = 1
wend

event.replyInteger = error
event.replyString = theResult
return true // handled
end if

return false // not handled

Wow! What's all that gibberish, you ask? Fear not: it's not that bad.

The first thing we do is check to see what Apple Event was sent: we only want to handle one particular kind of event. All Apple Events pass two four-character codes, a class and an ID. There are a number of standard events but ours will be a custom one. It is class "misc" (miscellaneous) and the ID is "dorb" (for "do RB Script"). (You'll notice these match the ones we used in the aete resource we created last time.) So the first line checks to see if that is the event received: if it is, we handle it. If not, we don't.

To handle the Apple Event, we do a few simple things. First, we initialize our error property to -1 (remember, we decided that -1 means "no error").

Next we extract the script from the passed Apple Event and assign it to the source property of rbScript1. That sounds more difficult than it is: the event object is our Apple Event and its stringParam property is what contains the code of our RB Script. For now, just ignore the "----" parameter -- it basically just means we're not asking for any particular kind of string. Think of it as the default response.

Once the source code of the RB Script is stored in the source property, we tell rbScript1 to run.

While the script runs, we put ourselves in a loop to wait for it to finish. The .state = 1 line means that the script is running. When the script finishes or if there's an error, the state will return a different value and the loop will be exited.

Once the script has finished running, we store the results back in the event object. The event object has special properties for our return purposes. We use the replyInteger and replyString to store the error code and the result text respectively.

Finally, all that's left is to return true meaning that we've handled the Apple Event. Our results are automatically returned to the program that sent the Apple Event (in this case, an AppleScript).

That's it for today. If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.

Next Week

We write an AppleScript to test DoRbScript.

Letters

Today's email is from Steen, and concerns parsing text.

Hello Marc!

I have a simple questions, I hope.

I made a small applescript where I write or paste some text into a editfield1. I then do a search inside the text with regex. If word is found then the whole line of the text will be placed in editfield2, and the found word is placed in edifield3.

So my questions would be: How do I let Realbasic read line by line, grab the line if a 'word' is found put it in a editfield and place the found word in another editfield?

Please mail me the answer and of course you can put my letter on the web or magazine. I think this will be helpful for others too.

I'm looking forward to the REALbasic Developer Magazine.

Regards

Steen

Hi Steen!

There really are two parts to your question. First, you're wanting to parse some text line by line. Then you're wanting to parse some text word by word.

Both of these functions are relatively easy in REALbasic with the nthField function. nthField is a great parsing command as it returns the "nth" field of whatever text we're parsing, using whatever we pass as the delimiter.

The parameters for the command are:

nthField(sourcetext, delimiter, fieldnumber)

The result is a string. If the field number you are requesting doesn't exist, an empty string is returned.

In our case, we want to parse some text by lines. Lines are separated by carriage returns, so we can search for chr(13). The command:

  
editField2.text = nthField(editField1.text, chr(13), 3)

would put the third line of editField1 into editField2.

If we then wanted to grab indivdiual words out of that line, we could use this:

  
editField3.text = nthField(editField2.text, " ", 3)

This would put the third word of editField2 into editField3. In this case, we're searching editField2 (which has a single line of text, not editField1 which has the whole thing), and we're looking for fields separated by spaces.

Here's where things could get a little tricky. In general, in English, words are separated by spaces. But there are situations where that's not always the case. For instance, do hyphenated words count as seperate words or one word? Do URLs, which can contain periods (but not spaces), count as a single word? The bottom line is that it's up to you to be as selective as you want with regards to what you consider words. You mention RegEx (short for Regular Expression), which is an advanced kind of text pattern matching that REALbasic supports. You could use that to do a more precise kind of word selection, though it's probably not necessary. For our example, we'll just use spaces as the divider between words, which works for 99% of cases.

Here's a little demo that does just what I've described. The text is in the first field (I used text from this tutorial for the sample), the second holds the line, and the third holds the word. Popup menus let you select the line and word you want displayed in the third field. Here's what it looks like running:

If you want the project file, can download it here.

I hope this answers your question.


About the Column
REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers.

Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.)

About the Author
is an author, philosopher, graphic designer, photographer, film director, soccer fanatic, and programmer (among other things). He writes for MacOpinion, runs his own software company, Stone Table Software, which sells the revolutionary Z-Write word processor, and is Publisher and Editor of REALbasic Developer. He lives in Northern California with his cats, Mischief and Mayhem, and is rapidly running out of free time.

See the REALbasic University Archives


REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.

.

.