I’m wondering if anyone has any applescript advice for me re: sending items in FT or TP to a URL scheme for the 2Do app? Although, I’m thinking this approach could be fairly extensible to any app with an URL scheme, right?
Anyway, I’m looking for a way to take some bit of data like example below and running an applescript and having it piped to a URL scheme to create items in the 2Do Mac app:
It seems it would be more complex to differentiate between @start and @due tags, but 2do URL scheme doesn’t take due or start dates anyway (although the app supports them).
I don’t really have any Applescript writing chops, but I’ve had good luck cut and pasting various bits from other people’s working examples. Just haven’t seen or understood any applescripts for FT or TP3 that might fit the bill here.
Don’t have a copy of 2Do here, so typing a little in the dark, but this rough and untested draft may give you an idea:
property pblnDebug : false
property precOptions : {listname:"From FoldingText"}
-- twodo:///add?task=[title]&forlist=¬e=[your note]&priority=[0,1,2,3]&tags=[comma separated names]
property pstrJS : "
function (editor, options) {
'use strict';
var tree=editor.tree(),
dctTags, lstKeys,
lstSelns = editor.selectedRanges(),
lstSeen = [],
lstURL=[], lstNoteParas, lstPriorities=['0','1','2','3'],
strNodePath,
strID, strValue, strNote,
strPrefix='twodo:///add?task=',
strListName=encodeURIComponent(options.listname),
strURL='', lngKeys, iIndex,blnPriority;
lstSelns.forEach(function (rngSeln) {
rngSeln.forEachNodeInRange(function (oNode) {
if (oNode.type() !== 'empty') {
strID = oNode.id;
// Unless we have already processed this node as note for a preceding line
if (lstSeen.indexOf(strID) == -1) {
// get text and target list
strURL=strPrefix + encodeURIComponent(oNode.text()) + '&forlist=' + strListName;
strNodePath='//@id=' + strID + '/@type=body/descendant-or-self::*';
lstNoteParas=tree.evaluateNodePath(strNodePath);
// collect any notes
if (lstNoteParas.length) {
strURL+='¬e=';
strNote='';
lstNoteParas.forEach(function(oChild) {
strNote+=(oChild.text() + '\\n');
lstSeen.push(oChild.id); // record this node as already processed
});
strURL+=encodeURIComponent(strNote);
}
// get any priorities
blnPriority=oNode.hasTag('priority');
if (blnPriority) {
strValue=oNode.tag('priority');
if (lstPriorities.indexOf(strValue) !== -1) {
strURL+= ('&priority=' + strValue);
}
}
// and any other remaining tag keys
dctTags=oNode.tags();
lstKeys = Object.keys(dctTags);
lngKeys = lstKeys.length;
if (lngKeys) {
if ((!blnPriority) || (lngKeys > 1)) {
strURL+='&tags=';
iIndex=lstKeys.indexOf('priority');
if (iIndex !== -1) {
lstKeys.splice(iIndex, 1); // remove any @priority tag
}
strURL+=encodeURIComponent(lstKeys.join('\\n'));
}
}
lstURL.push(strURL);
}
}
});
});
lstURL.forEach(function (strURL) {
editor.openLink(strURL);
});
return lstURL;
}
"
on run
set varResult to missing value
tell application "FoldingText"
if not pblnDebug then
set lstDocs to documents
if lstDocs ≠ {} then
tell item 1 of lstDocs
set varResult to (evaluate script pstrJS with options precOptions)
end tell
end if
else
-- debug script automatically refers to the SDK version of the editor
-- which must be open: FoldingText > Help > SDK > Run Editor
set varResult to (debug script pstrJS with options precOptions)
end if
end tell
return varResult
end run
I assume it will also work great in Taskpaper once the dev version reaches parity with the current FoldingText (I’m thinking FT is a bit ahead now–I got an error when I switched the "tell application “Taskpaper”: "TypeError: ‘undefined’ is not a function (evaluating ‘rngSeln.forEachNodeInRange’)
At any rate, your work with all these scripts for FT and TP is so useful to me. Thanks again!
Here is a version which I have edited a little for TaskPaper 3 (Dev):
forEachNodeInRange →forEachLineInRange
body → "note"
property pblnDebug : false
property precOptions : {listname:"From TaskPaper"}
-- twodo:///add?task=[title]&forlist=¬e=[your note]&priority=[0,1,2,3]&tags=[comma separated names]
property pstrJS : "
function (editor, options) {
'use strict';
var tree=editor.tree(),
dctTags, lstKeys,
lstSelns = editor.selectedRanges(),
lstSeen = [],
lstURL=[], lstNoteParas, lstPriorities=['0','1','2','3'],
strNodePath,
strID, strValue, strNote,
strPrefix='twodo:///add?task=',
strListName=options.listname,
strURL='', lngKeys, iIndex,blnPriority;
lstSelns.forEach(function (rngSeln) {
rngSeln.forEachLineInRange(function (oNode) {
if (oNode.type() !== 'empty') {
strID = oNode.id;
// Unless we have already processed this node as note for a preceding line
if (lstSeen.indexOf(strID) == -1) {
// get text and target list
debugger;
strURL=strPrefix + oNode.text() + '&forlist=' + strListName;
strNodePath='//@id=' + strID + '/@type=\"note\"/descendant-or-self::*';
lstNoteParas=tree.evaluateNodePath(strNodePath);
// collect any notes
if (lstNoteParas.length) {
strURL+='¬e=';
strNote='';
lstNoteParas.forEach(function(oChild) {
strNote+=(oChild.text() + '\\n');
lstSeen.push(oChild.id); // record this node as already processed
});
strURL+=strNote;
}
// get any priorities
blnPriority=oNode.hasTag('priority');
if (blnPriority) {
strValue=oNode.tag('priority');
if (lstPriorities.indexOf(strValue) !== -1) {
strURL+= ('&priority=' + strValue);
}
}
// and any other remaining tag keys
dctTags=oNode.tags();
lstKeys = Object.keys(dctTags);
lngKeys = lstKeys.length;
if (lngKeys) {
if ((!blnPriority) || (lngKeys > 1)) {
strURL+='&tags=';
iIndex=lstKeys.indexOf('priority');
if (iIndex !== -1) {
lstKeys.splice(iIndex, 1); // remove any @priority tag
}
strURL+=lstKeys.join(',');
}
}
lstURL.push(encodeURI(strURL));
}
}
});
});
lstURL.forEach(function (strEncodedURL) {
editor.openLink(strEncodedURL);
});
return lstURL;
}
"
on run
set varResult to missing value
tell application "TaskPaper"
if not pblnDebug then
set lstDocs to documents
if lstDocs ≠ {} then
tell item 1 of lstDocs
set varResult to (evaluate script pstrJS with options precOptions)
end tell
end if
else
-- debug script automatically refers to the SDK version of the editor
-- which must be open: FoldingText > Help > SDK > Run Editor
set varResult to (debug script pstrJS with options precOptions)
end if
end tell
return varResult
end run
Hey, that’s great. Works good. I did have to change a line because the tags were getting separated by a new line instead of a comma:
// and any other remaining tag keys
dctTags=oNode.tags();
lstKeys = Object.keys(dctTags);
lngKeys = lstKeys.length;
if (lngKeys) {
if ((!blnPriority) || (lngKeys > 1)) {
strURL+='&tags=';
iIndex=lstKeys.indexOf('priority');
if (iIndex !== -1) {
lstKeys.splice(iIndex, 1); // remove any @priority tag
}
strURL+=lstKeys.join(',');
(basically, just changed the \n to a comma in the last line above.
I’m now using foldingtext as well as omnifocus. Sometimes I need transfer some part of foldingtext file to OF. I found you’ve written some scripts two years ago. But it no longer works for FT3 & OF2. I know you’ve no longer use OF, but I think it may be a not-so-hard work to rewrite it again. I know nothing about coding. Do you or anybody else have interest to do this work?
I don’t have a copy of OF2, so I couldn’t test anything, but a couple of things come to mind:
Can it import TaskPaper files intelligently (mapping tags values to its own field values) ?
Can it import OPML ?
We could certainly write something to convert a FoldingText selection to a TaskPaper format, and there is already a script for saving tagged FoldingText outlines as OPML.
Failing that – it should be something which Omni Support could undertake, or help you with.
I think they, quite understandably, treat their forums more as a peer-to-peer help framework than as an arm of their support system. It might be worth logging a direct support request to them.
this may be the silliest question imaginable, but for the life of me I can’t figure it out – how do you USE this applescript to transfer Taskpaper to 2Do? Do I turn it into a service, or what?