Can someone help with a script to copy a section of OmniFocus tasks in TaskPaper format but with the OmniFocus tags removed?
Thank you
I am not familiar with OmniFocus and how it does the tags. If you share that with me I may be able to point to a previous script that takes tags out of task paper. I am not a programmer, but you may go and check the plugins and script page and see what is available.
To test this in Script Editor, set the language selector at top left to JavaScript
rather than AppleScript
:
( If it seems to do what you need, you could assign a keystroke to it with something like Keyboard Maestro or FastScripts )
Expand disclosure triangle to view JS source
(() => {
"use strict";
// Copy selected OmniFocus tasks (with descendants)
// as untagged Taskpaper string.
// Rob Trew @2023
// Ver 0.04
// 0.04 Tidied
// 0.03 Closed up redundant blank lines after
// noteless tasks.
// 0.02 Added copying of OmniFocus notes, and
// also tested on OmniFocus 4 Trial version.
ObjC.import("AppKit");
// MAIN :: IO()
const main = () => {
const
docWindow = Application("com.omnigroup.OmniFocus4")
.defaultDocument.documentWindows.at(0);
return either(
alert(
"Copy OmniFocus tasks as tagless TaskPaper"
)
)(
copyText
)(
docWindow.exists()
? (() => {
const
selectedTrees = docWindow.content
.selectedTrees();
return 0 < selectedTrees.length
? Right(
selectedTrees.flatMap(
tree => foldTree(
taskPaperText
)(
tree.value()
)
)
.join("\n")
)
: Left(
"No tasks selected in content panel."
);
})()
: Left("No windows open in OmnniFocus.")
);
};
// taskPaperText :: OF Task -> [String] -> [String]
const taskPaperText = task =>
taskPaperChildren => {
const note = task.note();
return [
// Task name bulleted,
`- ${task.name()}`,
// any note text indented,
...(
0 < note.length
? note.split("\n")
.map(additionalTab)
: []
),
// and all descendants indented.
...taskPaperChildren.flat()
.map(additionalTab)
];
};
// additionalTab :: String -> String
const additionalTab = s => `\t${s}`;
// ----------------------- JXA -----------------------
// alert :: String => String -> IO String
const alert = title =>
s => {
const sa = Object.assign(
Application("System Events"), {
includeStandardAdditions: true
});
return (
sa.activate(),
sa.displayDialog(s, {
withTitle: title,
buttons: ["OK"],
defaultButton: "OK"
}),
s
);
};
// copyText :: String -> IO String
const copyText = s => {
const pb = $.NSPasteboard.generalPasteboard;
return (
pb.clearContents,
pb.setStringForType(
$(s),
$.NSPasteboardTypeString
),
s
);
};
// -------------------- OMNIFOCUS --------------------
// Definitions of `root` and `nest` specialised
// for this application to OmniFocus.
const root = x => x;
const nest = x =>
0 < x.numberOfTasks()
? x.tasks()
: [];
// --------------------- GENERIC ---------------------
// Left :: a -> Either a b
const Left = x => ({
type: "Either",
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: "Either",
Right: x
});
// either :: (a -> c) -> (b -> c) -> Either a b -> c
const either = fl =>
// Application of the function fl to the
// contents of any Left value in e, or
// the application of fr to its Right value.
fr => e => "Left" in e
? fl(e.Left)
: fr(e.Right);
// foldTree :: (a -> [b] -> b) -> Tree a -> b
const foldTree = f => {
// The catamorphism on trees. A summary
// value obtained by a depth-first fold.
const go = tree => f(
root(tree)
)(
nest(tree).map(go)
);
return go;
};
// MAIN
return main();
})();
PS I’m not a user of OmniFocus. The version I tested this on is 3.15.4, which might not be up to date. Let me know if it doesn’t appear to copy the tasks selected in the OmniFocus content panel.
Updated draft above to Ver 0.02
- added copying of OmniFocus notes
- tested on OmniFocus 4 trial version
The version above references:
Application("com.omnigroup.OmniFocus4")
for OmniFocus 3, you can edit this to:
Application("com.omnigroup.OmniFocus3")
@complexpoint Thank you for the script,
It’s much appreciated.and runs well with OmniFocus 4.0.2 (v174.5.2)
Stan
Added to the scripts and themes page. Thank you @complexpoint