I’m having trouble figuring out how to write AppleScript to clear the style of a row in an OO 5 document. I thought something like the following would do it,
tell application "OmniOutliner"
tell front document
repeat with theRow in selected rows
set rowStyles to get style of theRow
repeat with theStyle in rowStyles
remove style theStyle of theRow
end repeat
end repeat
end tell
end tell
but this produces an error,
error "OmniOutliner got an error: Can’t make style
(item 1 of style of child 4 of child 15 of document
id \"cmtakl8ic3V\") of item 1 of every selected row
of document 1 into type list of specifier or specifier."
number -1700 from style (item 1 of style of child 4 of
child 15 of document id "cmtakl8ic3V") of item 1
of every selected row of document 1
and I’m kind of stuck there.
I bet someone among you has already done this in AppleScript – what is the correct incantation?
After experimentation, I think the problem is that a row always has a style; you can’t remove it. But you can set the ‘attributes’ of a row’s style to their default values. And you need to remove any ‘named style’ from the row’s style.
The script below succeeds in resetting most of the selected rows’ appearance to their defaults. It doesn’t change text color, though.
SG
tell application "OmniOutliner"
tell front document
repeat with aRow in selected rows
tell aRow's style
repeat with anAttr in its attributes
try
set anAttr's value to anAttr's default value
end try
end repeat -- attributes
try
remove named styles from its named styles
end try
end tell -- style
end repeat -- rows
end tell
end tell
One other approach (quite fast with longer documents) is to:
Reset all the attributes in the style of the first row, creating a vanilla or ‘factory-settings’ style,
then batch-set the style of all rows in the document to that vanilla style:
(If you also wanted to remove formats from particular text ranges, you would need to step through the attribute runs of topic cell rich texts)
on run
tell application "OmniOutliner"
if (count of documents) > 0 then
tell front document
-- VANILLA STYLE FOR ROW 1
script setAttrib
on |λ|(attrib, v)
set value of attrib to v
end |λ|
end script
tell style of front row
my zipWith(setAttrib, ¬
attributes, default value of attributes)
end tell
-- ALL ROWS RESET TO VANILLA
set style of rows to (style of front row)
end tell
end if
end tell
end run
-- GENERIC FUNCTIONS ----------------------------------------------
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
set lng to min(length of xs, length of ys)
set lst to {}
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, item i of ys)
end repeat
return lst
end tell
end zipWith
So basic AppleScript, slower than your advanced AppleScript but much faster than the original, could be something like this:
SG
tell application "OmniOutliner"'s front document
set selRow1 to selected rows's first item
repeat with anAttr in selRow1's style's attributes
try
set anAttr's value to anAttr's default value
end try
end repeat
try
remove named styles from selRow1's style's named styles
end try
set selected rows's style to selRow1's style -- batch reset
end tell
(You may also, I think, be able to get a little extra speed with a couple of batch reads at the start – fewer AppleEvents – less traffic, that is, across the slowish automation interface)
tell application "OmniOutliner"'s front document
set selRow1 to selected rows's first item
set oStyle to style of selRow1
set vs to default value of attributes of oStyle
set intAttribs to length of vs
set attribs to attributes of oStyle as list
repeat with i from 1 to intAttribs
set value of item i of attribs to item i of vs
end repeat
try
remove named styles from selRow1's style's named styles
end try
set selected rows's style to selRow1's style -- batch reset
end tell
Clearing special formatting attributes from particular attribute runs within texts might, of course, look something like this:
tell application "OmniOutliner"
tell front document
set vs to topic of its rows
set lng to length of vs
repeat with i from 1 to lng
set topic of row i to item i of vs
end repeat
end tell
end tell
Or, packaging up the clearing of row styles with the clearing of character run formats:
on run
tell application "OmniOutliner"
if (count of documents) > 0 then
tell front document
-- VANILLA STYLE FOR ROW 1
script setAttrib
on |λ|(attrib, v)
set value of attrib to v
end |λ|
end script
tell style of front row
my zipWith(setAttrib, ¬
attributes, default value of attributes)
end tell
-- ALL ROWS RESET TO VANILLA STYLE
set style of rows to (style of front row)
-- CHARACTER FORMATS CLEARED
script clearChars
on |λ|(oRow, strText)
set topic of oRow to strText
end |λ|
end script
my zipWith(clearChars, rows as list, topic of rows)
end tell
end if
end tell
end run
-- GENERIC FUNCTIONS ----------------------------------------------
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
set lng to min(length of xs, length of ys)
set lst to {}
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, item i of ys)
end repeat
return lst
end tell
end zipWith
In OmniOutliner 5.2 (not available publicly yet), I’ve added a couple new scripting capabilities that should make some of this easier. Once test builds are available, the attribute class will have a new has local value property, and will respond to a new clear command to remove any local value (leaving it to cascade from from any level style or inherit from an applied named style).
For example, if you have a row, you could do:
clear attributes of its style
or to remove styles from text spans in the row’s topic cell: