Here is a different experimental draft, sketched for Bike Preview 1.14 (152), updated to work with note type rows in Bike, rather than “>” prefixes.
It aims to toggle between:
- Omni group
_noteattributes (in OPML generated by OmniIOutliner, and opened in Bike) - leading
notetype children.
Not fully tested or recommended for use with real data. Back up any Bike file before you test this script.
Expand disclosure triangle to view AppleScript source
-- Possible approach ?
-- Not sure ...
-- EXPERIMENT ONLY – NOT READY FOR USE WITH REAL DATA
-- (I never like to share anything that uses a 'delete' method)
-- Ver 2.00
-- This cannot really be done in JXA I, I think,
-- for lack of location specifiers
-- e.g. in `make new row at beginning of rows`
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-- ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-- TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-- PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-- SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
-- ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-- OR OTHER DEALINGS IN THE SOFTWARE.
------- TOGGLE _NOTE ATTRIBUTES ⇄ NOTE TYPE CHILDREN ------
on run
tell application "Bike"
set doc to front document
if exists doc then
set docRows to a reference to rows of doc
set rowNotePairs to my docRowsWithNotes(docRows)
if 0 < length of rowNotePairs then
my noteAttribsToNoteChildren(doc, rowNotePairs)
else
my noteChildrenToNoteAttribs(docRows)
end if
else
"No document open in Bike"
end if
end tell
end run
--------------------- NOTE ATTRIBUTES --------------------
-- docRowsWithNotes :: Bike Doc -> IO [(Row, String)]
on docRowsWithNotes(rowsOfDoc)
using terms from application "Bike"
tell rowsOfDoc
set noteAttribs to a reference to ¬
(attributes where name is "_note")
end tell
script go
on |λ|(xs)
if {} ≠ xs then
{item 1 of xs}
else
{}
end if
end |λ|
end script
zip(concatMap(go, container row of noteAttribs), ¬
concatMap(my identity, value of noteAttribs))
end using terms from
end docRowsWithNotes
-- noteAttribsToNoteChildren :: [(Row, String)] -> IO ()
on noteAttribsToNoteChildren(doc, rowNotePairs)
using terms from application "Bike"
repeat with ab in rowNotePairs
set {attribRow, attribText} to ab
--
repeat with para in paragraphs of attribText
tell doc
make new row at beginning of rows of attribRow ¬
with properties ¬
{name:para, type:note}
end tell
set attrib to (a reference to ¬
(attribute "_note" of attribRow))
if exists attrib then delete attrib
end repeat
end repeat
end using terms from
end noteAttribsToNoteChildren
-- noteChildrenToNoteAttribs :: Char -> Rows -> IO ()
on noteChildrenToNoteAttribs(docRows)
using terms from application "Bike"
set noteRows to {}
repeat with oRow in docRows
set isParent to contains rows of oRow
if isParent then
set xs to (rows of oRow)
set lst to {}
repeat with oChild in xs
set x to oChild
if not (contains rows of x) then
if type of oChild is note then
set end of lst to name of oChild
set end of noteRows to x
end if
end if
end repeat
if {} ≠ lst then
tell oRow
make attribute with properties ¬
{name:"_note", value:my unlines(lst)}
end tell
end if
end if
end repeat
set n to length of noteRows
repeat with i from n to 1 by -1
delete item i of noteRows
end repeat
end using terms from
end noteChildrenToNoteAttribs
------------------------- GENERIC ------------------------
-- concatMap :: (a -> [b]) -> [a] -> [b]
on concatMap(f, xs)
set lng to length of xs
set acc to {}
tell mReturn(f)
repeat with i from 1 to lng
set acc to acc & (|λ|(item i of xs, i, xs))
end repeat
end tell
acc
end concatMap
-- identity :: a -> a
on identity(x)
-- The argument unchanged.
x
end identity
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- drop :: Int -> String -> String
on drop(n, xs)
if n < length of xs then
text (1 + n) thru -1 of xs
else
""
end if
end drop
-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set s to xs as text
set my text item delimiters to dlm
s
end unlines
-- zip :: [a] -> [b] -> [(a, b)]
on zip(xs, ys)
set n to min(length of xs, length of ys)
set lst to {}
repeat with i from 1 to n
set end of lst to {item i of xs, item i of ys}
end repeat
lst
end zip