8.6. Compiled Script Files as Script Objects
A script can read a compiled script file and
The mechanism depends upon three verbs. They're not part of AppleScript proper, but are implemented in a scripting addition (Chapter 3) that's standard on all machines.
Syntaxload script aliasOrFile DescriptionReturns the top-level script of the compiled script file or applet aliasOrFile as a script object. Exampleset myScript to load script alias "myDisk:myFile.scpt"
Syntaxrun script aliasOrFile [with parameters list ] Description
Tells the top-level script of the compiled script file, applet, or text file
aliasOrFile
to run (compiling first if necessary),
Examplerun script alias "myDisk:myFile.scpt"
Syntaxstore script scriptObject [in aliasOrFile [replacing yesno]] Description
Saves
scriptObject
to disk as a compiled script file or applet. Returns no value. If no further parameters are supplied,
Examplestore script sayHello in file "myDisk:myFile.scpt" replacing yes (On aliases and file specifiers and the differences between them, see Chapter 13. The verb run script , instead of a file, can take a string, and it then functions as a kind of second level of evaluation; see Chapter 19.) When you save a script object with store script , the lines delimiting the script object definition block (if any) are not included. This fact makes sense, since those lines were never part of the actual script object to begin with. So, for example:
script sayHello
display dialog "Hello"
end script
store script sayHello in file "myDisk:myFile.scpt" replacing yes
What is saved in myFile.scpt is the single line: display dialog "Hello" 8.6.1. Data Storage
Recall from earlier in this chapter that top-level script object entities are persistent, but that at the level of a file on disk, this persistence is unreliable, because it depends upon the environment where the script runs. For example, Entourage's Script menu doesn't save a compiled script file back to disk after execution, so top-level entities don't persist between executions. We can get around this uncertainty by storing needed data
Here's an example where we display the user's favorite
set thePath to (path to desktop as string) & "myPrefs.scpt"
script myPrefs
property favoriteColor : ""
end script
try
set myPrefs to load script file thePath
on error
set favoriteColor of myPrefs to text returned of ¬
(display dialog "Favorite Color:" default answer ¬
"" buttons {"OK"} default button "OK")
store script myPrefs in file thePath replacing yes
end try
display dialog "Your favorite color is " & favoriteColor of myPrefs
You might object that a file sitting on the user's desktop is a silly place to store our data. You're
set thePath to (path to me as string) & "Contents:Resources:myPrefs.scpt" Unfortunately, a script runner environment that doesn't implement persistence might not know about script bundles either. Perhaps a better place might be the user's Preferences folder: set thePath to (path to preferences as string) & "myPrefs.scpt"
If you
property favoriteColor : "" Don't worry! The decompiled version of the script, which is what you're seeing, shows the original bytecode, not the persistent data stored internally with the script. But the persistent data is there. (The only way I know of to get a look at the persistent data stored internally with a script is to use Script Debugger. Script Editor doesn't show it, and destroys it if you open and run the script directly.) 8.6.2. LibraryA compiled script file may be used to hold commonly needed routines. A running script can access the contents of the script file using load script . The script file's top-level entities, including its run handler, are then available to the running script that loads it. A compiled script file used in this way is called a library . For example, AppleScript has no native command to remove one item from a list (that is, to return a list without its n th item). Let's write one. Ooooh, we've already done it; see "LISP-likeness" in Chapter 4. Save that script (the AppleScript version, not the LISP version); for now, let's save it as library.scpt on the desktop. Here's how to use the library:
--
load the library...
set f to (path to desktop as string) & "library.scpt"
set lib to load script alias f
--
. . . and use it
set L to {"Mannie", "Moe", "Jack"}
set L2 to lib's remvix(2, L)
L2 --
{"Mannie", "Jack"}
What are the advantages and disadvantages of using a library ? An obvious advantage is that it makes code reusable and
A
With Script Debugger, a trick for working around this problem is to load any library files as part of your script property initialization:
--
load the library...
property f : (path to desktop as string) & "library.scpt"
property lib : load script alias f
--
. . . and use it
set L to {"Mannie", "Moe", "Jack"}
set L2 to lib's remvix(2, L)
L2 --
{"Mannie", "Jack"}
This works because, as explained earlier in this chapter, Script Debugger saves top-level entities into the compiled script file. So when you run this script and then save it as a compiled script file with Script Debugger, the property
lib
is saved in its
However, if you open this script with Script Editor, the script is ruined, because Script Editor
(Actually, Script Debugger helps you further in this situation as well. It lets you "flatten" a script so that it incorporates all library files on which it depends, and so has no load script dependencies.)
An interesting attempt to rationalize the library mechanism is the freeware utility Loader . The idea is to try to make it as easy to install and take advantage of libraries, even if they involve mutual dependencies, as in languages like Perl and Python. I haven't tried this
|