Mac OS • 1:02:31
With AppleScript, Mac OS X continues to provide the market-leading advantages of system-wide scripting. Learn how easy it is to establish a loyal customer base by providing unique, custom solutions with the adoption of AppleScript within your product.
Speaker: Chris Espinosa
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Good afternoon, everybody. I'm Chris Espinosa. I head the Components and Scripting group at Apple. If you've been to a few developers' conferences and the AppleScript sessions, I should be dullingly familiar by now. I'm going to be with you the rest of the afternoon. I'm standing between you and Memorial Day weekend, so I'm going to make it crisp. I'm going to try to make it clear, and I'm going to make it entirely Mac OS X focused.
What we're here to talk about today is the yearly update on the status of AppleScript, primarily focused on Mac OS X and the key changes in Mac OS X that affect you as scripters and affect you as developers. The first session is going to be mostly for scripters and developers. The second session will be exclusively for people writing software for Mac OS X.
So if you are a scripter, you can go play some pinball during the second session, and then we'll see you at the feedback forum immediately following. I am going to talk in the first session about things we are going to change in the future, things we know about in AppleScript 1.6, things we know about in Mac OS X that we're going to be addressing, but I'll be dealing with that only briefly.
There's not a lot of forward-looking promises in this session. It's going to be focused primarily on shipping apps and getting your scripts running on Mac OS X. What you'll learn is the new features of AppleScript 1.6 in Mac OS 9 and Mac OS X that you can take advantage of, what to do about your scripts and scripting additions, how to move them across, where to put them, things like that, and how to plan for changes that we expect in future versions.
But first, I want to thank all the developers who shipped scriptable applications this year. I couldn't fit it all on one screen. There are a lot of people that did updates to their applications. They shipped Mac OS X versions. They shipped new code, and I really, really appreciate your getting behind the platform and keeping your scriptable applications alive and fresh for Mac OS X.
And as usual, we had some version interesting things this year. Notice that we didn't do a .0.1 release. I consider that a personal triumph, is that most of the stuff we shipped was good the first time around. Chris Espinosa We shipped AppleScript 1.5 in the customer beta for Mac OS X. We shipped AppleScript 1.5.5 in the Mac OS 9.1 release, and it was a version of the Mac OS X version backported to Mac OS 9, and it had a few problems.
Chris Espinosa And when we came out with Mac OS X, we shipped 1.6 on Mac OS X, and then shortly thereafter as a software update for Mac OS 9. Chris Espinosa I highly recommend that you run AppleScript 1.5 in the customer beta for Mac OS X. Chris Espinosa If you have Mac OS 9.1, it's really the right version to be running. One of the most common problems that we've seen on the AppleScript lists is people saying, Chris Espinosa Oh, I run my scripts and my scripting additions aren't there, and I get all these Chevron syntax things in my scripts.
Chris Espinosa And the common thing is people have turned off their security extensions. One of the things that we did in 1.5.6, Chris Espinosa was allow the mount volume command to use the keychain, and in order to do that, we created a dependency on the security system extensions.
Chris Espinosa A lot of people turned those off. That turned off all of scripting additions, and we fixed that in 1.6. Chris Espinosa So if you're having problems that your scripts don't run or your scripting additions aren't recognized in Mac OS 9.1, upgrade to AppleScript 1.6, and that'll fix it.
Here are some of the new features that we introduced in 1.5, 1.5.5, and 1.6, basically since the last time we were here last year. For developers, one of the things I'm going to be covering is that we introduced into Carbon, into CarbonLib on Mac OS 9 and into the Carbon framework in Mac OS X, the AE Gizmos functionality that Jens Alfke wrote a low so many years ago and all of you have been using as a link library for many years. We actually built that into the operating system in 1.5. Scripters won't notice. It will have no effect on scripters, but it will help developers get their software to Mac OS X. We added a fix for the double as problem. I'll be going into that.
If you are frustrated with the finder, Andy Pachorski is happy. If you are frustrated with the problem that when you ask an application to get something as something else and you get an error can't coerce, we have a fix for you. It requires developers to modify their applications, but it allows them to do the right thing.
We are fully supporting Unicode text as a first class data type in Apple script. I'll be doing a demo of that. That's mainly important when you're using the Mac OS X finder, either for Mac OS X or from scripts running in the classic environment where the Mac OS X finder is the only finder around.
Mac OS X finder returns its file names as Unicode text, and if your scripts were expecting standard strings and were doing operations such as concatenation or text extraction on them, it would have failed in 1.5 and 1.5.5. Now it works in 1.6 because we have fully first class Unicode text support.
We added support for packaged apps and packaged scripting editions for Mac OS X, support for script files that don't have type in creators and have all of their script code in the data fork, and that's a fix. We have a Mac OS X convention so that you can actually send a script across the internet as a single file without having to bin hex it or compress it or do anything like that. It'll actually work when you get it to the other end. And we have a different methodology for dispatching events to scripting editions on Mac OS X. I'll talk a little bit about that.
We also fixed some bugs. Some of these you didn't know about. Some of these you've relied on and now you have to change. I don't think you relied on middle item of an empty list crashing. It's a convenient way to crash your machine if you need to, but we fixed that.
Chris Espinosa Item zero of a list used to not fail. It returned silently. Now it does fail, and so that should help you catch some bugs in your scripts where you're actually trying to get item zero of a list. Now it will actually fail, which is the correct behavior. The Info4 scripting edition couldn't handle files greater than two gigabytes in size. Now it can, files and folders. The text-to-Unicode text coercion assumed that the incoming text was Mac.
Now it looks at what your system script is, so if you're running a non-English system, the Unicode coercion will happen correctly. In random numbers, if you had similar large seed values, such as the current time as seconds, they would produce similar initial random numbers and then be random after that.
That disturbed some people because they wanted all the random numbers to be random rather than just the second through nth. So we fixed that. There's a very interesting problem where, I guess that's, I'm going to cast off commas here, one, two, three, four, five, 536,870,911 plus one equal negative 536,870,921, which is not the correct answer. We fixed that.
And Mount Volume didn't look at keychain, which some considered a bug. We considered it a new feature addition. We added that. In 1.6, which is what you get in Mac OS X and what you get when you do the software update to Mac OS 9.1, we fixed some read-write commands that we broke in 1.5.5. We just out-and-out checked in the wrong code, and we just had to fix it.
A problem that had been creeping around for quite a long time was manifesting itself different in different operating systems. It was that if you were displaying the contents of a string and there was a null character, an ASCII zero in there, it would display differently on different systems at different times. Sometimes it would just be blank. Sometimes it would be a backslash. Sometimes it would be a large number of garbage characters. We fixed it so that it now displays as an ASCII null character.
You can actually copy and paste and reinterpret. We believe that that's the correct behavior now. You will see it. It will look like an empty string in most fonts because most fonts don't have a glyph for the ASCII zero character. But it's actually a string with one character in there, which is an ASCII zero. If you copy and paste it, the right thing will happen.
[Transcript missing]
There are some bugs we know about in 1.6. These are things we've found since the introduction of 1.6 that we will be fixing in subsequent versions. The Info4 scripting edition fails if you target it at a Unix or an NFS file system. Don't try it. We'll be fixing it. The low-level Unicode text-to-text coercion is broken, so that if you get type Unicode text as an application developer and you try to use the low-level coercion, the Apple Event Manager coercion to coerce it to a type char, that will fail.
If you try to coerce it to a type styled text, that will succeed, and the type styled text is a record, one element of which is the type char. So that's your workaround. You coerce it to type styled text, coerce that to a record, get the first item of that record, which is the character element, and then that will be your plain text. And we'll be fixing that.
The mount volume command broke on third-party user authentication modules, and that includes Unix file servers and Windows 2000 AFP servers. We're still not sure why it did. We think it's something that happened in the Apple Share client itself, because we didn't change any of the mount volume code in this area.
We're trying to get to the bottom of that, but in the next version... We will make sure that Mountain Volume works on all major AFP platforms. The read as list using delimiters is broken. So even though we fixed the read-write OSACs, there are still a couple of little bugs hanging around. Read as list using delimiters is one of them.
And sometimes if you... Send a first event to an application from a script without launching it first. The first event will time out, but subsequent events, if you rerun the script, it'll work. We think that that's a subtle timing problem in the Apple Event Manager or something that we're doing wrong with noticing whether the application is up or not. We're going to address that in a future version.
Here are some new features, and these are primarily for developers. The AE Helpers, the support for the double-As problem, and the Unicode class support. I'm going to go over each of these. AE Helpers was born as AE Gizmos. It's a quick and easier way to deal with building Apple event descriptor records. Jens Alfke from the original AppleScript team wrote this support library in, I believe it was something like 1993 or 1994.
Shipped it as object code. People have been linking that with their systems and shipping that. That object code doesn't link, doesn't build anymore. You can't use it on Carbon systems. And developers have wanted another link library or access to the source code or something like that. We decided just to build that functionality into Carbon, into CarbonLib for Mac OS 9 and into the Carbon framework for Mac OS X.
What do these do? AE Build and Print are a very easy way to go between a textual description of your Apple event and the Apple event itself. Rather than going through, because an Apple event, as you know, can be a deeply nested structure with descriptors inside descriptors inside descriptors.
Rather than going through and building a descriptor, adding it to another descriptor, throwing away the original, coercing it to another descriptor, throwing away the other one, adding that to another descriptor, throwing it away, each time doing a relatively heavyweight handle-based memory event. What AE Build does is it takes a textual representation of your event, does substitution, like in a printf statement, of your actual variables for placeholders inside the text event, and then builds the whole descriptor or event in one shot, in one operation.
It's much faster, it's much lighter weight, it doesn't create nearly as many intermediate copies of things, just gets the job done much faster. AE Print is sort of the converse operation. It takes a descriptor record, which could be all the way up to an Apple event, and then spools it out in a reinterpretable text form to make an Apple event readable. This is very useful in debugging, and I'm going to show some examples of that. The principal routines are AE Build Desk, which builds a descriptor.
AE Parameters, which adds something to an already existing descriptor. Or AE Build Apple Event, which takes the appropriate parameters and builds an Apple event all in one. It's like AE Create Apple Event, but it lets you specify everything you need in one statement. And then the converse event is the AE Print functionality.
AE Print Desk to Handle takes a descriptor, a list, a record, an Apple event, and it prints it in raw text to a handle, which then you can print out or dump in a debug window or something like that. This text representation has a syntax all its own, and so far the only documentation for it is Jens' original documentation, which is back in the circa 1993 SDKs. We're working on updating that, but for now if you can find an old copy of that SDK and you can get the original documentation, that works.
We've only made a couple of changes. Jens' original implementation relied on high ASCII characters, curly quotes and chevrons, to encase strings and hexadecimal strings. And we've added some straight ASCII alternatives in case you happen to be working in an ASCII preferential development environment. The hex delimiters are dollar signs, you know, dollar signs at the beginning and the end.
And then we've added some straight ASCII alternatives in case you happen to be working in an ASCII preferential development environment. The hex delimiters are dollar signs, you know, dollar signs at the beginning and the end. And then we've added some straight ASCII alternatives in case you happen to be working in an ASCII preferential development environment. The hex delimiters are dollar signs, you know, dollar signs at the beginning and the end.
And the quote characters are straight single quotes, which you then have to escape, but you're grownups, you can do that. So the language has constants, it has a special interpretation for four character codes, because most events and descriptors are built out of four character codes. You can usually do four character codes just by typing the four characters. If there's high ASCII or something special in there, then you enclose them in here. You can use them in single quotes.
The language will do coercions in place. If you say four character code, paren, and then some value, it'll apply that coercion before it puts it in the event. And so you can do pretty much coercions in line in this text descriptor. I'll show you a little example of that. You can describe lists and records in the text format. And at the bottom you see the substitution language. An at sign substitutes an AEDESC.
AEDESC parameter, right in that position. A double at, a cast, that is a type and then an at sign in parentheses, takes a special structure which you have to build a struct for, which is a long of the length and then a pointer to the actual data. So you can put arbitrary data in as long as you create this struct which has the long and the pointer to it, the length and the pointer to it.
And then if you have a handle, when we can find the length of a handle, because, well, it's a handle. You just put in two at signs and then the value of that handle will be put in at that point in the event. So here's a basic usage. This is how you build a descriptor that says every line, the equivalent of every line of document, quote, name, end quote.
It would be that in Apple script. AE build desk first takes the destination desk, a pointer to that, a pointer to a build error structure which is really useful for debugging. This is something that we've added in the Carbon version. If there's an error, we tell you what the error is and what line of your text it occurred on, which is very helpful for debugging the syntax of this string. And then you pass it the string and then a variable list of parameters. And the string we're passing is first single quote OBJ single quote, which means we're going to build an object specifier.
And then parens, which means we're going to coerce into an object specifier from something else. And then the parens are braces, which means, oh, we're going to coerce into an object specifier from a record. Okay. Well, that makes sense. If you're building an object specifier in straight Apple event calls, that's what you do. You build a record and then you coerce it to an object specifier. Here instead of making three calls, we did it in seven characters, which is really nice.
And then we have our four fields of our record, the want, the from, the form, and the SELD. And the want is a CLIN coerced to a type type. That's nice. And the form is an INDX coerced to an enum. That's exactly what you want. And the SELD is a type form absolute position of ALL space. And because there's space in there, we have to put that in single quotes. And then notice the from parameter. The from is another object specifier. And see? We're building an object specifier inside an object specifier in one system call. That's what makes it fast.
And the from is another object specifier built pretty much the same way. A coercion of a record of a want, a from, a form, and an SELD. And the SELD is a TEXT with an at sign. And the at sign is our substitution. That means since this is the first at sign that's encountered in the text, substitute in the first following parameter in the call. And way down at the bottom of the screen, the first parameter is doc name.
So what it will do is it will take doc name as a pointer to text. And it will create a text AEDESC or text descriptor for the SELD. So here, if you want to build an object specifier with the value in it, with a nested object specifier, you can do it in one call.
Similarly, you can build whole Apple events that way. AE Build Apple Event looks a whole lot like AE Create Apple Event, except it takes, instead of giving you pretty much an empty Apple event, you then have to fill in, here's the direct parameter, and here are the optional parameters, and here are my other attributes.
You give it the event class and the event code. You give it the information, the target information, the type and a pointer to what it is and the size of that, the flags of what, the return flag and the transaction flag, and then you pass it a string. And this string says basically, our direct parameter, the quote dash dash dash end quote, is an alias.
And I'm going to show you how to do that. And I'm going to substitute in a handle, because the double ats, and that means the first parameter following the string had better be an alias handle, and in that case it is. And what this will do is it will build an Apple event with the direct parameter with an alias handle in that, and in one call.
And that saves you two additional calls and a dispose of a transitory descriptor. And this will make, if you're creating Apple events to send to yourself, using AE Build is going to be a lot easier. going to really speed things up. Let me show you the first demo on demo one, if we can get that up on both screens.
I have here our venerable simple text project. And let me go to... Where SimpleText has an event to send an open Apple event. I'm not exactly sure what they use it for, but I found it in here, so I decided to demo it. And they do a lot of things.
They null out all of the descriptors they build. Then they have to get current process and then create a descriptor and then create an Apple event and then put the parameter in as the direct object. And then they have to dispose of it later. And it gets to be a lot of work. Well, what we can do is we've got a replacement that uses AE helpers here. And we can just find all of this.
And notice what we do here in our replacement is we call AE build Apple event with the direct parameter and a single at sign and then the list that we've already got of things to open. So we save a couple of descriptors, we save having to dispose them, we save building an extra handle. It just makes it a lot easier to do that. It makes that much easier to implement.
There's another big package in A.E. Helpers called the A.E. Streams Package. And the Streams Package is a lot of calls for building a deep A.E. descriptor incrementally, little by little. And it basically works in an open, write, close kind of protocol. And if you're being nested, you open, write, open, write, open, write, write, write, close, close, close. There are a bunch of calls, basically open, write, and close for each kind of thing. in your writing.
And if you want to use them, basically this is what the code looks like. You open, you write, you write, you open a sub-record, you write, you write, you write, you write, you write, you close, you write some more, you write some more, you close, you close, and you're done. And this is more efficient than having to get all of the things that you need collected together at one time, and then creating a desk, and then putting that desk into another desk, and then putting that desk into another desk.
This saves copies, especially if you have a streaming model in the first place, and if you don't want to make multiple copies of large chunks of information, this allows you to stream into a descriptor without having to make multiple copies of large amount of information. It's a little more complex.
It'll be used in more rare circumstances. We actually use a lot of this inside AppleScript, but now it's available to you in the internet. It's called the AE Helpers package. So let me tell you what this means to you. For developers, for scripters, it doesn't mean anything. Hopefully it will mean that the applications that you're scripting will work a little better.
To developers, it means that if you've got code that relies on AE Gizmos, you can port it to Mac OS X or to Carbon applications on Mac OS 9 without having to carry on that old link library. And with the AE Print facility that I'm going to show you more of a little later, it helps you debug because you can actually see it. You can see what's going on inside your descriptors in a printf function.
So let's move on to the next one, support for the double as problem. How many of you have run into this in real life when you ask an application from a script to give you some value as some other type, and it gives you a list of things of that value and then complains that it can't coerce that list into what you asked for? Fair number have run into that.
That's because the as term is used in two ways in AppleScript. One, it's a binary coercion operator. Take this and coerce it to that type. And second, it's used as a parameter to events. And when it's used as a parameter to events, AppleScript isn't really smart enough to say, oh, I'm going to use this.
The application must have handled that, so I'm not going to do an additional coercion. It tries to be too helpful. It knows that you want, for example, the files as file specifications or as aliases. So it takes the result and it tries to coerce it to what you ask for, even if the result is a list.
Chris Espinosa And so you get one of two things. One is you either get a coercion error or you get a bad coercion. For example, if you ask for things as strings, it's going to take this list, and if the list can be coerced to a string, it'll do it. Chris Espinosa Which isn't nice if you were asking for the file names of every file and you get one string with all the file names concatenated together.
So this is primarily troublesome for plural key forms or whose clauses, which are really the most useful things, because whose clauses let the application do the work without you having to iterate. In order to work around this, you have to iterate, you have to send more events. It's much slower, and it forces scripters to write unnecessarily slow loops.
So we've got a solution, and the solution is, in your applications, if you handled the as parameter, all you have to do is to put an optional parameter in the reply of the getData event saying, I handled the as parameter. And AppleScript will look at that and say, hey, somebody handled the as parameter, and it won't try to do the coercion again. It's actually very straightforward. And it's compatible, so that if your application doesn't supply it, AppleScript will do it the old way.
Scripts that didn't work will continue not to work, and scripts that did use the workaround will continue to work. So that if you do this, let your scripters know that you do this, so that they won't have to use the workarounds anymore. So let me show you how it works. Once again, we're in our simple text application. Oh no, we're not in our simple text application, because we have a different application for this.
To demo this, we're using Quinn's vulnerable Moro SL. And more OSL is a lovely framework for building very scriptable applications. And one of the things, and let's just show an example of more OSL and run the application. And here's a script. It makes three new windows, and it gets the name of every window as string, right? Well, this is a classic double as case. Or let's say, I think that'll work.
So this makes three new windows, window A, window B, window C, and it returns the name of every window as Unicode text. But what happened is that MoroSL gave me the name of every window as a list of three Unicode text items, and then AppleScript said, oh, it wants that list as Unicode text. So it concatenated them all into one Unicode text string. So when my application has four windows named CBA and Untitled One. What I get is a single string that says CBA Untitled One. That's not very helpful.
[Transcript missing]
And what we do is right here, if this is a get data event, and if it has an as parameter, we took care of it. And so what we do is we basically put the IDAS, the I did as parameter, as true into the reply. Okay.
And that's basically all we do. Let's quit the application and rebuild it. And run it again. And this time when we run the script. You see our result is a list of four Unicode text strings, which is pretty much what we wanted. We wanted it as four Unicode text. So thank you, Quinn, for providing a great framework.
So it's really simple. If your application handled the as, all you do is put IDAS true in the reply, and there you go. And we have the slides back. What this means to you is you can choose, if you did the coercion, to let AppleScript know that you did it or not.
What this means to scripters is that applications should improve and you should be able to use fewer workarounds, fewer loops, and use more applications' native capabilities. Okay? Now, I got some Unicode text there, and you saw that the Unicode text all got concatenated together as a string. Well, that's something that didn't happen prior to AppleScript 1.6.
Unicode class support is something that we added in 1.6 primarily to handle what's going on with the finder. The finder 10 now returns all file names as Unicode text. AppleScript 1.4.3 could take these, and it could send them to other applications, but it displayed them as data, Chevron, UTXT, and then a bunch of hexadecimal. It was better than nothing, but it wasn't great. 1.5 and 1.5.5 added some Unicode text support, but it was broken into two. It was broken into two in some places, and it didn't have any of the concatenation operations.
It didn't have the substring operations. It didn't do anything that you wanted it to do. When we realized that if you were running Mac OS 9 scripts on Mac OS X, and the only finder around was the Mac OS X finder, and the Mac OS X finder always returned Unicode file names, and your scripts wanted to take file names and concatenate them and piece them apart and do all these things with them, those scripts. Those scripts would break unless we could do full Unicode text. So we moved that to high priority, and we implemented it in 1.6, both for 9 and for 10.
So Unicode strings for the scripter have character, word, paragraph, and text item elements, just like strings. They have a length property, just like strings. They have coercions to lists, records, strings, style text, and number. They have the concatenation operator. They have a number of comparison operators. Their comparisons obey the considerations, but they actually obey the considerations according to Unicode comparison rules, not the styled text comparison rules. So less than, greater than may be interpreted differently for Unicode text than you would expect it to be for style text, especially when it comes to things like case. And they support all of the key forms, absolute position, the first, last, middle, sum, every, and range.
Characters 1 through negative 2 of Unicode text. Some character of Unicode text. We'll pick one out of the middle. Chris Nebel always wants to do some integerization. and have that generate a random number, but that's a different item. So if we could have the Demo 1 machine up again. Quit this fine application. So here's a script that scripts the finder to get a name.
We'll get the class of the file name. That's not what I wanted. I wanted the class. The class of the file name is Unicode text. I can get the individual characters of the file name. This is a hack here because for some reason the finder is returning an extra garbage Unicode character at the end of a Japanese file name that it doesn't return at the end of a non-Japanese file name. So there's a hack here. We haven't figured out what's going on.
But if This is an English system. It's set to English language, but if I get the characters of the file name, I get them in Japanese in the script editor. I can say character 1 of the file name and... I'm going a little off-road here because I didn't practice this. And I get the concatenation of the Japanese character and the English character. So concatenation works. As you saw before, range works. If I say file one, and I say every word...
[Transcript missing]
Scripting editions are the first ones. There are some new features in Mac OS X that are actually really great. They're going to be hard to get used to, but they're really great. The scripting editions folders follow the locales model that Mac OS X introduced. What that means is that there isn't just a single system folder. There's no unity between you, your operating system, and your machine anymore. It used to be, when I was a young lad and we invented personal computers, that if you had a machine, the machine and your environment and the operating system software were all the same thing.
That's why it's so important to have a system that's as good as a machine. That's why there's one system folder on Mac OS 9. But that doesn't work for shared machines, and that doesn't work for machines in network environments, and that doesn't work for machines that you want to keep running reliably for long periods of time without screwing around with the system software.
So Mac OS X separates those. There is a system folder for the machine, there's a system folder for the operating system, and there's a system folder for each individual user. And when you log in as that user, you get your own special system extensions and editions. And we followed this model in that there are at least three scripting editions folders on every Mac OS X system, sometimes five. The three are systems, libraries, scripting editions, which is the one the operating system provides, and that's the one pre-populated with Apple editions, and that's where the standard editions are.
And we followed this model in that there are systems, libraries, scripting editions, which is common to that machine and which is changeable. If you're an administrator, you can put new scripting editions in there, and they will be available by all users on that machine without having to change what's in your scripting editions folder in your operating system. So that if you really want to get back to a clean default machine, just throw out slash library slash scripting editions, and the OS will be the way it was shipped.
You don't have to hunt through, you know, was this a system one? Or was this something I added? And then if you've got multiple users on the machine, every user has their own in their user folder, in their libraries folder, in their user folder, they can have a scripting editions folder. And if they populate that with scripting editions, those will be available just to that user, but they won't be available to other users.
So if you've got a machine that you want to use as a graphics processing workstation sometimes or as a database machine some other times, and they have different scripts. And they might conflict. You can have some in one and some in another and just log in as a different user and you get a different set and you can keep conflicting ones apart. It's actually a very useful structure.
The code model for writing scripting editions, if you're a developer, is different, and this is a little problematic. On Mac OS X, all code must be Carbon. On Mac OS 9, system code and scripting editions are system code because they can be invoked by any application, cannot be Carbon. And so that means it's technically impossible to write a scripting edition that will work on both 9 and 10.
And so don't even try it. It's just not worth it. If you want to ship Mac OS X scripting editions, you have to take your Mac OS 9 scripting edition, carbonize it, package it for Mac OS X, and ship it for Mac OS X. And they'll be separate. Scripting editions for Mac OS X can be either the CFM model that you build with CodeWarrior, or they can be the Mach-O model that you build with Project Builder.
And they can be flat, single file, or they can be packaged. In bundles, if you went to the application packaging and extensions, they're actually bundles, not packages, because packages are applications, but that's a different thing I don't quite understand yet. They're packages. They're not bundles. They are packages. Okay. They are bundles that are packages.
But theoretically, you could build a package that had both the classic and the Mac OS X deliverable in it, but that would be kind of useless. It would be helpful for you to upload and download just one copy, but the user would have to put it both in their Mac OS X scripting editions folder and in their Mac OS 9 scripting editions folder. And so you'd have a copy of a useless scripting edition in each of the folders.
You'd have four copies of the code. When you only really need to have two, it's just not worth it. So we don't recommend that. If you have old scripting editions, you want to migrate to 10. Migrate them to Carbon and ship them as Mac OS X only is the right way to do it.
Access to scripting editions is really interesting. I tried to go through this last year and I think I confused more people, including myself, than I got clear. Mac OS 9 and Classic really behave as always. Classic applications will only have access to classic scripting editions. Mac OS X scripts will have access to the Mac OS X scripting editions in all of the Mac OS X scripting editions folders.
And they can get at Mac OS 9 scripting editions by targeting a Mac OS 9 application with an event. So if you send an event from 10 to 9, from a 10 script to a 9 application, and that event is a scripting edition event, it will execute with 9 scripting editions. Which is both important to know if you want to invoke the 9 scripting edition, and important to know if you don't have a 10 equivalent of it.
The scripting edition will get invoked in that. So if you say, tell application launcher, display dialog, display dialog will happen in the 9 space. It will happen in classic, and the display dialog you'll get is 9's display dialog, not 10's display dialog, so it will come out platinum, not Aqua. Important to know.
Another important thing to know is that Mac OS X applications don't execute scripting additions in their own application space. In fact, most Mac OS X applications don't know about scripting additions. And so AppleScript in Mac OS X, if it sends a scripting addition event to an application and the application says, "I didn't handle that event," then AppleScript re-dispatches the scripting addition event to the sending application.
To get executed in the sending applications process. So if, sorry, I'm going back a little bit. To execute a scripting edition in 9, you've got to do two things. You've got to target a Mac OS 9 application, and what Doug Korns of our group tends to do is he puts Launcher in the startup items folder. And Launcher is a great application because you can target it with scripts, it always hangs around, it's relatively unobtrusive, and it's useful for launching your Mac OS 9 applications in Classic. And then he uses the using terms from clause to actually target, to actually compile the script.
So basically, you have to do a little setup to actually get at Launcher. You tell the Launcher, using terms from the real scripting edition, Get monitor depth or something like that. And then end and end. And this script, if you actually run it in 10 with classic running, it will send an event over to the launcher. Launcher will execute it in classic. It will execute even a 68K scripting edition and return the result back to your Mac OS X script. So if you want to use your old classic scripting editions for Mac OS X scripts, this is the structure that you use to do them.
On Mac OS X, scripting editions aren't loaded in the system heap at startup time because there is no system heap and there basically is no startup time. So we can't do that. We were thinking of loading scripting editions behind the back of every application, but that would burden every application launch time with the scripting edition's load time, and applications on 10 don't need to do more work at launch time. We don't want to add another bounce just for us.
So, to make us not have our own bounce for every application, applications don't load scripting editions, and when we send an application a scripting edition command, if it doesn't handle it, then we execute it basically ourselves in the current application context. So, an application, if it chooses to, if it's an OSA client, if it's going to execute scripts, and it would be better off to execute scripting editions in its own context, it'll have to do that. So, if it does have scripting editions, if not, we'll just handle it for it.
The result to the scripter should be transparent, and the result to the programmer should be that your application launches faster, and that people can send all sorts of scripting editions to your application. You just won't handle them. You'll never even see them, but the scripter will have the same result. Let's see how that works.
So here I've got a couple of scripting additions. I guess I can quit this. And I'll go to the finder and go to my home directory and to my libraries folder. And note that I don't have a scripting additions folder here. So I have to create one. And for now, I didn't add a space. That's an oversight that we hope to be able to fix. And I take a scripting edition, and I drop it in my scripting editions folder.
So now I have access to that scripting edition's terminology, and I can run it, and it works. And what's interesting is that... I still have access to scripting editions from all other applications. Let me go down and see if Simple Text is still running here. So here's Simple Text. Here's that script. I bet you didn't know Simple Text had this option, did you? So you can see that SimpleText has access to that scripting edition too.
Okay? Now, the Finder, The Finder doesn't execute scripts, so it doesn't have scripting editions loaded. So, this Open for Access scripting edition and this Parse XML scripting edition commands will be sent to the Finder, but the Finder's going to say, "I don't handle these." But instead of getting an error, event not handled, AppleScript will just resend it to the script editor.
The script editor will execute it, and you get the right results. And if you look at the event log, You'll see that you don't even see that redispatch. It thinks it's telling the finder, it thinks the finder's executing it, but the finder is not, script editor is, you're just getting the right result.
So what this means to developers is that you should port your scripting editions to Carbon in order to get them on Mac OS X. And you need to release both separate Mac OS 9 and Mac OS X versions of your scripting editions. To scripters, what this means is, you know, for optimum benefit, you could and should move your scripting edition calls out of your tell blocks.
Since if they're sent to an application that doesn't understand them, they're just going to be redispatched to the script application anyway. You might as well move them out of your telblocks. It'll just save an extra event send to the application for that. And if you want to target Mac OS 9 editions, you need to enclose those in a telblock for the Mac OS 9 edition. A couple more differences in Mac OS X that I want to cover before we end and go to questions.
One is the packages issue. Mac OS X apps are folders, not files. As you heard in the bundles and extensions discussion on Friday, this is for being able to work on non-HFS file systems and being able to transport things over the network without having resource forks and types and creators and things like that mangled. But there are some key differences there because your scripts, as scripters, probably assume that you're not going to be able to do that.
That if you get an application, it's a file. It's not a file. Info 4 will report that the application is a directory. If you ask for path 2 with an application, it's going to have a colon at the end. And it's going to end in .app actually. It's going to end in .app colon because that's its real name on the file system.
You are going to see differences between what the real thing is on the disk from what the user sees in the finder. Now, we're going to work on... showing you both versions and giving you access to what the truth is and what the user sees. We need some help from the finder and from the system in doing that.
That will come in subsequent versions. But for now, remember that when you use AppleScript, AppleScript will tell you the truth of the file system in that an app is a folder. It ends in a colon and it ends in .app even if it doesn't look like that in the finder.
Paths and extensions. We didn't change, and we're still using most of the Carbon APIs for this, we didn't change the way that we interpret and show things to the user in Mac OS X. If you're accustomed to colon-separated path names, you get colon-separated path names, so your scripts that parse colon paths will still work. If you ask the finder for every disk, you're going to get the disks on your desktop, and you can start a colon-delimited path with those disk names. That's not the way the file system really is, though.
The file system really starts at slash, and those disks are in slash volume slash something. We debated long and hard about whether to give you access to both colon-delimited and slash-delimited file names, and we thought that it was just going to be a total nightmare for scripters to do that.
So we're maintaining for the file and alias types, the colon-delimited file name, and for path two, and anything that returns the file name as a string. We're going to continue to do that. We will probably not ever support slash-delimited paths, but we'll support file URLs, which I'll talk about in the next session.
The Finder hides file extensions. It hides .app now. It will probably hide other extensions in the future. Info 4, if you want to do anything in the file system, you really need the full name with the extension. So if you say tell app simple text, we're doing a nice thing by not making you type simple text .app, but the real name of the application is simple text .app.
Info 4 will tell you that. Path 2, Info 4 will require that. Path 2 will tell you that. And in future releases, we'll provide you more information on what the file extension is and whether the file extension is showing or not in order to enable your scripts to do the right thing.
We are using extensions more in AppleScript. As was talked about in the presentation on Wednesday, extensions are not required, but if present, they'll be interpreted. So if you get a script across the internet that has no type, no creator, but ends in .script and you double-click it, the script editor will open and it will read it as a compiled script.
So scpt is our compiled script file. .applescript is our uncompiled raw text of AppleScript, and I assume that there will be other .script files that may or may not be opened in the script editor for other types. And we have two special types for terminologies. .osax is a scripting edition, and .asdictionary is for anything else that has an AppleScript dictionary, whether or not it has code attached to it. For now, if the user wants the extension on it, the user has to add the extension manually. We don't add any extensions automatically. As the system evolves to allow extensions to be added automatically, if the user desires that, we'll take advantage of that.
But for now, we don't put one on automatically. If the user wants one, they can use it. And the script editor will continue to set the type and creator of new files it creates, so that those files can be used on a Mac OS 9 system. And the AppleScript 1.6, the Mac OS 9 version, will also understand files without type and creator, but only in extension.
So let me tell you what we're working on before we close and go to questions. Our number one priority is getting more Apple applications scriptable. AppleScript itself, we think, is pretty good. We offered a solid product. It offers high degree of compatibility with Mac OS 9. It's reasonably bug-free, but it's the sound of one hand clapping. Until you can script the finder and the preferences and mail and connect to the Internet and choose printers, we don't think AppleScript is done on Mac OS X, and so we're continuing to work on those things.
We think the loss of networked Apple events is a big hole. We're working on that. That looks very good for the short-term future, is getting networked Apple events back in. We want to more smoothly integrate with features of Mac OS X. Paths and extensions are one. And the other capabilities of Mac OS X that allow you to, say, execute things in the terminal.
Let me just show you, because this is a little hack that somebody put together, but hacks are good, right? As I told you, there are separate folders in each domain, and there's a components folder in your library domain. And you can take, for example... A new OSA component and just drop it in your /library/components folder.
And when you run the script editor, you have multiple items here in your pop-up, so you have more than one OSA language. But this isn't Mark Aldrich's JavaScript, this is something called Bundle Shell. And I can type ps-ax, for example, and get a list of the processes running on the machine.
This is actually Bundle Shell. This is a cheap little demo which just takes the script and executes it from the Unix command line and takes the result and pipes it back. Just to prove it's Unix. There we go. There's your password file. Back to the slides, please. So that's what I mean by more integration with Mac OS X.
And then there are two perennial projects that I've been talking about forever and we're still working on. As soon as they stop revving the OS so we can sit and work on our own code for a while rather than port, we'll get through these. But a plug-in model for applications so that your applications can more easily support plug-ins.
And for AppleScript itself, so we can extend things like adding a full Unicode class without having to go into the bowels of AppleScript and hack everything ourselves. And then full object model support for lists, records, and strings and other classes. Because we know that scripters are really confused by using the object model in applications, but they can't delete a character from a string, for example.
So in summary, AppleScript in Mac OS X is pretty useful. It's pretty reliable. It's got everything that the 9 version has got. It works pretty well. We lack the scriptable applications on the Apple side, and we're getting good scriptable applications on the third-party side. We're continuing to add new stuff to AppleScript. We're not just sitting still with the implementation, but we are evolving it as we get a chance to, and we're trying to do so in a compatible way so that your scripts continue to run.
Chris Espinosa Mac OS X and classic versions will stay in sync for a while. While you are migrating your solutions from 9 to 10, we will continue to make sure that your scripts can run in either environment. There will be some point in the future where we'll discontinue 9 support, but that's in the distant future, not in the near future.
And the Mac OS X version will support new features and idiosyncrasies of the Mac OS, and that will only be in the Mac OS X version. So we'll start to diverge a little. We're not going to... We're not going to imbue 9 with all sorts of 10-like features, but we will make sure that 9 and 10 remain somewhat parallel.
There's another session coming up in about half an hour, which is the Building AppleScript Application session. If you are writing a scriptable application or writing an OSA client, that session is for you. If you are a scripter, go out and get a soda, play some pinball, and we'll see you at the feedback forum at 5 o'clock, which will be in room C, which is... If you have questions, I'm always available.
I'm the middle guy. Our technology manager is Jason Yeo, who is across the street doing Darwin presentations right now. And our esteemed marketing guy, Sal Sagoian. As always, the AppleScript implementers and AppleScript users lists are great places to get advice from other scripters or programmers. And I frequent the developers, the implementers list quite a bit, and Chris Nebel is on the users list quite frequently as well.