Skip to main content

3-1: Specifiers

A specifier is a composable query of relations. The concepts and syntax come directly from AppleScript.

See also: Quick Tutorial.

Relations#

Relations relate items to each other, connecting them through an item graph.

Relations are not themselves syntactic elements, but exist at runtime between items, and are described by specifiers.

There are two types of relations: element relations and property relations.

Chaining#

A specifier is a chain of relation descriptions, starting from a concrete root item.

For example, a specifier referring to the id property of a root item is a chain of one relation description. On the other hand, a specifier referring to the length property of the Calendar event before the event "Lunch" of the root item (a Calendar account) is a chain of three relation descriptions.

Element relations#

Element relations are one-to-many relations keyed by type. Elements can be specified via an indexing form, and possibly one or two additional identifying items.

Element specifiers#

An element specifier describes an element relation. The syntax varies by indexing form, but always includes a type term.

Indexing forms#

Each element relation has an indexing form that specifies how it selects items.

Simple#

Simple form is a convenience syntax for either Name or Index form, depending on the type of identifying item used.

Identifying item: A string, integer or real. string makes a Simple specifier act like a Name specifier; integer and real make a Simple specifier act like an Index specifier. An item that is not of one of these types produces a runtime error.

document "Untitled"
window 1

Name#

Name form specifies a single element according to the value of its ae4:pnam (name) property.

Identifying item: A string that a name property must match.

document named "Untitled"

Index#

Index form specifies a single element according to the value of its ae4:pidx (index) property.

Identifying item: A number that an index property must match.

window index 1

ID#

ID form specifies a single element according to the value of its ae4:ID   (id) property.

Identifying item: An item that an id property must match.

-- Suppose the document's identifying item is the integer 123.
document named "Untitled" --> document id 123
let docid be id of that --> 123
document id docid --> document id 123

Absolute positioning#

Absolute Positioning form specifies a single element according to its ordinal position within a container.

No identifying items, but the selection varies based on the positioning used.

The choice of first, middle, last or some affects the meaning of the specifier:

  • first selects the item ordered first in its container; typically equivalent to <type> index 1.
  • middle selects the item ordered at the center of its container (the median item), preferring the one ordered first when a two-way tie occurs. For a sequence with a length property, equivalent to <type> index (floor (length / 2)).
  • last selects the item ordered last in its container; for a sequence with a length property, equivalent to <type> index (length).
  • some selects a random item from the container. No, seriously. Listen, this was Apple's idea, not mine 👀.
first window
middle window
last window
some window

Relative positioning#

Relative Positioning form specifies a single element according to its ordinal position relative to another element in the same container.

No identifying items, but the selection varies based on the positioning used.

The choice of before or after affects the meaning of the specifier:

  • before selects the item ordered immediately before the reference element.
  • after selects the item ordered immediately after the reference element.

Note that the reference element is not an identifying item, but is rather the immediate parent of the specifier.

window before last window
window after that --> last window

To form a Relative Positioning specifier under the current default target, it must be used, since the syntax requires explicit mention of the parent after before/after; i.e., window after is not a syntactically valid specifier:

window after it

All#

All form specifies every element in a container.

No identifying items.

every window
all window

Range#

Range form specifies elements within a range of values in a container. The test used to determine whether an item is in the range depends on the element and container types, and possibly the type of the identifying items used.

Identifying items: One representing the lower bound, and another representing the upper bound.

paragraph 1 thru 2
window 2 through -1

Filter#

Filter form specifies elements that pass a certain custom test.

A Filter test is predicated on comparions between test specimen-rooted specifiers and other items. Logical operations can compose these tests to form new tests.

No identifying items, but a special test predicate expression is used instead.

The test expression should usually consist of binary comparison or logical operations.

Specimen specifiers#

Syntactically unrooted specifiers in the test expression are implicitly rooted in the test specimen item. Such specifiers are called specimen specifiers, and are reevaluated for each item tested.

window where name contains "Google"

name in this context is a specimen specifier.

Property relations#

A property relation relates a host item to a value item via a property term. While element relations are one-to-many, property relations are one-to-one. Property relations often describe the host item with number or string values, although they can also act as references to other complex items.

Property specifiers#

A property specifier describes a property relation, and is created by simply naming a property term.

name
current tab

Evaluation#

Evaluating a specifier follows its query chain to arrive at a value (or storage location for set).

Implicit evaluation#

Specifiers are implicitly evaluated in most expression contexts. This means that naming a specifier will, by default, result in the specifier's current value rather than a static, unevaluated specifier item.

The following are all the contexts where specifiers are not implicitly evaluated:

  • The argument of a reference expression (see below); e.g., ref window 1.
  • The target expression of a tell expression; e.g., tell window 1.
  • Key expressions in a record; e.g., {name: "abc"}.
  • The destination of a set expression; e.g., set URL to "https://google.com/".
  • The parent expression of a specifier phrase; e.g., name of window 1 (the final specifier will be evaluated, but window 1 will not).
  • Filter test expressions; e.g., window where name is "Untitled" (the final specifier will be evaluated, but name will not).

Explicit evaluation#

A specifier can be explicitly evaluated with a get expression. This always results in evaluation, even in contexts where implicit evaluation is disabled.

Reference expressions#

Implicit evaluation can be contextually disabled with a ref expression. This always creates a specifier item, which can then be sent in remote calls or evaluated later.

Last updated on by Ian Gregory