Object specifiers
How object specifiers work
[TO DO: finish (note that this is a bit of a rehash of ch.2; might be simpler just to refer users back to that)]
A property contains either a simple value describing an object attribute (name
, class
, creationDate
, etc.) or an object specifier representing a one-to-one relationship between objects (e.g. home
, currentTrack
).
Elements represent a one-to-many relationship between objects (documents
, folders
, fileTracks
, etc).
TO DO: note both appear as properties on XXSpecifier; users don't instantiate XXSpecifier directly but instead construct via chained property/method calls from XXApplication or generic specifier root (XXapp, XXcon, XXits)
characters/words/paragraphs of documents by index/relative-position/range/filter
[TO DO: list of supported reference forms, with links to sections below]
[TO DO: following sections should include AppleScript syntax equivalents for reference]
Reference forms
Property
-(instancetype)PROPERTY;
Syntax:
specifier.property
Examples:
textedit.name
textedit.documents[1].text
finder.home.files.name
All elements
-(instancetype)ELEMENTS;
Syntax:
specifier.elements
Examples:
finder.home.folders
textedit.documents
textedit.documents.paragraphs.words
Element by index
- (instancetype)objectAtIndexedSubscript:(int)idx;
- (instancetype)objectForKeyedSubscript:(id)key;
Syntax:
elements[selector]
selector : int | id -- the object's index (1-indexed), or other identifying value [1]
[1] While element indexes are normally integers, some applications may also accept other types (e.g. Finder's file/folder/disk specifiers also accept alias values). The only exceptions are NSString
and XXSpecifier
, which are used to construct by-name and by-test specifiers respectively.
Be aware that index-based object specifiers always use _one-indexing_ (i.e. the first item is 1, the second is 2, etc.), not zero-indexing as in Objective-C (where the first item is 0, the second is 1, etc.).
Examples:
words[3]
items[-1]
Element by name
- (instancetype)objectForKeyedSubscript:(id)key; // key must be NSString*
- (instancetype)named:(id)name;
Specifies the first element with the given name. (The subscript syntax is preferred; the named
method would only need used if a non-string value was required.)
Syntax:
elements[selector]
selector : NSString* -- the object's name (as defined in its 'name' property)
Applications usually treat object names as case-insensitive. Where multiple element have the same name, a by-name specifier only identifies the first element found with that name. (To identify all elements with a particular name, use a by-test specifier instead.)
Examples:
disks[@"Macintosh HD"]
files[@"index.html"]
Element by ID
- (instancetype)ID:(id);
Syntax:
[elements ID: selector]
selector : id -- the object's ID (as defined in its 'id' property)
Examples:
[windows ID: 4321]
Element by absolute position
- (instancetype)first;
- (instancetype)middle;
- (instancetype)last;
- (instancetype)any;
Syntax:
elements.first -- first element
elements.middle -- middle element
elements.last -- last element
elements.any -- random element
Examples:
documents.first
paragraphs.last
files.any
Element by relative position
- (instancetype)previous:(AEBSymbol *)elementClass;
- (instancetype)middle:(AEBSymbol *)elementClass;
Syntax:
// nearest element of a given class to appear before the specified element:
[element previous: typeName]
// nearest element of a given class to appear after the specified element
[element next: typeName]
typeName : AEBSymbol* -- the name of the previous/next element's class
Examples:
[words[3] next: TED.word] // word 4
[paragraphs[-1] previous: TED.character] // the last character before the last paragraph
Elements by range
- (instancetype)from:(id)to:(id);
Range references select all elements between and including two object specifiers indicating the start and end of the range. The start and end specifiers are normally declared relative to the container of the elements being selected.
These sub-specifiers are constructed using the glue's' XXcon
constant, e.g. TEDCon
, as their root. For example, to indicate the third paragraph relative to the currrent container object:
TEDCon.paragraphs[3]
Thus, to specify all paragraphs from paragraph 3 to paragraph -1:
[paragraphs from: TEDCon.paragraphs[3] to: TEDCon.paragraphs[-1]]
For convenience, sub-specifiers can be written in shorthand form where their element class is the same as the elements being selected; thus the above can be written more concisely as:
Some applications can handle more complex range references. For example, the following will work in Tex-Edit Plus:
[words from: TEPcon.characters[5] to: TEPcon.paragraphs[-2]]
Syntax:
[elements from: start to: end]
start : NSNumber* | NSString* | AEBSpecifier* -- start of range
end : NSNumber* | NSString* | AEBSpecifier* -- end of range
Examples:
[documents from: @1 to: @3]
[folders from: @"Documents" to: @"Movies"]
[text from: TEPCon.characters[5] to: TEPCon.words[-2]]
Elements by test
- (instancetype)objectForKeyedSubscript:(id)key; // key must be AEBSpecifier*
A specifier to each element that satisfies one or more conditions specified by a test specifier:
elements[selector]
selector : XXSpecifier* -- test specifier
Test expressions consist of the following:
A test specifier relative to each element being tested. This specifier must be constructed using the glue's 'XXits' root, e.g.
TEDIts
. Its-based references support all valid reference forms, allowing you to construct references to its properties and elements. For example:TEDIts TEDIts.size TEDIts.words.first
One or more conditional tests, implemented as operators/methods on the specifier being tested. The receiver must be an
XXSpecifier
instance; the argument can be anything.Syntax:
[specifier lt: value] // less than [specifier le: value] // less or equal [specifier eq: value] // equal [specifier ne: value] // not equal [specifier gt: value] // greater than [specifier ge: value] // greater or equal [specifier beginsWith: value] [specifier endsWith: value] [specifier contains: value] [specifier isIn: value]
Examples:
[TEDIts eq: @""] [FINits.size gt: @1024] [TEDIts.words.first beginsWith: @"A"] [TEDIts.characters.first eq: TEDIts.characters.last]
Zero or more logical tests, implemented as properties/methods on conditional tests. All arguments must be conditional and/or logic test specifiers.
Syntax:
[test AND: test] [test OR: test] test.NOT
Examples:
[TEDIts contains: @"?"].NOT [[FINits.size gt: @1024] AND: [FINits.size lt: @10240]] [[[TEDIts.words[1] beginsWith: @"A"] OR: [TEDIts.words[1] contains: @"ce"]] OR: [TEDIts.words[2] eq: @"foo"]]
Element insertion location
Insertion locations can be specified at the beginning or end of all elements, or before or after a specified element or element range.
- (instancetype)beginning;
- (instancetype)end;
- (instancetype)before;
- (instancetype)after;
Syntax:
elements.beginning
elements.end
element.before
element.after
Examples:
documents.end
paragraphs.last.before