To start with a particular example – the default underline style is UnderlineStyle.None,
but at present the following test seems to evaluate to a false negative:
Style.Attribute.UnderlineStyle.defaultValue === UnderlineStyle.None
More generally, human-readable names of omniJS Style Attribute enum values can already be used for imperatively setting styles, but if we want to read styles and conditionally branch the script behaviour accordingly (e.g. for custom exports and clipboards etc), we seem to get tripped and blocked by some obstacles in current builds (OO 5.2 test (v184 r294214)) of the omniJS interface to OmniOutliner.
- We don’t seem to be able to serialise style enum values (as returned by
Style.get or Style.Attribute.defaultValue
) to human-readable or JSON-friendly name strings. - We can’t (I think) test OO omniJS enum values (returned by
Style.get
orStyle.Attribute.defaultValue
) for equality using JavaScript equivalence operators (=== for simple fast equivalence, or == for slower equivalence after coercion)
For example, selecting a singly-underlined topic like:
The Automation Console returns the UnderlineStyle value as:
[object UnderlineStyle: 1]
The omniJS Console also evaluates the omniJS expression
UnderlineStyle.Single
to what looks like the same value:
So we might hope that
selectedTopicUnderline === singleUnderline
or
selectedTopicUnderline == singleUnderline
Would evaluate to true, and that we could make good use of this in a script.
In fact, however:
(The built-in JavaScript equivalence operators do not return true for two objects which simply have the same pattern of keys and values – in contrast with the AppleScript example of:
In JavaScript, while pairs of atomic values of types like Bool, Float, and String may be equivalent, two Arrays, Dictionaries or other compound values, however similar, are still two different (non-equivalent) objects in terms of the ( === / == ) operators.
( In JavaScript only two references to the identical instance of an Array or Dictionary object satisfy === )
We would be able to test, compare and branch on Style.Attribute enum values if they serialized to distinct strings (had some kind of string .identifier property, for example), but unfortunately the values which they return to .toString() are not distinct.
The members of the underlineStyle enum, for example, are accessible (for writing) through the 4 distinct internal keys:
Object.getOwnPropertyNames(UnderlineStyle).slice(2)
-> ['None', 'Single', 'Thick', 'Double']
But these keys are not available for testing or reading – simple coercion of the enum values to strings preserves no distinctions among them
Object.getOwnPropertyNames(UnderlineStyle).slice(2).map(k => UnderlineStyle[k].toString())
-> [ "[object UnderlineStyle]", "[object UnderlineStyle]", "[object UnderlineStyle]", "[object UnderlineStyle]" ]
and the enum value objects have no methods or properties which enable a script to distinguish between them:
JSON.stringify(UnderlineStyle['Double']) -> "{}"
while
Object.getOwnPropertyNames(UnderlineStyle['Double']) -> []
To summarise:
What we need is to be able to write code analogous to:
if (fontWeight > 8 || underlineStyle !== none) { etc. etc. }
and to easily serialise enum values to corresponding name strings which are:
- human-legible
- usable as JSON keys or JS identifiers
- comparable in terms of === and !==
[details=Test code] (() => {
‘use strict’;
const selectedTopicUnderline = document.editors[0]
.selectedNodes[0]
.valueForColumn(this.outlineColumn)
.style.get(Style.Attribute.UnderlineStyle);
const singleUnderline = UnderlineStyle.Single;
return [
selectedTopicUnderline,
singleUnderline,
selectedTopicUnderline === singleUnderline,
selectedTopicUnderline == singleUnderline
];
})();
[/details]