Script Properties

Ok, we’ve all done this before. You write a quick script, get it to work, and that’s all. A week later, (or an hour ^_^) you find something’s not quite exactly how you wanted it, or the requirements for the script change and going back to edit it you think, “now where was that thing again?”

I do it-we all do-but there’s a better way. The idea of making your script easier to come back to and edit (and helping you make new similar scripts, or scripts with similar functions) comes down to about 4 stages. The nice thing is, you don’t even have to work hard to do them, and you can do it like this the first time! Script properties, script handlers, script objects, and script libraries are these magical tools that will save your day. Today, I want to talk just on script properties.

Here’s a script in desperate need of “refactoring” (the process of making the script easier to read, maintain and modify)

tell application "Finder"
	repeat with each_file in list folder (path to desktop folder)
		display dialog "Do you want to move " & each_file & " to the trash?" buttons {"Don't Move to Trash", "Move to Trash"} default button "Move to Trash"
		if button returned of result is "Move to Trash" then
			move file ((path to desktop as string) & (each_file as string)) to trash
		end if
	end repeat
end tell

If we wanted to edit this script to change where it’s taking files from, or putting files, or the button text you have to edit a whole number of places, and hidden in a larger script this kind of thing is impossible to do.

Luckily for us, applescript gives us some tools at the language level to fight this kind of thing. The “property” keyword, not only makes things easier to maintain and edit, and it also will be displayed in the navigation bar in script editor, xcode or whatever other editor you happen to use. Let’s look at the (contrived) example from above with some of these things replaced with “properties.”

property inputPath : path to desktop folder
property outputPath : path to trash
property inputName : "Desktop"
property outputName : "Trash"
property dialogPrompt : "Do you want to move "
property confirmButton : "Move to " & outputName
property cancelButton : "Don't Move to " & outputName
property dialogButtons : {cancelButton, confirmButton}

tell application "Finder"
	repeat with eachFile in list folder inputPath
		display dialog (dialogPrompt & eachFile & " to " & outputName & "?") buttons dialogButtons default button confirmButton
		if button returned of result is confirmButton then
			move file ((inputPath as string) & (eachFile as string)) to outputPath
		end if
	end repeat
end tell

Okay… so it’s longer… and there are many other obvious improvements I could make to this, but that aside, looking at the code you can see that I can very easily change how this works simply be editing those key values at the top of the script. Also, even if I didn’t put them at the top of the script, they appear now in the navigation bar making them easy to find, and quick to reference. Basically anywhere you use a constant in your script, try to pull it out into a property. I could use this script with 10 seconds of modification or less to make it use my “Public” directory as a source and “Documents” as output instead of desktop and trash (especially because some of the properties I made to cascade, like “dialogButtons”). The best part is I don’t have to try to remember where I need to put alias/file, what needs to be coerced to a string value and what the syntax of the script is any more. I just edit those values, and never look at the code again. :slight_smile: - JOY!

As you can see, the basic syntax is “property” propertyName “:” value. (I named properties using the camelHump convention, but feel free to use any valid applescript identifier name)

cheese But wait! there’s MORE! cheese

Script properties can be written to have a special value called “missing value” which means you want the script to refer to this property, but you’re not sure what that value is yet :slight_smile: Also, if you set a property’s value, then when you run the script again (as long as you didn’t edit it in between) the property retains the value. Try running this a couple times and you’ll see that the default value stays between runs and can be used anywhere in the script:

property mySavedValue : missing value
property defaultSavedValue : "default text"

if mySavedValue is missing value then
	set mySavedValue to defaultSavedValue
end if

display dialog "what value do you want to save?" default answer mySavedValue
set mySavedValue to text returned of result

Note however this retained value technique doesn’t work in Applescript Studio (a common thing tried by people moving to Applescript Studio. Instead they should use the user defaults system.

In closing, script properties help organize your code, make it easier to adapt to new circumstances, and allow for some form of value persistence between runs of your script. Though the examples were just that, I hope you can see how separating out most of the constants into properties can benefit you by saving you time the second and third time you go to edit or reuse the code you worked hard to figure out.

Chris Moore for UnScripted