ScriptEditSnapshot/restore of scripts for the project rembers previous

Hello.

Revison 0001: Removed 2 bugs regarding saving of documents before trying to find out if there are any “eligible” documents to take snapshot of or restore. This bug caused a runtime error when trying to take a snapshot of unsaved documents. Sorry.

Revision 0002: English localization.

Usage:
The intention of this applet is to keep it (a copy of it) in a project folder.
The menu it displays gives you the choices of either take a snapshot of the scripts open in scripteditor at
the moment or restore to the files open if you have done something else, or restore the scripts which
where open at the moment you restored the previous snapshot.

I hope you find it useful. I'm still toying with it and will eventuall make another version, but when I' don't know.


McUsr ;) (c)

I have tried to localize it, but the name of a "new file" or "new document" probably isn't correct.

(*
TERMS OF USE. 
This applies only to posting code, as long as you don't post it, you are welcome to do
whatever you want to do with it without any further permission. 
Except for the following: Selling the code as is, or removing copyright statmentents and the embedded link in the code (without the http:// part) from the code. 

You must also state what you eventually have done with the original source. This obviously doesn't matter if you  distribure AppleScript as read only. I do not require you to embed any properties helding copyright notice for the code.

Credit for having contributed to your product would in all cases be nice!

If you use this code as part of script of yours you are of course welcome to post that code with my code in it here at macscripter.net. If you then wish to post your code elsewhere after having uploaded it to MacScripter.net please email me and ask for permission.

The ideal situation is however that you then refer to your code by a link to MacScripter.net
The sole reason for this, is that it is so much better for all of us to have a centralized codebase which are updated, than having to roam the net to find any usable snippets. Which some of us probabaly originated in the first hand.

I'm picky about this. If I find you to have published parts of my code on any other site without previous permission, I'll do what I can to have the site remove the code, ban you, and sue you under the jurisdiction of AGDER LAGMANNSRETT of Norway. Those are the terms you silently agree too by using this code. 

The above paragraphs are also valid if you violate any of my terms.

If you use this or have advantage of this code in a professional setting, where professional setting means that you use this code to earn money by keeping yourself more productive. Or if you as an employee share the resulting script with other coworkers, enhancing the productivity of your company, then a modest donation to MacScripter.net would be appreciated.
*)

property scriptList : {}
property oldScriptList : {}
property boundsAll : {}
property oldBoundsAll : {}
property libWinName : "Library" -- Library
property eventLogWinName : "Event logs" -- Event logs
property newWindowName : "new file" -- new file ??? - *You have to check this
property questionOfEmptyingTheApplet : "There is currently no files in the Script Editor sure you want to remove the previous snapshot?"
property questionOfMakingASeparateSnapshot : "Maybe you should create a snapshot of these files."
property messageOfnoFormerScriptsToRestore : "There were no scripts in the editor when you restored the snapshot."
property messageOfNoScriptsToRestore : "You haven't made a snapshot yet."
property messeageOfChooseOperation : "Please choose operation"
property unanticipatedErrorMessage : "Unanticipated Error: "
property commandList : {"Snapshot", "Restore", "Previous"}
property astid : ""
property wnCount : 0
global chosenOperation
on run
	global chosenOperation
	set chosenOperation to (choose from list my mkCommandsList() default items {"Snapshot"} with prompt my messeageOfChooseOperation with title my thisAppName()) as text
	
	if chosenOperation is "Snapshot" then
		my takeSnapshot()
	else if my chosenOperation is "Restore" then
		my restoreSnaphot()
	else if chosenOperation is "Previous" then
		my previousSnapshot()
	end if
	my cleanup()
	tell me to quit
end run

on mkCommandsList()
	local lesserCommandList
	if my scriptList = {} and my oldScriptList = {} then
		copy ({item 1} of my commandList) to lesserCommandList
	else if my scriptList ≠ {} and my oldScriptList = {} then
		copy (items 1 thru 2 of my commandList) to lesserCommandList
	else
		copy my commandList to lesserCommandList
	end if
	return lesserCommandList
end mkCommandsList

on takeSnapshot()
	local aDoc, docRef, commence, myrez
	set commence to true
	tell application "AppleScript Editor"
		activate
		close (every document whose name contains newWindowName and modified = false)
		save (every document whose modified = true)
		
		if not my eligibleDocumentsIsPresent() then
			if my scriptList ≠ {} then
				try
					display dialog my questionOfEmptyingTheApplet buttons {"Ok", "Cancel"} default button 2 with title my thisAppName() with icon 2
				on error e number n
					set commence to false
				end try
			else
				my cleanup()
				tell me to quit
			end if
		end if
		if commence = true then
			save (every document whose modified = true)
			close (every document whose name contains my newWindowName and modified = false)
			set my boundsAll to {}
			set my scriptList to {}
			set myrez to my createSnapshot(my scriptList, my boundsAll)
			set my scriptList to item 1 of the myrez
			
			set my boundsAll to item 2 of the myrez
			
		end if
	end tell
	
	my cleanup()
	tell me to quit
end takeSnapshot

on restoreSnaphot()
	-- we do store whatever windows may have been opened before we started restoring.
	local myrez
	tell application "AppleScript Editor"
		activate
		if my scriptList ≠ {} then
			
			set my oldBoundsAll to {}
			set my oldScriptList to {}
			close (every document whose name contains newWindowName and modified = false)
			save (every document whose modified = true)
			if my eligibleDocumentsIsPresent() then
				
				set myrez to my createSnapshot(my oldScriptList, my oldBoundsAll)
				set my oldScriptList to item 1 of the myrez
				set my oldBoundsAll to item 2 of the myrez
				my closeEligibleWindows(scriptList)
			end if
			
			set i to 1
			repeat with aScript in my scriptList
				open aScript as alias
				set bounds of window 1 to item i of my boundsAll
				set i to i + 1
			end repeat
		else
			display dialog "restoreSnaphot: " & my messageOfNoScriptsToRestore buttons {"Ok"} default button 1 with title my thisAppName() with icon 2
		end if
	end tell
	my cleanup()
	tell me to quit
end restoreSnaphot

on previousSnapshot()
	tell application "AppleScript Editor"
		activate
		if my oldScriptList ≠ {} then
			display dialog questionOfMakingASeparateSnapshot with title my thisAppName() buttons {"Ok"} default button 1 with icon 1
			if my eligibleDocumentsIsPresent() then
				save (every document whose modified = true)
				my closeEligibleWindows(oldScriptList)
			end if
			-- close every window whose visible = true  -- if you want to close the library windows.
			set i to 1
			repeat with aScript in oldScriptList
				open aScript as alias
				set bounds of window 1 to item i of my oldBoundsAll
				set i to i + 1
			end repeat
		else
			display dialog "previousSnapshot: " & my messageOfnoFormerScriptsToRestore with title my thisAppName() buttons {"Ok"} default button 1 with icon 2
		end if
	end tell
	my cleanup()
	tell me to quit
end previousSnapshot

on eligibleDocumentsIsPresent()
	local aDoc, wnCount
	tell application "AppleScript Editor"
		set wnCount to count of its windows
		if ((count of its documents) = 1 and name of its document 1 = my newWindowName and modified of document 1 = false) or (count of its documents) = 0 then
			return false
		else
			set n to 1
			repeat while n ≤ wnCount
				try
					if titled of window n = true and visible of window n = true then
						
						if not (name of window n = my libWinName or name of window n = my eventLogWinName or name of window n contains my newWindowName) then
							set aDoc to (document of window n) --as alias
							if (path of aDoc) does not contain ".sdef" then
								return true
							end if
						end if
					end if
					
				on error the error_message number the error_number
					display dialog "eligibleDocumentsIsPresent : " & my unanticipatedErrorMessage & the error_number & ". " & the error_message buttons {"OK"} default button 1 with title my thisAppName() with icon 2
				end try
				set n to n + 1
			end repeat
			return false
		end if
	end tell
end eligibleDocumentsIsPresent

--  eligble windows are windows who does not contain a library is the overview window of the 
-- library or the eventlog window.
to closeEligibleWindows(lstDocsToRestore)
	local wnCount, n, aDoc, docPath, docRef
	tell application "AppleScript Editor"
		set wnCount to count of its windows
		set n to 1
		repeat while n ≤ wnCount
			try
				if titled of its window n = true and visible of its window n = true then
					
					if not (name of its window n = my libWinName or name of its window n = my eventLogWinName or name of its window n contains newWindowName) then
						set aDoc to (document of its window n) --as alias
						set docPath to (path of aDoc)
						if docPath does not contain ".sdef" then
							set docRef to (a reference to POSIX file docPath) as alias
							if posInList(docRef, lstDocsToRestore) = 0 then
								close its window n
							end if
							-- ** hopper over vinduer vi skal åpne allikevel.
						end if
					end if
				end if
				
			on error the error_message number the error_number
			end try
			set n to n + 1
		end repeat
	end tell
	
end closeEligibleWindows


on cleanup()
	set AppleScript's text item delimiters to astid
end cleanup

on createSnapshot(theScriptList, theWinBoundsLIst)
	local wnCount, n, aDoc, docRef
	set theScriptList to {}
	set theWinBoundsLIst to {}
	tell application "AppleScript Editor"
		set wnCount to count of its windows
		set n to 1
		repeat while n ≤ wnCount
			try
				if titled of window n = true and visible of window n = true then
					
					if not (name of window n = my libWinName or name of window n = my eventLogWinName or name of window n contains newWindowName) then
						set aDoc to (document of window n) --as alias
						if (path of aDoc) does not contain ".sdef" then
							set docRef to (a reference to POSIX file (path of aDoc)) as alias
							set theScriptList to my listInsert(docRef, theScriptList, 1)
							set theWinBoundsLIst to my listInsert((bounds of window n), theWinBoundsLIst, 1)
						end if
					end if
				end if
				
			on error the error_message number the error_number
				display dialog "createSnapshot: " & my unanticipatedErrorMessage & the error_number & ". " & the error_message buttons {"OK"} default button 1 with title my thisAppName() with icon 2
			end try
			set n to n + 1
		end repeat
	end tell
	return {theScriptList as list, theWinBoundsLIst as list}
end createSnapshot


on quit
	continue quit
end quit

on posInList(what, mylist)
	local ctr
	if (count of mylist) = 0 then
		return 0 -- CANT BE FOUND 
	else
		set ctr to 1
		repeat with anItem in mylist
			if anItem contains what then
				return ctr
			else
				set ctr to ctr + 1
				
			end if
		end repeat
		return 0 -- NOT FOUND 
	end if
end posInList

-- This is made by Matt Neuberg
on listInsert(what, L, ix)
	if ix = 1 then
		return {what} & L
	else
		return {item 1 of L} & listInsert(rest of L, what, ix - 1)
	end if
end listInsert

-- returns the appname rather awkward because I intend to have a copy of the applet in each of my project folders.
on thisAppName()
	local thePath, myFullName, myName, parFolder, parPath, tempPath, grandFolder
	set tempPath to (path to me) as Unicode text
	set thePath to characters 1 thru -2 of tempPath as string
	set myFullName to my extract_filename_from(thePath)
	set myName to my extract_shortname_from(myFullName)
	set parFolder to my extract_parent_folder_name_from(thePath)
	set tempPath to my extract_parent_folder_path_from(thePath)
	set parPath to characters 1 thru -2 of tempPath as string
	set grandFolder to my extract_parent_folder_name_from(parPath)
	return myName & "_" & parFolder & "_" & grandFolder
end thisAppName

-- shamelessy stolen from the AppleScript SDK  written by Sal Soghoian

on extract_parent_folder_name_from(the_filepath)
	set the_filepath to the_filepath as text
	set x to the offset of ":" in (the reverse of every character of the_filepath) as string
	set the_filepath to (characters 1 thru -(x + 1) of the_filepath) as text
	set x to the offset of ":" in (the reverse of every character of the_filepath) as string
	return ((characters -(x - 1) thru -1 of the_filepath) as text)
end extract_parent_folder_name_from

on extract_parent_folder_path_from(the_filepath)
	set the_filepath to the_filepath as text
	set x to the offset of ":" in (the reverse of every character of the_filepath) as string
	set the_filepath to (characters 1 thru -(x) of the_filepath) as text
end extract_parent_folder_path_from

on extract_filename_from(the_filepath)
	set the_filepath to the_filepath as text
	set x to the offset of ":" in (the reverse of every character of the_filepath) as string
	return ((characters -(x - 1) thru -1 of the_filepath) as text)
end extract_filename_from

-- a derived version of one of the originals from the applescript SDK
on extract_shortname_from(the_filepath)
	set the_filepath to the_filepath as text
	set x to the offset of "." in (the reverse of every character of the_filepath) as string
	--	return ((characters -(x - 1) thru -1 of the_filepath) as text)
	return ((characters 1 thru -(x + 1) of the_filepath) as text)
end extract_shortname_from

OOps … The last handler i’snt from the SDK but from me. It still should work.
Matt Neuberg also deserves som credits for listInsert.

Let me add that I hope that you use it while I’m at it. It is of great value to me because now I can split different
source files which may pop up in the ScriptEditor to different projects. By making a copy of the snapshotter in a new directory for as many fiilesets/projects the files in script editor adds up to and firing it up for each. Then delete from each snapshot as needed. It also remembers window sizes. The greatest thing is that it remembers the files which were in the ScriptEditor before you restored a project. You can easily go back to the previous set of files with any ado.

Additions …
I have removed two bugs, regarding saving the stuff before taking a snapshot. and before restoring too.

I have used it lately with some scripts that was installed in Growl. I found out that the easiest way to reinstall them was to log out and in. And the Snapshot eased the process a lot as I didn’t have to load all of the files manually.

  • I didn’t have to write a script to do so neither.

You are the greatest!

Enjoy::smiley: