-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathTODO.txt
More file actions
117 lines (50 loc) · 13.3 KB
/
TODO.txt
File metadata and controls
117 lines (50 loc) · 13.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
TO DO:
- AutoReleasePools?
- there is a serious bug when comparing Any result to MissingValue:
print(try Finder().home.name.get() == MissingValue) // returns true!!! (should be false as result is a String value)
- another problem will be when using `==` on a result that may be a specifier, since == constructs a test clause; going to have to give these overloads more thought; at worst, switch to `eq`, `ne`, `lt`, etc, or custom operators which won't clash with builtins
- one problem with overriding `==` for use in test clauses is that swiftc is rather dopey about resolving ambiguous overloads; dunno if there's any way to tell it to ignore this override if LHS is not explicitly ObjectSpecifier, e.g.:
print(("" as Any) == ("" as Any))
error: cannot convert value of type 'Any' to expected argument type 'ObjectSpecifier'
print(("" as Any) == ("" as Any))
~~~^~~~~~
- amusing translation error:
tell application "Keynote"
--get font of object text of every text item of master slides of document 1
set font of object text of (every text item whose object text's font starts with "IowanOldStyle-") of master slides of document 1 to "Century Schoolbook"
end tell
gives:
try Keynote(name: "/Applications/Keynote.app").customRoot(Error -1700: Can't unpack malformed descriptor:
<AEDesc: 'obj '{ 'form':'test', 'want':'shtx', 'from':'obj '{ 'form':'indx', 'want':'KnMs', 'seld':'abso'($206C6C61$), 'from':'obj '{ 'form':'indx', 'want':'docu', 'seld':1, 'from':null() } }, 'seld':'cmpd'{ 'relo':'bgwt', 'obj1':'obj '{ 'form':'prop', 'want':'prop', 'seld':'font', 'from':'obj '{ 'form':'prop', 'want':'prop', 'seld':'pDTx', 'from':'exmn'($$) } }, 'obj2':'utxt'("IowanOldStyle-") } }>
Can't unpack object specifier's selector data. Can't unpack malformed descriptor:
<AEDesc: 'cmpd'{ 'relo':'bgwt', 'obj1':'obj '{ 'form':'prop', 'want':'prop', 'seld':'font', 'from':'obj '{ 'form':'prop', 'want':'prop', 'seld':'pDTx', 'from':'exmn'($$) } }, 'obj2':'utxt'("IowanOldStyle-") }>
Can't unpack comparison test: malformed descriptor.).objectText.font.set(to: "Century Schoolbook")
1. SpecifierFormatter.formatValue() needs to check for Error, and show opaque description string (e.g. "«malformed-descriptor»")
2. The above is due to a bug in the unpack code rather than a malformed AEDesc, so need to track down and fix that as well.
- starting to dislike PREFIXApp, PREFIXCon, PREFIXIts as they're a pain to type and inconsistent with other SA syntax; change to PREFIX.app, PREFIX.con, PREFIX.its and see how that compares (semantically it's a little awkward, since PREFIX is shorthand for PREFIXSymbol, but if we consider PREFIX a generic namespace used by glue to hold all related objects then it probably makes sense; one could even argue for all glue classes moving into that namespace, eliminating prefixes on their names - however, Swift lacks a definitive `namespace` statement so forces hacky workarounds using `class`/`struct`/`enum` instead, thereby muddying semantics even worse); note that app, con, its could also be defined as static constants on glue's Application class (whether this would help or confuse is unclear). Ah, the joys of bridging rigidly OO syntax+semantics to non-relational systems.
- For convenience, generated glues include a convenience initializer containing the bundleID for the target application, allowing user to write [e.g.] `TextEdit()` as shorthand for `TextEdit(bundleIndentifier: "com.apple.TextEdit")`. However, in Swift3/Xcode8, if the glue's application class uses the following convenience initializer, it crashes with EXC_BAD_ACCESS, presumably due to a Swift bug:
public class TextEdit: TEDRoot, Application {
public convenience init(launchOptions: LaunchOptions = DefaultLaunchOptions, relaunchMode: RelaunchMode = DefaultRelaunchMode) {
// call the by-bundleID convenience initializer defined in Application
self.init(bundleIdentifier: "com.apple.TextEdit", launchOptions: launchOptions, relaunchMode: relaunchMode) // CRASHES
}
}
For now, the workaround is for the initializer to call the superclass's required initializer `RootSpecifier.init(rootObject:appData:)` directly.
- Define standard structs for representing color, position, etc.? (And/Or support packing/unpacking Cocoa equivalents, e.g. NSColor?) The default behavior is to pack/unpack as Array<Int>, but type-safe alternatives could also be provided that ensure whatever type of descriptor an app returns (typeAEList/typeQDRectangle) the final result is normalized to the semantic type specified by the user (e.g. SwiftAutomation.RectangleRecord). Also, how practical to support packing/unpacking image types (a known mess), e.g. bridging typeTIFF, typePICT, etc to NSImage?
- once Swift fully supports redistributable frameworks, implement an `aeglue-framework` bash script that takes a folder of generated glue+sdef files then runs /usr/bin/swift to compile, build, and codesign them as an importable framework and/or Swift package
- check Symbol.symbol() lookup performance on on very large switches [e.g. InDesign]; if noticeable, a dictionary could be used to cache previous lookups
- canonicize most/all Swift method names, e.g. pack(value:) instead of pack(_ value:)?
- the `isInt64Compatible` flag's' default is `true` on the assumption that most apps will do the right thing upon receiving `typeUInt32`/`typeSInt64`/`typeUInt64` descriptors (i.e. coerce them to whatever type[s] they actually need, e.g. Double), and apps like Excel which only accept `SInt32` and `Double` (which are what AppleScript uses) and fail on anything else are in the minority. If that assumption turns out to be wrong, this flag will need to be made `false` by default (i.e. emulate AppleScript's behavior). Note that this only affects integers beyond ±2**31; integers than can be packed into SInt32 always will be.
- currently Application.customRoot(object) allows the creation of individual object specifiers with a non-typeNull terminator, e.g. `Finder().customRoot(aURL).name` is equivalent to `tell app "Finder" to name of POSIX file "..."`. In practice, this is almost never neeeded (or supported by apps), but it's included for maximum AppleScript 'quirk-for-quirk' compatibility. Should AppData also provide an option to set the default app root object to be used in building and unpacking _all_ object specifiers? The only place this might be useful is in Automator when packing fully qualified object specifiers; OTOH, fully qualified object specifiers always were a bad solution to the problem of binding AEAddressDescs to objspec descriptors, and Automator's a dead-end and largely moribund product anyway.
- note that file system specifiers (typeAlias, typeFileURL, typeFSRef, etc) currently don't roundtrip (they all get coerced down to typeFileURL, regardless of their original type, and URL instances always pack as typeFileURL); this may or may not be a problem when dealing with older Carbon apps. One solution may be an `isFileURLCompatible` flag that, if set to false, packs URLs as as typeAlias if the path identifies an existing FS object and typeFileURL if it does not. (Packing as typeFSRef is redundant and typeFSS is defunct, so those should not need supported.) -- TBH, probably best forget about roundtripping these types, pack all file: URLs as typeFileURL, and hope for the best: 1. there's no way to attach their AEDescs to a URL struct, and 2. URL structs don't support isFileReferenceURL so there's no way to tell if they're a bookmark (in which case pack as typeAlias) or a path (pack as typeFileURL)
- typeBookmark/typeAlias descriptors identify file system *objects* [e.g. by inode], whereas typeFSRef/typeFileURL identify file system locations; however, only NSURL can distinguish the two so for now any Bookmark/Alias information will be lost on conversion to Swift `URL` instances, while `URL` will always pack as typeFileURL. This may change in future depending on how many compatibility issues with older Carbon apps this lack of roundtripping throws up.]
- Q. how difficult would it be to auto-generate enum/struct/typealias type definitions from an app's AETE/SDEF? (bearing in mind that AETE/SDEF-supplied type info is frequently vague, ambiguous, incomplete, and/or wrong, so a manual option will always be required as well); this basically falls into same camp as how to auto-generate struct-based record definitions as a more static-friendly alternative to AppData's standard AERecordDesc<->[Symbol:Any] mapping; may be worth exploring later (and will need a manual format string option as well, e.g. "STRUCTNAME=PROPERTY1:TYPE1+PROPERTY2:TYPE2+...").
ANSWER: it'd be doable, but practically useless. Incomplete/incorrect type info is commoner than muck in app dictionaries - even the `path` property of Standard Suite's `document` class is wrong, declaring its type as `text` when it's really `text or missing value`; furthermore, because most Cocoa apps use `text` for both cText and typeUnicodeText, it's impossible to know which of these a given property actually holds. (Note: this also buggers up dictionary viewers and AEOM browsers by making it impossible to distinguish a property that represents an object attribute from a property that represents a one-to-one relationship with another object. Meantime, if the `text` property was declared correctly as a reference, getting document's properties as a record struct would break because the app automatically resolves the request to return text, not a reference.) In other words, generating correct glue classes is impossible without additional manual correction; if Apple's own devs can't get this information right in CocoaScripting's standard terminology and CocoaScripting lets them away with it too, what chance have Cocoa app developers of getting their app-specific terms correct; never mind Carbon apps which don't care about or use crappy AETE (or SDEF) type info at all?
FWIW, if a pure-Swift AEOM handler framework ever gets built, it could address all these issues by radically simplifying and comprehensively prescribing the AEOM spec, then generate a formal IDL from the implementation which could be used to generate a robust glue (not to mention much more detailed user documentation, free test suites, and reliable implementation). Until then, the only value in auto-generating these definitions (as format strings only, not as Swift code) would be to give users a starting point from which to make their own corrections; and under the circumstances it'd simpler for them just to write minimal format strings for the bits of records they'll actually use, or just use the standard [Symbol:Any] dictionaries and do their own checking/casting of property values as needed. (Though if SwiftAutomation ever catches on then app developers might consider creating and distributing ready-to-use glue modules themselves, saving users the hassle of generating their own, at which point more powerful tools might be of some advantage).
- worth including convenience API for interacting with `NSAppleScript`/`NSUserAppleScriptTask`/`OSAScript`? Given that SwiftAutomation provides automatic Swift<->AE type bridging, it seems a pity not to take advantage of it as it'll greatly reduce the amount of effort needed to make Swift apps attachable. Or should that be spun off into its own library to avoid crudding up SwiftAutomation's main API? (Probably the latter, as it allows that code to evolve independently later on. That may be particularly significant if the app also implements its own AEOM which attached scripts will want to interact with; doubly so if Swift ever gets a native AEOM framework [as a non-sucky alternative to CocoaScripting]; triply so if it can get a non-sucky replacement to the awful, archaic, and barely supported/supportable ComponentManager-based OpenScripting [OSA] framework.)
- default SendMode is currently [.waitForReply, .canInteract]; confirm this is same as AppleScript
- can custom mirrors be improved? what info should they show? (one problem is that playgrounds tend to display array of specifier as mirror, not description/debugDescription, which is unhelpful)
- need to check both AETE and SDEF parsers work correctly with apps that have multiple terminologies (e.g. if app also has scriptable plugins)
- also find out if macOS's SDEF-to-AETE converter now handles 'unprintable' OSTypes correctly (i.e. uses hex representation)
- add `GlueTable.export()` method that exports name-code tables in a generic data format (e.g. JSON or INI) that is trivial to edit and parse back in, allowing dynamic bridge users to work around buggy/broken terminology by manually exporting, patching, and reimporting terms (note: Swift users can just patch the generated .swift glue files directly).
Another possibility would be for user just to edit SDEF file then have dynamic bridge read that. Pro: using SDEF format avoids need for different file format. Cons: 1. 90% of sdef data is irrelevant and just takes up space, and 2. plain lookup tables are simpler to edit as they've already eliminated all duplicate definitions, whereas user'd need to edit all duplicates to avoid creating new problems. Though both cons could be ameliorated by an aeglue option that strips the sdef down to contain minimum information (e.g. all properties would appear on application class, and all attributes except name and code would be stripped from tags.