Automated Rutines, lesson 1. Working with Text.

(Script 1a): Convert text document file to Word document file. (Word file is saved to folder of text file):


set textFile to choose file of type "public.plain-text"
set textFilePath to quoted form of POSIX path of textFile

do shell script "textutil -convert doc " & textFilePath

(Script 1b): Batch convert text document files to Word document files. (Each Word file is saved to folder of each text file):


set rootFolder to ¬
	choose folder with prompt ¬
		"Please, select the \"root\" FOLDER" default location (path to documents folder)
set rootFolderPath to quoted form of POSIX path of rootFolder

set shellCommand to "mdfind -onlyin " & rootFolderPath & " 'kMDItemContentType = \"public.plain-text\"'"
set textFilePaths to paragraphs of shellCommand

repeat with textFilePath in textFilePaths
	set textFilePath to quoted form of textFilePath
	do shell script "textutil -convert doc " & textFilePath
end repeat


(Script 1c): Export Text using Chosen Fonts. (here is saved to desktop):


tell application "Font Book"
	set fontCollectionsNames to name of every font collection
	set collectionName to item 1 of (choose from list fontCollectionsNames with prompt "Choose a font collection")
	set fontNames to name of every font family of font collection collectionName
	quit
end tell

set aText to ""
repeat with aFontName in fontNames
	set aText to aText & aFontName & ":" & return & "\"Exporting Text using Chosen Fonts\"" & return & return
end repeat

tell application "TextEdit"
	set newDocument to make new document
	set text of newDocument to aText
	set aCounter to 0
	repeat with aFontName in fontNames
		set font of paragraph (aCounter + 1) of text of newDocument to "Helvetica"
		set font of paragraph (aCounter + 2) of text of newDocument to aFontName
		set aCounter to aCounter + 3
	end repeat
	save newDocument in file ((path to desktop as Unicode text) & "Exported Text using Chosen Fonts.rtf")
	close front document
end tell


(Script 1d): Display text document statistics. (The document should be opened. It may be new created too. That is, unsaved in the file yet):


tell application id "com.apple.TextEdit"
	try
		tell front document to display dialog (count every character) & " characters" & return ¬
			& (count every word) & " words" & return & (count every paragraph) & " paragraphs" as text ¬
			with title "Statistics for '" & (name of it as text) & ¬
			"'" buttons {"OK"} default button 1 cancel button 1
	end try
end tell


(Script 1e): Trim White Spaces Around the Text. (From “AsObjC rutines”):


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

trimWhiteSpaceAroundString("	  How now brown cow. 	")

on trimWhiteSpaceAroundString(thisString)
	set cocoaString to ¬
		current application's NSString's stringWithString:thisString
	set whiteSpaceCharacters to ¬
		current application's NSCharacterSet's whitespaceAndNewlineCharacterSet()
	set cocoaString to cocoaString's stringByTrimmingCharactersInSet:whiteSpaceCharacters
	return cocoaString as text
end trimWhiteSpaceAroundString


(Script 1f): Text replication. (From “AsObjC rutines”):


use framework "Foundation"

set theString to "Robert"
set nReplications to 5

set theString to current application's NSString's stringWithString:theString

(theString's stringByPaddingToLength:(nReplications * (theString's |length|())) ¬
	withString:theString startingAtIndex:0) as text


(Script 1g): Decode %-coded text. (From “AsObjC rutines”):


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

decodePercentEncoding("Once%20upon%20the%20rainbow%E2%80%99s%20end%2E")
--> "Once upon the rainbow’s end."

on decodePercentEncoding(sourceText)
	-- create a Cocoa string from the passed AppleScript string
	set sourceString to ¬
		current application's NSString's stringWithString:sourceText
	-- apply the indicated transformation to the Cooca string
	set adjustedString to ¬
		sourceString's stringByRemovingPercentEncoding()
	-- coerce from Cocoa string to AppleScript string
	return (adjustedString as text)
end decodePercentEncoding


(Script 1h): List ocurrences of the Words in the Text file . (From “AsObjC rutines”):


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set myTextFile to choose file
set myTextFileContents to (read myTextFile)

set theWords to current application's class "NSArray"'s arrayWithArray:(words of myTextFileContents) -- These will be AppleScript's idea of "words".
set theWords to theWords's valueForKey:("capitalizedString")

set wordCounter to current application's class "NSCountedSet"'s alloc()'s initWithArray:(theWords)
set sortedWords to wordCounter's sortedArrayUsingDescriptors:({current application's class "NSSortDescriptor"'s sortDescriptorWithKey:("self") ascending:(true)})

set wordCount to current application's class "NSMutableArray"'s new()
repeat with thisWord in sortedWords
	tell wordCount to addObject:((thisWord as text) & ": " & (wordCounter's countForObject:(thisWord)))
end repeat

return (wordCount's componentsJoinedByString:(linefeed)) as text


(Script 1i): List ocurrences of the Words in the Text file, sorted alphabetically. (From “AsObjC rutines”):


use scripting additions
use framework "Foundation"
property |⌘| : a reference to current application
property NSMutableArray : a reference to NSMutableArray of |⌘|
property NSCountedSet : a reference to NSCountedSet of |⌘|
property NSDictionary : a reference to NSDictionary of |⌘|
property NSSortDescriptor : a reference to NSSortDescriptor of |⌘|


set aText to "There seem to be two issues with Image Events and Catalina. 
First, it doesn't seem to be able to deal with aliases.
In the sample code above, the open command returns missing value,
 so the rest of the script goes nowhere. However,
 if you pass a file reference -- «class furl» -- the open command works.

The second issue is that, depending where the image is,
 you may need permission to read the file, and in such cases no prompt appears.
 Presumably that's because Image Events is a background-only app.
 You can get around this by going to System Preferences -> Security & Privacy -> Privacy
 and adding Image Events to Full Disk Access."

set aList to words of aText
set anArray to NSMutableArray's array()
set aSet to NSCountedSet's setWithArray:aList

repeat with anObject in aSet's allObjects()
	set theObjects to {anObject, (aSet's countForObject:anObject)}
	set theKeys to {"aWord", "aCount"}
	(anArray's addObject:(NSDictionary's dictionaryWithObjects:theObjects forKeys:theKeys))
end repeat

set descriptorOne to NSSortDescriptor's sortDescriptorWithKey:"aCount" ascending:false
set descriptorTwo to NSSortDescriptor's sortDescriptorWithKey:"aWord" ascending:true ¬
	selector:"localizedCaseInsensitiveCompare:"
anArray's sortUsingDescriptors:{descriptorOne, descriptorTwo}

anArray as list


(Script 1j): Change the Register of the Text. (From “AsObjC rutines”):


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

changeCaseOfText("how now brown cow", 2)
--> "How Now Brown Cow"

on changeCaseOfText(sourceText, caseIndicator)
	-- create a Cocoa string from the passed text, using NSString class method stringWithString:
	set the sourceString to ¬
		current application's NSString's stringWithString:sourceText
	-- apply the indicated transformation to the Cocoa string
	if the caseIndicator is 0 then
		-- optional: localizedUppercaseString
		set the adjustedString to sourceString's uppercaseString()
	else if the caseIndicator is 1 then
		-- optional: localizedLowercaseString
		set the adjustedString to sourceString's lowercaseString()
	else
		-- optional: localizedCapitalizedString
		set the adjustedString to sourceString's capitalizedString()
	end if
	-- convert from Cocoa string to AppleScript string
	return (adjustedString as text)
end changeCaseOfText


(Script 1k): Replace Substring in the Text. (From “AsObjC rutines”):


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

replaceStringInString("How now brown cow.", "cow", "pig")

on replaceStringInString(sourceText, searchString, replacementString)
	set aString to current application's NSString's stringWithString:sourceText
	set resultString to ¬
		aString's stringByReplacingOccurrencesOfString:searchString withString:replacementString
	return resultString as text
end replaceStringInString


(Script 1l): Trim from the Text indicated by list Subsrtrings. (From “AsObjC rutines”):


use AppleScript version "2.4"
use framework "Foundation"

set strTest to "	Hello World! "
set strTrimmed to trimThis(strTest, missing value, left) -- result: "Hello World! "
set strTrimmed to trimThis(strTest, missing value, right) -- result: "    Hello World!"
set strTrimmed to trimThis(strTest, tab & return & linefeed, missing value) -- result: "Hello World! "

on trimThis(pstrSourceText, pstrCharToTrim, pstrTrimDirection)
	-- pstrCharToTrim     : A list of characters to trim, or true to use default
	-- pstrSourceText : The text to be trimmed
	-- pstrTrimDirection : Direction of Trim left, right or any value for full
	if pstrCharToTrim = missing value or pstrCharToTrim = true then
		set setToTrim to current application's NSCharacterSet's whitespaceAndNewlineCharacterSet()
	else
		set setToTrim to current application's NSCharacterSet's characterSetWithCharactersInString:pstrCharToTrim
	end if
	
	set anNSString to current application's NSString's stringWithString:pstrSourceText
	if pstrTrimDirection = left then
		set theRange to anNSString's rangeOfCharacterFromSet:(setToTrim's invertedSet())
		if |length| of theRange = 0 then return ""
		set anNSString to anNSString's substringFromIndex:(theRange's location)
	else if pstrTrimDirection = right then
		set theRange to anNSString's rangeOfCharacterFromSet:(setToTrim's invertedSet()) options:(current application's NSBackwardsSearch)
		if |length| of theRange = 0 then return ""
		set anNSString to anNSString's substringToIndex:(theRange's location)
	else
		set anNSString to anNSString's stringByTrimmingCharactersInSet:setToTrim
	end if
	return anNSString as text
end trimThis


(Script 1m): Parse the Text by Keywords. (by Yvan Koenig):


set aText to "“more text Message-ID:<1>more text”
I want to return 1 in this case

“more text 
Message-ID:      <1234567> more text”
I want to return 1234567 in this case

“more text   Message-ID:    
    <1asioduasdoipasu877> more text”
I want to return 1asioduasdoipasu877 in this case

“more text   Message-ID:
    
<asdkjdfkjdfkj@sdfksjfd>more text”
I want to return asdkjdfkjdfkj@sdfksjfd in this case

“more text   Message-ID:    
    <1asioduasdoipasu877> more text”
I want to return 1asioduasdoipasu877 in this case

“more text   Message-ID:
    
<asdkjdfkjdfkj@sdfksjfd>more text”
I want to return asdkjdfkjdfkj@sdfksjfd in this case"

set inList to rest of my decoupe(aText, "Message-ID:")
set allStrings to {}
repeat with aString in inList
	set aString to (item 2 of my decoupe(aString, {"<", ">"})) as text
	if aString is not in allStrings then set end of allStrings to aString
end repeat
allStrings

on decoupe(t, d)
	local oTIDs, l
	set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
	set l to text items of t
	set AppleScript's text item delimiters to oTIDs
	return l
end decoupe


(Script 1n): Extract Email Addresses from plain text. (by Shane Stanley):


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

on findEmailAddressesIn:theString
	-- Locate all the "links" in the text.
	set theNSDataDetector to current application's NSDataDetector's dataDetectorWithTypes:(current application's NSTextCheckingTypeLink) |error|:(missing value)
	set theString to current application's NSString's stringWithString:theString
	set theURLsNSArray to theNSDataDetector's matchesInString:theString options:0 range:{location:0, |length|:theString's |length|()}
	-- Extract email links
	set emailPredicate to current application's NSPredicate's predicateWithFormat:"self.URL.scheme == 'mailto'"
	set emailURLs to theURLsNSArray's filteredArrayUsingPredicate:emailPredicate
	-- Get just the addresses
	set emailsArray to emailURLs's valueForKeyPath:"URL.resourceSpecifier"
	--eliminate duplicates
	set emailsArray to (current application's NSSet's setWithArray:emailsArray)'s allObjects()
	-- Join the remainder as a single, return-delimited text
	set emailAddresses to emailsArray's componentsJoinedByString:(return)
	-- Return as AppleScript text
	return emailAddresses as text
end findEmailAddressesIn:


set aText to "Hello, guys.
My email address is \"kniazidis.rompert@gmail.com.\"
I am looking for a way to change all the email addresses
 and all the website urls in a text to the same email address
 and website url preceding the text <\\!s>.
 Possibly using a grep command or anything. Is there anyone here who can help me?
 Would be great, I've been trying myself for a few days, but cannot get to any result."

set emailAddresses to {its findEmailAddressesIn:aText}