minor fix

minor fix

on findByName(theElement, theName)
	set theTitle to missing value
	tell application "System Events"
		try
			set theTitle to title of theElement
			if theTitle is equal to theName then
				return theElement
			end if
		end try
		repeat with e in UI elements of theElement
			set theTitle to my findByName(e, theName)
			if theTitle is not missing value then
				return theTitle
			end if
		end repeat
		return missing value
	end tell
end findByName

on run argv
	tell application "System Events"
		return my findByName(process "Appium", "Launch")
	end tell
end run

on findByName(theElement, theName)
	set theTitle to missing value
	tell application "System Events"
		try
			set theTitle to title of theElement
			if theTitle is equal to theName then
				return theElement
			end if
		end try
		repeat with e in UI elements of theElement
			set theTitle to my findByName(e, theName)
			if theTitle is not missing value then
				return theTitle
			end if
		end repeat
		return missing value
	end tell
end findByName

on run argv
	tell application "System Events"
		click my findByName(process "Appium", "Launch")
	end tell
end run


moveForMon.applescript, from darwin13

moveForMon.applescript, from darwin13

property DEF_ALL : false
property DEF_DEBUG_LEVEL : 1

on moveForMon(pars)

	set {all, debug_level} to {DEF_ALL, DEF_DEBUG_LEVEL}
	try
		set all to all of pars
	end try
	try
		set debug_level to debug_level of pars
	end try

	-- debug mode
	if debug_level > 0 then
		log "debug mode = " & debug_level
		if debug_level > 1 then
			display dialog "debug mode = " & debug_level
		end if
	end if

	-- set monitoring tools' positions
	-- SimpleFloatingClock
	set w_sfcCEST to 1
	set w_sfcJST to 2

	-- XRG
	set w_XRG to 1

	-- set monitoring tool's name
	-- GeekTool
	set s_gtCal to "gcalCal"
	set s_gtGcal to "gcalList"
	set s_gtTask to "gtasklist"
	set s_gtPs to "myps"

	-- x posiiotn for monitoring
	set ledge to -160
	set ledgeSFCoffset to 20

	-- y positions
	set y_sfcCEST to 30
	set y_sfcJST to y_sfcCEST + 100
	set y_gtCal to y_sfcJST + 105
	set y_gtGcal to y_gtCal + 115
	set y_gtTask to y_gtGcal + 175
	set y_gtPs to y_gtTask + 85
	set y_XRG to y_gtPs + 75

	-- app to be excepted
	set expApp to {"XRG"}

	-- app to be half size, in left monitor (0.7 times full)
	set halfSizeApp_L to {}

	-- app to be half size, in right monitor (0.7 times full)
	set halfSizeApp_R to {"AdobeReader"}

	-- app only to be moved, in left monitor
	set noResizeApp_L to {}

	-- app only to be moved, in right monitor
	set noResizeApp_R to {"Finder", "Skype", "Microsoft Word", "Microsoft Excel", "Microsoft PowerPoint"}

	-- app to be moved left
	set app_L to {"firefox", "Evernote", "thunderbird", "thunderbird-bin", "Mail"}

	-- app to be moved right
	set app_R to {"iTerm"}

	-- get screen size
	tell application "Finder"
		set scriptPath to (path to me)'s folder as text
	end tell
	set windowSizeScpt to scriptPath & "windowSize.scpt"
	set windowSize to load script file windowSizeScpt

	-- main screen
	set svs to windowSize's getVisibleFrame(1, 1) --+1 is used to avoid edge, especially needed for y position
	set dPosX to (item 1 of svs) + 1
	set dPosY to (item 2 of svs) + 1
	set dWidth to item 3 of svs
	set dHeight to item 4 of svs

	-- try to get left screen
	set dPosX_L to dPosX + 1
	set dPosY_L to dPosY + 1
	try
		set svsL to windowSize's getVisibleFrame(-1, 1)
		set dPosX_L to (item 1 of svsL) + 1
		set dPosY_L to (item 2 of svsL) + 1
	end try

	-- try to get right screen
	set dPosX_R to dPosX + 1
	set dPosY_R to dPosY + 1
	try
		set svsR to windowSize's getVisibleFrame(dPosX + dWidth + 1, 1)
		set dPosX_R to (item 1 of svsR) + 1
		set dPosY_R to (item 2 of svsR) + 1
	end try

	-- move monitoring tools
	if dPosX_L < 0 then
		if debug_level > 0 then
			log "ledge to ledgeDual"
		end if
	else
		set ledge to dWidth + ledge
		if debug_level > 0 then
			log "ledge to ledgeSingle"
		end if
	end if

	tell application "System Events"
		-- SimpleFloatingClock
		try
			set appName to "SimpleFloatingClock"
			tell process appName
				tell window w_sfcCEST
					set size to {1000, 1000}
					set position to {ledge + ledgeSFCoffset, y_sfcCEST}
				end tell
				tell window w_sfcJST
					set size to {1000, 1000}
					set position to {ledge + ledgeSFCoffset, y_sfcJST}
				end tell
			end tell
		end try

		---- GeekTool
		--try
		--	--set appName to "GeekTool"
		--	set appName to "GeekTool Helper" -- for GeekTool 3
		--
		--	tell process appName
		--		set nW to number of windows
		--		--display dialog appName & " in process, nWindows=" & nW
		--		tell window w_gtCal
		--		end tell
		--		tell window w_gtGcal
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtGcal}
		--		end tell
		--		tell window w_gtTask
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtTask}
		--		end tell
		--		tell window w_gtPs
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtPs}
		--		end tell
		--	end tell
		--	--on error errMsg
		--	--	display dialog "ERROR: " & errMsg
		--end try

		-- XRG
		try
			set appName to "XRG"
			tell process appName
				tell window w_XRG
					set size to {1000, 2000}
					set position to {ledge, y_XRG}
				end tell
			end tell
		end try
	end tell

	-- GeekTool (should be outside of application "System Events", and use application "GeekTool Helper" ?)
	-- can't use position to geeklets
	tell application "GeekTool Helper" -- can not use appName (variable), which shows error at id?
		--geeklets
		repeat with g in every «class gLet»
			tell g
				name
				if name is s_gtCal then
					set «class xpos» to ledge
					set «class ypos» to y_gtCal
				else if name is s_gtGcal then
					set «class xpos» to ledge
					set «class ypos» to y_gtGcal
				else if name is s_gtTask then
					set «class xpos» to ledge
					set «class ypos» to y_gtTask
				else if name is s_gtPs then
					set «class xpos» to ledge
					set «class ypos» to y_gtPs
				end if
			end tell
		end repeat
	end tell

	-- Move/Resize other windows
	if all then
		-- get application name
		tell application "System Events"
			set appList to (get name of every application process whose visible is true)
		end tell

		-- repeat for all app
		repeat with appName in appList
			if appName is not in expApp then
				tell application "System Events"
					try
						tell process appName
							set nW to number of windows
							repeat with i from 1 to nW
								if debug_level > 0 then
									log appName & " " & i
									if debug_level > 1 then
										display dialog appName & " " & i
									end if
								end if
								if appName is in halfSizeApp_L then
									if debug_level > 0 then
										log "half size left"
										if debug_level > 1 then
											display dialog "half size left"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, xsize:0.7, ysize:0.7, moveForMon:false, debug_level:debug_level})
								else if appName is in halfSizeApp_R then
									if debug_level > 0 then
										log "half size right"
										if debug_level > 1 then
											display dialog "half size right"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, xsize:0.7, ysize:0.7, moveForMon:false, debug_level:debug_level})
								else if appName is in noResizeApp_L then
									if debug_level > 0 then
										log "half size left"
										if debug_level > 1 then
											display dialog "half size left"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, resize:0, moveForMon:false, debug_level:debug_level})
								else if appName is in noResizeApp_R then
									if debug_level > 0 then
										log "move right"
										if debug_level > 1 then
											display dialog "move right"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, resize:0, moveForMon:false, debug_level:debug_level})
								else if appName is in app_L then
									if debug_level > 0 then
										log "move left full size"
										if debug_level > 1 then
											display dialog "move left full size"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, moveForMon:false, debug_level:debug_level})
								else if appName is in app_R then
									if debug_level > 0 then
										log "move right full size"
										if debug_level > 1 then
											display dialog "move right full size"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, moveForMon:false, debug_level:debug_level})
								end if
							end repeat
						end tell
					end try
				end tell
			end if
		end repeat
	end if
end moveForMon

on run
	moveForMon({})
end run

property DEF_ALL : false
property DEF_DEBUG_LEVEL : 1

on moveForMon(pars)

	set {all, debug_level} to {DEF_ALL, DEF_DEBUG_LEVEL}
	try
		set all to all of pars
	end try
	try
		set debug_level to debug_level of pars
	end try

	-- debug mode
	if debug_level > 0 then
		log "debug mode = " & debug_level
		if debug_level > 1 then
			display dialog "debug mode = " & debug_level
		end if
	end if

	-- set monitoring tools' positions
	-- SimpleFloatingClock
	set w_sfcCEST to 1
	set w_sfcJST to 2

	-- XRG
	set w_XRG to 1

	-- set monitoring tool's name
	-- GeekTool
	set s_gtCal to "gcalCal"
	set s_gtGcal to "gcalList"
	set s_gtTask to "gtasklist"
	set s_gtPs to "myps"

	-- x posiiotn for monitoring
	set ledge to -160
	set ledgeSFCoffset to 20

	-- y positions
	set y_sfcCEST to 30
	set y_sfcJST to y_sfcCEST + 100
	set y_gtCal to y_sfcJST + 105
	set y_gtGcal to y_gtCal + 115
	set y_gtTask to y_gtGcal + 175
	set y_gtPs to y_gtTask + 85
	set y_XRG to y_gtPs + 75

	-- app to be excepted
	set expApp to {"XRG"}

	-- app to be half size, in left monitor (0.7 times full)
	set halfSizeApp_L to {}

	-- app to be half size, in right monitor (0.7 times full)
	set halfSizeApp_R to {"AdobeReader"}

	-- app only to be moved, in left monitor
	set noResizeApp_L to {}

	-- app only to be moved, in right monitor
	set noResizeApp_R to {"Finder", "Skype", "Microsoft Word", "Microsoft Excel", "Microsoft PowerPoint"}

	-- app to be moved left
	set app_L to {"firefox", "Evernote", "thunderbird", "thunderbird-bin", "Mail"}

	-- app to be moved right
	set app_R to {"iTerm"}

	-- get screen size
	tell application "Finder"
		set scriptPath to (path to me)'s folder as text
	end tell
	set windowSizeScpt to scriptPath & "windowSize.scpt"
	set windowSize to load script file windowSizeScpt

	-- main screen
	set svs to windowSize's getVisibleFrame(1, 1) --+1 is used to avoid edge, especially needed for y position
	set dPosX to (item 1 of svs) + 1
	set dPosY to (item 2 of svs) + 1
	set dWidth to item 3 of svs
	set dHeight to item 4 of svs

	-- try to get left screen
	set dPosX_L to dPosX + 1
	set dPosY_L to dPosY + 1
	try
		set svsL to windowSize's getVisibleFrame(-1, 1)
		set dPosX_L to (item 1 of svsL) + 1
		set dPosY_L to (item 2 of svsL) + 1
	end try

	-- try to get right screen
	set dPosX_R to dPosX + 1
	set dPosY_R to dPosY + 1
	try
		set svsR to windowSize's getVisibleFrame(dPosX + dWidth + 1, 1)
		set dPosX_R to (item 1 of svsR) + 1
		set dPosY_R to (item 2 of svsR) + 1
	end try

	-- move monitoring tools
	if dPosX_L < 0 then
		if debug_level > 0 then
			log "ledge to ledgeDual"
		end if
	else
		set ledge to dWidth + ledge
		if debug_level > 0 then
			log "ledge to ledgeSingle"
		end if
	end if

	tell application "System Events"
		-- SimpleFloatingClock
		try
			set appName to "SimpleFloatingClock"
			tell process appName
				tell window w_sfcCEST
					set size to {1000, 1000}
					set position to {ledge + ledgeSFCoffset, y_sfcCEST}
				end tell
				tell window w_sfcJST
					set size to {1000, 1000}
					set position to {ledge + ledgeSFCoffset, y_sfcJST}
				end tell
			end tell
		end try

		---- GeekTool
		--try
		--	--set appName to "GeekTool"
		--	set appName to "GeekTool Helper" -- for GeekTool 3
		--
		--	tell process appName
		--		set nW to number of windows
		--		--display dialog appName & " in process, nWindows=" & nW
		--		tell window w_gtCal
		--		end tell
		--		tell window w_gtGcal
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtGcal}
		--		end tell
		--		tell window w_gtTask
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtTask}
		--		end tell
		--		tell window w_gtPs
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtPs}
		--		end tell
		--	end tell
		--	--on error errMsg
		--	--	display dialog "ERROR: " & errMsg
		--end try

		-- XRG
		try
			set appName to "XRG"
			tell process appName
				tell window w_XRG
					set size to {1000, 2000}
					set position to {ledge, y_XRG}
				end tell
			end tell
		end try
	end tell

	-- GeekTool (should be outside of application "System Events", and use application "GeekTool Helper" ?)
	-- can't use position to geeklets
	tell application "GeekTool Helper" -- can not use appName (variable), which shows error at id?
		--geeklets
		repeat with g in geeklets
			tell g
				name
				if name is s_gtCal then
					set x position to ledge
					set y position to y_gtCal
				else if name is s_gtGcal then
					set x position to ledge
					set y position to y_gtGcal
				else if name is s_gtTask then
					set x position to ledge
					set y position to y_gtTask
				else if name is s_gtPs then
					set x position to ledge
					set y position to y_gtPs
				end if
			end tell
		end repeat
	end tell

	-- Move/Resize other windows
	if all then
		-- get application name
		tell application "System Events"
			set appList to (get name of every application process whose visible is true)
		end tell

		-- repeat for all app
		repeat with appName in appList
			if appName is not in expApp then
				tell application "System Events"
					try
						tell process appName
							set nW to number of windows
							repeat with i from 1 to nW
								if debug_level > 0 then
									log appName & " " & i
									if debug_level > 1 then
										display dialog appName & " " & i
									end if
								end if
								if appName is in halfSizeApp_L then
									if debug_level > 0 then
										log "half size left"
										if debug_level > 1 then
											display dialog "half size left"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, xsize:0.7, ysize:0.7, moveForMon:false, debug_level:debug_level})
								else if appName is in halfSizeApp_R then
									if debug_level > 0 then
										log "half size right"
										if debug_level > 1 then
											display dialog "half size right"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, xsize:0.7, ysize:0.7, moveForMon:false, debug_level:debug_level})
								else if appName is in noResizeApp_L then
									if debug_level > 0 then
										log "half size left"
										if debug_level > 1 then
											display dialog "half size left"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, resize:0, moveForMon:false, debug_level:debug_level})
								else if appName is in noResizeApp_R then
									if debug_level > 0 then
										log "move right"
										if debug_level > 1 then
											display dialog "move right"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, resize:0, moveForMon:false, debug_level:debug_level})
								else if appName is in app_L then
									if debug_level > 0 then
										log "move left full size"
										if debug_level > 1 then
											display dialog "move left full size"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, moveForMon:false, debug_level:debug_level})
								else if appName is in app_R then
									if debug_level > 0 then
										log "move right full size"
										if debug_level > 1 then
											display dialog "move right full size"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, moveForMon:false, debug_level:debug_level})
								end if
							end repeat
						end tell
					end try
				end tell
			end if
		end repeat
	end if
end moveForMon

on run
	moveForMon({})
end run


BBEdit SQL query fixer - more for 1.3

BBEdit SQL query fixer - more for 1.3

-- BBEdit_upgrade_SQL_Query_to_newer_format({})
-- Dan Shockley, NYHTC
-- BBEdit - upgrade SQL Query to newer format

(*
HISTORY:
	1.3 - 2018-09-04 ( dshockley ): Added regex to remove extra spaces before semicolons. Fix for optional space at end of SQL_Field line in whereEqualsClause regex search.
	1.2 - 2018-05-22 ( dshockley ): modified to also convert the query to use List to separate the components of the query.
	1.1 - 2017-12-11 ( dshockley ): disable the usually no-longer-needed SQL_EscapeString, but WARN and comment, since it might sitll be needed when using with something OTHER THAN SQL_Where criteria.
	1.0 - 2017-09-15 ( dshockley ): first created.
*)

on run
	BBEdit_upgrade_SQL_Query_to_newer_format({})
end run

--------------------
-- START OF CODE
--------------------

on BBEdit_upgrade_SQL_Query_to_newer_format({})

	set regexSearch_SQL_Table to "Quote *\\( *TableNameOfField *\\( *([^\\)]+) *\\) *\\)"
	set regexReplace_SQL_Table to "SQL_Table ( \\1 )"

	set regexSearch_SQL_Field to "Quote *\\( ?FieldNameShort *\\( *([^\\)]+) *\\) *\\)"
	set regexReplace_SQL_Field to "SQL_Field ( \\1 )"

	set regexSearch_WhereEqualsClause to "^([\\t ]*)& *SQL_Field *\\( *([^\\)]+) *\\) *
[\\t ]*& \" *= *\"
[\\t ]*& ([^\\r]+)\\r"

	set regexReplace_WhereEqualsClause to "\\1\\& SQL_Where ( \\2 ; \"=\" ; \\3 )\\r"

	set regexSearch_EscapeStringWARN to "SQL_EscapeString *\\( *([^\\)]+) *\\)"

	set regexReplace_EscapeStringWARN to "\\1 /* WARNING!! Had SQL_EscapeString probably NO LONGER NEEDED, so DISABLED! */"

	set regexSearch_ExtraSpacesBeforeSemicolon to "([^\r])  +;"

	set regexReplace_ExtraSpacesBeforeSemicolon to "\\1 ;"

	tell application "BBEdit"
		activate

		tell window 1

			replace regexSearch_SQL_Table using regexReplace_SQL_Table options {search mode:grep, starting at top:true}

			replace regexSearch_SQL_Field using regexReplace_SQL_Field options {search mode:grep, starting at top:true}

			replace regexSearch_WhereEqualsClause using regexReplace_WhereEqualsClause options {search mode:grep, starting at top:true}
			replace regexSearch_EscapeStringWARN using regexReplace_EscapeStringWARN options {search mode:grep, starting at top:true}
			replace regexSearch_ExtraSpacesBeforeSemicolon using regexReplace_ExtraSpacesBeforeSemicolon options {search mode:grep, starting at top:true}

			try
				(* convert to using List ( ) for whitespace formatting of query: *)
				set stringStartQuery to "; sqlQuery = "
				set stringEndQuery to "^([\\t]+); sqlResult = "
				set posQueryStart to characterOffset of found object of (find stringStartQuery)
				set posQueryEnd to (characterOffset of found object of (find stringEndQuery options {search mode:grep})) - 1
				select (characters posQueryStart through posQueryEnd)

				replace "\"SELECT" using "List ( \\r\\t\\t  \"SELECT" searching in selection options {search mode:grep}
				replace "^([\\t]+)& " using "\\t\\t; " searching in selection options {search mode:grep}

				set character posQueryEnd to return & tab & tab & ")" & (contents of character posQueryEnd)

			end try

		end tell

	end tell

end BBEdit_upgrade_SQL_Query_to_newer_format

--------------------
-- END OF CODE
--------------------

-- BBEdit_upgrade_SQL_Query_to_newer_format({})
-- Dan Shockley, NYHTC
-- BBEdit - upgrade SQL Query to newer format

(*
HISTORY:
	1.3 - 2018-09-04 ( dshockley ): fix for optional space at end of SQL_Field line in whereEqualsClause regex search.
	1.2 - 2018-05-22 ( dshockley ): modified to also convert the query to use List to separate the components of the query.
	1.1 - 2017-12-11 ( dshockley ): disable the usually no-longer-needed SQL_EscapeString, but WARN and comment, since it might sitll be needed when using with something OTHER THAN SQL_Where criteria.
	1.0 - 2017-09-15 ( dshockley ): first created.
*)

on run
	BBEdit_upgrade_SQL_Query_to_newer_format({})
end run

--------------------
-- START OF CODE
--------------------

on BBEdit_upgrade_SQL_Query_to_newer_format({})

	set regexSearch_SQL_Table to "Quote *\\( *TableNameOfField *\\( *([^\\)]+) *\\) *\\)"
	set regexReplace_SQL_Table to "SQL_Table ( \\1 )"

	set regexSearch_SQL_Field to "Quote *\\( ?FieldNameShort *\\( *([^\\)]+) *\\) *\\)"
	set regexReplace_SQL_Field to "SQL_Field ( \\1 )"

	set regexSearch_WhereEqualsClause to "^([\\t ]*)& *SQL_Field *\\( *([^\\)]+) *\\) *
[\\t ]*& \" *= *\"
[\\t ]*& ([^\\r]+)\\r"

	set regexReplace_WhereEqualsClause to "\\1\\& SQL_Where ( \\2 ; \"=\" ; \\3 )\\r"

	set regexSearch_EscapeStringWARN to "SQL_EscapeString *\\( *([^\\)]+) *\\)"

	set regexReplace_EscapeStringWARN to "\\1 /* WARNING!! Had SQL_EscapeString probably NO LONGER NEEDED, so DISABLED! */"

	tell application "BBEdit"
		activate

		tell window 1

			replace regexSearch_SQL_Table using regexReplace_SQL_Table options {search mode:grep, starting at top:true}

			replace regexSearch_SQL_Field using regexReplace_SQL_Field options {search mode:grep, starting at top:true}

			replace regexSearch_WhereEqualsClause using regexReplace_WhereEqualsClause options {search mode:grep, starting at top:true}
			replace regexSearch_EscapeStringWARN using regexReplace_EscapeStringWARN options {search mode:grep, starting at top:true}

			try
				(* convert to using List ( ) for whitespace formatting of query: *)
				set stringStartQuery to "; sqlQuery = "
				set stringEndQuery to "^([\\t]+); sqlResult = "
				set posQueryStart to characterOffset of found object of (find stringStartQuery)
				set posQueryEnd to (characterOffset of found object of (find stringEndQuery options {search mode:grep})) - 1
				select (characters posQueryStart through posQueryEnd)

				replace "\"SELECT" using "List ( \\r\\t\\t  \"SELECT" searching in selection options {search mode:grep}
				replace "^([\\t]+)& " using "\\t\\t; " searching in selection options {search mode:grep}

				set character posQueryEnd to return & tab & tab & ")" & (contents of character posQueryEnd)

			end try

		end tell

	end tell

end BBEdit_upgrade_SQL_Query_to_newer_format

--------------------
-- END OF CODE
--------------------


update

update

-- 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(artist, title, status)
		if isGrowlRunning = false then return
		tell application id "com.Growl.GrowlHelperApp"
			if title = "" then set title to "unknown"
			set the_title to title
			if artist is not equal to "" then set the_title to 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

-- FetchLyric
-- DESCRIPTION: 让iTunes内当前被选中的曲目自动下载并保存歌词，若歌词已存在将被忽略，支持Growl通知
-- 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 : {"歌词已存在，无需再获取。", "歌词获取成功。", "歌词获取失败。", "未选择歌曲。"}
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(artist, title, status)
    if isGrowlRunning = false then return
    tell application id "com.Growl.GrowlHelperApp"
        if title = "" then set title to "unknown"
        set the_title to title
        if artist is not equal to "" then set the_title to 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
        -- 尝试使用歌曲封面作为Growl图标出错
    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
        -- 只有当歌曲中未存在歌词时才尝试获取歌词
        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
            -- 歌词成功获取
            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
-- 如果Growl未运行则显示对话框
if isGrowlRunning = false then
    display dialog return & "歌词获取结束！" buttons {"确定"} default button 1 with icon 1 giving up after 5 with title scriptName
end if
end tell


[NEW] --log-command model comment option for when you want to see the executed mogenerator invocation in Console.app.

property kExplicitlyProcessedOptions : {"--human-dir ", "--machine-dir ", "--output-dir ", "--log-command"}

tell application "Xcode"
	if not (exists active project document) then
		error "No active project. Please open an Xcode project and re-run the script."
	try
		my updateProjectXmod(project of active project document)
	on error errMsg
		my logger("Xmod.scpt exception: " & errMsg)
	end try
end tell

on updateProjectXmod(_project)
	tell application "Xcode"
		-- Iterate over every .xcdatamodel in the project.
		set modelList to every file reference of _project whose file kind is "wrapper.xcdatamodel"
		repeat with modelItr in modelList
			set theComments to the comments of modelItr
			if theComments contains "xmod" then

				set modelInfo to my getModelInfo(full path of modelItr, theComments)
				set humanGroupRef to null
				set machineGroupRef to null

				-- Figure out the model's parent group.
				-- Unversioned models are simple files so their group is the answer.
				-- Version models are bundles, which are represented as pseudo-groups in Xcode. You can't ask a pseudo-group for its parent group,
				-- so we discover it by querying project-wide all groups that contain the pseudo-group and using the first result.
				set modelItemRef to item 1 of (every item reference of _project whose full path is (full path of modelItr))
				set modelGroupRef to group of modelItemRef
				if isBundle of modelInfo then
					set modelGroupRef to item 1 of (every group of _project whose groups contains modelGroupRef)
				end if

				-- look for a group in the project that has the full path of the human manageable files
				set groupRefs to (every group of _project whose full path is (humanDirPath of modelInfo))
				-- if we don't find one, create it in the same group as the model file
				if (count of groupRefs) = 0 then
					tell modelGroupRef
						-- if we have different human and machine paths, then append '_human' to the model name for the group name
						if (humanDirPath of modelInfo) is not equal to (machineDirPath of modelInfo) then
							make new group with properties {full path:(humanDirPath of modelInfo), name:(name of modelInfo & "_human")}
						else
							make new group with properties {full path:(humanDirPath of modelInfo), name:(name of modelInfo)}
						end if
						set groupRefs to (every group of _project whose full path is (humanDirPath of modelInfo))
					end tell
				end if
				set humanGroupRef to item 1 of groupRefs

				-- if we have different human and machine paths, then look for a group for the machine files
				if (humanDirPath of modelInfo) is not equal to (machineDirPath of modelInfo) then
					set groupRefs to (every group of _project whose full path is (machineDirPath of modelInfo))
					-- if we don't find one, create it in the same group as the model file... named with '_machine' appended to the model name
					if (count of groupRefs) = 0 then
						tell modelGroupRef
							make new group with properties {full path:(machineDirPath of modelInfo), name:(name of modelInfo & "_machine")}
						end tell
						set groupRefs to (every group of _project whose full path is (machineDirPath of modelInfo))
					end if
					set machineGroupRef to item 1 of groupRefs
				end if

				-- Create the do shell script string and append any custom per model options to it, skipping the ones we've already parsed out
				set logCommand to false
				set theScript to "/usr/bin/mogenerator --model '" & full path of modelItr & "' --human-dir '" & (humanDirPath of modelInfo) & "' --machine-dir '" & (machineDirPath of modelInfo) & "'"
				set theParagraphs to every paragraph of theComments
				repeat with theParagraph in theParagraphs
					if theParagraph starts with "--" then
						set isExplicitlyProcessedOption to false
						repeat with explicitlyProcessedOption in kExplicitlyProcessedOptions
							if theParagraph starts with explicitlyProcessedOption then set isExplicitlyProcessedOption to true
						end repeat
						if not isExplicitlyProcessedOption then
							set theScript to theScript & " " & the text of theParagraph
						end if
						if theParagraph starts with "--log-command" then
							set logCommand to true
						end if
					end if
				end repeat

				--	Meat.
				if logCommand then
					my logger(theScript)
				end if
				do shell script theScript

				my addFilesFromPathToGroup(_project, modelItr, humanGroupRef)
				if machineGroupRef is not null then
					my addFilesFromPathToGroup(_project, modelItr, machineGroupRef)
				end if
			end if
		end repeat
	end tell
end updateProjectXmod

on everyTargetWithBuildFilePath(_project, _buildFilePath)
	set theResult to {}
	tell application "Xcode"
		repeat with targetItr in (every target of _project)
			repeat with buildFileItr in build files of targetItr
				if full path of file reference of buildFileItr is _buildFilePath then set theResult to theResult & {(targetItr as anything)}
			end repeat
		end repeat
	end tell
	return theResult
end everyTargetWithBuildFilePath

on getModelInfo(modelFileUnixPath, theComments)
	set modelFilePosixRef to POSIX file modelFileUnixPath
	set modelFileAlias to modelFilePosixRef as alias
	set theOutputDir to ""
	set theHumanDir to ""
	set theMachineDir to ""

	-- check for any directory path options specified in the commments
	set theParagraphs to every paragraph of theComments
	repeat with theParagraph in theParagraphs
		set paragraphLength to (length of theParagraph)
		if (offset of "--human-dir " in theParagraph) = 1 then
			set remainderOffset to (length of "--human-dir ") + 1
			if remainderOffset > paragraphLength then
				set theHumanDir to ""
			else
				set theHumanDir to text remainderOffset thru -1 of theParagraph
			end if
		else if (offset of "--machine-dir " in theParagraph) = 1 then
			set remainderOffset to (length of "--machine-dir ") + 1
			if remainderOffset > paragraphLength then
				set theMachineDir to ""
			else
				set theMachineDir to text remainderOffset thru -1 of theParagraph
			end if
		else if (offset of "--output-dir " in theParagraph) = 1 then
			set remainderOffset to (length of "--output-dir ") + 1
			if remainderOffset > paragraphLength then
				set theOutputDir to ""
			else
				set theOutputDir to text remainderOffset thru -1 of theParagraph
			end if
		end if
	end repeat

	-- remove any leading/trailing spaces or tabs from the paths
	if (length of theHumanDir) > 0 then
		repeat while character 1 of theHumanDir = tab or character 1 of theHumanDir = space
			set theHumanDir to text 2 thru -1 of theHumanDir
		end repeat
		repeat while last character of theHumanDir = tab or last character of theHumanDir = space
			set theHumanDir to text 1 thru -2 of theHumanDir
		end repeat
	end if

	if (length of theMachineDir) > 0 then
		repeat while character 1 of theMachineDir = tab or character 1 of theMachineDir = space
			set theMachineDir to text 2 thru -1 of theMachineDir
		end repeat
		repeat while last character of theMachineDir = tab or last character of theMachineDir = space
			set theMachineDir to text 1 thru -2 of theMachineDir
		end repeat
	end if

	if (length of theOutputDir) > 0 then
		repeat while character 1 of theOutputDir = tab or character 1 of theOutputDir = space
			set theOutputDir to text 2 thru -1 of theOutputDir
		end repeat
		repeat while last character of theOutputDir = tab or last character of theOutputDir = space
			set theOutputDir to text 1 thru -2 of theOutputDir
		end repeat
	end if

	-- get actual the model info and modify value for theOutputDir if necessary
	tell application "Finder"
		set modelFileFolder to folder of modelFileAlias

		set isModelBundle to name of modelFileFolder ends with ".xcdatamodeld"
		if isModelBundle then
			set modelFileAlias to (folder of modelFileAlias) as alias -- it's a bundle, go up one folder
			set modelFileFolder to folder of modelFileAlias
		end if

		set modelFileName to name of modelFileAlias
		if isModelBundle then
			set extensionLength to length of ".xcdatamodeld"
		else
			set extensionLength to length of ".xcdatamodel"
		end if

		set modelName to text 1 thru -(extensionLength + 1) of modelFileName -- pull off the extension

		-- if we didn't find any directory specifiers in the comments, then make theOutputDir the folder containg the model file
		if ((length of theOutputDir) = 0) and ((length of theHumanDir) = 0) and ((length of theMachineDir) = 0) then
			set modelSrcFolder to folder modelName of modelFileFolder
			set theOutputDir to text 1 thru -2 of (POSIX path of (modelSrcFolder as alias))
			-- otherwise, if theOutputDir isn't a full path itself already, set theOutputDir to a full path relative to the model file
		else if theOutputDir does not start with "/" then
			set modelFolderPath to text 1 thru -2 of (POSIX path of (modelFileFolder as alias))
			if (length of theOutputDir) = 0 then
				set theOutputDir to modelFolderPath
			else
				copy modelFolderPath & "/" & theOutputDir to theOutputDir
			end if
		end if

	end tell

	-- if theHumanDir is empty, use theOutputDir value instead, if theHumanDir not empty and it isn't a full path, then treat it as a relative path to theOutputDir
	if (length of theHumanDir) = 0 then
		set theHumanDir to theOutputDir
	else if theHumanDir does not start with "/" then
		copy theOutputDir & "/" & theHumanDir to theHumanDir
	end if

	-- if theMachineDir is empty, use theOutputDir value instead, if theMachineDir not empty and it isn't a full path, then treat it as a relative path to theOutputDir
	if (length of theMachineDir) = 0 then
		set theMachineDir to theOutputDir
	else if theMachineDir does not start with "/" then
		copy theOutputDir & "/" & theMachineDir to theMachineDir
	end if

	-- ensure the directories exist
	do shell script "mkdir -p '" & theHumanDir & "'"
	do shell script "mkdir -p '" & theMachineDir & "'"

	-- the following should resolve any symlinks, '..', or '~' in the paths
	tell application "System Events"
		set dirAlias to POSIX file theHumanDir as alias
		set theHumanDir to (POSIX path of (dirAlias as alias))
		set dirAlias to POSIX file theMachineDir as alias
		set theMachineDir to (POSIX path of (dirAlias as alias))
	end tell

	return {name:modelName, isBundle:isModelBundle, machineDirPath:theMachineDir, humanDirPath:theHumanDir}

end getModelInfo

on logger(msg)
	do shell script "logger '" & msg & "'"
end logger

on addFilesFromPathToGroup(_project, modelItr, groupRef)
	tell application "Xcode"
		-- get the full path of the directory that the groupRef represents
		set groupPath to full path of groupRef

		--	Build a list of source files in the group's directory
		tell application "System Events"
			set modelSrcDirAlias to POSIX file groupPath as alias
			set fileList to (every file of modelSrcDirAlias whose (name ends with ".m" or name ends with ".mm" or name ends with ".h"))
			set pathList to {}
			repeat with fileItem in fileList
				set pathList to pathList & POSIX path of fileItem
			end repeat
		end tell

		--	Add the source files to the group and the model's targets, but only if they don't exist already
		set targetList to null
		repeat with pathItr in pathList
			tell groupRef
				set fileRefs to (every file reference of _project whose full path is pathItr)
				if (count of fileRefs) = 0 then
					set modelSrcFileRef to make new file reference with properties {full path:pathItr, name:name of (info for POSIX file pathItr)}
					if targetList is null then
						set targetList to my everyTargetWithBuildFilePath(_project, full path of modelItr)
					end if
					repeat with targetIndex from 1 to (count of targetList)
						set targetItr to item targetIndex of targetList
						add modelSrcFileRef to targetItr
					end repeat
				end if
			end tell
		end repeat
	end tell
end addFilesFromPathToGroup

property ASDScriptUniqueIdentifier : "Xmod.applescript"

tell application "Xcode"
	if not (exists active project document) then
		error "No active project. Please open an Xcode project and re-run the script."
	try
		my updateProjectXmod(project of active project document)
	on error errMsg
		my logger("Xmod.scpt exception: " & errMsg)
	end try
end tell

on updateProjectXmod(_project)
	tell application "Xcode"
		-- Iterate over every .xcdatamodel in the project.
		set modelList to every file reference of _project whose file kind is "wrapper.xcdatamodel"
		repeat with modelItr in modelList
			set theComments to the comments of modelItr
			if theComments contains "xmod" then

				set modelInfo to my getModelInfo(full path of modelItr, theComments)
				set humanGroupRef to null
				set machineGroupRef to null

				-- Figure out the model's parent group.
				-- Unversioned models are simple files so their group is the answer.
				-- Version models are bundles, which are represented as pseudo-groups in Xcode. You can't ask a pseudo-group for its parent group,
				-- so we discover it by querying project-wide all groups that contain the pseudo-group and using the first result.
				set modelItemRef to item 1 of (every item reference of _project whose full path is (full path of modelItr))
				set modelGroupRef to group of modelItemRef
				if isBundle of modelInfo then
					set modelGroupRef to item 1 of (every group of _project whose groups contains modelGroupRef)
				end if

				-- look for a group in the project that has the full path of the human manageable files
				set groupRefs to (every group of _project whose full path is (humanDirPath of modelInfo))
				-- if we don't find one, create it in the same group as the model file
				if (count of groupRefs) = 0 then
					tell modelGroupRef
						-- if we have different human and machine paths, then append '_human' to the model name for the group name
						if (humanDirPath of modelInfo) is not equal to (machineDirPath of modelInfo) then
							make new group with properties {full path:(humanDirPath of modelInfo), name:(name of modelInfo & "_human")}
						else
							make new group with properties {full path:(humanDirPath of modelInfo), name:(name of modelInfo)}
						end if
						set groupRefs to (every group of _project whose full path is (humanDirPath of modelInfo))
					end tell
				end if
				set humanGroupRef to item 1 of groupRefs

				-- if we have different human and machine paths, then look for a group for the machine files
				if (humanDirPath of modelInfo) is not equal to (machineDirPath of modelInfo) then
					set groupRefs to (every group of _project whose full path is (machineDirPath of modelInfo))
					-- if we don't find one, create it in the same group as the model file... named with '_machine' appended to the model name
					if (count of groupRefs) = 0 then
						tell modelGroupRef
							make new group with properties {full path:(machineDirPath of modelInfo), name:(name of modelInfo & "_machine")}
						end tell
						set groupRefs to (every group of _project whose full path is (machineDirPath of modelInfo))
					end if
					set machineGroupRef to item 1 of groupRefs
				end if

				-- Create the do shell script string and append any custom per model options to it, skipping the ones we've already parsed out
				set theScript to "/usr/bin/mogenerator --model '" & full path of modelItr & "' --human-dir '" & (humanDirPath of modelInfo) & "' --machine-dir '" & (machineDirPath of modelInfo) & "'"
				set theParagraphs to every paragraph of theComments
				repeat with theParagraph in theParagraphs
					if (length of the characters of theParagraph) is greater than 2 then
						set theToken to the first character of theParagraph & the second character of theParagraph
						if theToken is "--" then
							if ((offset of "--human-dir " in theParagraph) = 0) and ((offset of "--machine-dir " in theParagraph) = 0) and ((offset of "--output-dir " in theParagraph) = 0) then
								set theScript to theScript & " " & the text of theParagraph
							end if
						end if
					end if
				end repeat

				--	Meat.
				do shell script theScript

				my addFilesFromPathToGroup(_project, modelItr, humanGroupRef)
				if machineGroupRef is not null then
					my addFilesFromPathToGroup(_project, modelItr, machineGroupRef)
				end if
			end if
		end repeat
	end tell
end updateProjectXmod

on everyTargetWithBuildFilePath(_project, _buildFilePath)
	set theResult to {}
	tell application "Xcode"
		repeat with targetItr in (every target of _project)
			repeat with buildFileItr in build files of targetItr
				if full path of file reference of buildFileItr is _buildFilePath then set theResult to theResult & {(targetItr as anything)}
			end repeat
		end repeat
	end tell
	return theResult
end everyTargetWithBuildFilePath

on getModelInfo(modelFileUnixPath, theComments)
	set modelFilePosixRef to POSIX file modelFileUnixPath
	set modelFileAlias to modelFilePosixRef as alias
	set theOutputDir to ""
	set theHumanDir to ""
	set theMachineDir to ""

	-- check for any directory path options specified in the commments
	set theParagraphs to every paragraph of theComments
	repeat with theParagraph in theParagraphs
		set paragraphLength to (length of theParagraph)
		if (offset of "--human-dir " in theParagraph) = 1 then
			set remainderOffset to (length of "--human-dir ") + 1
			if remainderOffset > paragraphLength then
				set theHumanDir to ""
			else
				set theHumanDir to text remainderOffset thru -1 of theParagraph
			end if
		else if (offset of "--machine-dir " in theParagraph) = 1 then
			set remainderOffset to (length of "--machine-dir ") + 1
			if remainderOffset > paragraphLength then
				set theMachineDir to ""
			else
				set theMachineDir to text remainderOffset thru -1 of theParagraph
			end if
		else if (offset of "--output-dir " in theParagraph) = 1 then
			set remainderOffset to (length of "--output-dir ") + 1
			if remainderOffset > paragraphLength then
				set theOutputDir to ""
			else
				set theOutputDir to text remainderOffset thru -1 of theParagraph
			end if
		end if
	end repeat

	-- remove any leading/trailing spaces or tabs from the paths
	if (length of theHumanDir) > 0 then
		repeat while character 1 of theHumanDir = tab or character 1 of theHumanDir = space
			set theHumanDir to text 2 thru -1 of theHumanDir
		end repeat
		repeat while last character of theHumanDir = tab or last character of theHumanDir = space
			set theHumanDir to text 1 thru -2 of theHumanDir
		end repeat
	end if

	if (length of theMachineDir) > 0 then
		repeat while character 1 of theMachineDir = tab or character 1 of theMachineDir = space
			set theMachineDir to text 2 thru -1 of theMachineDir
		end repeat
		repeat while last character of theMachineDir = tab or last character of theMachineDir = space
			set theMachineDir to text 1 thru -2 of theMachineDir
		end repeat
	end if

	if (length of theOutputDir) > 0 then
		repeat while character 1 of theOutputDir = tab or character 1 of theOutputDir = space
			set theOutputDir to text 2 thru -1 of theOutputDir
		end repeat
		repeat while last character of theOutputDir = tab or last character of theOutputDir = space
			set theOutputDir to text 1 thru -2 of theOutputDir
		end repeat
	end if

	-- get actual the model info and modify value for theOutputDir if necessary
	tell application "Finder"
		set modelFileFolder to folder of modelFileAlias

		set isModelBundle to name of modelFileFolder ends with ".xcdatamodeld"
		if isModelBundle then
			set modelFileAlias to (folder of modelFileAlias) as alias -- it's a bundle, go up one folder
			set modelFileFolder to folder of modelFileAlias
		end if

		set modelFileName to name of modelFileAlias
		if isModelBundle then
			set extensionLength to length of ".xcdatamodeld"
		else
			set extensionLength to length of ".xcdatamodel"
		end if

		set modelName to text 1 thru -(extensionLength + 1) of modelFileName -- pull off the extension

		-- if we didn't find any directory specifiers in the comments, then make theOutputDir the folder containg the model file
		if ((length of theOutputDir) = 0) and ((length of theHumanDir) = 0) and ((length of theMachineDir) = 0) then
			set modelSrcFolder to folder modelName of modelFileFolder
			set theOutputDir to text 1 thru -2 of (POSIX path of (modelSrcFolder as alias))
			-- otherwise, if theOutputDir isn't a full path itself already, set theOutputDir to a full path relative to the model file
		else if theOutputDir does not start with "/" then
			set modelFolderPath to text 1 thru -2 of (POSIX path of (modelFileFolder as alias))
			if (length of theOutputDir) = 0 then
				set theOutputDir to modelFolderPath
			else
				copy modelFolderPath & "/" & theOutputDir to theOutputDir
			end if
		end if

	end tell

	-- if theHumanDir is empty, use theOutputDir value instead, if theHumanDir not empty and it isn't a full path, then treat it as a relative path to theOutputDir
	if (length of theHumanDir) = 0 then
		set theHumanDir to theOutputDir
	else if theHumanDir does not start with "/" then
		copy theOutputDir & "/" & theHumanDir to theHumanDir
	end if

	-- if theMachineDir is empty, use theOutputDir value instead, if theMachineDir not empty and it isn't a full path, then treat it as a relative path to theOutputDir
	if (length of theMachineDir) = 0 then
		set theMachineDir to theOutputDir
	else if theMachineDir does not start with "/" then
		copy theOutputDir & "/" & theMachineDir to theMachineDir
	end if

	-- ensure the directories exist
	do shell script "mkdir -p '" & theHumanDir & "'"
	do shell script "mkdir -p '" & theMachineDir & "'"

	-- the following should resolve any symlinks, '..', or '~' in the paths
	tell application "System Events"
		set dirAlias to POSIX file theHumanDir as alias
		set theHumanDir to (POSIX path of (dirAlias as alias))
		set dirAlias to POSIX file theMachineDir as alias
		set theMachineDir to (POSIX path of (dirAlias as alias))
	end tell

	return {name:modelName, isBundle:isModelBundle, machineDirPath:theMachineDir, humanDirPath:theHumanDir}

end getModelInfo

on logger(msg)
	do shell script "logger '" & msg & "'"
end logger

on addFilesFromPathToGroup(_project, modelItr, groupRef)
	tell application "Xcode"
		-- get the full path of the directory that the groupRef represents
		set groupPath to full path of groupRef

		--	Build a list of source files in the group's directory
		tell application "System Events"
			set modelSrcDirAlias to POSIX file groupPath as alias
			set fileList to (every file of modelSrcDirAlias whose (name ends with ".m" or name ends with ".mm" or name ends with ".h"))
			set pathList to {}
			repeat with fileItem in fileList
				set pathList to pathList & POSIX path of fileItem
			end repeat
		end tell

		--	Add the source files to the group and the model's targets, but only if they don't exist already
		set targetList to null
		repeat with pathItr in pathList
			tell groupRef
				set fileRefs to (every file reference of _project whose full path is pathItr)
				if (count of fileRefs) = 0 then
					set modelSrcFileRef to make new file reference with properties {full path:pathItr, name:name of (info for POSIX file pathItr)}
					if targetList is null then
						set targetList to my everyTargetWithBuildFilePath(_project, full path of modelItr)
					end if
					repeat with targetIndex from 1 to (count of targetList)
						set targetItr to item targetIndex of targetList
						add modelSrcFileRef to targetItr
					end repeat
				end if
			end tell
		end repeat
	end tell
end addFilesFromPathToGroup

property ASDScriptUniqueIdentifier : "Xmod.applescript"