forked from mattneub/applescript-stdlib
-
Notifications
You must be signed in to change notification settings - Fork 5
/
TODOs.txt
294 lines (129 loc) · 29.6 KB
/
TODOs.txt
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
TO DO:
- TestTools contains various TODOs, mostly enhancements, but since that library is currently somewhat hamstrung by AS compiler bug those should be tabled for now
- TypeSupport contains various TODOs - enhancements, safety improvements, etc:
- coercing a record to `any[thing]` throws error -1700(!) due to AS stupidity; need to go through handlers below and check they coerce to `any` where appropriate (i.e. to ensure ASOC objects are converted to their AS equivalents before use), with workarounds as necessary (e.g. in `asList`, to handle the case where the item is a record or specifier)
- note: make sure `asTYPEParameter` handlers will always accept ASOC objects, coercing to corresponding AS type (i.e. don't add any checks that'd cause them to reject 'ocid' specifiers), e.g. `asNumberParameter` will probably currently fail on ASOC object as it doesn't first coerce to `any`; might be best if all `asTYPEParameter` handlers first coerce to `any` before coercing to actual required type (the only exception would be an `asReferenceParameter` handler, as that needs to typecheck only, as coercing a specifier dereferences it) -- OTOH, coercing a specifier to list is semantically ambiguous (should it dereference in hope of receiving a list?), while AS fails when coercing a record to any
- should asTextParameter() always throw an error if value is a list? (i.e. avoids inconsistent concatenation results due to TIDs); another option would be to whitelist some or all known 'safe' types (integer/real, text, date, alias/file/furl, etc) and reject everything else; this should ensure stable predictable behavior - even where additional custom coercion handlers are installed (users can still use other types of values, of course; they just have to explicitly coerce them first using `as` operator)
- `missing value` and other type/constant symbols are currently accepted by asTextParameter, though may coerce to either keyword name text or raw chevron text, which may be a reason for `asTextParameter` to disallow them
- add more AS-to-ASOC handlers? also include error checking, and provide both `asNSCLASS` and `asNSCLASSParameter` variants
- various TODOs in Web
- finish tests, documentation
======================================================================
The following TODOs are deferred/ignored/rejected:
- ideally, these libraries would be owned by Apple and always use all-lowercase four-char codes to avoid any conflicts with 3rd-party (mixed-case) codes; however, changing their dictionaries this way would only be practical if Apple took over these libraries before they were widely distributed, as once they're in the wild it'll be a giant PITA to change their current four-char codes without breaking users' existing scripts)
----------------------------------------------------------------------
Date
----------------------------------------------------------------------
- what about NSDateComponentsFormatter, NSDateIntervalFormatter? (e.g. handy for formatting time intervals, although it is possible to kludge that already using date arithmetic)
- see also NSFormattingContext... constants in NSFormatter.h for fine-tuning capitalization for standalone/start-of-sentence/in-sentence use (TBH, any user who needs this level of control would be better using Cocoa classes directly)
- what additional info should appear in `locale info` record? (see NSLocale Component Key constants)
----------------------------------------------------------------------
File
----------------------------------------------------------------------
- add support for enumeration type in `parse command line arguments`, where valueType is a list of allowed text values, e.g. {"yes", "no", "maybe"}; allowed chars would be same as for long option names (Q. should it be case sensitive?)
- Standard Additions' `read` and `write` commands don't always provide good explanatory error messages (e.g. passing wrong `as` parameter just gives 'Parameter error.' -50); Cocoa error messages often aren't very helpful either. Not sure there's anything can be done about this.
- is there any benefit to adding `with UTF8 byte order mark` option to `write to file`? (NSString automatically adds UTF16/32 BOMs, but doesn't add UTF8 BOM for compatibility's sake; however, users might want to add UTF8 BOM to improve portability of files they intend to distribute)
- commands for safely creating temp file/dir? (challenge here is doing it securely, via `do shell script`; see: http://developer.apple.com/library/etc/redirect/xcode/mac/1153/documentation/OpenSource/Conceptual/ShellScripting/ShellScriptSecurity/ShellScriptSecurity.html)
- is there a Cocoa API to fuzzily convert IANA charset names to NSString encodings? if so, would be better than hardcoded list of encoding constants. A. Doesn't appear to be; also, NSStringEncodings aren't a directly interchangeable subset of CFStringEncodings, and since CFString APIs aren't accessible via ASOC there isn't any way to access the additional CF encodings anyway
- implement Windows path support in `convert path`? (TBH, CFURLCreateWithFileSystemPath and CFURLCopyFileSystemPath don't do a convincing job of this on OS X, so probably best forget about this)
- any way to determine (via Cocoa) if stdout/stderr is connected to a terminal? if so, get rid of `terminal styles` parameter in `format command line help`? or provide separate `outputs to terminal` command that returns true/false (isStyled should only be true if help text will be displayed in Terminal.app or other VT100 terminal emulator) - A. probably not: isatty() is part of C stdlib, which ASOC can't import AFAIK, and NSFileHandle doesn't provide an equivalent method
- if isStyled, text should be auto-wrapped to terminal width; Q. any way to get current terminal width, if available? (suspect that's a C call only [e.g. see osatest's terminalColumns() function]; anything in NSUserDefaults?)
- in `read from file` allow `unknown encoding` to be passed, in which case use NSString's stringWithContentsOfFile:usedEncoding:error:, which tries to determine file's text encoding in various ways (e.g. by checking for BOM or "com.apple.TextEncoding" extended file attribute)? downside of that approach is that it really ought to return the encoding along with text for caller's information, which would make the command's return type inconsistent; another option might be to cheat it and implement a separate `detect encoding` and/or `guess encoding` command that returns just the encoding (ideally along with a value that indicates whether it's a reliable determination based on BOM or extended attribute or a heuristic guess)
- what is status of alias and bookmark («class bmrk») objects in AS? (the former is deprecated everywhere else in OS X; bmrk objects are poorly supported, with crashing bugs, and rarely appears); what can/should/shouldn't be done to support these?
----------------------------------------------------------------------
List
----------------------------------------------------------------------
- implement `ordered comparator for {enum_1, enum_2, ..., enum_N}` that works for any enumeration, including boolean
- in _sort(), if resultListObject's _list_'s length>someLargeThreshold then use median of 3 items? (TBH, picking a good midrange pivot is probably least of its problems performance-wise)
- stable sorting? A. currently out of scope: a non-stable sort is still better than no sort at all, although `sort list` documentation does need to state that it isn't stable sort so items that are 'equal' aren't guaranteed to maintain their original order, e.g. sorting {{name:"Bob", age:33}, {name:"Jan", age:33}} on age only can return either {{name:"Bob", age:33}, {name:"Jan", age:33}} or {{name:"Jan", age:33}, {name:"Bob", age:33}}
- what about lists containing lots of duplicates, e.g. when sorting a large list containing only numbers from 0 to 10, or only true/false? basic quicksort gets pathological on those cases, so a three-way quicksort or a mergesort would work much better there
- might consider using NSMutableArray when sorting simple uniform lists of text or number without a user-supplied comparator (would need to compare costs of ASOC bridging vs native sorting to see which performs better); not sure about dates given that they're mutable (ASOC will perform deep copy of list, so resulting list will contain copies of the original date objects, whereas native sort preserves the original date objects); complex values (e.g. list of records) will still be sorted natively, of course (though even there it might be possible to use NSArray to sort an array of [key,valueIndex] and then iterate the result to reposition values in output list, making the [slow] AS part of the code O(2n))
- would it be worth implementing an ArrayCollection object that encapsulates list lookup kludges, and just encouraging users to use that for manipulating lists (in which case some/most of the below handlers might be as well made into methods on that); A. out of scope for stdlib: since it's an AS flaw it should be fixed at source, though would be useful as a 3rd-partly library
- in `search text`, when matching with TIDs, optionally accept a list of multiple text values to match? (note:TIDs can do that for free, so it'd just be a case of relaxing restriction on 'for' parameter's type when pattern matching is false to accept a list of text as well); also optionally accept a corresponding list of replacement values for doing mapping? (note that map will need to be O(n) associative list in order to support considering/ignoring, although NSDictionary should be usable when matching case-sensitively)
----------------------------------------------------------------------
Number
----------------------------------------------------------------------
- what about NSByteCountFormatter, NSEnergyFormatter, NSMassFormatter, NSLengthFormatter, MKDistanceFormatter? Also, is it worth trying to support AS's largely neglected and awkwardly incomplete unit types, or is it better just to leave those to do their own thing (i.e. limited range unit conversions) and deal solely with plain numbers? If the latter, would it be worth provided more comprehensive `convert [length/mass/volume/etc] NUMBER from UNIT to UNIT` commands here, eliminating the need for users to use AS's unit types completely?
- what else needs implemented? e.g. atan2? (note that trivial operations such as `hypotenuse`, `square` and `square root` are not implemented as those are simple to do using AS's existing `^` operator (e.g. sqrt(n)=n^0.5), while `floor`, `ceil`, etc. are already covered by `round number`
- support `NSNumberFormatterOrdinalStyle`, `NSNumberFormatterCurrencyISOCodeStyle `, etc (10.11+) in `parse/format number`?
- in `format number`, any way to include "+" sign for exponent, same as AS? (e.g. "1.0E+8" rather than "1.0E8")
----------------------------------------------------------------------
Objects
----------------------------------------------------------------------
- worth adding 'maximum size' option to stack and queue constructors? (simplest way to implement it is to define a script object can inherit either StackCollection or QueueCollection [caveat this will obscure original object's name, which users should be able to see when logging/displaying a script object, e.g. for troubleshooting purposes], overriding addItem() to check `my _count` before continuing)
- any other data structures worth adding? e.g. PriorityQueueCollection?
- decide naming convention for constructors; e.g. `make dictionary object` vs `make dictionary` vs `dictionary object` vs `new dictionary`? (`new ...` might be safest, as 'new' isn't an existing AS keyword, whereas `make ...` will try to to compile as `[make] [identifier]` if the full command isn't found) (note: if sticking to verb-noun format, `create ...` might be an option: while 'create' keyword was used as a synonym for 'make' in some early apps, e.g. FMP, 'create' isn't a keyword in AS dictionary itself); would quite like to get rid of 'object' suffix (which is really only included to make the keyword more 'unique' and less likely to conflict/compile incorrectly) as it isn't used consistently and smacks of restating the obvious; another consideration: comparator constructors use noun-only names, e.g. `text comparator`, which suggests `dictionary collection`, `unique collection`, `queue sequence`, `stack sequence` might be better names for constructors
- decide naming convention for object methods: traditional positional parameters or ObjC-style syntax? e.g. `setItem(k, v)` vs `setValue: v forKey: k` (while the former doesn't explicitly describe each parameter, the latter is visually ambiguous and often needs parentheses to avoid being mis-read by both AS and users)
- Is it worth implementing a growable bucket list? or would a balanced B-tree be more efficient? (it would eliminate the significant impact of dynamically growing bucket list, though lookups will be O(log n) rather than ameliorated O(1) [degrades as collisions increase] and inserts will likely be slower due to rebalancing [which requires each traversed node's key to be re-compared]); TBH, the simplest and most efficient option would probably be to use a default size (e.g. 1024) suitable for light-to-medium use, but allow a different size to be optionally passed to constructor command if user needs a particularly large or small collection; however, that isn't very user-friendly, in which case a better option may be to grow by fixed sizes only (e.g. 128->2048->32768)
- Is it worth implementing a case-insensitive Dictionary? (client code traditionally normalizes keys (e.g. by lowercasing) prior to adding items, but it may be more user-friendly to do it automatically)
- option to specify no. of buckets? (cheaper than growing dynamically, but also less user-friendly); if so, would probably make more sense to use enum rather than int, e.g. `small`/`default`/`large`; however, probably best to try a conservative growing algorithm first (e.g. starts at 256 and grows 4x/8x each time, with additional tweak to pre-grow dictionary before adding a large list of items) and see how well that works in practice (i.e. if auto-growing proves to be 'good enough' then it's best to keep things simple for users and not complicate its API with technical housekeeping crud); alternatively, maybe just stick with 1024-item bucket list as a reasonable compromise (users who need more speed and are only working with basic types can still use NSMutableDictionary if they wish)
- if implementing variable size bucket lists, addDictionary() will be faster if records include hashNum, avoiding need to fully re-hash keys
- removed `unique collection` for now as it's a quick-n-dirty implementation (just a wrapper around `dictionary collection`) and currently lacks most set functionality (union, intersection, etc). Furthermore, there is a good argument to be made for using NSMutableSet, either directly or in a script object wrapper, as unlike `dictionary collection` it only has to support a few basic AS types - integer, real, text, date - which are all fully bridged and safely round-trippable. (Ideally, type and constant names would also be supported, but NSAppleEventDescriptors aren't hashable and there's probably not much need for it in practice.) The downside of using NSMutableSet is that it breaks autosave and serialization, something these libraries aim to avoid, so might be best left to a third-party library.
----------------------------------------------------------------------
TestTools
----------------------------------------------------------------------
- implement line-wrapping in TestSupport.scpt to improve readability when displaying reports in Terminal
----------------------------------------------------------------------
Text
----------------------------------------------------------------------
- extended backreference syntax should really allow backslash-escaped “}” and “\” characters to appear within braces (currently these two characters are disallowed by _tokens pattern)
- fix inconsistency: `search text`'s `for` parameter doesn't allow list of text but `split text`'s `using` parameter does, even though both commands are supposed to support same matching options for consistency
- should line break normalization (in `normalize text` and `join paragraphs`) also recognize `Unicode line break`, `Unicode paragraph break` constants?
- need to decide exactly what constitutes a line break in `transform text`, and make sure both paragraph element and pattern based splitting are consistent (e.g. what about form feeds and Unicode line/paragraph breaks?)
- 10.11 provides -[NSString stringByApplyingTransform:reverse:]; currently this is only used to convert Unicode codepoint escapes (e.g. "\u1234"), but in future could be expanded on, e.g. `transform text` could add `smart punctuation` and `ASCII punctuation` options, options to convert text between Asian and Latin representations, etc.
- add `matching first item only` boolean option to `search text` (this allows users to perform incremental matching fairly efficiently without having to use an Iterator API)? Currently inclined to reject this, as `search text` command is already fairly complex so am reluctant to add any more parameters unless a convincing use case is identified first.
- would it be worth implementing a `compare text` command that allows considering/ignoring options to be supplied as `considering`/`ignoring` parameters (considering/ignoring blocks can't be parameterized as they require hardcoded constants) as this would allow comparisons to be safely performed without having to futz with considering/ignoring blocks all the time (c.f. Number library's `compare number`); for extra flexibility, the comparator constructor should also be exposed as a public command, and the returned object implement the same `makeKey`+`compareItems` methods as List library's sort comparators, allowing them to be used interchangeably (one could even argue for putting all comparators into their own lib, which other libraries and user scripts can import whenever they need to parameterize comparison behavior). Currently inclined to reject this: while reliably comparing text in AS is a PITA, don't think having such a command will do much to improve things (end users will likely continue to use standard operators in their own code, and library developers will be better off adding considering/ignoring blocks as required.)
- in `_findText`, is it worth switching to a more efficient algorithim when hypens, punctuation, and white space are all considered and numeric strings ignored (the default)? i.e. given a fixed-length match, the endIndex of a match can be determined using `forText's length + startIndex - 1` instead of measuring the length of all remaining text after `text item i`; will need to implement both approaches and profile them to determine if it makes any significant difference to speed
- `literal representation` - problem with this is that while it's straightforward enough to use OSAKit running in a background process to format AS values (just wrap the values in a script object and send that to the process via Apple event), ASOC's ocid specifiers can't be sent out of process so any lists/records containing those will cause a serialization error when packed into an AE. While lists could (laboriously) be recursively formatted one item at a time to avoid this, there's no way to iterate records natively (passing them to ASOC won't help as its record-to-NSDictionary conversion screws up a lot of record contents). Add the extra problems of formatting application references and type/constant names (which will appear as raw chevron syntax unless app terminology is explicitly loaded at runtime), and really the only satisfactory solution is for AS to implement this feature as a built-in command. (Alternatively, being able to call OSAKit methods directly on ASOC-hosted script objects might work better with ocids as it'd avoid going out of process, but ASOC doesn't expose public APIs for manipulating those script objects as OSAScript instances.)
- `insert into text`, `delete from text` for inserting/replacing/deleting ranges of characters (c.f. `insert into list`, `delete from list` in List library)
----------------------------------------------------------------------
TypeSupport
----------------------------------------------------------------------
- should asPOSIXPath[Parameter] include options for expanding/normalizing path when a text value is given rather than an alias/file/POSIX file? given that AS isn't too clever when passed relative paths, this might be wise (although there is the question of what to do about tildes, as those should only be expanded automatically when processing shell script arguments; Cocoa's stringByStandardizingPaths is excessively aggressive here)
- add `isValueListOfType` for checking if value is a *list* of the specified type
(Note that checking if value is a record of specific form, e.g. `{name:text, isDone:boolean}`, is impractical due to the lack of AS introspection and the inability of ASOC's record-to-NSDictionary conversion to preserve keyword based names, therefore it's not worth trying to implement that.)
(Be aware that while the `count` command's `each` parameter claims to accept a list of type classes, this is no good for actually determining if all list items are one of those types. It looks like when a list is given it actually counts all the values that can be _coerced_ one of specified types (as per `as` operator enhancement in 10.10), not whether the value is actually one of those types. Thus when checking a list for multiple types, it's necessary to check each item against each type O(nm), as it's possible for two type names to match the same item (e.g. counting each `integer`, then each `real`, then each `text` and summing the result should be ok, but counting each `integer`, then each `number`, then each `real` would result in all integer and real items being counted twice), resulting in an incorrect count when the subtotals for each time are finally added up. While AS's collection type names is quite stable, making it tempting to hack in special-case checks to prevent such overcounts, it's impossible to guarantee new names won't be added in future, so that isn't a safe solution.)
- add `canValueCoerceToType` handler that checks if value can [safely?] be coerced to the specified type (Q. does `count {theValue} each {theType}` work same as `theValue as {theType}` by first testing for exact type then testing for coercibility?)
- add `isValueOfObjCClass` handler that checks if value is ocid specifier and its class name is specified string? (note: it'd be better to use standard Cocoa methods to check it's a [sub]class of a specific class - checking string-based class names is hardly robust)
----------------------------------------------------------------------
Web
----------------------------------------------------------------------
- how to split path components from parameter strings? RFC2396 allows parameters on all path portions (NSURL only allows parameters after final path portion), so probably also need to rework/rewrite `split/join URL` handlers to support this newer form as standard; see also Python's urllib.parse.urlsplit(), which unlike its older NSURL-like urlparse() function doesn't split parameters from path (although Python doesn't provide a parse function for such paths either, presumably leaving it to users to deal with themselves as needed).
3.3. Path Component
The path component contains data, specific to the authority (or the
scheme if there is no authority component), identifying the resource
within the scope of that scheme and authority.
--path = [ abs_path | opaque_part ]
--path_segments = segment *( "/" segment )
--segment = *pchar *( ";" param )
--param = *pchar
--pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | ","
The path may consist of a sequence of path segments separated by a
single slash "/" character. Within a path segment, the characters
"/", ";", "=", and "?" are reserved. Each path segment may include a
sequence of parameters, indicated by the semicolon ";" character.
The parameters are not significant to the parsing of relative
references.
- NSURL's component properties don't appear to support generic resource locators, e.g. given "mailto:[email protected]", NSURL.path returns nil; may be the case that a vanilla parser implemented according to RFC3986 would be a better solution than using NSURL
- in `send HTTP request`:
-how to support authentication, e.g. tie into keychain? (might be best to leave that for now)
- requestBodyData/responseBodyType could also be file object/`file`, in which case upload/download tasks could be used (Q. will NSSession supply Content-Length automatically when a file is given? also, will it supply Content-Type automatically, or is there a way to get file's MIME type via Cocoa APIs?)
- if responseBodyType is `text` and requestHeaders doesn't include "Accept*" headers, add appropriate content negotiation header (e.g. "Accept: text/*") automatically? (what about common application/… headers, e.g. application/json, application/xml? TBH, it'd be a shot in the dark; probably best to leave it entirely to user)
- add `normalize URL` handler? see NSURL's standardizedURL(); need to decide if it's worth putting in for users to call directly (note that `split URL` and anything else that uses TypeSupport's asNSURLParameter() already normalizes URLs automatically; OTOH, `join URL` does not)
- what about `split/join URL parameter string`? (see also below)
- commands for converting HTML entities? (&/</>/"); what about '? what about non-ASCII entities? (decode command would need to handle all entities; encode command could probably just do required entities which is sufficient for use in Unicode [UTF8] encoded documents, possibly providing a Boolean option to encode all non-ASCII entities should users have to produce non-Unicode documents [though this shouldn't be encouraged])
- OTOH, one might argue that if users are dealing with HTML content they should use a proper library that understands and processes all HTML data correctly, and providing commands here for encoding/decoding HTML entities is just encouraging them to hack it (something a stdlib really shouldn't do); given what a mess of complexity it is, might be wisest to leave HTML processing for other libraries to deal with
- for numeric entities only, see NSString's stringByApplyingTransform:reverse:, using "Any-Hex/XML;Any-Hex/XML10" to convert "" and "" (Q. what about HTML entity names? Cocoa's existing ICU transforms aren't much use if they can't convert those too)
----------------------------------------------------------------------
Additional libraries
----------------------------------------------------------------------
- Logging -- commands for logging messages and info at various levels (debug, info, warning, error, fatal), plus configurable, composable objects for filtering+writing logged messages to various destinations (file, email, screen, etc), c.f. Python's `logging` module.
Note: Big problem with this is that it really needs to be stateful, with a Logging module instance being configured and shared across main script and all its libraries. However, AS's library loader doesn't respect separation between unrelated scripts (it requires applications to instantiate new CIs for every unrelated user script, even though apps - and even NSAppleScript - have spent the last 20 years happily sharing the same CI). Thus while a Logging library would be usable within standalone AS applets and ASOC apps, or with apps that use NSUserAppleScriptTask to run scripts, it would be a usability disaster used within scripts run within attachable apps that run OSA scripts in-process. This alone rules it out for stdlib inclusion, though it might still be of use as a third-party module with its limitations clearly described.
- Defaults -- commands for interacting with NSUserDefaults. Very problematic for stdlib as retaining ASOC objects between commands breaks script serialization and SE autosave. Plus NSUserDefaults' native API is fairly low level and not very AS-friendly. Plus all data needs to be converted to and from ASOC, with all the quirks, limitations, and silent corruptions that involves (e.g. records lose keyword-based properties, app object specifiers lose target app identifier, etc). Plus live changes to defaults data structures won't be stored automatically. One alternative would be to add simple `read preferences` and `write preferences` to File module that uses StdAdditions read/write commands to read and write records of prefs data explicitly; crude, but might be adequate for AS users' needs.
- Errors -- get descriptions of Carbon/Cocoa/etc error codes
----------------------------------------------------------------------
Other issues
----------------------------------------------------------------------
- Should (and can?) ALL ObjC class, method, enum, etc names always be enclosed in pipes? e.g. The File library was accidentally recompiled and resaved after AS converted 'NSURL' identifiers to 'nsurl', causing handlers that used it to break as ASOC, unlike AS, is case-sensitive.
Normalizing identifier case in not just current script but all imported scripts too is a fundamental AS flaw that will continue to break users' ASOC code until fixed at source, but these libraries need to be as robust as possible, even if that means crudding up the ASOC parts with pipes.
The big annoyance is that unless identical names but with different case are also defined without pipes, AS will remove the pipes from names that do have them on compilation, whereupon the library code is right back where it started, at risk of breaking in future use.