So, I’ve been taking notes via OmniOutliner on a daily basis, organizing one week’s worth of notes into a file. Is there a way to easily concatenate a whole bunch of them into one monolithic document? I’ve got over a year’s worth of notes that I’m interested in combining into one document.
Maybe this works for you. This script merges currently opened OmniOutliner documents.
Code:
-- unlocked2412
-- V0.02
--This script merges currently opened OmniOutliner documents.
tell application "OmniOutliner"
tell every document
set refRows to a reference to (every child)
end tell
set mergedDocument to make new document with properties {name:"Merged Document"}
duplicate refRows to end of every row of mergedDocument
end tell
Thanks for doing this! I just tried this, and I got an interesting outcome. For each top-level row, everything and its child row was included as expected. But it looks like it then iterated through each child row and copied those as top-level rows in the merged document.
Tell me if it works for you
Thanks! It does now!
A shorter version:
tell application "OmniOutliner"
duplicate documents's rows to end of (make new document)'s rows
end tell
This seems to bring over graphics better if you have any in your notes.
SG
I’ve started to take a serious look at switching my nots to a monolithic document, and I’ve found one thing missing in your merge script. I often embed audio clips (of meetings) in my outline files and occasionally attach other files like images. Is there a way to get them included in the merged document?
I looked into this and I think I found a solution. Tell me if it works for you, @omnifocuser.
Code:
-- unlocked2412
-- V0.02
-- This script merges currently open OO documents
on run
tell application "OmniOutliner"
set listA to my concat(every row of every document)
set ooDoc to (make new document with properties {name:"MergedDocument"})
set applyDup to |λ|(ooDoc) of my curry(dupRows)
my map(applyDup, my concat(every child of every document))
set listB to every row of ooDoc
my zipWith(dupAttachments, listA, listB)
end tell
end run
on dupRows(destDoc, anItem)
tell application "OmniOutliner"
duplicate anItem to end of every child of destDoc
end tell
end dupRows
on dupAttachments(rowA, rowB)
tell application "OmniOutliner"
try
duplicate every attachment of rich text of cell 1 of rowA to end of every attachment of rich text of cell 1 of rowB
end try
end tell
end dupAttachments
-- GENERIC FUNCTIONS ---------------------------------------------------------
-- concat :: [[a]] -> [a] | [String] -> String
on concat(xs)
if length of xs > 0 and class of (item 1 of xs) is string then
set acc to ""
else
set acc to {}
end if
repeat with i from 1 to length of xs
set acc to acc & item i of xs
end repeat
acc
end concat
-- curry :: (Script|Handler) -> Script
on curry(f)
script
on |λ|(a)
script
on |λ|(b)
|λ|(a, b) of mReturn(f)
end |λ|
end script
end |λ|
end script
end curry
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- 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
-- 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
Based on draft8 advice, I updated the code. It now preserves outline structure.