Save previous path from file choose dialog until next choose dialog

Hello.

I hope you like and use this, and posts if there are any problems or questions.

Enjoy! :slight_smile:

Introduction

I really find it unnecessary to wade through file or folder choose dialogs, when it should be reasonable to demand from the script to remember the last location. The last location, -is the obvious choice under the rerun of a script in a great many circumstances. instead of having to start all over again.

This is isn’t exactly rocket science, but still useful; so I thought it would be nice to have that functionality provided by a script object once and for all.

Preliminaries
You need to declare an empty property for each path which should be saved in your script.
It demands an initialPath, or starting point in some file structure.
This kind of initial path, is not chosen by the user, but by what the programmer (You) finds to be sensible in context of the purpose of the script.

This is rather in opposite to when you beg a user to set an initial path during first run, because the path is to some dedicated files structure for the script you have no idea about where resides.
(You could still use this package for that purpose if you supplied an initial path of:


	(POSIX file "/" as text)

If you need to qualify a path to a subtree and that subtree are guaranteed to contain one known subfolder then see this post.

Overview

The script smartPathParadigm contains all necessary functionality and must be copied into your script.

The handler smartPathParadigm’s initiateSmartPath initiates a script object with necessary functionality.

The resulting script object has three handlers

[b][color=blue]getPrevPath[/color]()[/b] returns the previous path.

[b][color=blue]setPrevPath[/color](hfsNewPrevPathAsText)[/b] sets a path explicitly from a folder.

[b][color=blue]updatePrevPath[/color](hfsNewPrevPathAsText)[/b] sets the previous path regardless if it was given a file or folder.
-it will always use the parent folder  from the path it was given.

[b][color=blue]withinRealm[/color][/b]([b][color=red]hfsFilePathAsText[/color][/b]) Returns [b][color=blue]true[/color][/b] if this path is within the realms - subfolder or file the path denotes is within
the [b][color=blue]intitalPath[/color][/b] and [b][color=blue]false [/color][/b] otherwise.

Implementation

I wanted to encapsulate as much as possible of this behaviour in an object,
and let it be transparent to actual choosing of files and such, since this functionality will will vary wildly from context to context and programmer to programmer. This is meant to be a “one size fits all” solution.
The object is created by a handler.

Prerequisites
You need to declare empty properties in you main script, and initiate the properties with your chosen initial with something similar to this:


property scoFirstPathToBeUsed : {} -- say for finding a source folder
	smartPathParadigm's initiateSmartPath(scoFirstPathToBeUsed, (path to documents folder as text))

You will need one object for each of the paths in your script or applet.
You need two lines of code per path to initiate a path to be remembered.

Usage Details
The difference of setting a previous path implicitly or explicitly.

You don’t need and you shouldn’t do any “massage” of paths of your own. Use the specialiced call setPrevPath when you know that this is the explicit path you want to set as the previous path, only containing folders, if not; if your path is within a successful result from say a choose file/folder dialog then use updatePreviousPath which extracts the parent folder of whatever.

Important

You must take precautions to get the properties written back to the script.
-You can’t just bail out of your script with error number −128 anymore.
You have to return in order to save the previous path back into the script

The solution can’t be used directly in an applet
In order to use this in an applet, you must save the properties as a script object into the the bundle of the applet in the Quit handler.

Demo Example




-- The Idea and implementation and any faults is totally mine. © McUsr 2010 and put in the Public Domain.
-- The usually guarrantees about nothing what so ever applies, use it at your own risk.
-- Read the documentation.
-- You are not allowed to post this code elsewhere, but may of course refer to the post at macscripter.net.
” macscripter.net/viewtopic.php?id=12895
property scoFirstPathToBeUsed : {} -- say for finding a source folder
property scoSecondPathToBeUsed : {} -- and for a target folder


set scoFirstPathToBeUsed to smartPathParadigm's initiateSmartPath(scoFirstPathToBeUsed, (path to documents folder as text))
set scoSecondPathToBeUsed to smartPathParadigm's initiateSmartPath(scoSecondPathToBeUsed, (path to scripts folder from user domain as text))

scoFirstPathToBeUsed's initialPath --> "Macintosh HD:Users:You:Documents:"
scoSecondPathToBeUsed's initialPath --> "Macintosh HD:Users:You:Library:Scripts:"

scoFirstPathToBeUsed's getPrevPath() --> "Macintosh HD:Users:You:Documents:"
scoSecondPathToBeUsed's getPrevPath() --> "Macintosh HD:Users:You:Library:Scripts:"

” *** Line below sets path explicitly ***
scoFirstPathToBeUsed's setPrevPath((path to documents folder as text))
”  *** Observe: the same path is returned ***
scoFirstPathToBeUsed's getPrevPath() --> "Macintosh HD:Users:You:Documents:"

” *** Lines below updates path conditionally ->condition: path is within realm of initial path
local blnIsWithinRealm ” A boolean
set blnIsWithinRealm to  scoFirstPathToBeUsed's withinRealm(theScriptLibrary as text)
		-- this tells us if the user has surpassed the inital realm of the library path.

if blnIsWithinRealm is true then scoFirstPathToBeUsed's updatePrevPath(theScriptLibrary as text) 
-- saves the path for next time
		



” *** Line below sets path implicitly from the parent path wether it is folder app or file ***
scoFirstPathToBeUsed's updatePrevPath("Macintosh HD:Users:You:Applications:HardwareGrowler.app:")
” *** Observe: the parent path is returned ***
scoFirstPathToBeUsed's getPrevPath() --> "Macintosh HD:Users:You:Applications"


You are supposed to know that the choose file and choose folder returns an alias or raises error −128 if you hit escape or Cancel. But choose from list returns false. :slight_smile:

The Code


-- The Idea and implementation and any faults is totally mine. © McUsr 2010 and put in the Public Domain.
-- The usually guarrantees about nothing what so ever applies, use it at your own risk.
-- Read the documentation.
-- You are not allowed to post this code elsewhere, but may of course refer to the post at macscripter.net.
-- macscripter.net/viewtopic.php?id=129895
(*
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.
*)

-- See macscripter.net/viewtopic.php?pid=129895#p129895 For Documentation
-- © McUsr 2010 and put in the public domain.
script smartPathParadigm
	property McUsr : "1.2 polymorphic and Debugged"
	property initialPath : ""
	property prevPath : ""
	-- maybe remake the object model a little as well.
	on makeSmartPath(hfsInitialPathAsText)
		script o
			property parent : smartPathParadigm
			property initialPath : "" & hfsInitialPathAsText -- doesn't harm
			property prevPath : ""
		end script
		o
	end makeSmartPath
	
	on getInitialPath()
		-- gets the initial path from the last initialization
		my initialPath
	end getInitialPath
	
	on getPrevPath()
		-- gets the previous path. - there is no current.
		if my prevPath is "" then
			my initialPath
		else
			my prevPath
		end if
	end getPrevPath
	
	on updatePrevPath(hfsReturnedPathAsText)
		-- sets the previous path to this parent folder of the path delivered.
		local newPath
		set hfsReturnedPathAsText to "" & hfsReturnedPathAsText
		set newPath to smartPathParadigm's getPathToParentFolder(hfsReturnedPathAsText)
		
		if my prevPath is not newPath then
			set my prevPath to newPath
		end if
	end updatePrevPath
	
	on withinRealm(hfsFilePathAsText)
		-- check to see if a path is in within the realm of the initial path.
		set hfsFilePathAsText to "" & hfsFilePathAsText
		if hfsFilePathAsText contains my initialPath then
			return true
		else
			return false
		end if
	end withinRealm
	
	on setPrevPath(hfsNewPrevPathAsText)
		-- sets a path literally
		set hfsNewPrevPathAsText to "" & hfsNewPrevPathAsText -- doesn't harm
		set my prevPath to hfsNewPrevPathAsText
	end setPrevPath
	
	on initiateSmartPath(scoForPath, hfsIntialPathAsText)
		-- constructor which allows reuse.
		script o
			property pathobj : scoForPath
		end script
		set hfsIntialPathAsText to "" & hfsIntialPathAsText
		if scoForPath is {} then
			set o's pathobj to smartPathParadigm's makeSmartPath(hfsIntialPathAsText)
		else
			set o's pathobj's initialPath to hfsIntialPathAsText
			set o's pathobj's prevPath to ""
		end if
		o's pathobj
	end initiateSmartPath
	
	on getPathToParentFolder(hfsFileOrFolderPathAsText)
		-- return sparehtn folder.
		local tids, theFile
		set hfsFileOrFolderPathAsText to "" & hfsFileOrFolderPathAsText -- doesn't harm.
		set tids to AppleScript's text item delimiters
		set AppleScript's text item delimiters to ":"
		if character (length of hfsFileOrFolderPathAsText) of hfsFileOrFolderPathAsText is ":" then
			set hfsFileOrFolderPathAsText to text items 1 thru -3 of hfsFileOrFolderPathAsText
		else
			set hfsFileOrFolderPathAsText to text items 1 thru -2 of hfsFileOrFolderPathAsText
		end if
		set hfsFileOrFolderPathAsText to "" & hfsFileOrFolderPathAsText -- necessary here.
		set AppleScript's text item delimiters to tids
		return hfsFileOrFolderPathAsText
	end getPathToParentFolder
end script

Best Regards

Mcusr

Hello.

I have updated the smartPathParadigm to work flawlessly under Tiger.

Best Regards

McUsr

Hello.

I have updated it with the handler [b]withinRealm/b Returns true if this path is within the realms - within the intitalPath and false otherwise.

Best Regards

McUsr

Hello.

I have added an example of using the [b]withinRealm/b handler.

Best Regards

McUsr

Hello.

I have updated the “object model” of this smarterPath in the hope that it should consume less resources. -I have not tested how much it uses neither before nor after, but less is always better! :slight_smile:

I have done that by letting the object the constructor returns inherit the functions of the object convoluting the constructor, and having all the handlers there, exploiting the resident polymorphism of AppleScript.

I haven’t tried to measure any gains of this, but it should be something to be gained. It can’t make it worse, and I think this is a somewhat cleaner approach. -At least logically, when reading the code.

Now it is polymorphic! :frowning: