anyone have an idea of whether or not this will copy a string?
When you copy nodes, various types of data are placed in the clipboard, including a stringification of those nodes, which you can paste into a text editor.
The osascript
evaluateJavascript method does give finer control (tho only available on macOS)
I personally wouldn’t call it from AppleScript though (in the way that @chipotle has bravely done, quoting the JS code as a string, which can get fiddly) – it’s a lot more straightforward to do from JXA. You just define a JS function in the JXA code, and pass its name to .evaluateJavaScript( … ) with a .toString()
suffix to automatically obtain its source code as an oven-ready string, as in:
Application('OmniOutliner').evaluateJavascript(
'(' + myOmniJSFunction.toString() + ')()'
)
The value returned by .evaluateJavascript()
can then be placed in the clipboard by JXA.
Example: .evaluateJavascript() from JXA
(() => {
'use strict';
// OMNIJS CONTEXT -------------------------------------
// fountainExport :: OmniJS () -> String
function fountainExport() {
return rootItem.descendants.map(
item => '#'.repeat(item.level) + ' ' +
item.topic + (
item.note ? (
'\n= ' + item.note
) : ''
)
).join('\n\n');
}
// JXA CONTEXT ----------------------------------------
// main :: IO ()
const main = () => {
const
oo = Application('OmniOutliner'),
docs = oo.documents,
sa = Object.assign(Application.currentApplication(), {
includeStandardAdditions: true
});
return 0 < docs.length ? (() => {
const strFountain = oo.evaluateJavascript(
`(${fountainExport})()`
);
return Boolean(strFountain) ? (() => {
const dct = sa.displayDialog(
'Export Fountain text to: ', {
buttons: ['Cancel', 'Clipboard', 'File'],
defaultButton: 'Clipboard',
cancelButton: 'Cancel'
}
);
return dct.gaveUp ? (
''
) : 'Clipboard' === dct.buttonReturned ? (
sa.setTheClipboardTo(strFountain),
'Copied to clipboard'
) : (() => {
const fp = sa.chooseFileName({
withPrompt: 'Save as',
defaultName: (
takeBaseName(docs.at(0).name())
) + ".fountain"
});
return alert('Fountain export')(
(fp instanceof Path ? (
writeFile(fp.toString())(strFountain) ? (
'written to:'
) : 'could not be written to:'
) : 'File could not be written to: ') + '\n' +
fp.toString()
)
})();
})() : 'No export string returned.'
})() : 'No documents open in OmniOutliner';
};
// ----------------------------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
);
};
// ---------------------GENERIC FUNCTIONS---------------------
// https://github.com/RobTrew/prelude-jxa
// takeBaseName :: FilePath -> String
const takeBaseName = strPath =>
('' !== strPath) ? (
('/' !== strPath[strPath.length - 1]) ? (() => {
const fn = strPath.split('/').slice(-1)[0];
return fn.includes('.') ? (
fn.split('.').slice(0, -1).join('.')
) : fn;
})() : ''
) : '';
// writeFile :: FilePath -> String -> IO ()
const writeFile = strPath => strText =>
$.NSString.alloc.initWithUTF8String(strText)
.writeToFileAtomicallyEncodingError(
$(strPath)
.stringByStandardizingPath, false,
$.NSUTF8StringEncoding, null
);
// MAIN
return main();
})();