draft8
May 14, 2018, 12:30pm
1
Cycle the case of the selected text through three states:
Mixed case -> Upper -> Lower -> Title Case -> Upper
etc.
http://actions.getdrafts.com/a/1I9
JS source:
(() => {
'use strict';
// main :: () -> IO String
const main = () => {
const
e = editor,
strReCased = caseToggled(
e.getSelectedText()
);
return strReCased.length > 0 ? (
e.setSelectedText(
strReCased
),
strReCased
) : '';
};
// caseToggled :: String -> String
const caseToggled = s => {
const cs = chars(s);
return !any(isUpper, cs) ? (
toInitialCaps(s)
) : !any(isLower, cs) ? (
toLower(s)
) : toUpper(s);
};
// GENERIC FUNCTIONS ------------------------------------
// any :: (a -> Bool) -> [a] -> Bool
const any = (p, xs) => xs.some(p);
// chars :: String -> [Char]
const chars = s => s.split('');
// isLower :: Char -> Bool
const isLower = c =>
/[a-z]/.test(c);
// isUpper :: Char -> Bool
const isUpper = c =>
/[A-Z]/.test(c);
// 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();
// toInitialCaps :: String -> String
const toInitialCaps = 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();
// MAIN ---
return main();
})();
4 Likes
Love it, thank you one less action to make.
1 Like
AFC
May 14, 2018, 6:19pm
3
Will try to put the text format in a Prompt or would you know if that’s been done? Thx
1 Like
Sounds like a good exercise
dfay
May 14, 2018, 7:42pm
5
There’s a bug in this such that single letter words disappear when toggling to title case.
Also it’s not true title case, it’s just capitalized. Not to be pedantic but this matters if you’re trying to keep a clean bibliographic database. See my Alfred workflow for the difference and an example for how to implement in Perl: https://www.alfredforum.com/topic/2180-case-converter-including-title-case/
And here’s a JS implementation based on the Perl script that I borrowed there:
/*
* To Title Case 2.1 – http://individed.com/code/to-title-case/
* Copyright © 2008–2013 David Gouch. Licensed under the MIT License.
*/
String.prototype.toTitleCase = function(){
var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
return this.replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, function(match, index, title){
if (index > 0 && index + match.length !== title.length &&
match.search(smallWords) > -1 && title.charAt(index - 2) !== ":" &&
(title.charAt(index + match.length) !== '-' || title.charAt(index - 1) === '-') &&
title.charAt(index - 1).search(/[^\s-]/) < 0) {
return match.toLowerCase();
}
if (match.substr(1).search(/[A-Z]|\../) > -1) {
return match;
}
This file has been truncated. show original
Thanks for the bug report, and sure – it’s the most simple-minded version of Title Case - better described as Capitalized – as in the NSString method: capitalizedStringWithLocale
single letter words disappear when toggling to title case
Could you give us an example ?
(I can see single letter words left unaffected by case toggling, but I haven’t managed to get one to disappear yet).
Ah. Got it : -)
Single-character-word issue fixed now, I think, and ‘title’ changed to ‘Initial Caps’
Thanks again, and let me know if there’s anything else.
http://actions.getdrafts.com/a/1I9
1 Like
Updated the Initial Caps phase of the cycle to work with diacritics on latin alphabets.
http://actions.getdrafts.com/a/1I9
1 Like
Updated again – to select the nearest word (before case-cycling) if the selection is collapsed.
http://actions.getdrafts.com/a/1I9
2 Likes
draft8
May 23, 2018, 11:50am
10
I notice that output from this regex doesn’t always match that produced with AP, MLA, Chicago or Wikipedia settings from online converters like:
https://titlecaseconverter.com/
or
https://capitalizemytitle.com/
(particularly when small words are flanked by or adjacent to hyphens or other punctuation)
Is there a tool which seems more or less canonical to you for Anglo title casing, and which could be used for testing a slightly more legible and maintainable JS function ?
Great action. Just found it. Can this be updated for Sentence case? That is, first letter of first word capitalized, rest of words lowercase.
@draft8 great action. Can you add sentence case to the list of toggles (i.e. first word capitalized, rest lower case?). That would help immensely.