DekGenius.com
[ Team LiB ] Previous Section Next Section

19.3 What's in a Dictionary

This section describes the contents of a dictionary. This is primarily so that you can interpret a dictionary when you read it in an application such as the Script Editor.

19.3.1 Enumerations

An enumeration is a value that must be one of a fixed list of four-letter codes. These four-letter codes are called enumerators ; and the enumeration itself also has a four-letter code, identifying the entire set of its enumerators. Thus, by using the four-letter code of an enumeration, a dictionary can specify that a value must be one of the enumerators of that enumeration.

For example, BBEdit's dictionary entry for the close command reads, in part:

close reference [saving yes/no/ask]

The triad of values yes/no/ask is an enumeration. The dictionary actually just says here that the saving parameter is a 'savo'. That's the four-letter code for an enumeration. The script editor application, presenting this information in human-readable form, has looked up the 'savo' enumeration in the dictionary and has fetched the English-like equivalents of its three enumerators. The four-letter code for the enumeration itself, 'savo', has no English-like equivalent.

By and large, an enumerator is the same thing as a constant, as discussed in Chapter 17. If you ask AppleScript for the class of yes, it tells you it's a constant.

AppleScript uses this information to translate between English-like terms and four-letter codes, but the compiler does not check to see whether the value you actually supply is an enumerator of the specified enumeration.

19.3.2 Value Type

At various points in a dictionary, a value type is specified. For example, a command parameter is of some type; a command reply is of some type; every property of an object is of some type.

This notion corresponds to a datatype or class (Chapter 13). Thus, a value type is specified in a dictionary by means of the four-letter code for a class. An application can define classes beyond those that are native to AppleScript itself. There is also a wild-card value type ('****'), whose English-like rendering is "anything." A slightly less wild wild-card type ('obj ') may be used when the value is some object belonging to the application; the English-like rendering is " reference." A value type that is itself a class ('type') has the English-like rendering "type class."

A value type may be a list (since a list is a class); in the special case where the list is all of one class of item, there is a way to say so in the dictionary, and the English-like rendering for this is "a list of" followed by the name of the class. A value type may be an enumeration, or even a list of some one type of enumeration.

Here is part of the dictionary entry for the Finder's count command:

count reference -- the object whose elements are to be counted
        Result: integer -- the number of elements

The dictionary says that the parameter is an 'obj ' and the reply is a 'long'. These are rendered as "reference" and "integer" respectively. A "reference" is a wild card denoting some object belonging to the Finder; "integer" is the built-in integer class (Section 13.2).

Here is the dictionary entry for the Finder's make command:

make 
        new type class -- the class of the new element
        at location reference -- the location at which to insert the element
        [to reference] -- 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
        [with properties record] -- the initial values for the properties of the element
        Result: reference -- to the new object(s)

The new parameter is a "type class," meaning that its value is itself a class, so that the Finder knows what class of object to create. The to parameter, and the result, are a "reference." A "record" is the built-in record class (Section 13.13). For "location reference" and the insertion location class, see Section 10.7.7.

In Mailsmith, a mail message's delivery path property appears in the dictionary like this:

delivery path a list of string [r/o]

A "string" is the built-in string class (Section 13.4). The dictionary actually says that this property's class is 'TEXT', and also specifies that the value type is a list. If you ask Mailsmith for the delivery path of a message, you'll see that it is indeed a list of strings, one for each "Received:" entry in the header.

In Mailsmith, a mail message's status property appears in the dictionary like this:

status a list of seen/answered/forwarded/redirected/deleted/flagged/draft/
        recent/sent [r/o] -- List of status flags

Mailsmith implements an enumeration called 'Eflg' whose enumerators are the constants seen, answered, forwarded, and so forth. The dictionary actually says that the status property's class is 'Eflg' and that its value type is a list. This makes sense, since the possible kinds of status are limited but a message might have more than one status.

This information is for the human reader only. The AppleScript compiler does not check to see whether the value you actually supply is of a specified type, and the runtime engine doesn't care what type of value a scriptable application returns.

19.3.3 Event

An event is a command. You can think of it as a verb; you can also think of it as an Apple event (hence the name). It is specified with two four-letter codes. The rendering of both codes together, separated by slash (or backslash) and delimited by single quotes, is a common convention. So, for example, the Finder's reveal command is the event 'misc/mvis'. The dictionary lists the command's parameters; it specifies each parameter's value type, and whether the parameter is optional or required. The dictionary also specifies whether the command has a reply; if it does, the dictionary specifies the reply's value type.

There are two types of parameter. A parameter may be the command's direct object (Section 10.2.4). Every event listed in a dictionary must say whether the command has a direct object. For example, the Finder's quit command has no direct object:

tell application "Finder" to quit -- don't try this at home

The Finder's reveal command has a direct object:

tell application "Finder"
        reveal item 1 of desktop
        -- or, alternatively:
        tell item 1 of desktop
                reveal
        end tell
end tell

The other type of parameter is a labeled parameter (Section 8.3.3). For every labeled parameter, the label is specified as a four-letter code and as an English-like equivalent. From an Apple event point of view, a label is a property; when the command is sent as a message, the labeled parameters appear as items of a record. For example, recall that the Finder's make command appears in the dictionary like this:

make 
        new type class -- the class of the new element
        at location reference -- the location at which to insert the element
        [to reference] -- 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
        [with properties record] -- the initial values for the properties of the element
        Result: reference -- to the new object(s)

The command has parameters labeled new, at, to, and with properties. The first two parameters are required, and the second two are optional. So the following AppleScript code:

tell application "Finder"
        make new folder at desktop with properties {name:"Jack"}
end tell

generates this Apple event:

        core/crel{ 
                kocl:'cfol', 
                insh:obj { 
                        form:'prop', 
                        want:'prop', 
                        seld:'desk', 
                        from:'null'(  ) 
                }, 
                prdt:{ 
                        pnam:"Jack" 
                }
        }

You can see the two four-letter codes specifying the event ('core/crel'), followed by a record where the names of the items are the four-letter codes for the three parameters we supplied: 'kocl', 'insh', and 'prdt' are the four-letter codes for new, at, and with properties.

You probably know enough by now to understand the rest of what's happening here too. 'cfol' is the four-letter code for the folder class; the last parameter is a record, and we've already mentioned that 'pnam' is the name property. The term desktop is a property, which is rendered as an object specifier, as mentioned in Section 10.7.

The AppleScript compiler enforces the rule that the only parameters following a command should be the direct object and the labeled parameters defined by that particular command. It knows nothing about required and optional parameters, however.

19.3.4 Classes

A class is a datatype (see Chapter 13). Applications are free to define new datatypes in addition to those provided by AppleScript. These will generally correspond to the various types of thing the application operates on. For example, the Finder is all about files and folders on hard drives; thus it has a file class, a folder class, and a disk class.

If a value type is of a particular class, the dictionary will say the name of the class. See Section 19.3.2, earlier in this chapter, for the ways in which a value type may be expressed in the dictionary.

19.3.4.1 Plurals

For most classes defined by an application, the dictionary will provide both a singular and a plural form for the English-like term. So, for example, the Finder defines both file and files, both folder and folders, both disk and disks. In the dictionary, the mechanism for doing this is to list the class a second time, along with a pseudo-property marking it as a plural.

For example, in the Finder's dictionary, the listing for folder is immediately followed by a listing for folders. They both have the same four-letter code ('cfol'), and folders has the pseudo-property marking it as a plural. Therefore AppleScript knows that folders is the English-like plural of folder. The human-readable presentation in the Script Editor simply combines these into one listing:

Class folder: A folder
Plural form:
        folders

The only time a dictionary won't provide a plural form for a class name is when there is only one object of that class; you can't say every, because this class occurs only as a property, not an element. For example, the Finder provides only the singular for desktop-object, the class of the desktop. It is also possible for a class to be declared as its own plural (text does this, for example).

The compiler uses this information to treat singular and plural alternatives with some intelligence; see Section 19.2.2, earlier in this chapter.

19.3.4.2 Class inheritance

A dictionary can specify a class as inheriting from another class. The mechanism for this is a special pseudo-property; if a class has this property, the property's value is the class from which this class inherits. For example, in the Finder, there is a class item; both the file class and the container class have the pseudo-property stipulating that they inherit from item. We also say that item is the superclass of file and container, and that file and container are two of its subclasses. Similarly, the class folder is a subclass of container. Thus we have a hierarchy of inheritance.

The nature of this inheritance is that a subclass has all the properties and elements of its superclass. It may also implement some properties and elements that it doesn't inherit, and it passes these along to its own subclasses as well. For example, in the Finder, the item class has a name property; therefore, so does the container class, and so does the folder class. The container class has an entire contents property; therefore, so does the folder class.

Because of class inheritance, it is possible for a class to be abstract—that is, a class exists only as a way of encapsulating a set of elements and properties so that other classes can inherit them, and is not the class of any actual object to which the programmer will ever make or obtain a reference. For example, BBEdit's dictionary defines an item class to act as an ultimate superclass, just so that every other class will have an ID property inherited from it; there's no property or element anywhere in the dictionary whose class is item.

The Finder, too, has an item class that acts primarily as a superclass, though there's a slight difference: some classes do have an item element, so you can refer to the item class in this way. Nevertheless, the reference you wind up with is an item subclass, not an item; so it is reasonable to describe the Finder's item class as abstract. For example:

tell application "Finder"
        class of item 1 of desktop -- document file (not item)
end tell

The chief value of inheritance is that it makes the dictionary smaller. (Historically, in fact, this is why class inheritance in the dictionary was implemented; QuarkXPress's dictionary was too large to be displayed by the Script Editor, which had a 32K limit on the size of dictionary text.) For example, in the Finder, a file and a folder have lots of properties in common. Rather than having to list all these properties twice, once for the file class and once for the folder class, the dictionary simply lists them once, for the item class, and both file and folder inherit them from item.

Unfortunately for the human reader, a dictionary may be displayed in a way that makes inheritance more of a stumbling block than a convenience. In the Script Editor, for example, inheritance actually makes it harder for you to learn what a class's properties are. When you look at the listing for the Finder's file class, you see about five properties, preceded by a statement that the file class inherits from the item class. So if you want to know about the file class's other two dozen properties, you have to find the listing for the item class and look in that! You thus spend all your time slogging from class to class trying to remember what's in each one.

Script Debugger is much more helpful. The listing for a class optionally shows you its inherited attributes along with its own, so it suffices to look just in the listing for the Finder's file class to learn about all its properties, including those it inherits from item. And Script Debugger even displays the inheritance hierarchy graphically; Figure 19-1 shows its nice hierarchical display of some of the Finder's classes, including item, container, file, and folder.

Figure 19-1. Part of the Finder's class inheritance structure
figs/as_1901.gif

The implementation of inheritance of elements (as opposed to properties) is rather confusing. Most dictionaries behave as if there were no such thing. Thus, for example, in the Finder the elements of the folder class are the same as the elements of the container class, and folder inherits from container, but the identity of their elements is not a consequence of inheritance; their elements are stated separately in the dictionary, the same list of elements appearing twice. (This is not an artifact of the way the Finder's dictionary is presented to a human user in a script editor application; I'm describing the Finder's 'aete' resource.) If the Finder believed in inheritance of elements, it wouldn't need to do this, and more space would be saved. On the other hand, some applications, such as FrameMaker and Adobe Illustrator, do display element inheritance.

The truth is, however, that none of this matters much. The compiler doesn't enforce (or care about) encapsulation of property and element names with respect to their class (Section 19.2.2, earlier in this chapter), so class inheritance in the dictionary has no effect whatever on how AppleScript works. Class inheritance in the dictionary is merely a form of shorthand to save space; it is meaningless except to the human reader, and its chief effect upon that human reader is to make the dictionary harder to read.

19.3.5 Properties and Elements

Recall from Section 10.6 that an object can have two kinds of attribute: properties and elements. For every class listed in a dictionary, its properties and elements are listed along with it.

AppleScript uses the property listings to translate between their English-like names and their four-letter codes, but that's all. The compiler does not enforce the distinction between a property and an element, and does not enforce encapsulation (for example, it doesn't look in the dictionary to see whether the property you are ascribing to an object really is a property of that object). See Section 19.2.2, earlier in this chapter.

19.3.5.1 How properties are listed

The dictionary listing for a property consists of two four-letter codes—the four-letter code for the name of the property, and the four-letter code for the class of its value type. For example, in the Finder the name property of the item class has the four-letter code 'pnam', and its value type is specified as 'utxt', that is to say, Unicode text. As with any value type (see Section 19.3.2, earlier in this chapter), the dictionary can specify that the property's value is an enumeration, or a list whose items are of some one particular class or enumeration. It can also specify that the value is read-only; this appears in the human-readable rendering as "[r/o]". Here's part of the listing for the Finder's item class:

Class item: An item
Properties:
        name Unicode text -- the name of the item
19.3.5.2 How elements are listed

The dictionary listing for an element is the four-letter code of a class—which must be defined elsewhere, of course—along with a list of the forms of specifier that may be used to refer to this element. (Naturally, there are four-letter codes for the element specifier forms.) For example, in the Finder the folder class has a 'file' element with specifier forms 'indx' and 'name'. The four-letter code 'file' is paired with the English-like term file elsewhere, namely at the point where the file class is defined. So this is a way of saying that a folder can have file elements which can be referred to by index or by name. This information appears in the human-readable rendering of the dictionary, which says, in part:

Class folder: A folder
Elements:
        file by numeric index, by name
19.3.5.3 The object model

An object belonging to a scriptable application is of some class. That class can have properties and elements. All of the elements, and possibly some of the properties, represent objects belonging to the application as well. Thus, properties and elements together bind all of an application's objects into a hierarchy, whereby it should be possible to specify every object that actually exists. This is called the application's object model .

Much of the struggle of using a dictionary involves trying to work out the object model, so that you can refer to the object you want to refer to. (See Chapter 3.) This is another area where Script Debugger is particularly helpful. It charts the element hierarchy in a manner similar to the way it charts the class inheritance hierarchy (Figure 19-1); and it displays hierarchically all of an application's actual objects, telling you their values and how to refer to them (Figure 2-4).

19.3.6 Pseudo-Classes

A pseudo-class is a record that's listed as a class in the dictionary. This publicizes the names of the items of the record, making them part of the application's terminology, as well as informing the human reader about the structure of the record.

A good example is the text style info that some applications return as a description of how text is styled. Tex-Edit Plus is such an application. In its dictionary, there's a listing for a text style info class with properties on styles and off styles, each of which has a value that's a list of an enumeration ('styl'):

Class text style info: The on and off styles of a text object
Properties:
        on styles list of plain/bold/italic/underline/outline/shadow/
                condensed/expanded/strikethrough/all caps/
                all lowercase/hidden [r/o]
        off styles list of plain/bold/italic/underline/outline/shadow/
                condensed/expanded/strikethrough/all caps/
                all lowercase/hidden [r/o]

Tex-Edit Plus's dictionary says that the text class has a uniform styles property whose class is text style info. But that's not really true; the dictionary does not distinguish between a real class and a pseudo-class. When you ask for a text object's uniform styles property, you get a record:

tell application "Tex-Edit Plus" to get uniform styles of the selection
-- {class:text style info, on styles:{bold, italic}, ¬
        off styles:{underline, outline, shadow, condensed, ¬
        expanded, strikethrough, all caps, all lowercase, hidden}}

However, AppleScript is able to characterize a record as being of a particular class; you can see this happening in the Apple event version of the result from the previous example ('tsty' is the four-letter code for the text style info pseudo-class):

        tsty{ 
                        onst:[ 
                                'bold', 
                                'ital' 
                        ], 
                        ofst:[ 
                                'undl', 
                                'outl', 
                                'shad', 
                                'cond', 
                                'pexp', 
                                'strk', 
                                'alcp', 
                                'lowc', 
                                'hidn' 
                        ] 
                }

And within your script, the resulting record has been consequently endowed with an item whose name is class, so that if you ask about its class, you'll be told it is a text style info.

To retrieve items of a pseudo-class record outside of a tell block targeting the original application may require the use of raw four-letter codes (see Section 19.2.3, earlier in this chapter). For example, this works:

tell application "BBEdit"
        set r to check syntax file "xxx:Users:mattneub:testing.html"
        get result_file of item 1 of r
end tell

But the following code doesn't, because AppleScript has no way to associate the term result_file with the four-letter code that identifies it internally within the record:

tell application "BBEdit"
        set r to check syntax file "xxx:Users:mattneub:testing.html"
end tell
get result_file of item 1 of r -- error

You can get around this error by using the raw four-letter code:

tell application "BBEdit"
        set r to check syntax file "xxx:Users:mattneub:testing.html"
end tell
get «class Efil» of item 1 of r

The reason why the same problem doesn't arise with text style info is that all the terms involved are defined within AppleScript's own dictionary (see Section 19.4, later in this chapter, and Appendix A).

19.3.7 Suites

At the top level of a dictionary, events and classes are clumped into suites. What is a suite? In part, it's just a way of organizing the top level of a dictionary. This is supposed to make it easier for the human user to navigate the dictionary, but the result is often just the opposite. Typically, you don't get to see classes and events in alphabetical order; you don't get to see them in any order. They are clumped into suites, and within each suite they come in what seems an arbitrary order (it is whatever order the dictionary's designer felt like giving them).

Thus, suites can actually make it harder to find a particular class or event because you don't know what suite it's in or where it will appear within its suite. Once again, Script Debugger can be a big help here, because it lets you view all classes or events in alphabetical order, dispensing with suites altogether.

A suite also has a second use, behind the scenes. Suites are an attempt to bring some semblance of standardization to the anarchic world of terminology. Even before AppleScript was made public, back in the earliest days of System 7 when there were just Apple events, Apple began fostering an attempt to make Apple events more uniform from one application to another. Since it couldn't do this at System level, it resorted to a combination of propaganda and browbeating aimed at developers. An Apple event czar was appointed—the Apple event registrar—whose job was to organize and codify commonly used Apple events into a centralized database—the Apple event registry. The suites resulted from this codification.

You will thus see, recurring amongst applications, a few suites that have become informally conventional. An example is the Miscellaneous Suite, a frequent repository for commands like copy, cut, and undo. But Apple did more than just ask developers to implement and conform to the suites; they incorporated some suites into AppleScript's own dictionary (and you can see them in Appendix A). They did this in such a way that there would be no breach of the freedom of developers to devise their own repertories of Apple events and their own dictionaries. The suites incorporated into AppleScript itself are mostly voluntary. An application may adopt none or any or all of these suites; it may adopt any suite in part, as a whole, or with extensions; it may adopt events and classes as is, or it may change them. In other words, the suites incorporated into AppleScript itself function as starting points.

Some of AppleScript's own suites, such as the Macintosh Connectivity Classes, are relatively obscure and rarely adopted, but others are frequently adopted by scriptable applications. The Standard Suite, sometimes referred to as the Core Suite, shows up quite a lot in one form or another; it contains terms like exists, make, and select. And the Text Suite, containing terms like word and text style info, is sometimes used as a starting point by applications that do that sort of thing.

There used to be a suite called the Required Suite; in the current implementation of AppleScript this is empty. It dates back to the invention of Apple events and System 7, where all applications, scriptable or not, had to respond to four particular Apple events or they couldn't exist as System 7-native applications at all. That's because these are fundamental Apple events sent by the Finder to the application in order to notify it that the user wants to do such things as launch it, open a document owned by it, or quit it. These Apple events now have analogues in the Standard Suite, but the original Required Suite Apple events are not listed, because it is certain that every application responds to them. They are shown in Table 19-1.

Table 19-1. The original Required Apple events

Command

Four-letter code

Effect

run

'aevt/oapp'

Launch the application

open

'aevt/odoc'

Open a document or documents

print

'aevt/pdoc'

Print a document or documents

quit

'aevt/quit'

Quit

    [ Team LiB ] Previous Section Next Section