AppleScript_ The Definitive Guide - Matt Neuburg [112]
tell application "TextEdit"
tell text of document 1
get every word where it contains "t"
get words whose it contains "t"
end tell
end tell
The two formulations shown are equivalent, but most people prefer the former, as being more English-like. (AppleScript has no equivalent for where it, such as "which" or "that"; it doesn't let you be as English-like as all that.)
That example works because when you ask TextEdit for words, you get a list of strings; each string then functions as the first operand of contains. But this is by no means how every application works. For example, in BBEdit, when you ask for words you get a list of references. To obtain the text of each word you ask for its contents, so you don't end up using it at all:
tell application "BBEdit"
tell text 1 of window 1
get every word whose contents contains "t"
end tell
end tell
Finally, here's an example involving an index specifier other than every:
tell application "BBEdit"
tell text 1 of window 1
get word 1 whose contents contains "t"
end tell
end tell
When you use every, if no elements satisfy the text, you get an empty list. But when you specify the index, if that index doesn't exist, you get an error. (This is because you get an error if you ask for a nonexistent item of any list.) You can easily catch such an error and handle it (see Chapter 19), but it's something to watch out for.
If the target application is willing, you may even be able to combine multiple boolean tests (see "Boolean Operators" in Chapter 15). The syntax rules require that you supply a first operand for the second test, even if this is the same as the first operand of the first test:
tell application "TextEdit"
tell document 1
words where it begins with "t" and it ends with "t" -- {"test"}
end tell
end tell
The boolean test, where it works, is a very powerful specifier; with a single Apple event you're getting the target application to do a lot of searching for you. Unfortunately, you never know whether it will work; only experimentation will tell you.
AppleScript itself, most disappointingly, fails to implement boolean test specifiers for its own lists. The two halves of this example are parallel, yet the second fails:
tell application "Finder"
get every disk whose name begins with "g" -- "gromit"
end tell
set pepBoys to {"Mannie", "Moe", "Jack"}
tell pepBoys
get every item whose text begins with "M" -- error: Can't get...
end tell
As a workaround, use the list-filtering handler developed earlier in this book (under "Power Handler Tricks" in Chapter 9).
Operations on Multiple References
When an element specifier would return a list of references, it may be possible to ask for an attribute of this list as a shorthand for asking for that attribute of each element of the list in turn; the request to fetch the attribute is applied distributively to each item of the list.
For example, this works, and returns a list of strings, the names of each disk in turn:
tell application "Finder" to get name of every disk
Similarly:
tell application "iTunes"
tell view of browser window 1
get name of every track
end tell
end tell
Possibly you can even apply this construct to the result of a boolean test:
tell application "iTunes"
tell view of browser window 1
get database ID of every track whose name contains "Palestrina"
end tell
end tell
Those examples illustrate a property; the same thing may work for an element:
tell application "Finder"
get file 1 of every folder
end tell
When you request multiple elements distributed across a list in this way, whether you get back a list of lists or a single flattened list depends upon the individual application. For example:
tell application "Address Book"
get every email of every person
end tell
The result of that code is a list of lists—the outer list has as many items as there are persons, with each item being a list of every email address of the corresponding person. But when you try something