Very useful !
A quick footnote re this:
The JavaScript it uses I found on the web (sorry, I can't remember where)
It's a safe rule of thumb that if we can't remember where we found code, then we also can't remember whose work it is, and what copyright license was attached to it, whether explicitly or implicitly.
Here is a piece of functionally similar code which you are definitely free to copy, subject to the usual MIT terms, including retention of the attribution:
Click to reveal JS source
(() => {
'use strict';
ObjC.import('AppKit');
// Rob Trew 2020
// MIT License
// Ver 0.0
// main :: IO ()
const main = () =>
either(alert('Nato phonetic alphabet'))(
compose(copyText, natoPhonetic)
)(
clipTextLR()
);
// natoPhonetic :: String -> String
const natoPhonetic = s =>
transcribed(dictNato)('-')(s);
// transcribed :: Dict -> String -> String
const transcribed = dict =>
defaultChar => s => s.split('').reduce(
(a, c) => a + (
dict[c.toUpperCase()] || (
c !== '\n' ? (
defaultChar
) : '\n'
)
) + ' ',
''
);
// dictNato :: Dict
const dictNato = {
'0': 'Zero',
'1': 'One',
'2': 'Two',
'3': 'Three',
'4': 'Four',
'5': 'Five',
'6': 'Six',
'7': 'Seven',
'8': 'Eight',
'9': 'Nine',
'A': 'Alpha',
'B': 'Bravo',
'C': 'Charlie',
'D': 'Delta',
'E': 'Echo',
'F': 'Foxtrot',
'G': 'Golf',
'H': 'Hotel',
'I': 'India',
'J': 'Juliett',
'K': 'Kilo',
'L': 'Lima',
'M': 'Mike',
'N': 'November',
'O': 'Oscar',
'P': 'Papa',
'Q': 'Quebec',
'R': 'Romeo',
'S': 'Sierra',
'T': 'Tango',
'U': 'Uniform',
'V': 'Victor',
'W': 'Whiskey',
'X': 'X-Ray',
'Y': 'Yankee',
'Z': 'Zulu',
'@': '▶at◀',
'.': '▶dot◀',
',': '▶comma◀',
' ': '▶⬜︎◀'
};
// ----------------------- JXA ------------------------
// alert :: String -> String -> IO String
const alert = title =>
s => (sa => (
sa.activate(),
sa.displayDialog(s, {
withTitle: title,
buttons: ['OK'],
defaultButton: 'OK'
}),
s
))(Object.assign(Application('System Events'), {
includeStandardAdditions: true
}));
// clipTextLR :: () -> Either String String
const clipTextLR = () => {
const
v = ObjC.unwrap($.NSPasteboard.generalPasteboard
.stringForType($.NSPasteboardTypeString));
return Boolean(v) && v.length > 0 ? (
Right(v)
) : Left('No utf8-plain-text found in clipboard.');
};
// copyText :: String -> IO String
const copyText = s => {
// String copied to general pasteboard.
const pb = $.NSPasteboard.generalPasteboard;
return (
pb.clearContents,
pb.setStringForType(
$(s),
$.NSPasteboardTypeString
),
s
);
};
// --------------------- GENERICS ---------------------
// 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
});
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
const compose = (...fs) =>
// A function defined by the right-to-left
// composition of all the functions in fs.
fs.reduce(
(f, g) => x => f(g(x)),
x => 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 => 'Either' === e.type ? (
undefined !== e.Left ? (
fl(e.Left)
) : fr(e.Right)
) : undefined;
// ---
return main()
})();