The Preferences Pattern
When writing my AppleScripts I try to allow for enough flexibility for each user to set the script up to his/her liking, without requiring that all of the questions be answered each time the action is performed. In other words: saved preferences.
In my latest scripts to be updated (Rename Files and Remove Missing Tracks), I have switched to a new form of preferences (writing a structure to a file) and have tried to create a series of functions and properties which can work together and be the same in all of the scripts.
The preferencesFilename
property stores the name of the file that will be stored in the preferences directory. All of these files names should begin with net.plaidcow.
The LoadPreferences()
function is responsible for loading the preferences from the disk and assigning them into the global variables. A template of is shown in this code
(Edit):
on LoadPreferences() SetDefaultPreferences() set theFile to (path to preferences from user domain as string) ¬ & preferencesFilename as file specification try set thePreferences to item 1 of (read theFile as list) -- Set all of the globals based on the data in the file, -- wrapping each set statement in its own try block try -- Set the global to the data from the file end try end try my UpdatePreferencesDependencies() end LoadPreferences |
The function starts off with a call to UpdatePreferencesDependencies()
which will ensure that all of the preferences have been set to valid values. Since the read
command is located within a try block, not error will be thrown if the file doesn’t exist. Assuming that the file was read, each of the parameters can then be read out of the structure that was read from the file. By wrapping each of the command to set a single parameter in its own try block, any parameter can not exist the the reading of the preferences will not fail. (This should allow the adding and removing of parameters between versions with no ill effects.)
The SavePreferences()
function calls is a simple aggregation of the global preferences into a list, and then the writing of that to the preferencesFilename
. In this sample code (Edit), the global notificationType
is being saved:
on SavePreferences() set thePreferences to {notificationType:notificationType} set theFile to (path to preferences from user domain as string) ¬ & preferencesFilename as file specification try open for access theFile with write permission set eof of theFile to 0 write (thePreferences) to theFile starting at eof as list close access theFile on error try close access theFile end try end try end SavePreferences |
UpdatePreferences()
calls a series of user interface command to get the user to input new values for some or all of the preferences. After inputing these, the UpdatePreferencesDependencies()
function is called. Unless another mechanism is being used, this is the time to cal SavePreferences()
The ResetPreferences()
function calls the private SetDefaultPreferences()
, followed by private UpdatePreferencesDependencies()
. This code should be the same for every implementation (Edit):
on ResetPreferences() SetDefaultPreferences() UpdatePreferencesDependencies() end ResetPreferences |
The last of the preferences function are two that should not be called from outside of the other preferences functions. (Alas, there is no way to declare private functions, so just don’t do it.) SetDefaultPreferences()
sets all of the global preferences to their default values. UpdatePreferencesDependencies()
updates any of the other variables in the script which may depend on the value of one of the preferences. One example of this is the notifier object, which saves it’s type of notification in a global variable.