A case-toggler (case 'cycler' really):
- Mixed case -> Upper
- Upper case -> Lower
- Lower -> Initial Caps
Change case of selected text (Title -> Upper -> Lower -> Title).kmmacros (21.7 KB)
JS source:
(() => {
'use strict';
// main :: () -> IO String
const main = () => {
const
sa = standardAdditions(),
clip = sa.theClipboard(),
strReCased = typeof clip !== 'object' ? (
caseToggled(
sa.theClipboard()
)
) : '';
return strReCased.length > 0 ? (
sa.setTheClipboardTo(
strReCased
),
strReCased
) : '';
};
// caseToggled :: String -> String
const caseToggled = s => {
const cs = chars(s);
return !any(isUpper, cs) ? (
toTitle(s)
) : !any(isLower, cs) ? (
toLower(s)
) : toUpper(s);
};
// GENERIC FUNCTIONS --------------------------------------
// | True if any contained element satisfies the predicate.
// any :: (a -> Bool) -> [a] -> Bool
const any = (p, xs) => xs.some(p);
// chars :: String -> [Char]
const chars = s => s.split('');
// filter :: (a -> Bool) -> [a] -> [a]
const filter = (f, xs) => xs.filter(f);
// isLower :: Char -> Bool
const isLower = c =>
/[a-z]/.test(c);
// isUpper :: Char -> Bool
const isUpper = c =>
/[A-Z]/.test(c);
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
// regexMatches :: String -> String -> [[String]]
const regexMatches = (strRgx, strHay) => {
const rgx = new RegExp(strRgx, 'g');
let m = rgx.exec(strHay),
xs = [];
while (m)(xs.push(m), m = rgx.exec(strHay));
return xs;
};
// toLower :: String -> String
const toLower = s => s.toLowerCase();
// toTitle :: String -> String
const toTitle = s =>
regexMatches(/(\w)(\w+)(\b[\W]*|$)/g, s)
.map(ms => ms[1].toUpperCase() + ms[2].toLowerCase() + ms[3])
.join('');
// toUpper :: String -> String
const toUpper = s => s.toUpperCase();
// JXA ---
// standardAdditions :: () -> Application
const standardAdditions = () =>
Object.assign(Application.currentApplication(), {
includeStandardAdditions: true
});
// MAIN ---
return main();
})();