DekGenius.com
[ Team LiB ] Previous Section Next Section

12.4 Using Terms From

A terms block (as I call it) has the following structure:

using terms from application
        -- code
end using terms from

A terms block dictates what application's dictionary AppleScript should get the enclosed terminology from, without actually targeting that application. On the usual principle that the innermost block takes precedence, if multiple terms blocks are nested, only the innermost terms block containing a given line of code has any effect on that line. Similarly, a terms block overrides the dictionary-seeking function of an enclosing tell block. A terms block doesn't override an enclosed tell, but if an enclosed tell would not permit AppleScript to obtain a dictionary that it needs, a terms block may do so.

Thus, this will not compile:

tell application "Finder"
        using terms from application "Mailsmith"
                get name of folder 1 -- compile-time error
        end using terms from
end tell

The problem there is that AppleScript must seek folder in Mailsmith's dictionary, and doesn't find it. But this will compile:

using terms from application "Finder"
        tell application someVariable
                get name of folder 1
        end tell
end using terms from

AppleScript has no idea what someVariable will be at runtime, so it follows the instructions of the terms block and thus is able at compile time to obtain a dictionary that resolves the enclosed terminology. This, however, does not guarantee that the code will run. Perhaps someVariable will specify an application that knows what a folder is; perhaps not. Basically you're telling AppleScript to suspend judgment and just believe that the Finder's notion of a folder will work here. You could be lying. For example, this will compile, but it won't run:

tell application "Finder"
        using terms from application "Mailsmith"
                get mailbox 1
        end using terms from
end tell

It will compile because the terms block adduces Mailsmith to make the notion mailbox meaningful; but it won't run, because the Finder is the target, and when told to get a mailbox the Finder has no idea what this means.

The chief use of a terms block is to allow compilation of a script targeting a remote application. We have seen that AppleScript must be able to resolve all terminology at compile time, and that normally it attempts to do this by using the dictionary of the targeted application. When an application is on another computer, this might not be possible at the time the script is compiled: the remote machine might be unavailable, the remote application might not be running, or the script might specify the target machine dynamically. A terms block lets you get past these hurdles by specifying a local source for the terminology you're using.

In this example, I'll talk to my iBook in the next room using Rendezvous, having first turned on Remote Apple Events on the iBook in the Sharing preferences panel:

set whatMachine to text returned of ¬
        (display dialog "Machine to connect to:" default answer "eppc://")
--  I enter: eppc://little-white-duck.local 
tell application "Finder" of machine whatMachine
        using terms from application "Finder"
                get name of disk 1 -- "OmniumGatherum"
        end using terms from
end tell

That script works equally well whether the tell block encloses the terms block or vice versa. (For more examples, see Section 21.1.4.)

In this next example, we demonstrate how the target can be treated as a variable thanks to a terms block. There is no tell anywhere in this script, and the script has to determine the target entirely at runtime using a reference to the application, which is passed as a parameter. The main hurdle is getting the script to compile, since AppleScript must be able to resolve all terminology at compile time; we get over that hurdle with terms blocks:

global doThis
on getMailbox(whatApp)
        using terms from application "Mailsmith"
                get name of mailbox 1 of whatApp
        end using terms from
end getMailbox
on getFolder(whatApp)
        using terms from application "Finder"
                get name of folder 1 of whatApp
        end using terms from
end getFolder
on getTheRightThing(whatApp)
        if whatApp is application "Finder" then
                set doThis to getFolder
        else if whatApp is application "Mailsmith" then
                set doThis to getMailbox
        end if
        tell whatApp to my doThis(whatApp)
end getTheRightThing
getTheRightThing(application "Mailsmith") -- (drafts)
getTheRightThing(application "Finder") -- "Mannie"

If you tell AppleScript to look for a dictionary in an application that is a web URL, AppleScript won't actually look there, but will assume that this application is a SOAP or XML-RPC server. We can use this as a trick to treat the target as a variable when doing a SOAP call over the Internet. This example, based on a script distributed by Apple, shows how to write a general SOAP-calling handler. The handler, generalSOAP( ), contains no hardcoded information at all, except the application URL named in the terms block; this URL is a complete fake, and is intended only to satisfy the compiler that it's okay to use the call soap command. The actual parameters supplied in the last line fetch the current Apple stock price over the Internet:

on generalSOAP(u, m, s, a, p)
        using terms from application "http://www.apple.com/placebo"
                tell application u
                        call soap ¬
                                {method name:m, ¬
                                 method namespace uri:s, ¬
                                 parameters:p, ¬
                                 SOAPAction:a}
                end tell
        end using terms from
end generalSOAP
generalSOAP("http://services.xmethods.net:80/soap", ¬
        "getQuote", "urn:xmethods-delayed-quotes", ¬
        "", {Symbol:"AAPL"}) -- 18.8

See also Section 21.1.5.

    [ Team LiB ] Previous Section Next Section