(() => {
'use strict';
// Rob Trew 2020
// Sketch of a menu choices report string with
// (non-Oxford) commas and a penultimate 'and'.
// main :: IO ()
const main = () => {
const
kmVarName = 'itemList',
items = Application('Keyboard Maestro Engine')
.getvariable(kmVarName)
.split('\n')
return either(
// Explanatory message (e.g. user cancelled)
alert('Choices')
)(
choiceReport
)(
1 < items.length ? (
showMenuLR(true)('Choices')(
'⌘-click one or more:'
)(items)(items[0])
) : 0 < items[0].length ? (
Right(items[0])
) : Left(`No list found in KMVar :: ${kmVarName}`)
);
};
// ----------------- REPORTED CHOICE -----------------
// choiceReport :: [String] -> String
const choiceReport = choices => {
const
xs = choices.map(toLower),
intItems = xs.length,
listString = 0 < intItems ? (
1 < intItems ? (
`${init(xs).join(', ')} and ${last(xs)}`
) : xs[0]
) : 'nothing';
return `I bought ${listString}.`
}
// ----------------------- 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
);
};
// showMenuLR :: Bool -> String -> String ->
// [String] -> String -> Either String [String]
const showMenuLR = blnMult =>
// An optionally multi-choice menu, with
// a given title and prompt string.
// Listing the strings in xs, with
// the the string `selected` pre-selected
// if found in xs.
title => prompt => xs =>
selected => 0 < xs.length ? (() => {
const sa = Object.assign(
Application('System Events'), {
includeStandardAdditions: true
});
sa.activate();
const v = sa.chooseFromList(xs, {
withTitle: title,
withPrompt: prompt,
defaultItems: xs.includes(selected) ? (
[selected]
) : [xs[0]],
okButtonName: 'OK',
cancelButtonName: 'Cancel',
multipleSelectionsAllowed: blnMult,
emptySelectionAllowed: false
});
return Array.isArray(v) ? (
Right(v)
) : Left('User cancelled ' + title + ' menu.');
})() : Left(title + ': No items to choose from.');
// --------------------- GENERIC ---------------------
// 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);
// 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;
// init :: [a] -> [a]
const init = xs => (
// All elements of a list except the last.
ys => 0 < ys.length ? (
ys.slice(0, -1)
) : undefined
)(xs);
// last :: [a] -> a
const last = xs => (
// The last item of a list.
ys => 0 < ys.length ? (
ys.slice(-1)[0]
) : undefined
)(xs);
// toLower :: String -> String
const toLower = s =>
// Lower-case version of string.
s.toLocaleLowerCase();
// MAIN ---
return main()
})();
Hi @Pedro.Carmo, welcome to Keyboard Maestro (KM) and its Forum.
KM is one of the best Mac automation tools available, its Forum is one of the best and friendliest forums on the Internet. Whenever you reach a tough stumbling block trying to use KM, please feel free to post your question/problem here for help.