Capitalize String

i dont know where anyone would use this but ill put it here anyway.

its a function that i wrote thought i’d share,
that returns a string with the first letter of every word capitalized, without the use of additional tools

set thisString to "THIS STRING WILL COME BACK WITH THE FIRST LETTER OF EVERY WORD BEING A CAPITAL AND THE REST WILL BE UPPER CASE"

CapitalizeFirstLetter_ofEveryWord(thisString)

on CapitalizeFirstLetter_ofEveryWord(InputString)
	set TheString to do shell script "echo " & InputString & " | tr '[A-Z]'  '[a-z]'"
	set wordsofTheString to words of TheString as list
	set TotalCount to count of wordsofTheString
	set theCount to 1
	repeat until theCount is greater than TotalCount
		set theWord to item theCount of wordsofTheString
		set theChars to characters of theWord as list
		set Capital to item 1 of theChars
		set item 1 of theChars to do shell script "echo " & Capital & " | tr '[a-z]' '[A-Z]'"
		if theCount is less than TotalCount then
			set theWord to (theChars as string) & " "
		else
			set theWord to (theChars as string)
		end if
		set item theCount of wordsofTheString to theWord
		set theCount to theCount + 1
	end repeat
	set TheString to wordsofTheString as string
	return TheString
end CapitalizeFirstLetter_ofEveryWord

If you’re going to use Do Shell Script, you could also do it this way:

set thisString to "THIS STRING WILL COME BACK WITH THE FIRST LETTER OF EVERY WORD BEING A CAPITAL AND THE REST WILL BE LOWER CASE"

CapitalizeFirstLetter_ofEveryWord(thisString)

on CapitalizeFirstLetter_ofEveryWord(InputString)
	set newString to ""
	repeat with currentWord in (every word of InputString)
		do shell script "ruby -e 'puts \"" & currentWord & "\".capitalize'"
		set newString to newString & result & " "
	end repeat
	return (characters 1 through -2 of newString as text)
end CapitalizeFirstLetter_ofEveryWord

Model: Mac mini
AppleScript: 1.10
Browser: Safari 412
Operating System: Mac OS X (10.4)

that made it a lot smaller

Here’s a version that works properly (i.e. won’t drop all non-alphabetic characters as the above examples do) and is unicode-aware:

on titlecase(txt)
    return do shell script "python -c \"import sys; print unicode(sys.argv[1], 'utf8').title().encode('utf8')\" " & quoted form of txt
end titlecase

Like most ‘do shell script’-based solutions it passes the input data on the command line, so the size of text it can process is limited. But it should be adequate for most tasks.

Even better!

Evolved from Apple’s ‘Change Case of Item Names.scpt’ - part of the Finder scripts.
You have the option of UPPER, lower, Title or Sentence cases.
Accepts non-alphabetic characters.

Edit: Added illegal case error code (if this_case was not UPPER, lower or Title, it was counted as Sentence).:stuck_out_tongue:
Edit 2: Now only uses capital when case is title if the current character is whitespace. (X-ray and Don’t as opposed to X-Ray and Don’T)

property lower_alphabet : "abcdefghijklmnopqrstuvwxyz"
property upper_alphabet : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
property white_space : {space, tab, return, ASCII character 10, ASCII character 13}

set this_string to "THIS STRING WILL COME BACK WITH THE FIRST LETTER OF EVERY WORD BEING A CAPITAL AND THE REST WILL BE LOWER CASE. Text containing punctuation: x-ray, don't."

get change_case(this_string, "Title")

on change_case(this_text, this_case)
	set new_text to ""
	if this_case is not in {"UPPER", "lower", "Title", "Sentence"} then
		return "Error: Case must be UPPER, lower, Title or Sentence"
	end if
	if this_case is "lower" then
		set use_capital to false
	else
		set use_capital to true
	end if
	repeat with this_char in this_text
		set x to offset of this_char in lower_alphabet
		if x is not 0 then
			if use_capital then
				set new_text to new_text & character x of upper_alphabet as string
				if this_case is not "UPPER" then
					set use_capital to false
				end if
			else
				set new_text to new_text & character x of lower_alphabet as string
			end if
		else
			if this_case is "Title" and this_char is in white_space then
				set use_capital to true
			end if
			set new_text to new_text & this_char as string
		end if
	end repeat
	return new_text
end change_case

I tried Querty Denzel’s version of the script, and it doesn’t seem to work for Sentence case - subsequent sentences are not initially capitalized. What I have below seems to work, but I’m no applescript wizard, so it’s probably not pretty.

property lowerAlphabet : "abcdefghijklmnopqrstuvwxyz"
property upperAlphabet : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-- includes ¿ and ¡
property whiteSpace : {space, tab, return, ASCII character 10, ASCII character 13, ASCII character 168, ASCII character 173}
-- includes !, ., ;, ?, ¿, and ¡
property sentencePunctuation : {ASCII character 33, ASCII character 46, ASCII character 59, ASCII character 63, ASCII character 168, ASCII character 173}

set thisString to "THIS STRING WILL COME BACK WITH THE FIRST LETTER OF EVERY SENTENCE BEING A CAPITAL AND THE REST WILL BE LOWER CASE. text containing punctuation: x-ray, don't. ¡ole! yay."

get changeCase(thisString, "Sentence")

on changeCase(thisText, thisCase)
	set newText to ""
	if thisCase is not in {"UPPER", "lower", "Title", "Sentence"} then
		return "Error: Case must be UPPER, lower, Title or Sentence"
	end if
	if thisCase is "lower" then
		set useCapital to false
	else
		set useCapital to true
	end if
	repeat with thisChar in thisText
		set x to offset of thisChar in lowerAlphabet
		if x is not 0 then
			if useCapital then
				set newText to newText & character x of upperAlphabet as string
				if thisCase is not "UPPER" then
					set useCapital to false
				end if
			else
				set newText to newText & character x of lowerAlphabet as string
			end if
		else
			if thisCase is "Title" and thisChar is in whiteSpace then
				set useCapital to true
			else if thisCase is "Sentence" and ((thisChar is in sentencePunctuation) or (lastChar is in sentencePunctuation)) then
				set useCapital to true
			end if
			set newText to newText & thisChar as string
		end if
		set lastChar to thisChar
	end repeat
	return newText
end changeCase

I adopted this handler some time ago, as it considerably reduced the number of handlers in my text library.
Then I started getting errors…
They were caused by strings starting with a numeral. This gets you offset = 0, so control passes to the else clause in the repeat, where it encounters an undefined lastChar variable.This is my fix:

.
set lastChar to ""-- ADDED
repeat with thisChar in thisText
.

This is a modern version of the script with help of AppleScriptObjC

use AppleScript version "2.5"
use framework "Foundation"
use scripting additions

set sampleString to "THIS STRING WILL COME BACK WITH THE FIRST LETTER OF EVERY WORD BEING A CAPITAL AND THE REST WILL BE LOWER CASE. Text containing punctuation: x-ray, don't."

get changeCase(sampleString, "Sentence")

on changeCase(theText, mode)
	if mode is not in {"UPPER", "lower", "Title", "Sentence"} then
		return "Error: Case must be UPPER, lower, Title or Sentence"
	end if
	set cocoaString to current application's NSMutableString's stringWithString:theText
	if mode is "UPPER" then
		return cocoaString's uppercaseString() as text
	else if mode = "lower" then
		return cocoaString's lowercaseString() as text
	else if mode = "title" then
		return cocoaString's capitalizedString() as text
	else
		set cocoaString to cocoaString's lowercaseString()
		set startOfSentence to true
		set whiteSpaceCharacterSet to current application's NSCharacterSet's whitespaceAndNewlineCharacterSet()
		repeat with i from 0 to (cocoaString's |length|()) - 1
			set charRange to {location:i, |length|:1}
			set aChar to (cocoaString's substringWithRange:charRange)
			if startOfSentence then
				set unichar to (cocoaString's characterAtIndex:i)
				if ((whiteSpaceCharacterSet's characterIsMember:unichar) as boolean) is false then
					(cocoaString's replaceCharactersInRange:charRange withString:(aChar's uppercaseString()))
					set startOfSentence to false
				end if
			else if aChar as text is "." then
				set startOfSentence to true
			end if
		end repeat
		return cocoaString as text
	end if
end changeCase