Probably a bit niche – a simple macro for toggling comma-delimited ⇄ multiple line.
( First draft – always test with dummy data to check that you understand what it does. )
JS source (for Script Editor etc, with language set to JS)
(() => {
'use strict';
// Toggle <--> between a single (selected) comma-delimited line
// and a series of sibling lines without commas:
// alpha, beta, gamma, delta
// <-->
// alpha
// beta
// gamma
// delta
// Rob Trew 2019
// Ver 0.01
// JS FOR AUTOMATION CONTEXT --------------------------
const main = () => {
// TASKPAPER JS CONTEXT ---------------------------
const tp3Context = (editor, options) => {
const inner = () => {
const
rgxCommas = /,\s*/g,
item = editor.selection.startItem,
locn = editor.getLocationForItemOffset(item, 0),
itemText = item.bodyContentString,
outline = editor.outline;
return rgxCommas.test(itemText) ? (() => {
const xs = itemText.split(rgxCommas);
return (
// Effects
outline.groupUndoAndChanges(() => {
item.parent.insertChildrenBefore(
xs.slice(1).map(
s => outline.createItem(s)
),
item.nextSibling
);
item.bodyContentString = xs[0];
}),
editor.moveSelectionToRange(locn, locn),
// Value
xs.join('\n')
);
})() : (() => {
const followingLeafSiblings = (
until(
xs => {
const
h = xs[0],
none = null === h,
txt = none ? '' : (
h.bodyContentString.trim()
);
return none || h.hasChildren || (
1 > txt.length
) || txt.includes(',');
},
xs => [xs[0].nextSibling].concat(xs),
[item.nextSibling]
).slice(1)
);
return 0 < followingLeafSiblings.length ? (
// Effects
outline.groupUndoAndChanges(() => (
item.bodyContentString = [
item
]
.concat(reverse(followingLeafSiblings))
.map(x => x.bodyContentString).join(', '),
outline.removeItems(followingLeafSiblings)
)),
editor.moveSelectionToRange(locn, locn),
// Value
item.bodyContentString
) : '';
})()
};
// GENERAL FUNCTIONS FOR TASKPAPER JS CONTEXT--
// until :: (a -> Bool) -> (a -> a) -> a -> a
const until = (p, f, x) => {
let v = x;
while (!p(v)) v = f(v);
return v;
};
// reverse :: [a] -> [a]
const reverse = xs =>
xs.slice(0).reverse();
return inner();
};
const ds = Application('TaskPaper').documents;
return bindLR(
0 < ds.length ? (
Right(ds.at(0))
) : Left('No documents open in TaskPaper'),
d => d.evaluate({
script: tp3Context.toString(),
withOptions: {
optionName: 'someValue'
}
})
);
};
// GENERAL FUNCTIONS FOR JS FOR AUTOMATION CONTEXT ----
// https://github.com/RobTrew/prelude-jxa
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
// bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
const bindLR = (m, mf) =>
undefined !== m.Left ? (
m
) : mf(m.Right);
// MAIN ---
return main();
})();