fix to compile htcLib into Compiled folder

-- main_helper
-- Erik Shagdar, NYHTC
-- Helper script that compiles all .applescript files into a folder of compiled .scpt files, then builds the htcLib app to reference those compiled scripts.

(* HISTORY:
	2019-12-10 ( dshockley ): Changed to COMPILE each handler, then also compile htcLib into the same folder.
	2017-12-18 ( eshagdar ): skip files whose name begins wtih 'WIP_' ( work in progress ).
	2017-11-14 ( dshockley ): open system preference pane even from command line.
	2017-10-20 ( eshagdar ): allow running with params. If ran with 'False', dialogs ( and re-enabling assistve devices ) is suppressed.
	2017-10-18 ( eshagdar ): debugMode is a property. htcLib scriptName is 'htcLib', not 'main.scpt'.
	2017-10-06 ( eshagdar ): added library folder to skip when generating htcLib. renamed variables for clarity.
	2017-09-12 ( eshagdar ): attempt to de-select and re-select the htcLib checkbox.
	2017-06-29 ( eshagdar ): check to see if htcLib exists.
	2017-06-26 ( eshagdar ): quit the app before deleting it.
	2017-06-14 ( eshagdar ): also make an app.
	2016-04-21 ( eshagdar ): Updated clickCommandPosix path.
	2016-03-17 ( eshagdar ): Added DebugMode and clickCommandPosix properties.
	2016-03-15 ( eshagdar ): added documentation to main script. Separated individual functions into library directories and updated run code to loop over files in sub-directories.
	2016-03-14 ( eshagdar ): first created.
*)

property debugMode : true

property LF : ASCII character 10
property tempFileName : "temp.applescript"

property mainFileName : "main.scpt"
property appName : "htcLib"
property appExtension : ".app"
property compiledFolderName : "CompiledHandlers"
property securityPrefPanePosix : "/System/Library/PreferencePanes/Security.prefPane"

on run prefs
	set defaultPrefs to {true}
	if class of prefs is script or prefs is equal to {} then set prefs to defaultPrefs
	set showDialogs to ((item 1 of prefs) as boolean)

	set shouldBuildAPP to true
	if showDialogs then
		display dialog "Build (or rebuild/replace) the htcLib?" buttons {"Cancel", "Only Scripts", "App & Scripts"} default button "App & Scripts"
		if button returned of result is "Only Scripts" then
			set shouldBuildAPP to false
		end if
	end if

	set folderName_library to "library:"
	set folderName_toSkip to "standalone"
	set fileNamePrefix_toSkip to "WIP_"

	set tempCode to ""
	set commentBreaker to "--------------------"
	set codeStart to commentBreaker & LF & "-- START OF CODE" & LF & commentBreaker
	set codeEnd to commentBreaker & LF & "-- END OF CODE" & LF & commentBreaker

	-- substrings for parsing sub-handler code:
	set subStr_handlerProperties to "property debugMode: false" & LF & "property ScriptName: \"" & appName & "\"" & LF
	set subStr_beforeHandlerName to LF & "on "
	set subStr_beforeHandlerParams to "("
	set subStr_endPrefixHandler to LF & "end "

	set subStr_templateHandlerWrapperCode to
		"	tell application \"Finder\" to set handlerPath to " &
		"((container of (path to me)) as text) & \"###HANDLER_NAME###\" & \".scpt\"" & LF &
		"	tell (load script alias handlerPath) to return ###HANDLER_CALL###"

	set subStr_special_clickAtCoords_InternalCode_InsertAfter to (ASCII character 9) & "try" & LF
	set subStr_special_clickAtCoords_InternalCode_ToAdd to
		"tell application \"Finder\" to set clickCommandPosix to POSIX path of (((container of container of (path to me)) as string) & \"vendor:cliclick:cliclick\")" & LF

	tell application "Finder"
		set pathRoot to (folder of (path to me)) as string
		set thisFileName to name of (path to me)
	end tell

	set pathTempCode to pathRoot & tempFileName
	set pathMain to pathRoot & mainFileName
	set pathLibrary to pathRoot & folderName_library
	set pathCompiledFolder to pathRoot & compiledFolderName & ":"
	set pathApp to pathCompiledFolder & appName & appExtension

	set libraryNames to list folder (pathLibrary) without invisibles

	-- loop over each sub-directory, compiling each handler and adding to htcLib APP code:
	repeat with dirCount from 1 to count of libraryNames
		set oneLibraryName to item dirCount of libraryNames
		set pathOneLibrary to pathLibrary & oneLibraryName
		if oneLibraryName is equal to folderName_toSkip then
			-- skip this folder because it contains standalone handlers
		else
			-- get all files in the the folder
			set fileNamesInOneLibrary to list folder (pathOneLibrary) without invisibles

			-- append all libraries into a single file
			repeat with fileCount from 1 to count of fileNamesInOneLibrary

				-- read one file and get everything above the helper methods
				set oneFileName to item fileCount of fileNamesInOneLibrary
				if oneFileName does not start with fileNamePrefix_toSkip then
					set pathOneFileinOneLibrary to pathOneLibrary & ":" & oneFileName
					set oneFileRawCode to read file pathOneFileinOneLibrary
					if oneFileRawCode contains codeStart and oneFileRawCode contains codeEnd then
						set codeOneHandler to getTextBetween({oneFileRawCode, codeStart, codeEnd})
					else
						set codeOneHandler to oneFileRawCode
					end if

					set handlerCall to getTextBetween({codeOneHandler, subStr_beforeHandlerName, LF})
					if handlerCall contains subStr_beforeHandlerParams then
						set handlerName to getTextBefore(handlerCall, "(")
					else
						set handlerName to handlerCall
					end if

					if handlerName is "clickAtCoords" then
						-- SPECIAL MODIFICATION to bring a "property" into the actual handler code.
						set codeOneHandler to my replaceSimple({codeOneHandler, subStr_special_clickAtCoords_InternalCode_InsertAfter, subStr_special_clickAtCoords_InternalCode_InsertAfter & subStr_special_clickAtCoords_InternalCode_ToAdd})
					end if

					if shouldBuildAPP then
						-- APPEND TO APP: now append to htcLib APP code:

						set handlerInternalCode to replaceSimple({replaceSimple({subStr_templateHandlerWrapperCode, "###HANDLER_NAME###", handlerName}), "###HANDLER_CALL###", handlerCall})
						set codeHandlerWrapper to subStr_beforeHandlerName & handlerCall & LF & handlerInternalCode & subStr_endPrefixHandler & handlerName & LF

						if (length of tempCode) is greater than 0 then set tempCode to tempCode & return & return & return
						set tempCode to tempCode & codeHandlerWrapper

					end if

					-- SUBHANDLERS: process each sub-handler this handler depends upon:

					set codeSubHandlers to getTextAfter(oneFileRawCode, codeEnd)

					-- trim the Handler code now (NOT above, since it needs the leading linefeed before the handler call):
					set codeOneHandler to trimWhitespace(codeOneHandler)

					set codeHandlerWithNewSubCalls to subStr_handlerProperties & codeOneHandler
					repeat while codeSubHandlers contains subStr_beforeHandlerName
						set skipThisSubhandler to false
						set oneSubhandlerCall to getTextBetween({codeSubHandlers, subStr_beforeHandlerName, LF})
						if oneSubhandlerCall contains subStr_beforeHandlerParams then
							set oneSubhandlerName to getTextBefore(oneSubhandlerCall, "(")
						else
							set oneSubhandlerName to oneSubhandlerCall
						end if

						if oneSubhandlerName is "coerceToString" then
							if codeOneHandler does not contain "coerceToString" then
								-- the coerceToString was NOT used in the main handler, so we don't actually NEED it:
								-- so SKIP this:
								set skipThisSubhandler to true
							end if
						end if

						if not skipThisSubhandler then
							-- we DO need this subhandler, so reformat it:
							set subHandlerInternalCode to replaceSimple({replaceSimple({subStr_templateHandlerWrapperCode, "###HANDLER_NAME###", oneSubhandlerName}), "###HANDLER_CALL###", oneSubhandlerCall})
							set oneSubHandlerCode to subStr_beforeHandlerName & oneSubhandlerCall & LF & subHandlerInternalCode & subStr_endPrefixHandler & oneSubhandlerName & LF

							set codeHandlerWithNewSubCalls to codeHandlerWithNewSubCalls & LF & oneSubHandlerCode
						end if

						set codeSubHandlers to getTextAfter(codeSubHandlers, subStr_endPrefixHandler & oneSubhandlerName)

					end repeat

					-- write the modified code into a temporary file:
					try
						close access fileRef
					end try
					set fileRef to (open for access file pathTempCode with write permission)
					set eof of fileRef to 0 --> empty file contents if needed
					write codeHandlerWithNewSubCalls to fileRef
					close access fileRef

					-- COMPILE the temporary file to the desired destination:
					set compiledFileName to replaceSimple({oneFileName, ".applescript", ".scpt"})
					set pathCompiled to (pathCompiledFolder & compiledFileName)
					do shell script "osacompile -o " & quoted form of POSIX path of pathCompiled & " " & quoted form of POSIX path of pathTempCode

				end if
			end repeat
		end if
	end repeat

	if shouldBuildAPP then
		-- prepend code with documentation
		set docCode to "-- main script"
		set docCode to docCode & LF & "-- Erik Shagdar, NYHTC"
		set docCode to docCode & LF
		set docCode to docCode & LF & "-- Generated: " & (do shell script "date '+%Y-%m-%d %T'")
		set docCode to docCode & LF & "-- Run " & quoted form of thisFileName & " to after making changes in any .applescript file and after each git pull."
		set docCode to docCode & LF & "-- Assumes file is located at '~/Code/applescript-fm-helper/'. If it is not, make sure to update clickCommandPosix property and 'vendor.sh' script."
		set docCode to docCode & LF
		set docCode to docCode & LF & "property DebugMode : " & debugMode
		set docCode to docCode & LF & "property ScriptName : \"" & appName & "\""
		set docCode to docCode & LF & "property clickCommandPosix : POSIX path of (((path to home folder) as string)) & \"Code/applescript-fm-helper/vendor/cliclick/cliclick\""

		set tempCode to docCode & LF & LF & LF & tempCode

		-- create a temp file of all libaries, then create a compiled version of it.
		--	do shell script "echo " & quoted form of tempCode & " > " & quoted form of POSIX path of pathTempCode

		try
			close access fileRef
		end try
		set fileRef to (open for access file pathTempCode with write permission)
		set eof of fileRef to 0 --> empty file contents if needed
		--> now write the flag
		--	write ((ASCII character 239) & (ASCII character 187) & (ASCII character 191)) to fileRef --> not as class utf8
		--> now write the data
		write tempCode to fileRef
		close access fileRef

		do shell script "osacompile -o " & quoted form of POSIX path of pathMain & " " & quoted form of POSIX path of pathTempCode
		do shell script "pwd"
		do shell script "sh " & quoted form of (POSIX path of (pathRoot & "vendor.sh"))
		if result does not contain "SUCCESS" then return "Error: unable to run vendor.sh"

		set appExists to false
		tell application "Finder"
			if exists pathApp then set appExists to true
		end tell

		--quit the pre-existing app
		if appExists then
			tell application appName to quit
		end if

		-- remove pre-existing app file
		tell application "Finder"
			if appExists then delete file pathApp
		end tell

		-- now make it into an app
		do shell script "osacompile -s -o " & quoted form of POSIX path of pathApp & " " & quoted form of POSIX path of pathTempCode

		if showDialogs then
			tell it to activate
			set AsstAccessDlg to display dialog "You must enable assistive access for " & appName & "." with title appName buttons {"Open", "OK"} default button "OK"

			-- navigate to security preference pane
			if button returned of AsstAccessDlg is equal to "Open" then

				tell application "System Preferences" to activate
				do shell script "open " & quoted form of securityPrefPanePosix

				tell application "System Events"
					tell process "System Preferences"
						click radio button "Privacy" of tab group 1 of window 1

						-- get htcLib checkbox
						set htcLibRow to (first row of table 1 of scroll area 1 of group 1 of tab group 1 of window 1 whose value of static text 1 of UI element 1 contains "htcLib")
						set htcLibCheckbox to checkbox 1 of UI element 1 of htcLibRow
						select htcLibRow

						-- unlock if needed
						set canMakeChanges to enabled of htcLibCheckbox
						if canMakeChanges is false then
							click button 1 of window 1
							display dialog "You must deselect, then reselect the " & appName & " checkbox" buttons "OK" default button "OK"
							return true
						end if

						-- uncheck, then recheck to re-allow control of htcLib
						click htcLibCheckbox
						delay 0.5
						click htcLibCheckbox
						delay 0.5
						set visible to false
					end tell
				end tell

				tell me to activate
				display dialog appName & " is ready" buttons "OK" default button "OK"
			end if
			return true
		else

			tell application "System Preferences" to activate
			do shell script "open " & quoted form of securityPrefPanePosix

			return "you must re-allow assistive devices to '" & appName & "'."

		end if

	end if -- should build APP.

	-- remove the temp file
	tell application "Finder"
		if exists pathTempCode then delete file pathTempCode
	end tell

end run

--------------------
-- HELPER FUNCTIONS
--------------------

on parentFolderOfPath(incomingPath)
	--version 1.1, Daniel A. Shockley

	set incomingPath to incomingPath as string
	if incomingPath is "" then
		error "Cannot find a parent folder for a path that is blank." number -1027
	end if

	if last character of incomingPath is ":" then
		-- if it ends with ":" (a folder), leave that off for the code below
		set incomingPath to (text 1 through -2 of incomingPath) as string
	end if

	set {od, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ":"}
	if (count of text items of incomingPath) is 1 then
		-- the item in question is a disk, so CANNOT return a parent folder
		set AppleScript's text item delimiters to od
		error "Cannot find a parent folder of a DISK: " & incomingPath & "." number -1027
	else
		set enclosingFolder to (text items 1 through -2 of incomingPath as string)
	end if

	set AppleScript's text item delimiters to od
	return enclosingFolder & ":"

end parentFolderOfPath

on getTextBetween(prefs)
	-- version 1.6, Daniel A. Shockley <http://www.danshockley.com>

	set defaultPrefs to {textItemNum:2, includeMarkers:false}

	if (class of prefs is not list) and ((class of prefs) as string is not "record") then
		error "getTextBetween FAILED: parameter should be a record or list. If it is multiple items, just make it into a list to upgrade to this handler." number 1024
	end if
	if class of prefs is list then
		if (count of prefs) is 4 then
			set textItemNum of defaultPrefs to item 4 of prefs
		end if
		set prefs to {sourceTEXT:item 1 of prefs, beforeText:item 2 of prefs, afterText:item 3 of prefs}
	end if
	set prefs to prefs & defaultPrefs -- add on default preferences, if needed
	set sourceTEXT to sourceTEXT of prefs
	set beforeText to beforeText of prefs
	set afterText to afterText of prefs
	set textItemNum to textItemNum of prefs
	set includeMarkers to includeMarkers of prefs

	try
		set {oldDelims, AppleScript's text item delimiters} to {AppleScript's text item delimiters, beforeText}
		set the prefixRemoved to text item textItemNum of sourceTEXT
		set AppleScript's text item delimiters to afterText
		set the finalResult to text item 1 of prefixRemoved
		set AppleScript's text item delimiters to oldDelims

		if includeMarkers then set finalResult to beforeText & finalResult & afterText

	on error errMsg number errNum
		set AppleScript's text item delimiters to oldDelims
		-- 	tell me to log "Error in getTextBetween() : " & errMsg
		set the finalResult to "" -- return nothing if the surrounding text is not found
	end try

	return finalResult

end getTextBetween

on trimWhitespace(inputString)
	-- version 1.2:

	set whiteSpaceAsciiNumbers to {13, 10, 32, 9} -- characters that count as whitespace.

	set textLength to length of inputString
	if textLength is 0 then return ""
	set endSpot to -textLength -- if only whitespace is found, will chop whole string

	-- chop from end
	set i to -1
	repeat while -i is less than or equal to textLength
		set testChar to text i thru i of inputString
		if whiteSpaceAsciiNumbers does not contain (ASCII number testChar) then
			set endSpot to i
			exit repeat
		end if
		set i to i - 1
	end repeat

	if -endSpot is equal to textLength then
		if whiteSpaceAsciiNumbers contains (ASCII number testChar) then return ""
	end if

	set inputString to text 1 thru endSpot of inputString
	set textLength to length of inputString
	set newStart to 1

	-- chop from beginning
	set i to 1
	repeat while i is less than or equal to textLength
		set testChar to text i thru i of inputString
		if whiteSpaceAsciiNumbers does not contain (ASCII number testChar) then
			set newStart to i
			exit repeat
		end if
		set i to i + 1
	end repeat

	set inputString to text newStart thru textLength of inputString

	return inputString

end trimWhitespace

on getTextAfter(sourceTEXT, afterThis)
	-- version 1.2

	try
		set {oldDelims, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {afterThis}}

		if (count of text items of sourceTEXT) is 1 then
			-- the split-string didn't appear at all
			set AppleScript's text item delimiters to oldDelims
			return ""
		else
			set the resultAsList to text items 2 thru -1 of sourceTEXT
		end if
		set AppleScript's text item delimiters to {afterThis}
		set finalResult to resultAsList as string
		set AppleScript's text item delimiters to oldDelims
		return finalResult
	on error errMsg number errNum
		set AppleScript's text item delimiters to oldDelims
		return "" -- return nothing if the stop text is not found
	end try
end getTextAfter

on getTextBefore(sourceTEXT, stopHere)
	-- version 1.1

	try
		set {oldDelims, AppleScript's text item delimiters} to {AppleScript's text item delimiters, stopHere}
		if (count of text items of sourceTEXT) is 1 then
			set AppleScript's text item delimiters to oldDelims
			return ""
		else
			set the finalResult to text item 1 of sourceTEXT
		end if
		set AppleScript's text item delimiters to oldDelims
		return finalResult
	on error errMsg number errNum
		set AppleScript's text item delimiters to oldDelims
		return "" -- return nothing if the stop text is not found
	end try
end getTextBefore

on replaceSimple(prefs)
	-- version 1.4

	set defaultPrefs to {considerCase:true}

	if class of prefs is list then
		if (count of prefs) is greater than 3 then
			-- get any parameters after the initial 3
			set prefs to {sourceTEXT:item 1 of prefs, oldChars:item 2 of prefs, newChars:item 3 of prefs, considerCase:item 4 of prefs}
		else
			set prefs to {sourceTEXT:item 1 of prefs, oldChars:item 2 of prefs, newChars:item 3 of prefs}
		end if

	else if class of prefs is not equal to (class of {someKey:3}) then
		-- Test by matching class to something that IS a record to avoid FileMaker namespace conflict with the term "record"

		error "The parameter for 'replaceSimple()' should be a record or at least a list. Wrap the parameter(s) in curly brackets for easy upgrade to 'replaceSimple() version 1.3. " number 1024

	end if

	set prefs to prefs & defaultPrefs

	set considerCase to considerCase of prefs
	set sourceTEXT to sourceTEXT of prefs
	set oldChars to oldChars of prefs
	set newChars to newChars of prefs

	set sourceTEXT to sourceTEXT as string

	set oldDelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to the oldChars
	if considerCase then
		considering case
			set the parsedList to every text item of sourceTEXT
			set AppleScript's text item delimiters to the {(newChars as string)}
			set the newText to the parsedList as string
		end considering
	else
		ignoring case
			set the parsedList to every text item of sourceTEXT
			set AppleScript's text item delimiters to the {(newChars as string)}
			set the newText to the parsedList as string
		end ignoring
	end if
	set AppleScript's text item delimiters to oldDelims
	return newText

end replaceSimple

-- main_helper
-- Erik Shagdar, NYHTC
-- Helper script that compiles all .applescript files into a folder of compiled .scpt files, then builds the htcLib app to reference those compiled scripts.

(* HISTORY:
	2019-12-06 ( dshockley ): Changed to COMPILE each handler, then also compile htcLib into the same folder.
	2017-12-18 ( eshagdar ): skip files whose name begins wtih 'WIP_' ( work in progress ).
	2017-11-14 ( dshockley ): open system preference pane even from command line.
	2017-10-20 ( eshagdar ): allow running with params. If ran with 'False', dialogs ( and re-enabling assistve devices ) is suppressed.
	2017-10-18 ( eshagdar ): debugMode is a property. htcLib scriptName is 'htcLib', not 'main.scpt'.
	2017-10-06 ( eshagdar ): added library folder to skip when generating htcLib. renamed variables for clarity.
	2017-09-12 ( eshagdar ): attempt to de-select and re-select the htcLib checkbox.
	2017-06-29 ( eshagdar ): check to see if htcLib exists.
	2017-06-26 ( eshagdar ): quit the app before deleting it.
	2017-06-14 ( eshagdar ): also make an app.
	2016-04-21 ( eshagdar ): Updated clickCommandPosix path.
	2016-03-17 ( eshagdar ): Added DebugMode and clickCommandPosix properties.
	2016-03-15 ( eshagdar ): added documentation to main script. Separated individual functions into library directories and updated run code to loop over files in sub-directories.
	2016-03-14 ( eshagdar ): first created.
*)

property debugMode : true

property LF : ASCII character 10
property tempFileName : "temp.applescript"

property mainFileName : "main.scpt"
property appName : "htcLib"
property appExtension : ".app"
property compiledFolderName : "CompiledHandlers"
property securityPrefPanePosix : "/System/Library/PreferencePanes/Security.prefPane"

on run prefs
	set defaultPrefs to {true}
	if class of prefs is script or prefs is equal to {} then set prefs to defaultPrefs
	set showDialogs to ((item 1 of prefs) as boolean)

	set shouldBuildAPP to true
	if showDialogs then
		display dialog "Build (or rebuild/replace) the htcLib?" buttons {"Cancel", "Only Scripts", "App & Scripts"} default button "App & Scripts"
		if button returned of result is "Only Scripts" then
			set shouldBuildAPP to false
		end if
	end if

	set folderName_library to "library:"
	set folderName_toSkip to "standalone"
	set fileNamePrefix_toSkip to "WIP_"

	set tempCode to ""
	set commentBreaker to "--------------------"
	set codeStart to commentBreaker & LF & "-- START OF CODE" & LF & commentBreaker
	set codeEnd to commentBreaker & LF & "-- END OF CODE" & LF & commentBreaker

	-- substrings for parsing sub-handler code:
	set subStr_handlerProperties to "property debugMode: false" & LF & "property ScriptName: \"" & appName & "\"" & LF
	set subStr_beforeHandlerName to LF & "on "
	set subStr_beforeHandlerParams to "("
	set subStr_endPrefixHandler to LF & "end "

	set subStr_templateHandlerWrapperCode to
		"	tell application \"Finder\" to set handlerPath to " &
		"((container of (path to me)) as text) & \"###HANDLER_NAME###\" & \".scpt\"" & LF &
		"	tell (load script alias handlerPath) to return ###HANDLER_CALL###"

	set subStr_special_clickAtCoords_InternalCode_InsertAfter to (ASCII character 9) & "try" & LF
	set subStr_special_clickAtCoords_InternalCode_ToAdd to
		"tell application \"Finder\" to set clickCommandPosix to POSIX path of (((container of container of (path to me)) as string) & \"vendor:cliclick:cliclick\")" & LF

	tell application "Finder"
		set pathRoot to (folder of (path to me)) as string
		set thisFileName to name of (path to me)
	end tell

	set pathTempCode to pathRoot & tempFileName
	set pathMain to pathRoot & mainFileName
	set pathApp to pathRoot & appName & appExtension
	set pathLibrary to pathRoot & folderName_library
	set libraryNames to list folder (pathLibrary) without invisibles
	set pathFunctionLib to pathRoot & compiledFolderName & ":"

	-- loop over each sub-directory, compiling each handler and adding to htcLib APP code:
	repeat with dirCount from 1 to count of libraryNames
		set oneLibraryName to item dirCount of libraryNames
		set pathOneLibrary to pathLibrary & oneLibraryName
		if oneLibraryName is equal to folderName_toSkip then
			-- skip this folder because it contains standalone handlers
		else
			-- get all files in the the folder
			set fileNamesInOneLibrary to list folder (pathOneLibrary) without invisibles

			-- append all libraries into a single file
			repeat with fileCount from 1 to count of fileNamesInOneLibrary

				-- read one file and get everything above the helper methods
				set oneFileName to item fileCount of fileNamesInOneLibrary
				if oneFileName does not start with fileNamePrefix_toSkip then
					set pathOneFileinOneLibrary to pathOneLibrary & ":" & oneFileName
					set oneFileRawCode to read file pathOneFileinOneLibrary
					if oneFileRawCode contains codeStart and oneFileRawCode contains codeEnd then
						set codeOneHandler to getTextBetween({oneFileRawCode, codeStart, codeEnd})
					else
						set codeOneHandler to oneFileRawCode
					end if

					set handlerCall to getTextBetween({codeOneHandler, subStr_beforeHandlerName, LF})
					if handlerCall contains subStr_beforeHandlerParams then
						set handlerName to getTextBefore(handlerCall, "(")
					else
						set handlerName to handlerCall
					end if

					if handlerName is "clickAtCoords" then
						-- SPECIAL MODIFICATION to bring a "property" into the actual handler code.
						set codeOneHandler to my replaceSimple({codeOneHandler, subStr_special_clickAtCoords_InternalCode_InsertAfter, subStr_special_clickAtCoords_InternalCode_InsertAfter & subStr_special_clickAtCoords_InternalCode_ToAdd})
					end if

					if shouldBuildAPP then
						-- APPEND TO APP: now append to htcLib APP code:

						set handlerInternalCode to replaceSimple({replaceSimple({subStr_templateHandlerWrapperCode, "###HANDLER_NAME###", compiledFolderName & ":" & handlerName}), "###HANDLER_CALL###", handlerCall})
						set codeHandlerWrapper to subStr_beforeHandlerName & handlerCall & LF & handlerInternalCode & subStr_endPrefixHandler & handlerName & LF

						if (length of tempCode) is greater than 0 then set tempCode to tempCode & return & return & return
						set tempCode to tempCode & codeHandlerWrapper

					end if

					-- SUBHANDLERS: process each sub-handler this handler depends upon:

					set codeSubHandlers to getTextAfter(oneFileRawCode, codeEnd)

					-- trim the Handler code now (NOT above, since it needs the leading linefeed before the handler call):
					set codeOneHandler to trimWhitespace(codeOneHandler)

					set codeHandlerWithNewSubCalls to subStr_handlerProperties & codeOneHandler
					repeat while codeSubHandlers contains subStr_beforeHandlerName
						set skipThisSubhandler to false
						set oneSubhandlerCall to getTextBetween({codeSubHandlers, subStr_beforeHandlerName, LF})
						if oneSubhandlerCall contains subStr_beforeHandlerParams then
							set oneSubhandlerName to getTextBefore(oneSubhandlerCall, "(")
						else
							set oneSubhandlerName to oneSubhandlerCall
						end if

						if oneSubhandlerName is "coerceToString" then
							if codeOneHandler does not contain "coerceToString" then
								-- the coerceToString was NOT used in the main handler, so we don't actually NEED it:
								-- so SKIP this:
								set skipThisSubhandler to true
							end if
						end if

						if not skipThisSubhandler then
							-- we DO need this subhandler, so reformat it:
							set subHandlerInternalCode to replaceSimple({replaceSimple({subStr_templateHandlerWrapperCode, "###HANDLER_NAME###", oneSubhandlerName}), "###HANDLER_CALL###", oneSubhandlerCall})
							set oneSubHandlerCode to subStr_beforeHandlerName & oneSubhandlerCall & LF & subHandlerInternalCode & subStr_endPrefixHandler & oneSubhandlerName & LF

							set codeHandlerWithNewSubCalls to codeHandlerWithNewSubCalls & LF & oneSubHandlerCode
						end if

						set codeSubHandlers to getTextAfter(codeSubHandlers, subStr_endPrefixHandler & oneSubhandlerName)

					end repeat

					-- write the modified code into a temporary file:
					try
						close access fileRef
					end try
					set fileRef to (open for access file pathTempCode with write permission)
					set eof of fileRef to 0 --> empty file contents if needed
					write codeHandlerWithNewSubCalls to fileRef
					close access fileRef

					-- COMPILE the temporary file to the desired destination:
					set compiledFileName to replaceSimple({oneFileName, ".applescript", ".scpt"})
					set pathCompiled to (pathFunctionLib & compiledFileName)
					do shell script "osacompile -o " & quoted form of POSIX path of pathCompiled & " " & quoted form of POSIX path of pathTempCode

				end if
			end repeat
		end if
	end repeat

	if shouldBuildAPP then
		-- prepend code with documentation
		set docCode to "-- main script"
		set docCode to docCode & LF & "-- Erik Shagdar, NYHTC"
		set docCode to docCode & LF
		set docCode to docCode & LF & "-- Generated: " & (do shell script "date '+%Y-%m-%d %T'")
		set docCode to docCode & LF & "-- Run " & quoted form of thisFileName & " to after making changes in any .applescript file and after each git pull."
		set docCode to docCode & LF & "-- Assumes file is located at '~/Code/applescript-fm-helper/'. If it is not, make sure to update clickCommandPosix property and 'vendor.sh' script."
		set docCode to docCode & LF
		set docCode to docCode & LF & "property DebugMode : " & debugMode
		set docCode to docCode & LF & "property ScriptName : \"" & appName & "\""
		set docCode to docCode & LF & "property clickCommandPosix : POSIX path of (((path to home folder) as string)) & \"Code/applescript-fm-helper/vendor/cliclick/cliclick\""

		set tempCode to docCode & LF & LF & LF & tempCode

		-- create a temp file of all libaries, then create a compiled version of it.
		--	do shell script "echo " & quoted form of tempCode & " > " & quoted form of POSIX path of pathTempCode

		try
			close access fileRef
		end try
		set fileRef to (open for access file pathTempCode with write permission)
		set eof of fileRef to 0 --> empty file contents if needed
		--> now write the flag
		--	write ((ASCII character 239) & (ASCII character 187) & (ASCII character 191)) to fileRef --> not as class utf8
		--> now write the data
		write tempCode to fileRef
		close access fileRef

		do shell script "osacompile -o " & quoted form of POSIX path of pathMain & " " & quoted form of POSIX path of pathTempCode
		do shell script "pwd"
		do shell script "sh " & quoted form of (POSIX path of (pathRoot & "vendor.sh"))
		if result does not contain "SUCCESS" then return "Error: unable to run vendor.sh"

		set appExists to false
		tell application "Finder"
			if exists pathApp then set appExists to true
		end tell

		--quit the pre-existing app
		if appExists then
			tell application appName to quit
		end if

		-- remove pre-existing app file
		tell application "Finder"
			if appExists then delete file pathApp
		end tell

		-- now make it into an app
		do shell script "osacompile -s -o " & quoted form of POSIX path of pathApp & " " & quoted form of POSIX path of pathTempCode

		if showDialogs then
			tell it to activate
			set AsstAccessDlg to display dialog "You must enable assistive access for " & appName & "." with title appName buttons {"Open", "OK"} default button "OK"

			-- navigate to security preference pane
			if button returned of AsstAccessDlg is equal to "Open" then

				tell application "System Preferences" to activate
				do shell script "open " & quoted form of securityPrefPanePosix

				tell application "System Events"
					tell process "System Preferences"
						click radio button "Privacy" of tab group 1 of window 1

						-- get htcLib checkbox
						set htcLibRow to (first row of table 1 of scroll area 1 of group 1 of tab group 1 of window 1 whose value of static text 1 of UI element 1 contains "htcLib")
						set htcLibCheckbox to checkbox 1 of UI element 1 of htcLibRow
						select htcLibRow

						-- unlock if needed
						set canMakeChanges to enabled of htcLibCheckbox
						if canMakeChanges is false then
							click button 1 of window 1
							display dialog "You must deselect, then reselect the HtcLib checkbox" buttons "OK" default button "OK"
							return true
						end if

						-- uncheck, then recheck to re-allow control of htcLib
						click htcLibCheckbox
						delay 0.5
						click htcLibCheckbox
						delay 0.5
						set visible to false
					end tell
				end tell

				tell me to activate
				display dialog "HtcLib is ready" buttons "OK" default button "OK"
			end if
			return true
		else

			tell application "System Preferences" to activate
			do shell script "open " & quoted form of securityPrefPanePosix

			return "you must re-allow assistive devices to '" & appName & "'."

		end if

	end if -- should build APP.

	-- remove the temp file
	tell application "Finder"
		if exists pathTempCode then delete file pathTempCode
	end tell

end run

--------------------
-- HELPER FUNCTIONS
--------------------

on parentFolderOfPath(incomingPath)
	--version 1.1, Daniel A. Shockley

	set incomingPath to incomingPath as string
	if incomingPath is "" then
		error "Cannot find a parent folder for a path that is blank." number -1027
	end if

	if last character of incomingPath is ":" then
		-- if it ends with ":" (a folder), leave that off for the code below
		set incomingPath to (text 1 through -2 of incomingPath) as string
	end if

	set {od, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ":"}
	if (count of text items of incomingPath) is 1 then
		-- the item in question is a disk, so CANNOT return a parent folder
		set AppleScript's text item delimiters to od
		error "Cannot find a parent folder of a DISK: " & incomingPath & "." number -1027
	else
		set enclosingFolder to (text items 1 through -2 of incomingPath as string)
	end if

	set AppleScript's text item delimiters to od
	return enclosingFolder & ":"

end parentFolderOfPath

on getTextBetween(prefs)
	-- version 1.6, Daniel A. Shockley <http://www.danshockley.com>

	set defaultPrefs to {textItemNum:2, includeMarkers:false}

	if (class of prefs is not list) and ((class of prefs) as string is not "record") then
		error "getTextBetween FAILED: parameter should be a record or list. If it is multiple items, just make it into a list to upgrade to this handler." number 1024
	end if
	if class of prefs is list then
		if (count of prefs) is 4 then
			set textItemNum of defaultPrefs to item 4 of prefs
		end if
		set prefs to {sourceTEXT:item 1 of prefs, beforeText:item 2 of prefs, afterText:item 3 of prefs}
	end if
	set prefs to prefs & defaultPrefs -- add on default preferences, if needed
	set sourceTEXT to sourceTEXT of prefs
	set beforeText to beforeText of prefs
	set afterText to afterText of prefs
	set textItemNum to textItemNum of prefs
	set includeMarkers to includeMarkers of prefs

	try
		set {oldDelims, AppleScript's text item delimiters} to {AppleScript's text item delimiters, beforeText}
		set the prefixRemoved to text item textItemNum of sourceTEXT
		set AppleScript's text item delimiters to afterText
		set the finalResult to text item 1 of prefixRemoved
		set AppleScript's text item delimiters to oldDelims

		if includeMarkers then set finalResult to beforeText & finalResult & afterText

	on error errMsg number errNum
		set AppleScript's text item delimiters to oldDelims
		-- 	tell me to log "Error in getTextBetween() : " & errMsg
		set the finalResult to "" -- return nothing if the surrounding text is not found
	end try

	return finalResult

end getTextBetween

on trimWhitespace(inputString)
	-- version 1.2:

	set whiteSpaceAsciiNumbers to {13, 10, 32, 9} -- characters that count as whitespace.

	set textLength to length of inputString
	if textLength is 0 then return ""
	set endSpot to -textLength -- if only whitespace is found, will chop whole string

	-- chop from end
	set i to -1
	repeat while -i is less than or equal to textLength
		set testChar to text i thru i of inputString
		if whiteSpaceAsciiNumbers does not contain (ASCII number testChar) then
			set endSpot to i
			exit repeat
		end if
		set i to i - 1
	end repeat

	if -endSpot is equal to textLength then
		if whiteSpaceAsciiNumbers contains (ASCII number testChar) then return ""
	end if

	set inputString to text 1 thru endSpot of inputString
	set textLength to length of inputString
	set newStart to 1

	-- chop from beginning
	set i to 1
	repeat while i is less than or equal to textLength
		set testChar to text i thru i of inputString
		if whiteSpaceAsciiNumbers does not contain (ASCII number testChar) then
			set newStart to i
			exit repeat
		end if
		set i to i + 1
	end repeat

	set inputString to text newStart thru textLength of inputString

	return inputString

end trimWhitespace

on getTextAfter(sourceTEXT, afterThis)
	-- version 1.2

	try
		set {oldDelims, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {afterThis}}

		if (count of text items of sourceTEXT) is 1 then
			-- the split-string didn't appear at all
			set AppleScript's text item delimiters to oldDelims
			return ""
		else
			set the resultAsList to text items 2 thru -1 of sourceTEXT
		end if
		set AppleScript's text item delimiters to {afterThis}
		set finalResult to resultAsList as string
		set AppleScript's text item delimiters to oldDelims
		return finalResult
	on error errMsg number errNum
		set AppleScript's text item delimiters to oldDelims
		return "" -- return nothing if the stop text is not found
	end try
end getTextAfter

on getTextBefore(sourceTEXT, stopHere)
	-- version 1.1

	try
		set {oldDelims, AppleScript's text item delimiters} to {AppleScript's text item delimiters, stopHere}
		if (count of text items of sourceTEXT) is 1 then
			set AppleScript's text item delimiters to oldDelims
			return ""
		else
			set the finalResult to text item 1 of sourceTEXT
		end if
		set AppleScript's text item delimiters to oldDelims
		return finalResult
	on error errMsg number errNum
		set AppleScript's text item delimiters to oldDelims
		return "" -- return nothing if the stop text is not found
	end try
end getTextBefore

on replaceSimple(prefs)
	-- version 1.4

	set defaultPrefs to {considerCase:true}

	if class of prefs is list then
		if (count of prefs) is greater than 3 then
			-- get any parameters after the initial 3
			set prefs to {sourceTEXT:item 1 of prefs, oldChars:item 2 of prefs, newChars:item 3 of prefs, considerCase:item 4 of prefs}
		else
			set prefs to {sourceTEXT:item 1 of prefs, oldChars:item 2 of prefs, newChars:item 3 of prefs}
		end if

	else if class of prefs is not equal to (class of {someKey:3}) then
		-- Test by matching class to something that IS a record to avoid FileMaker namespace conflict with the term "record"

		error "The parameter for 'replaceSimple()' should be a record or at least a list. Wrap the parameter(s) in curly brackets for easy upgrade to 'replaceSimple() version 1.3. " number 1024

	end if

	set prefs to prefs & defaultPrefs

	set considerCase to considerCase of prefs
	set sourceTEXT to sourceTEXT of prefs
	set oldChars to oldChars of prefs
	set newChars to newChars of prefs

	set sourceTEXT to sourceTEXT as string

	set oldDelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to the oldChars
	if considerCase then
		considering case
			set the parsedList to every text item of sourceTEXT
			set AppleScript's text item delimiters to the {(newChars as string)}
			set the newText to the parsedList as string
		end considering
	else
		ignoring case
			set the parsedList to every text item of sourceTEXT
			set AppleScript's text item delimiters to the {(newChars as string)}
			set the newText to the parsedList as string
		end ignoring
	end if
	set AppleScript's text item delimiters to oldDelims
	return newText

end replaceSimple


fiddle with where the padding spaces are added

-- This script grabs the current article in NetNewsWire and copies relevant information about it
--    to a new outgoing message in Mail
-- the intended use is that the user wants to send email about the current article, and
--    would fill in the recipient and then send the message

-- sometimes, an article has contents, and sometimes it has html contents
-- this function getContentsOrHtml() gets the contents as text, despite the representation
-- first it checks to see if there are plain text contents
-- if not, it looks for html contents, and converts those to plain text using a shell script that invokes textutil
-- if it can't find either plain text or html, it returns "couldn't find article text"
to getContentsOrHtml()
	tell application "NetNewsWire"
		set textContents to the contents of the current article
		if textContents is not "" then
			return textContents
		else
			set htmlContents to html of the current article
			if htmlContents is not "" then
				set shellScript to " echo '" & htmlContents & "' | /usr/bin/textutil -stdin -stdout -format html -convert txt"
				set pureText to do shell script shellScript
				return pureText
			end if
		end if
	end tell
	return "couldn't find article text"
end getContentsOrHtml

-- given a list of author names, generate a happily formatted list like "Jean MacDonald and James Dempsey"
-- if the list is more than two names, use Oxford comma structure: "Brent Simmons, Jean MacDonald, and James Dempsey"

to formatListOfNames(listOfNames)
	set c to count listOfNames
	if c is 1 then
		set formattedList to item 1 of listOfNames
	else if c is 2 then
		set formattedList to item 1 of listOfNames & " and " & item 2 of listOfNames
	else
		set frontOfList to items 1 thru (c - 1) of listOfNames
		set lastName to item c of listOfNames
		set tid to AppleScript's text item delimiters
		set AppleScript's text item delimiters to ", "
		set t1 to frontOfList as text
		set formattedList to t1 & ", and " & lastName
		set AppleScript's text item delimiters to tid
	end if
	return formattedList
end formatListOfNames

-- sometimes, an article has an author, sometimes it has more than one, sometimes there's no author
-- this function getAuthorStub() returns a string like " from Jean MacDonald "  that can be used in crafting a message
-- about the current article.  If there are no authors, it just returns a single space.
to getAuthorStub(authorNames)
	try
		if ((count authorNames) is greater than 0) then
			return " from " & formatListOfNames(authorNames) & " "
		end if
	end try
	return " "
end getAuthorStub

-- Here's where the script starts

-- first, get some relevant info out for NetNewsWire
tell application "NetNewsWire"
	set articleUrl to the url of the current article
	set articleTitle to the title of the current article
	set authorNames to name of authors of the current article
end tell

-- then, prepare the message subject and message contents
set messageSubject to "From NetNewsWire to you: " & articleTitle
set myIntro to "Here's something" & getAuthorStub(authorNames) & "that I was reading on NetNewsWire: "
set messageContents to myIntro & return & return & articleUrl & return & return & getContentsOrHtml()

-- lastly, make a new outgoing message in Mail with the given subject and contents
tell application "Mail"
	set m1 to make new outgoing message with properties {subject:messageSubject}
	set content of m1 to messageContents
end tell

-- This script grabs the current article in NetNewsWire and copies relevant information about it
--    to a new outgoing message in Mail
-- the intended use is that the user wants to send email about the current article, and
--    would fill in the recipient and then send the message

-- sometimes, an article has contents, and sometimes it has html contents
-- this function getContentsOrHtml() gets the contents as text, despite the representation
-- first it checks to see if there are plain text contents
-- if not, it looks for html contents, and converts those to plain text using a shell script that invokes textutil
-- if it can't find either plain text or html, it returns "couldn't find article text"
to getContentsOrHtml()
	tell application "NetNewsWire"
		set textContents to the contents of the current article
		if textContents is not "" then
			return textContents
		else
			set htmlContents to html of the current article
			if htmlContents is not "" then
				set shellScript to " echo '" & htmlContents & "' | /usr/bin/textutil -stdin -stdout -format html -convert txt"
				set pureText to do shell script shellScript
				return pureText
			end if
		end if
	end tell
	return "couldn't find article text"
end getContentsOrHtml

-- given a list of author names, generate a happily formatted list like "Jean MacDonald and James Dempsey"
-- if the list is more than two names, use Oxford comma structure: "Brent Simmons, Jean MacDonald, and James Dempsey"
-- the returned string is padded by spaces on both sides

to formatListOfNames(listOfNames)
	set c to count listOfNames
	if c is 1 then
		set formattedList to item 1 of listOfNames
	else if c is 2 then
		set formattedList to item 1 of listOfNames & " and " & item 2 of listOfNames
	else
		set frontOfList to items 1 thru (c - 1) of listOfNames
		set lastName to item c of listOfNames
		set tid to AppleScript's text item delimiters
		set AppleScript's text item delimiters to ", "
		set t1 to frontOfList as text
		set formattedList to t1 & ", and " & lastName
		set AppleScript's text item delimiters to tid
	end if
	return " from " & formattedList & " "
end formatListOfNames

-- sometimes, an article has an author, sometimes it has more than one, sometimes there's no author
-- this function getAuthorStub() returns a string like " by Kaya Thomas "  that can be used in crafting a message
-- about the current article.  If there are no authors, it just returns a single space.
to getAuthorStub(authorNames)
	try
		if ((count authorNames) is greater than 0) then
			return formatListOfNames(authorNames)
		end if
	end try
	return " "
end getAuthorStub

-- Here's where the script starts

-- first, get some relevant info out for NetNewsWire
tell application "NetNewsWire"
	set articleUrl to the url of the current article
	set articleTitle to the title of the current article
	set authorNames to name of authors of the current article
end tell

-- then, prepare the message subject and message contents
set messageSubject to "From NetNewsWire to you: " & articleTitle
set myIntro to "Here's something" & getAuthorStub(authorNames) & "that I was reading on NetNewsWire: "
set messageContents to myIntro & return & return & articleUrl & return & return & getContentsOrHtml()

-- lastly, make a new outgoing message in Mail with the given subject and contents
tell application "Mail"
	set m1 to make new outgoing message with properties {subject:messageSubject}
	set content of m1 to messageContents
end tell


TAB to Space

TAB to Space

-- FetchLyric
-- DESCRIPTION: iTunesQS_MR	-NvfvꁨRN}v^OX[Lk͋Lk͋]X[(W\_eu/ecGrowlw
-- AUTHOR: JinnLynn http:://jeeker.net
-- LAST UPDATED: 2012-05-04
-- INTRO PAGE: http://jeeker.net/fetch-lyric-for-itunes/
-- REF: Martian http://blog.4321.la/articles/2012/01/27/use-applescript-to-set-itunes-lyrics/
property scriptName : "FetchLyric"
property baseURL : "http://lyrics.sinaapp.com/"
property isGrowlRunning : false
property statusDesc : {"Lk͋]X[(WeQS0", "Lk͋SbR0", "Lk͋S1Y%0", "*g	bLkf0"}
property STATUS_LYRIC_EXIST : 1
property STATUS_LYRIC_SUCCESS : 2
property STATUS_LYRIC_FAIL : 3
property STATUS_LYRIC_UNSELECTED : 4

tell application "System Events"
    set isGrowlRunning to (count of (every process whose bundle identifier is "com.Growl.GrowlHelperApp")) > 0
end tell

script growl
    on growlNotify(song_artist, song_title, status)
        if isGrowlRunning = false then return
        tell application id "com.Growl.GrowlHelperApp"
            if song_title = "" then set song_title to "unknown"
            set the_title to song_title
            if song_artist is not equal to "" then set the_title to song_artist & " - " & the_title
            set the_desc to item status of statusDesc
            set the allNotificationsList to {scriptName}
            set the enabledNotificationsList to {scriptName}
            register as application
                scriptName all notifications allNotificationsList
                default notifications enabledNotificationsList
                icon of application "iTunes"
            notify with name
                scriptName title
                the_title description
                the_desc application name scriptName
            -- \ՋO(uLkf\b\O:NGrowlVhQ
        end tell
    end growlNotify
end script

tell application "iTunes"
    if selection is {} then
        tell growl to growlNotify("", "", STATUS_LYRIC_UNSELECTED)
        return
    end if
    set k to count (item of selection)
    set i to 1
    repeat
        set theTrack to (item i of selection)
        set this_artist to (get artist of theTrack)
        set this_title to (get name of theTrack)
        set this_lyric to (get lyrics of theTrack)
        -- set this_artwork to data of artwork 1 of theTrack

        set fetch_status to STATUS_LYRIC_FAIL

        if length of this_lyric < 1 then
            -- S	gS_Lkf-N*gX[(WLk͋eMb\ՋSLk͋
            set requestData to "title=" & this_title & "&artist=" & this_artist
            set songLyrics to do shell script "curl -d '" & requestData & "' " & baseURL
            if length of songLyrics > 1 then
                -- Lk͋bRS
                set lyrics of theTrack to songLyrics
                set fetch_status to STATUS_LYRIC_SUCCESS
            end if
        else
            set fetch_status to STATUS_LYRIC_EXIST
        end if

        tell growl to growlNotify(this_artist, this_title, fetch_status)

        set i to i + 1
        if i > k then exit repeat
    end repeat
    -- YgGrowl*gЏLR>f:y[݋Fh
    if isGrowlRunning = false then
        display dialog return & "Lk͋S~_g" buttons {"nx["} default button 1 with icon 1 giving up after 5 with title scriptName
    end if
end tell


Update halt_vagrant.applescript

Update halt_vagrant.applescript

set close_ubervu_vagrant to "cd ~/uberVU/puppet/hs_analytics_vagrant; vagrant halt -f;"

-- close vagrant
tell application "iTerm"
	activate
	set myterm to (make new terminal)
	tell myterm
		launch session "Default"
		set mysession to current session
	end tell

	tell mysession
		write text close_ubervu_vagrant
	end tell
end tell

set close_ubervu_vagrant to "cd ~/uberVU/puppet; vagrant halt -f;"
set close_hs_vagrant to "cd ~/hootsuite/dash-board; vagrant halt -f;"

-- close vagrant
tell application "iTerm"
	activate
	set myterm to (make new terminal)
	tell myterm
		launch session "Default"
		set mysession to current session
	end tell

	tell mysession
		write text close_ubervu_vagrant
		write text close_hs_vagrant
	end tell
end tell


Fixed for any version of alfred

Fixed for any version of alfred

Fixed for any version of alfred

(*
	Get images in Finder selection, then call the workflow again with
	the first selected image.

	If no images are selected, return an error message, which
	can be passed to a Post Notification action.
*)

-- The filetypes understood by Google Image Search
set imageExtensions to {"jpg", "jpeg", "bmp", "gif", "png"}

-- Return list of files selected in Finder whose extensions are
-- in imageExtensions
on selectedImages()
	set theImages to {}
	tell application "Finder"
		set theSelection to the selection
		if (the count of theSelection) is greater than 0 then
			repeat with theFile in theSelection
				if the name extension of theFile is in my imageExtensions then
					set the end of theImages to (theFile as alias)
				end if
			end repeat
		end if
		log ((the count of theImages) as text) & " image(s) selected"
	end tell
	return theImages
end selectedImages

set theImages to my selectedImages()
if (count of theImages) is greater than 0 then
	set theImage to item 1 of theImages
	set thePath to POSIX path of theImage

	-- Use the workflow's own external trigger
	tell application id "com.runningwithcrayons.Alfred" to run trigger "Find Similar Images" in workflow "net.deanishe.alfred-google-similar-images" with argument thePath
else
	return "No images selected"
end if

(*
	Get images in Finder selection, then call the workflow again with
	the first selected image.

	If no images are selected, return an error message, which
	can be passed to a Post Notification action.
*)

-- The filetypes understood by Google Image Search
set imageExtensions to {"jpg", "jpeg", "bmp", "gif", "png"}

-- Return list of files selected in Finder whose extensions are
-- in imageExtensions
on selectedImages()
	set theImages to {}
	tell application "Finder"
		set theSelection to the selection
		if (the count of theSelection) is greater than 0 then
			repeat with theFile in theSelection
				if the name extension of theFile is in my imageExtensions then
					set the end of theImages to (theFile as alias)
				end if
			end repeat
		end if
		log ((the count of theImages) as text) & " image(s) selected"
	end tell
	return theImages
end selectedImages

set theImages to my selectedImages()
if (count of theImages) is greater than 0 then
	set theImage to item 1 of theImages
	set thePath to POSIX path of theImage

	-- Use the workflow's own external trigger
	tell application "Alfred 4" to run trigger "Find Similar Images" in workflow "net.deanishe.alfred-google-similar-images" with argument thePath
else
	return "No images selected"
end if


INTEGRATION: CWS changefileheader (1.3.160); FILE MERGED 2008/03/31 16:04:19 rt 1.3.160.1: #i87441# Change license header to LPGL v3.

(*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: PostInstall.applescript,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 *************************************************************************)

-- This is the PostInstall -script for .pkg installation
--
-- Currently this script does the following things:
--   1) Uses fondu to extract and convert .dfont -fonts from Mac OS X system to .ttf -fonts for OpenOffice.org

(*==== (global variables as get-functions) ====*)

on getOOInstallPath()
	return (((path to me) as string) & "Contents:")
end getOOInstallPath

on getOOResourcesPath()
	return (((path to me) as string) & "Contents:Resources:")
end getOOResourcesPath

on getOOProgramPath()
	return (getOOInstallPath() & "MacOS:")
end getOOProgramPath

-- OSXSystemFontPathList : {"/System/Library/Fonts/", "/Library/Fonts/"}
-- OSXUserFontPathList : {"~/Library/Fonts/"}

on getOSXSystemFontPathList()
	return {(path to fonts folder from system domain) as string,
		(path to fonts folder from local domain) as string}
end getOSXSystemFontPathList

on getOSXUserFontPathList()
	return {(path to fonts folder from user domain) as string}
end getOSXUserFontPathList

on getOOSystemFontPath()
	return (getOOInstallPath() & "share:fonts:truetype:")
end getOOSystemFontPath

on getOOUserSettingsPath()
	return (((path to home folder) as string) & "Library:Application Support:OpenOffice.org:%USERDIRPRODUCTVERSION:")
end getOOUserSettingsPath

on getOOUserFontPath()
	return (getOOUserSettingsPath() & "user:fonts:")
end getOOUserFontPath

on getOOCookieSystemFondu()
	-- nosystemfondu : file does exist if user does not want to use fondu for system fonts
	return "no_system_fondu"
end getOOCookieSystemFondu

on getOOCookieSystemFonduDone()
	-- systemfondudone : file does exist if native fonts already extracted from system fonts
	return "system_fondu_done"
end getOOCookieSystemFonduDone

on getOOCookieUserFondu()
	-- nouserfondu : file does exist if user does not want to use fondu for user fonts
	return "no_user_fondu"
end getOOCookieUserFondu

on getOOCookieUserFonduDone()
	-- userfondudone : file does exist if native fonts already extracted from user fonts
	return "user_fondu_done"
end getOOCookieUserFonduDone

--
-- the default handler: run
--

on run
	-- Check for that OOo can be found
	if (not isRealPath(getOOProgramPath())) then
		logEvent("(scripts/PostInstall) ERROR: could not find OOo installation from " & POSIX path of getOOProgramPath())
		return
	end if

	-- checks are ok, now we can start doing the real stuff
	firstLaunch()
	runSystemFondu()
	runUserFondu()

	return
end run

-------------------------------------------------------------

on runSystemFondu()
	-- check if user does not want font conversion
	if (isRealPath(getOOSystemFontPath() & getOOCookieSystemFondu())) then
		return
	end if

	-- check if font conversion was already run
	if (isRealPath(getOOSystemFontPath() & getOOCookieSystemFonduDone())) then
		return
	end if

	logEvent("(scripts/PostInstall) Extracting system fonts...")
	-- else try to create footprint
	if (setCookie(getOOSystemFontPath(), getOOCookieSystemFonduDone())) then
		-- call fondu for each font (i.e. without wildcard), so if it crashes only one font is missing
		fonduConvertFonts(getOOSystemFontPath(), getOSXSystemFontPathList())
	end if
	logEvent("(scripts/PostInstall) Extracting system fonts completed.")
end runSystemFondu

on runUserFondu()
	-- check if user does not want font conversion
	if (isRealPath(getOOUserFontPath() & getOOCookieUserFondu())) then
		return
	end if

	-- check if font conversion was already run
	if (isRealPath(getOOUserFontPath() & getOOCookieUserFonduDone())) then
		return
	end if

	logEvent("(scripts/PostInstall) Extracting user fonts...")
	-- try to create footprint
	if (setCookie(getOOUserFontPath(), getOOCookieUserFonduDone())) then
		-- call fondu for each font (i.e. without wildcard), so if it crashes only one font is missing
		fonduConvertFonts(getOOUserFontPath(), getOSXUserFontPathList())
	end if
	logEvent("(scripts/PostInstall) Extracting user fonts completed.")
end runUserFondu

on firstLaunch()
	-- continue only if OOSysFontdir exists
	if (not isRealPath(getOOSystemFontPath())) then
		logEvent("(scripts/PostInstall) ERROR: could not find System font folder from " & POSIX path of getOOSystemFontPath())
		return
	end if

	if (setCookie(getOOSystemFontPath(), getOOCookieSystemFondu() & ".in_progress")) then
		-- Has user already decided that he does not want to extract system fonts ?
		if (not isRealPath(getOOSystemFontPath() & getOOCookieSystemFondu())) then
			-- Are system fonts already extracted ?
			if (not isRealPath(getOOSystemFontPath() & getOOCookieSystemFonduDone())) then
				-- ask if the user wants to use fondu to extract system fonts
				set yesKey to getMessage("YES_KEY")
				set noKey to getMessage("NO_KEY")
				display dialog getMessage("OOO_EXTRACT_NATIVE_SYSFONTS") buttons {noKey, yesKey} default button yesKey
				set theResult to the button returned of the result
				if theResult is noKey then
					-- not use fondu for system fonts extraction !
					setCookie(getOOSystemFontPath(), getOOCookieSystemFondu())
					logEvent("(scripts/PostInstall) Setting: no system fonts")
				end if
			end if
		end if
	end if

	-- continue only if OOUserFontdir exists
	if (not isRealPath(getOOUserFontPath())) then
		logEvent("(scripts/PostInstall) ERROR: could not find User font folder from " & POSIX path of getOOUserFontPath())
		return
	end if

	-- Has user already decided that he does not want to extract user fonts ?
	if (not isRealPath(getOOUserFontPath() & getOOCookieUserFondu())) then
		-- Are system fonts already extracted ?
		if (not isRealPath(getOOUserFontPath() & getOOCookieUserFonduDone())) then
			-- ask if the user wants to use fondu to extract user fonts
			set yesKey to getMessage("YES_KEY")
			set noKey to getMessage("NO_KEY")
			display dialog getMessage("OOO_EXTRACT_NATIVE_USERFONTS") buttons {noKey, yesKey} default button yesKey
			set theResult to the button returned of the result
			if theResult is noKey then
				-- not use fondu for user fonts extraction !
				setCookie(getOOUserFontPath(), getOOCookieUserFondu())
				logEvent("(scripts/PostInstall) Setting: no user fonts")
			end if
		end if
	end if

end firstLaunch

on fonduConvertFonts(targetPath, sourcePathList)

	-- define the location of fondu
	set fondu to quoted form of (POSIX path of getOOProgramPath() & "fondu")

	-- first go to the target directory
	set fonduCmd to "cd " & (quoted form of POSIX path of targetPath) & "; "

	repeat with q from 1 to number of items in sourcePathList
		set aPath to POSIX path of (item q of sourcePathList)
		set fonduCmd to fonduCmd & "for i in " & aPath & "*; do " & fondu & " -force \"$i\" >> /dev/null 2>&1; done; "
	end repeat
	try
		-- ignore errors
		-- with admin privileges does not work well on panther
		do shell script "sh -c " & quoted form of fonduCmd
	end try
	logEvent("fonduCMD: " & fonduCmd)

end fonduConvertFonts

(* ===== (Helper functions) ======= *)

-- set a cookiefile. The content is empty.
on setCookie(aPath, cookieFile)
	try
		if (isRealPath(aPath)) then
			set newFile to (aPath & cookieFile)
			open for access file newFile
			close access file newFile
			return true
		else
			return false
		end if
	on error
		return false
	end try
end setCookie

-- get a localized string
on getMessage(aKey)
	try
		if (aKey is equal to "YES_KEY") then
			return "Yes"
		end if

		if (aKey is equal to "NO_KEY") then
			return "No"
		end if

		if (aKey is equal to "OOO_EXTRACT_NATIVE_SYSFONTS") then
			return "Do you want OpenOffice.org to use the Apple system fonts?"
		end if

		if (aKey is equal to "OOO_EXTRACT_NATIVE_USERFONTS") then
			return "Do you want OpenOffice.org to use the fonts you have installed on this system?"
		end if
	end try
end getMessage

-- function for checking if a path exists
on isRealPath(aPath)
	try
		alias aPath
		return true
	on error
		-- error number -43 from aPath
		-- display dialog "NotRP -- " & aPath
		return false
	end try
end isRealPath

-- function for logging script messages
on logEvent(themessage)
	set theLine to (do shell script
		"date  +'%Y-%m-%d %H:%M:%S'" as string)
		& " " & themessage
	do shell script "echo " & quoted form of theLine &
		" >> ~/Library/Logs/OpenOffice%USERDIRPRODUCTVERSION.log"
end logEvent

(*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: PostInstall.applescript,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: ihi $ $Date: 2007-06-05 11:52:07 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 *************************************************************************)

-- This is the PostInstall -script for .pkg installation
--
-- Currently this script does the following things:
--   1) Uses fondu to extract and convert .dfont -fonts from Mac OS X system to .ttf -fonts for OpenOffice.org

(*==== (global variables as get-functions) ====*)

on getOOInstallPath()
	return (((path to me) as string) & "Contents:")
end getOOInstallPath

on getOOResourcesPath()
	return (((path to me) as string) & "Contents:Resources:")
end getOOResourcesPath

on getOOProgramPath()
	return (getOOInstallPath() & "MacOS:")
end getOOProgramPath

-- OSXSystemFontPathList : {"/System/Library/Fonts/", "/Library/Fonts/"}
-- OSXUserFontPathList : {"~/Library/Fonts/"}

on getOSXSystemFontPathList()
	return {(path to fonts folder from system domain) as string,
		(path to fonts folder from local domain) as string}
end getOSXSystemFontPathList

on getOSXUserFontPathList()
	return {(path to fonts folder from user domain) as string}
end getOSXUserFontPathList

on getOOSystemFontPath()
	return (getOOInstallPath() & "share:fonts:truetype:")
end getOOSystemFontPath

on getOOUserSettingsPath()
	return (((path to home folder) as string) & "Library:Application Support:OpenOffice.org:%USERDIRPRODUCTVERSION:")
end getOOUserSettingsPath

on getOOUserFontPath()
	return (getOOUserSettingsPath() & "user:fonts:")
end getOOUserFontPath

on getOOCookieSystemFondu()
	-- nosystemfondu : file does exist if user does not want to use fondu for system fonts
	return "no_system_fondu"
end getOOCookieSystemFondu

on getOOCookieSystemFonduDone()
	-- systemfondudone : file does exist if native fonts already extracted from system fonts
	return "system_fondu_done"
end getOOCookieSystemFonduDone

on getOOCookieUserFondu()
	-- nouserfondu : file does exist if user does not want to use fondu for user fonts
	return "no_user_fondu"
end getOOCookieUserFondu

on getOOCookieUserFonduDone()
	-- userfondudone : file does exist if native fonts already extracted from user fonts
	return "user_fondu_done"
end getOOCookieUserFonduDone

--
-- the default handler: run
--

on run
	-- Check for that OOo can be found
	if (not isRealPath(getOOProgramPath())) then
		logEvent("(scripts/PostInstall) ERROR: could not find OOo installation from " & POSIX path of getOOProgramPath())
		return
	end if

	-- checks are ok, now we can start doing the real stuff
	firstLaunch()
	runSystemFondu()
	runUserFondu()

	return
end run

-------------------------------------------------------------

on runSystemFondu()
	-- check if user does not want font conversion
	if (isRealPath(getOOSystemFontPath() & getOOCookieSystemFondu())) then
		return
	end if

	-- check if font conversion was already run
	if (isRealPath(getOOSystemFontPath() & getOOCookieSystemFonduDone())) then
		return
	end if

	logEvent("(scripts/PostInstall) Extracting system fonts...")
	-- else try to create footprint
	if (setCookie(getOOSystemFontPath(), getOOCookieSystemFonduDone())) then
		-- call fondu for each font (i.e. without wildcard), so if it crashes only one font is missing
		fonduConvertFonts(getOOSystemFontPath(), getOSXSystemFontPathList())
	end if
	logEvent("(scripts/PostInstall) Extracting system fonts completed.")
end runSystemFondu

on runUserFondu()
	-- check if user does not want font conversion
	if (isRealPath(getOOUserFontPath() & getOOCookieUserFondu())) then
		return
	end if

	-- check if font conversion was already run
	if (isRealPath(getOOUserFontPath() & getOOCookieUserFonduDone())) then
		return
	end if

	logEvent("(scripts/PostInstall) Extracting user fonts...")
	-- try to create footprint
	if (setCookie(getOOUserFontPath(), getOOCookieUserFonduDone())) then
		-- call fondu for each font (i.e. without wildcard), so if it crashes only one font is missing
		fonduConvertFonts(getOOUserFontPath(), getOSXUserFontPathList())
	end if
	logEvent("(scripts/PostInstall) Extracting user fonts completed.")
end runUserFondu

on firstLaunch()
	-- continue only if OOSysFontdir exists
	if (not isRealPath(getOOSystemFontPath())) then
		logEvent("(scripts/PostInstall) ERROR: could not find System font folder from " & POSIX path of getOOSystemFontPath())
		return
	end if

	if (setCookie(getOOSystemFontPath(), getOOCookieSystemFondu() & ".in_progress")) then
		-- Has user already decided that he does not want to extract system fonts ?
		if (not isRealPath(getOOSystemFontPath() & getOOCookieSystemFondu())) then
			-- Are system fonts already extracted ?
			if (not isRealPath(getOOSystemFontPath() & getOOCookieSystemFonduDone())) then
				-- ask if the user wants to use fondu to extract system fonts
				set yesKey to getMessage("YES_KEY")
				set noKey to getMessage("NO_KEY")
				display dialog getMessage("OOO_EXTRACT_NATIVE_SYSFONTS") buttons {noKey, yesKey} default button yesKey
				set theResult to the button returned of the result
				if theResult is noKey then
					-- not use fondu for system fonts extraction !
					setCookie(getOOSystemFontPath(), getOOCookieSystemFondu())
					logEvent("(scripts/PostInstall) Setting: no system fonts")
				end if
			end if
		end if
	end if

	-- continue only if OOUserFontdir exists
	if (not isRealPath(getOOUserFontPath())) then
		logEvent("(scripts/PostInstall) ERROR: could not find User font folder from " & POSIX path of getOOUserFontPath())
		return
	end if

	-- Has user already decided that he does not want to extract user fonts ?
	if (not isRealPath(getOOUserFontPath() & getOOCookieUserFondu())) then
		-- Are system fonts already extracted ?
		if (not isRealPath(getOOUserFontPath() & getOOCookieUserFonduDone())) then
			-- ask if the user wants to use fondu to extract user fonts
			set yesKey to getMessage("YES_KEY")
			set noKey to getMessage("NO_KEY")
			display dialog getMessage("OOO_EXTRACT_NATIVE_USERFONTS") buttons {noKey, yesKey} default button yesKey
			set theResult to the button returned of the result
			if theResult is noKey then
				-- not use fondu for user fonts extraction !
				setCookie(getOOUserFontPath(), getOOCookieUserFondu())
				logEvent("(scripts/PostInstall) Setting: no user fonts")
			end if
		end if
	end if

end firstLaunch

on fonduConvertFonts(targetPath, sourcePathList)

	-- define the location of fondu
	set fondu to quoted form of (POSIX path of getOOProgramPath() & "fondu")

	-- first go to the target directory
	set fonduCmd to "cd " & (quoted form of POSIX path of targetPath) & "; "

	repeat with q from 1 to number of items in sourcePathList
		set aPath to POSIX path of (item q of sourcePathList)
		set fonduCmd to fonduCmd & "for i in " & aPath & "*; do " & fondu & " -force \"$i\" >> /dev/null 2>&1; done; "
	end repeat
	try
		-- ignore errors
		-- with admin privileges does not work well on panther
		do shell script "sh -c " & quoted form of fonduCmd
	end try
	logEvent("fonduCMD: " & fonduCmd)

end fonduConvertFonts

(* ===== (Helper functions) ======= *)

-- set a cookiefile. The content is empty.
on setCookie(aPath, cookieFile)
	try
		if (isRealPath(aPath)) then
			set newFile to (aPath & cookieFile)
			open for access file newFile
			close access file newFile
			return true
		else
			return false
		end if
	on error
		return false
	end try
end setCookie

-- get a localized string
on getMessage(aKey)
	try
		if (aKey is equal to "YES_KEY") then
			return "Yes"
		end if

		if (aKey is equal to "NO_KEY") then
			return "No"
		end if

		if (aKey is equal to "OOO_EXTRACT_NATIVE_SYSFONTS") then
			return "Do you want OpenOffice.org to use the Apple system fonts?"
		end if

		if (aKey is equal to "OOO_EXTRACT_NATIVE_USERFONTS") then
			return "Do you want OpenOffice.org to use the fonts you have installed on this system?"
		end if
	end try
end getMessage

-- function for checking if a path exists
on isRealPath(aPath)
	try
		alias aPath
		return true
	on error
		-- error number -43 from aPath
		-- display dialog "NotRP -- " & aPath
		return false
	end try
end isRealPath

-- function for logging script messages
on logEvent(themessage)
	set theLine to (do shell script
		"date  +'%Y-%m-%d %H:%M:%S'" as string)
		& " " & themessage
	do shell script "echo " & quoted form of theLine &
		" >> ~/Library/Logs/OpenOffice%USERDIRPRODUCTVERSION.log"
end logEvent


Update chapter list for PDF

Update chapter list for PDF

############################
# How to generate the PDFs #
############################
# 1. Update cover.html with the new version date
# 2. Open cover.html in safari and generate Cover.pdf
# 3. Place Cover.pdf in ~/Downloads folder
# 4. Ensure "Downloads" folder is an option when "Export to PDF…" in Safari
# 5. In terminal, run "osascript pdf.scpt"

set theChaptersStr to "index
who-is-this-guide-for
what-does-this-guide-cover
how-to-get-help
what-is-serverless
why-create-serverless-apps
create-an-aws-account
create-an-iam-user
what-is-iam
what-is-an-arn
configure-the-aws-cli
create-a-dynamodb-table
create-an-s3-bucket-for-file-uploads
create-a-cognito-user-pool
create-a-cognito-test-user
setup-the-serverless-framework
add-support-for-es6-es7-javascript
add-a-create-note-api
add-a-get-note-api
add-a-list-all-the-notes-api
add-an-update-note-api
add-a-delete-note-api
deploy-the-apis
create-a-cognito-identity-pool
cognito-user-pool-vs-identity-pool
test-the-apis
create-a-new-reactjs-app
add-app-favicons
setup-custom-fonts
setup-bootstrap
handle-routes-with-react-router
create-containers
adding-links-in-the-navbar
handle-404s
configure-aws-amplify
create-a-login-page
login-with-aws-cognito
add-the-session-to-the-state
load-the-state-from-the-session
clear-the-session-on-logout
redirect-on-login-and-logout
give-feedback-while-logging-in
create-a-signup-page
create-the-signup-form
signup-with-aws-cognito
add-the-create-note-page
call-the-create-api
upload-a-file-to-s3
list-all-the-notes
call-the-list-api
display-a-note
render-the-note-form
save-changes-to-a-note
delete-a-note
setup-secure-pages
create-a-route-that-redirects
use-the-redirect-routes
redirect-on-login
deploy-the-frontend
create-an-s3-bucket
deploy-to-s3
create-a-cloudfront-distribution
setup-your-domain-with-cloudfront
setup-www-domain-redirect
setup-ssl
deploy-updates
update-the-app
deploy-again
wrapping-up
giving-back
changelog
staying-up-to-date
api-gateway-and-lambda-logs
debugging-serverless-api-issues
serverless-environment-variables
stages-in-serverless-framework
configure-multiple-aws-profiles
customize-the-serverless-iam-policy
code-splitting-in-create-react-app
environments-in-create-react-app
connect-to-api-gateway-with-iam-auth
serverless-nodejs-starter"

set text item delimiters to "
"

set theChapters to text items of theChaptersStr

#################
# Download PDFs #
#################
#repeat with theCurrentChapter in theChapters
#  downloadPdf(theCurrentChapter)
#end repeat

##############
# Merge PDFs #
##############
set outputFile to "~/Downloads/ServerlessStack.pdf"

set pdfFiles to "~/Downloads/Cover.pdf"
repeat with theCurrentChapter in theChapters
  set pdfFiles to pdfFiles & " ~/Downloads/" & theCurrentChapter & ".pdf"
end repeat

do shell script "/System/Library/Automator/Combine\\ PDF\\ Pages.action/Contents/Resources/join.py " & "-o " & outputFile & " " & pdfFiles

on downloadPdf(theChapterName)
  tell application "System Events"

    tell process "Safari"
      set frontmost to true

      if ((theChapterName as string) is equal to "index") then
        set urlPath to theChapterName
      else
        set urlPath to "chapters/" & theChapterName
      end if
      open location "https://serverless-stack.com/" & urlPath & ".html"

      delay 1

      repeat until menu item "Export as PDF…" of menu "File" of menu bar 1 exists
        delay 0.2
      end repeat
      repeat until menu item "Export as PDF…" of menu "File" of menu bar 1 is enabled
        delay 0.2
      end repeat
      click menu item "Export as PDF…" of menu "File" of menu bar 1

      tell window 1
        repeat until sheet 1 exists
        end repeat

        tell sheet 1
          keystroke theChapterName
          click pop up button "Where:"

          repeat until menu 1 of pop up button "Where:" exists
          end repeat
          click menu item "Downloads" of menu 1 of pop up button "Where:"
          click button "Save"
        end tell

      end tell

      click menu item "Close Tab" of menu "File" of menu bar 1

    end tell

  end tell
end downloadPdf

############################
# How to generate the PDFs #
############################
# 1. Update cover.html with the new version date
# 2. Open cover.html in safari and generate Cover.pdf
# 3. Place Cover.pdf in ~/Downloads folder
# 4. Ensure "Downloads" folder is an option when "Export to PDF…" in Safari
# 5. In terminal, run "osascript pdf.scpt"

set theChaptersStr to "index
who-is-this-guide-for
what-does-this-guide-cover
how-to-get-help
what-is-serverless
why-create-serverless-apps
create-an-aws-account
create-an-iam-user
what-is-iam
what-is-an-arn
configure-the-aws-cli
create-a-dynamodb-table
create-an-s3-bucket-for-file-uploads
create-a-cognito-user-pool
create-a-cognito-test-user
setup-the-serverless-framework
add-support-for-es6-es7-javascript
add-a-create-note-api
add-a-get-note-api
add-a-list-all-the-notes-api
add-an-update-note-api
add-a-delete-note-api
deploy-the-apis
create-a-cognito-identity-pool
cognito-user-pool-vs-identity-pool
test-the-apis
create-a-new-reactjs-app
add-app-favicons
setup-custom-fonts
setup-bootstrap
handle-routes-with-react-router
create-containers
adding-links-in-the-navbar
handle-404s
create-a-login-page
login-with-aws-cognito
add-the-session-to-the-state
load-the-state-from-the-session
clear-the-session-on-logout
redirect-on-login-and-logout
give-feedback-while-logging-in
create-a-signup-page
create-the-signup-form
signup-with-aws-cognito
add-the-create-note-page
connect-to-api-gateway-with-iam-auth
call-the-create-api
upload-a-file-to-s3
clear-aws-credentials-cache
list-all-the-notes
call-the-list-api
display-a-note
render-the-note-form
save-changes-to-a-note
delete-a-note
setup-secure-pages
create-a-route-that-redirects
use-the-redirect-routes
redirect-on-login
deploy-the-frontend
create-an-s3-bucket
deploy-to-s3
create-a-cloudfront-distribution
setup-your-domain-with-cloudfront
setup-www-domain-redirect
setup-ssl
deploy-updates
update-the-app
deploy-again
code-splitting-in-create-react-app
wrapping-up
giving-back
older-versions
staying-up-to-date
serverless-es7-service"

set text item delimiters to "
"

set theChapters to text items of theChaptersStr

#################
# Download PDFs #
#################
#repeat with theCurrentChapter in theChapters
#  downloadPdf(theCurrentChapter)
#end repeat

##############
# Merge PDFs #
##############
set outputFile to "~/Downloads/ServerlessStack.pdf"

set pdfFiles to "~/Downloads/Cover.pdf"
repeat with theCurrentChapter in theChapters
  set pdfFiles to pdfFiles & " ~/Downloads/" & theCurrentChapter & ".pdf"
end repeat

do shell script "/System/Library/Automator/Combine\\ PDF\\ Pages.action/Contents/Resources/join.py " & "-o " & outputFile & " " & pdfFiles

on downloadPdf(theChapterName)
  tell application "System Events"

    tell process "Safari"
      set frontmost to true

      if ((theChapterName as string) is equal to "index") then
        set urlPath to theChapterName
      else
        set urlPath to "chapters/" & theChapterName
      end if
      open location "https://serverless-stack.com/" & urlPath & ".html"

      delay 1

      repeat until menu item "Export as PDF…" of menu "File" of menu bar 1 exists
        delay 0.2
      end repeat
      repeat until menu item "Export as PDF…" of menu "File" of menu bar 1 is enabled
        delay 0.2
      end repeat
      click menu item "Export as PDF…" of menu "File" of menu bar 1

      tell window 1
        repeat until sheet 1 exists
        end repeat

        tell sheet 1
          keystroke theChapterName
          click pop up button "Where:"

          repeat until menu 1 of pop up button "Where:" exists
          end repeat
          click menu item "Downloads" of menu 1 of pop up button "Where:"
          click button "Save"
        end tell

      end tell

      click menu item "Close Tab" of menu "File" of menu bar 1

    end tell

  end tell
end downloadPdf