Section 20.8. Inadequacies of the Dictionary


20.8. Inadequacies of the Dictionary

One function of the dictionary is to show the human user how to speak AppleScript to a scriptable application in order to drive that application. But the very nature of a dictionary renders it insufficiently expressive to fulfill this function. A dictionary is merely a list of words. Words don't make a language. The problem, as Austin famously put it, is how to do things with words. That's what you want to know, but it's just what the dictionary is incapable of telling you. Dictionaries can be more discursive and explanatory thanks to the new sdef format, and it is to be hoped that developers will take advantage of this to improve them; but few dictionaries use this format, and even when they do, the fundamental problem will remain: a vocabulary list is not documentation.

Here's an eclectic collection of some of the various ways in which the dictionary can fail the user. Forewarned is forearmed; I hope this discussion will make you a sharper reader of dictionaries and a wiser AppleScript programmer.

This discussion is not meant to imply that all dictionaries are bad. On the contrary, some developers have worked hard to write careful, informative dictionaries. But it is hard work. You have to know AppleScript, you have to anticipate your users' needs and expectations, and you have to know the dictionary format and how to make the best of it. Most important, your application's scriptability has to have been well implemented to start with; for some useful guidelines from Apple, see http://developer.apple.com/technotes/tn2002/tn2106.html.


20.8.1. Defects in the Object Model

An application's object model is a hierarchy, essentially equivalent to the chain of ofs allowing you specify any of the application's objects (see "Properties and Elements," earlier in this chapter). Clearly this hierarchy requires a starting point; there must be some ultimate, top-level object in terms of which all others may be specified. In an Apple event, that top-level object is null( ). But in AppleScript there is no way to express this null( ) explicitly; it is simply supplied for you as the end of the chain, whenever you specify an object. (You can see this in Example 3-1.) Therefore you must rely on convention. And the convention is that the application class should correspond to the top-level null( ) object. This makes sense, as in a tell block the application is ultimately the only thing you can get a reference to in order to start referring to its objects. That's why your starting place when you study a dictionary is usually its application class. You assume that this is the top of the object model hierarchy, and you look to see what properties and elements it has, in the expectation that these will lead you wherever you want to go.

The object model, however, may not be a simple hierarchy. A number of things can undermine this straightforward picture.

Secret shortcuts

Here are the elements of iTunes's application class: browser window, encoder, EQ preset, EQ window, playlist window, source, visual, window. You'll notice that none of these is your library, and none of them is a playlist. Yet these are the things you're most likely to want to refer to. So how are you expected to talk about them? You can spend ages mucking about in the dictionary looking for some way to reach playlist level from herebut it turns out that you could have asked for a playlist directly all along. Indeed, it turns out your library is a playlist:

 tell application "iTunes"     get playlist "library" -- library playlist id 40 of source id 35 end tell

Notice the discrepancy between what you said to iTunes and the reference iTunes handed you. In theory a playlist is an element of a source, and a source is an element of the application, and that's the path you should have to travel to reach a playlist. But in actual fact there's a shortcut that lets you jump right from the application to a playlist. That's excellent, but the dictionary never told you so.

This book has been full of examples of the Finder doing the same sort of thing:

 tell application "Finder"     get folder 1 -- folder "Mannie" of desktop end tell

As you can see, folder 1 is not the first folder at the top of your startup disk, as you might expect: it's the first folder on your desktop. Again, the dictionary never told you about this.

Your main source in iTunes (called the Library source), and the desktop in the Finder, are implicit subcontainers supplied when you speak of certain elements without qualification. The application gives you a shortcut for reaching certain places in its object model with traversing the whole path explicitly. But this fact isn't documented in the dictionary.

Such shortcuts needn't start at the top level. Consider the following:

 tell application "Microsoft Entourage"     get email address 1 of contact 1 -- "matt@tidbits.com"     get label of email address 1 of contact 1 -- home end tell

The first line makes it appear that "email address 1 of contact 1" is a string, but that makes the second line anomalous, as a string has no label property. The truth is that the email address class has a contents property; when you ask for an email address object (as opposed to a property of such an object), Entourage takes a secret shortcut and returns the value of its contents property instead.

Some applications are particularly badly behaved in this regard. A good example is Eudora. There is a mailbox class in Eudora, but how can you speak of any particular mailbox? The only place a mailbox element appears in the dictionary is under the mail folder class. But in fact not every mailbox in Eudora is in a mail folder, so how can you ever speak of such a mailbox at all? It looks impossible. Yet it turns out (after some experimentation) that you can speak of a mailbox directly:

 tell application "Eudora" to count messages of mailbox "In"

That's nice, but if it's legal, why doesn't the dictionary say so? Why isn't mailbox an element of the application class? In Eudora's dictionary, mailbox is an orphan class.

A dictionary may also simply omit pieces of the puzzle, such as not bothering to list all of a class's elements. If you read Appendix A you'll see me spending much of my time discovering that in FrameMaker an anchored frame can be an element of a paragraph or of a document. This discovery comes as a relief, and makes the ultimate solution possible, but the dictionary says no such thing; only experimentation reveals the facts.

Something quite similar happens in the Finder's dictionary. The dictionary quite clearly states that a Finder window has no elements (and it doesn't inherit from anything that has elements). Yet the following is both legal and useful:

 tell application "Finder" to get item 1 of Finder window 1

Thus an application can have a perfectly reasonable object model in its head, as it were, but fail to reveal it to you in its dictionary. In the dictionary, the object model is defective. And the dictionary is all you've got.

20.8.2. Defective Element Specifiers

There are many ways to refer to an element (see "Element Specifiers" in Chapter 11), but you can't be sure from the dictionary which ones are implemented for any particular element. The dictionary format has a place for this information, but developers often fail to provide it correctly, leaving you to discover the truth by experimentation. Even if the correct information is present in the dictionary, the Tiger version of Script Editor omits it altogether from its dictionary display.

For example, according to the Finder's dictionary, a container's file elements can be specified by name and by index. But those are not, in fact, the only specifier forms that work. The range specifier form works too:

 tell application "Finder" to get files 1 thru 2 of folder 1

The Finder also lists in its dictionary specifier forms that do not work. For example, the dictionary says you can specify a folder by ID. But you can't get a folder's ID, so that's not true.

An application can implement element specifier forms in bizarre ways. For example, in Eudora, you can't say this:

 tell application "Eudora" to get mailbox 1 -- error: Can't get mailbox 1

But you can say this:

 tell application "Eudora" to get name of mailbox 1 -- "In"

Or this:

 tell application "Eudora" to count messages of mailbox 1

So you can't get a mailbox by index, but you can get its name and messages by index? What's the underlying logic here? Weirdest of all, you can't say this:

 tell application "Eudora" to count mailboxes -- error: Can't get every mailbox

So how are you supposed to learn how many mailboxes there are? You can't. So how can you cycle through all mailboxes? As far as I know, the only way is to keep cycling by index number, incrementing the index, until you get an error.

Boolean test specifiers are, of course, the most chancy, but when they work they are wonderfully elegant and powerful. A simple listing in the dictionary could never tell you everything you want to know about boolean test specifiers, because it can't possibly let you know all the various tests that work and don't work; so experimentation is your only option. The same goes for properties of multiple references, such as "get name of every..." (Chapter 11); the dictionary has no way to tell you whether expressions like these will work, so you just have to try them and see.

20.8.3. Properties with Eponymous Classes

A common developer mistake is to give a property the same name and four-letter code as a class. This causes errors in the user's script that can be difficult to track down. Also, it's just confusing.

For example, in Entourage, a message has recipients, and a recipient has an address property which is itself of the address class. To learn, as a string, who the addressee is, you have to ask for an address's address property. This requires a nutty way of talking ("address of address"?); and to make things worse, it doesn't seem to work:

 tell application "Microsoft Entourage"     tell folder 1         tell message 1             tell recipient 1                 get address of address -- error: Can't get address of address             end tell         end tell     end tell end tell

The problem is that a property and a class have the same name; this causes the script to resolve the terms incorrectly. To solve the problem, you must help AppleScript to understand that you mean the property, not the class:

 tell application "Microsoft Entourage"     tell folder 1         tell message 1             tell recipient 1                 get address of its address -- "matt@tidbits.com"             end tell         end tell     end tell end tell

Even worse is what happens when a property and a class have the same four-letter code but different English-like names. For example, in Panther, here's what happens when you ask the Finder for the class of its desktop property:

 tell application "Finder" to get class of desktop -- desktop

But there is no desktop class! The correct answer is desktop-object; the problem is that the four-letter codes for desktop-object and desktop are the same. (The term desktop comes first in the dictionary and hides the term desktop-object during decompilation.) The mistake is fixed in Tiger's version of the Finder dictionary.

20.8.4. Clashes with AppleScript

An application's dictionary should not clash with the AppleScript language itself. When it does, the language is perverted, and scripts that should compile don't, or compile oddly.

We've already seen some examples of trouble caused by poor choice of terminology in an application's dictionary. The use of the term end transaction by FileMaker Pro as the English-like equivalent of the 'misc\endt' Apple event conflicts with AppleScript's own use of end transaction as the closing phrase of a transaction block. BBEdit's use of the term contents as a property of a text-object conflicts with AppleScript's own contents of operator.

Another example is Entourage's recipient class, which has a recipient type property whose four-letter code is 'rtyp'. This conflicts with a fundamental feature of the AppleScript languageit's the same as the as in get...as (see Chapter 14). Thus if you enter this code:

 tell application "Microsoft Entourage"     get path to desktop as string end tell

it compiles and decompiles to yield this (after which, of course, it won't compile at all):

 tell application "Microsoft Entourage"     get path to desktop recipient type string end tell

20.8.5. Wrong Value Types

Dictionaries are notorious for stating incorrectly the value type of a property, a command parameter, or a command return type. Only experimentation will reveal the truth.

For example, Entourage's application class lists the value type of most of its properties as "reference" (meaning 'obj '; see "Value Types," earlier in this chapter). This is true as far as it goes, but it's unnecessarily vague. The class of the in box folder property, for example, is folder; it will never be anything else. So why not say so in the dictionary?

We saw earlier that iTunes misstates the class of the direct object of the convert command. Recall also that GraphicConverter's dictionary says it expects an alias as the in parameter of the save command. That puts the user in a quandary, because you might want save to create a new file, but you can't use an alias where the file doesn't already exist. Experimentation reveals that a string will do:

 tell application "GraphicConverter"     set s to "feathers:Users:mattneub:Desktop:joconde"     save window 1 in s as PICT end tell

Interestingly, the AppleScript 'aeut' resource contains an alias or string class, presumably intended exactly for this situationthat is, it exists just so that a dictionary has a way to tell the user that an alias or a string is acceptable as a parameter. GraphicConverter's dictionary fails to take advantage of this. However, the real problem here is a shortcoming in the underlying dictionary format, which makes it hard to express alternative value types. (The new sdef format goes some way towards solving this.)

Then there's the matter of the result returned from a command. Sometimes a result's value type will be documented incorrectly. For example, the StandardAdditions dictionary says that do shell script returns a string, but it returns Unicode text (and the distinction can be crucial). It says that choose URL returns a URL; it returns a string. StuffIt Expander's dictionary contains just one entrythe verb expandso wouldn't you think that the developers could be bothered to write it truthfully? Well, they couldn't. The dictionary says that this verb returns an integer representing the number of files that were successfully expanded. It doesn't. Because of this falsehood in the dictionary, a simple script that should take minutes to write can take hours (I speak from experience).

Sometimes a command will be documented as not returning any result when in fact it does, or vice versa. The Finder's reveal command is an example; the dictionary does not say it returns any value, but it actually returns a reference to the item revealed. This sort of thing is crucial to know, especially as it can affect the value of the implicit result of a line of your code, or even of a handler or the script as a whole.

A related problem is that the dictionary doesn't distinguish between a reference and a record as returned value types (see "Records," earlier in this chapter). This can make a big difference to your script. As a careful programmer you will probably want to know whether what you have is a reference, and whether fetching a property of it will send an Apple event. Yet experimentation is the only way to find out.

It also doesn't help matters that the very same command can return different types of value under different circumstances. A common source of error is a construct of this form:

 tell application "Finder"     repeat with d in (get every disk)         -- do something here     end repeat end tell

The problem is that every disk returns a list unless there is only one disk, in which case it returns a reference to a single disk object. Thus, this script can break in a subtle way: if you have more than one disk, you're cycling through disks; if you have just one disk, you're cycling through top-level folders. And you may have no way to find this out! You can test your script until you're blue in the face, believe that it works fine, and distribute it to others, only to learn later that it mysteriously breaks on someone else's computer.

20.8.6. Wrong Parameter Details

Aside from their value types, command parameters are all too often described incorrectly in the dictionary. First, is a parameter optional ? The dictionary has a place for this information, but developers sometimes get it wrong. Second, if a parameter is optional, what is the default? (That is, what will happen if the parameter is omitted?) There is no formal provision for answering this question, but there's a place for a comment on each parameter, and you'd think the developers would answer it here. But sometimes they don't.

For example, the Finder's dictionary says that when you're using the make command, the at parameter is compulsory, not optional. That just isn't true; this works:

 tell application "Finder" to make Finder window

With iTunes's add command, the to parameter is optional. If you omit it, what will this file be added to? You can probably guessbut you shouldn't have to. The dictionary should tell you what this command will do, so you don't have to waste time experimenting to find out.

20.8.7. Make

Some common commands are particularly troublesome, and none more so than the verb make, used to create objects in AppleScript. No action is so fundamental as creating somethinga window, a document, a mail message, a piece of textand yet nothing in AppleScript is more difficult to do. The make command typically has the same basic set of parameters in every application, yet it is implemented in a bewildering variety of ways (sometimes it seems that every application implements it differently) and usually little or no assistance is provided by the dictionary.

The make command appears in the dictionary with its first parameter preceded by new. But in actual fact you can omit the word new; what follows the word make, where the direct object would go, is taken to be the new parameter. The dictionary fails to express this fact, which is hard-coded into the inner workings of AppleScript itself.


The first question is what to make. It's going to be a class belonging to the target application, and it will almost surely be a class that functions as an element in the application's object model. Nevertheless, for a given act of creation, it is not always clear what class you should try to make. You might think, for example, that to make a new email message in Mailsmith I mean a new outgoing message, one that you intend to populate with an address, a body, and so forth, so as to send it lateryou'd ask to make a new message; but it turns out that this creates a new incoming message (which makes no sense whatsoeverwhy in the world would you ever want to do such a thing?). The way to make a new outgoing message is to ask for a new message window. Nothing in the dictionary would lead you to this solution. Similarly, the way you create a new window in AppleWorks isn't to ask for a new window, which just gets you an incomprehensible error message, but to ask for a new document. The way you create a new window in the Finder isn't to ask for a new window but to ask for a new Finder window.

Often (but not always) you must also say where to create the new object. The dictionary lists this parameter:

 at location reference -- the location at which to insert the element

Every application seems to have a different idea of what constitutes an appropriate location. (See also the section "Relative" in Chapter 11.) In Eudora, for example, if you're trying to make an outgoing message, it turns out that the place to create it is at the end of the "Out" mailbox:

 tell application "Eudora"     make new message at end of mailbox "Out" end tell

This seems particularly nutty. In Eudora's interface, it's easy to make a new outgoing message: you just choose Message New Message. You dont have to say where to make this new message! You just say you want one, and Eudora makes it in some sensible place. This is exactly what I'm trying to do in AppleScript; surely I should be able to say simply "make new message" and Eudora should create the outgoing message in precisely the same manner. But that's not the case. You must say the magic words or you won't get any new message. And don't expect the dictionary to tell you what the magic words are, either.

With Cocoa applications, the at parameter must typically refer to a collection (sometimes imaginary) of the same things you're trying to make one of. For instance, in the outliner NoteTaker , to make a new outline entry, you have to say something like this:

 tell application "NoteTaker"     tell current notebook         tell current page             make new entry at beginning of entries         end tell     end tell end tell

If you target the wrong object, or if you don't say at beginning of entries, you get an error, or nothing happens, or NoteTaker crashes.

Not only the at parameter, but also the meaning of at, varies from application to application. This code inserts a new word after word 2:

 tell application "BBEdit"     tell window 1         make new word at word 2 with data "howdy"     end tell end tell

This code inserts a new word replacing word 2:

 tell application "TextEdit"     tell text of document 1         make new word at word 2 with data "howdy"     end tell end tell

This code inserts a new folder inside folder 1:

 tell application "Finder"     make new folder at folder 1 end tell

Then there's the with parameter. This is the most troublesome at all. Actually your choices are usually with data and with properties; some applications let you say only a particular one of these, but some let you say either (or both).

In the case of with data, you are probably setting some fundamental aspect of the new object's initial state; but you don't know, until you try it, exactly what aspect this will be. In the examples with BBEdit and TextEdit, it turns out that with a word, its data is its text.

In the case of with properties, what you're providing is a record; the properties and values you supply will be used to set the inital values of the corresponding properties in the newly created object. You don't usually need to supply an initial value for all of the new object's properties, but sometimes you have to supply an initial value for at least some of them. You might expect that you would be permitted to make a new, essentially blank object; the make command returns a reference to the new object, so you could then proceed to populate its properties afterwards. But some applications don't let you do this; they require you to provide certain initial valuesand the problem is that you don't know which ones.

For example, the way to add an address to a Mailsmith message window is as follows:

 tell application "Mailsmith"     tell message window 1         make new to_recipient with properties {address:"matt@tidbits.com"}     end tell end tell

If you leave out the with properties parameter, you'll get a runtime error.

20.8.8. Selection

Another extraordinarily difficult concept to express in AppleScript is the selection , which is usually implemented through a selection property. The selection can be tricky to get and tricky to set.

Some applications give you no access to the selection at all. For example, in TextEdit there is no provision for learning what is selected. Similarly, Apple Mail lets you learn what messages are selected but not what text is selected in a message. This is a clear deficiency and should be regarded as a bug, as it is perfectly reasonable that you would want a script to operate on the selected text.

Of what should the selection be a property? Different applications have different philosophies about this. Be sure to look through the dictionary to see where the selection is implemented. The safest assumption is that there is an application-wide selection, and so it is the application class's selection property that is most likely to be appropriate. If an application has multiple windows, and you have selected something in several of them, only the selection in the frontmost window is the application-wide selection. But an application may also let you specify the selection in terms of some other physical container, such as a window. Thus, for example, BBEdit lets you work with the selection of a non-frontmost window; but the Finder does not.

When you ask for the selection, what kind of result is returned? The answer will vary from application to application, but what you hope for is a reference (or list of references). Learning what kind of object this is a reference to, and what you can do with this information, might require experimentation. If it is a list, you might have to cycle through its items to work further with them. For example, in Address Book, this doesn't work:

 tell application "Address Book"     name of selection     -- error: Address Book got an error: Can't make name of selection into type reference end tell

The selection is a list, and Address Book is not willing to distribute a property over the items in that list (see "Operations on Multiple References" in Chapter 11). You have to cycle through the list yourself:

 tell application "Address Book"     set L to {}     repeat with aThing in (get selection)         set end of L to (get name of aThing)     end repeat     L end tell

Sometimes, the selection property is not what you really want. If you're simply trying to get a reference to what's frontmost in the application, look for properties with "current" in their name, such as iTunes's current playlist. Similarly, in Entourage, the selection might be a list of references (to messages selected in a window that lists messages, for example), or it might be the selected text (as Unicode text, not a reference); but Entourage implements a current messages property that always returns a list of messages, which is far more likely to be useful.

Then there is the matter of how to set the selection. An application that implements selection will usually implement a select command to go with it. Most applications don't let you say "set selection," and those that do mean something else. For example, in BBEdit, "set selection" is a way of replacing the selected text. Microsoft Word , where the selection is often crucial for performing operations on text, provides many ways to manipulate the selection.

20.8.9. Idioms for Common Tasks

Think of AppleScript as an interface to an application, just like the interface you see on the screen. One is a programming interface, the other is a graphical interface. It is not always easy to see how the latter maps to the former. You are accustomed to doing things in an application's graphical interface, in what you think of as a simple, straightforward way. When you're using AppleScript, you often want to "translate" a common interface operation into the AppleScript language. The trouble is that the command repertory, the object model, and the dictionary are often structured quite differently from the graphical interface. Thus the object model is often not at all like the mental picture of the application you've built up from using it in the ordinary way. The verbs you think you need aren't there, or the verbs that are there don't do what you expect. This is probably somewhat inevitable, given the nature of AppleScript (the AppleScript interface to an application is necessarily different from the graphical interface) and the nature of the dictionary (it is a list of words, not to a how-to manual). But it's also very frustrating. Your mind thinks in terms of tasks; you're presented with some vocabulary. You're told some words, but not how to do things with them.

No matter how inevitable this disconnect may be, there is little doubt that some applications carry it much further than necessary. Eudora is a classic example. As we've already seen ("Make," earlier in this chapter), you can't create a new outgoing message with AppleScript in Eudora as simply as you would do it in the graphical interface; you have to say the magic words that tell Eudora where to create the new message, even though there is only one place where it could ever be meaningfully created. Similarly, deleting a message in Eudora is extraordinarily difficult. Once again, the simplicity of the graphical interface misleads you. You're used to simply selecting a message and deleting it (with the Delete key). This sounds like the delete event, so you try it:

 tell application "Eudora"     delete message 1 of mailbox "Out"     -- error: Message 1 of mailbox 'Out' doesn't understand the delete message end tell

So how on earth are you supposed to delete it? The solution, it turns out, is to move the message into the trash:

 tell application "Eudora"     move message 1 of mailbox "Out" to end of mailbox "Trash" end tell

Who would ever have thought of saying something like that? And the dictionary doesn't tell you to say it, so how are you supposed to find out?

Another good example is how you insert text into a BBEdit window. There is no insert verb, and make turns out to be unreliable. The best way, apparently, is to position the selection where you want to insert the text and then say "set selection to" the new text.

20.8.10. Events and Classes

A dictionary lists events (verbs) and classes (nouns), but it doesn't tell you what verbs apply to what nouns. The verb make creates a new object, but what objects am I allowed to create? The verb delete deletes things, but what objects am I allowed to delete? The dictionary doesn't say.

The problem is particularly acute when the dictionary entry for a verb doesn't provide any meaningful information. For example, here's how delete is listed in most dictionaries:

 delete reference -- the element to delete

That could mean anything, so it means nothing. The only way to find out what it does mean is by trying it. Another good example is close; there are usually very few objects in an application that can be closed (windows, typically) so why doesn't the dictionary tell you?

Script Debugger is particularly helpful here, because for every class it lists all the places in the dictionary where it's used. But of course this is only as good as the dictionary itself; Script Debugger doesn't have xray eyes that can peer into the workings of an application, and if a dictionary is not specific about what class or classes can serve as the object of a verb, no amount of cross-referencing can tell you.

Part of the problem here is that the dictionary is not designed to communicate the desired information in any complete and coherent manner. The new sdef format may, in some cases, improve the situation. A Cocoa application's sdef can actually include implementation information in the dictionary; a class can list the commands it responds to, and a dictionary display will then be able to pass this along to the human reader.

Until the new sdef format is widely adopted, we're left with trial and error. If AppleScript or an application doesn't want to apply a particular verb to a particular object, it will usually return an error message that "such-and-such an object doesn't understand the so-and-so message." In other words: sorry, guess again.

20.8.11. Coercions

Dictionaries don't list the coercions that can be performed by an application in response to get...as. (See "Explicit Coercion" in Chapter 14.) Only trial and error can give you this information.

A rare exception is the Finder, which defines a class alias list and almost tells you (but not quite) that the purpose of this class is to let you coerce to it:

 tell application "Finder"     get every disk as alias list     -- {alias "feathers:", alias "gromit:", alias "Network:"} end tell

Sometimes, for particular verbs, a comment can help to fill the gap. But sometimes the comment is lying. The path to scripting addition command has an as parameter; the comment tells you that your choices are string and alias. But you can also say Unicode text, and it might be important to do so; the dictionary fails to mention this.

The problem is particularly acute for scripting additions. A scripting addition can implement a coercion, which then works as if it were part of the AppleScript language. (A good example is Jon's Commands , which lets you coerce a script object to a string.) But because coercions are not listed in the dictionary, you have no way to find out about this (except from some other documentation). Even worse, if you then run a script in the absence of that scripting addition, this coercion will break and you might not know why, because you didn't realize that it was working in the first place only because of that scripting addition.

20.8.12. Bad Grammar

When developers decide on the English-like terminology for a dictionary, do they think about the experience of the users who will actually employ this terminology in typical AppleScript expressions? I sometimes wonder, when I find myself saying something like this to the Finder:

 if application file n has scripting terminology then

That's illegal, and generates a compile-time error. Instead, you have to say this ungrammatical-sounding phrase:

 if application file n is has scripting terminology then -- "is has"???

The trouble is that has scripting terminology is the name of a property. Why would anyone make a property name a verb? If the name of this property were an adjective, such as scriptable, it could be used without sounding unnatural. (See "The "English-likeness " Monster" in Chapter 4.)

20.8.13. Multiple Listings

Sometimes an entry in a dictionary will appear as several different entries, distributed over different suites. For example, in the Finder's dictionary, the application class appears twice, once in the Finder Basics suites, and again in the Legacy suite. This sort of thing probably arises out of decent motivesto categorize different parts of a thing (here, different properies of the same class) by their functionalitybut it is utterly maddening for the user. The prospect of having to flip back and forth between two listings of something is unbearable, assuming that one is even aware to start with that there are two listings for it, which is unlikely. If suites are the work of the devil, splitting something over two different suites is punishable in the eighth circle.

Once again, Script Debugger comes to the rescue; if it finds an entry repeated between multiple suites, it collapses them into a single entry in the dictionary display.

20.8.14. Busted Scriptability

Sometimes the reason why you can't figure out how to do something is that it can't be done. For instance, there is no way to close a "dirty" TextEdit document without saving it. (The close command is documented as having a saving parameter to which you can supply a value no, but it doesn't actually work.) And, as we've already seen, you can't get or set the selection in TextEdit. The best approach here is, if at all possible, just to walk away! Don't expect every application to be equally scriptable. TextEdit's scriptability is fundamentally busted, so find some other application that can do what you want to do. (For example, if you need a text processor or word processor, BBEdit , Tex-Edit Plus , and Microsoft Word are wonderfully scriptable.)

20.8.15. Bad Comments

A dictionary is, as I've argued, by the very nature of its underlying format, inadequately informative to users. But everything in a dictionary has a feature that can help compensate for this inadequacya comment. A comment is simply a string, so it is a developer's opportunity to say anything at all to the user, in what amounts to a free form, untramelled by the formal restrictions of dictionary structure. A comment is not a perfect medium of communication (it's just a string, it is of limited length, and it can appear only in a restricted set of places in the dictionary), but it is certainly the developer's best chance to make up for the shortcomings of a dictionary entry.

It's surprising, then, that developers fail so often to take advantage of comments. For example, earlier I mentioned that the close command is likely to operate on a restricted set of objects. The comment might be a good place to explain what these are. But here's the Finder's comment on the close command: "Close an object." And here's its comment on the close command's direct object: "The object to close." Thanks for nothing, Finder!

Here's an example of a good commentthe to parameter from the Finder's make command: "When creating an alias file, the original item to create an alias to or when creating a file viewer window, the target of the window." That tells me exactly what this parameter is for; it's used on a limited set of occasions, and the comment says just what they are.

A dictionary with some really splendid comments is Mailsmith's. In a few words it explains how to think about an entry, and even provides examples. Here's how Mailsmith's dictionary describes the text_object class: "Abstract class describing a text object and its basic properties." That is really superb. The dictionary itself has no way to let you know a class is abstract, so the Mailsmith folks come right out and tell you in a comment. And here's what it says about the text_object class's offset property: "Offset of a text object from the beginning of the document (first char has offset 1)." This description actually explains how the characters are numbered! Would that all comments were like these.

Possibly the greatest promise of the new sdef format is that it provides the opportunity for unlimited comments. A comment can be of any length, and it can be formatted (using XHTML). This means that we may hope some day soon to see dictionary presentations that read more like proper documentation.




AppleScript. The Definitive Guide
AppleScript: The Definitive Guide, 2nd Edition
ISBN: 0596102119
EAN: 2147483647
Year: 2006
Pages: 267
Authors: Matt Neuburg

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net