Bit of a question and a quandary here for you folks, trying to get my head around this and feeling a bit at a loss, I’ve been through the scripting guide, I’ve been trawling through forums and I seem to get myself further in a tizzy so I come to ask my question here.
I’m trying to get some variables to persist through running, I’ve got some running through a PLIST but my quandary is coming towards locations, I’m trying to get a folder location that could be changed at short notice but also may not be changed for some time, my problem comes into storing the location, I was thinking to store it within a PLIST with the other items but I cannot get it to store within there, it’ll prompt to select the folder but when saving it I cannot find any record of it in the PLIST file.
So I’m wondering if any the more experienced folks here have any information or recommendations?
As ever I appreciate all of the help from you folks and the time you take to answer.
I save all my script preferences in “.dat” files saved as an AppleScript list.
Super easy to save and read back in.
I have a Script Library I made that has the getPrefs and setPrefs routine
here is the library. “ScriptPreferences.scpt”
You send it the name of the preference file you want. I use filenames that end with .dat like so “AppPreferences.dat”
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on get_prefs(pFile as string)
local cfile, show_list
set cfile to (path to preferences as text) & "ScriptPrefs:" & pFile
try
set cfile to open for access cfile with write permission
on error
display alert "Uh-oh! Error opening file…" giving up after 10
return false
end try
try
set show_list to read cfile from 1 as list
on error
display alert "File Empty!" giving up after 5
write {} to cfile as list
set show_list to {}
end try
close access cfile
return show_list
end get_prefs
on set_Prefs(pFile as string, pList as list)
local cfile, flag
set flag to false
try
set cfile to (path to preferences as text) & "ScriptPrefs:" --& "com.rmf.test.prefs"
alias cfile
on error eStr number eNum
set flag to true
end try
if flag then
try
tell application "System Events"
set cfile to path of (make new folder at end of (path to preferences) with properties {name:"ScriptPrefs"})
end tell
on error
display alert "Uh-oh! Error creating folder \"ScriptPrefs\" in Preferences folder." giving up after 10
return false
end try
end if
set cfile to cfile & pFile
try
set cfile to open for access cfile with write permission
on error eStr number eNum
display alert "Uh-oh! Error opening file…" giving up after 10
return false
end try
try
set eof cfile to 0
write pList to cfile as list
on error
display alert "Error! Can't write to preference file…" giving up after 10
end try
close access cfile
return true
end set_Prefs
Robert has provided a fine solution.
If you need to use plists specifically then you can use these…
edit: universal path for easier testing.
--11/18/24 https://www.macscripter.net/u/paulskinner/
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
set dtp to (path to the desktop folder) as text
set fileObject to dtp & "plist.plist" --Path to the plist. It need not exist.
set theArray to {dtp} --Your path as text in a list.
FileSystem_Plist_Write(fileObject, theArray)
(item 1 of FileSystem_Plist_Read(fileObject)) as text --> "Macintosh HD:Users:paulskinner:Desktop:"
on FileSystem_Plist_Read(fileObject)
try
set fileObject to FileSystem_Object_As_Posix_Path(fileObject)
set theData to current application's NSData's dataWithContentsOfFile:fileObject
set theArray to current application's NSPropertyListSerialization's propertyListWithData:theData options:0 format:(missing value) |error|:(missing value) -- read file
return theArray
on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType --Unhandled errors in the handler are caught here.
error "<FileSystem_Plist_Read>" & space & errorText number errornumber partial result errorResults from errorObject to errorExpectedType --Error messages generated in this handler are modified to include the name of the handler.
end try
end FileSystem_Plist_Read
on FileSystem_Plist_Write(fileObject, theArray)
try
set fileObject to my FileSystem_Object_As_Posix_Path(fileObject)
set {theData, theError} to current application's NSPropertyListSerialization's dataWithPropertyList:theArray format:(current application's NSPropertyListBinaryFormat_v1_0) options:0 |error|:(reference)
set theResult to theData's writeToFile:fileObject atomically:true -- write to file
on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType --Unhandled errors in the handler are caught here.
error "<FileSystem_Plist_Write>" & space & errorText number errornumber partial result errorResults from errorObject to errorExpectedType --Error messages generated in this handler are modified to include the name of the handler.
end try
end FileSystem_Plist_Write
on FileSystem_Object_As_Posix_Path(FileSystemObject)
try
try
return POSIX path of FileSystemObject
on error
try
tell application "System Events"
return POSIX path of ((path of disk item (FileSystemObject as string)) as alias)
end tell
on error
return POSIX path of (FileSystemObject as alias)
end try
end try
on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
error "<FileSystem_Object_As_Posix_Path>" & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
end try
end FileSystem_Object_As_Posix_Path
Like Paul, I use ASObjC to save a file/folder path to a plist file. If someone wants a simple solution, a text file can be used. BTW, I don’t believe an alias or file object can be saved in a plist file. It would have to be converted to either an NSURL or a POSIX or HFS path.
set theFolder to (choose folder) as text --just for testing
set settingsFile to POSIX path of (path to documents folder) & "Save Path.txt" --set to desired value
do shell script "echo " & theFolder & " > " & quoted form of settingsFile --save file path
--try --get saved file path
-- set savedFolder to paragraph 1 of (read POSIX file settingsFile as «class utf8»)
--on error
-- display dialog "The settings file was not found" buttons {"OK"} cancel button 1 default button 1
--end try
There’s a lengthy chapter in Shane’s ASObjC on saving preferences, but my needs are very simple, and the following has always worked for me. However, it does require the Foundation Framework, which some might prefer to avoid. Error correction needs to be added to deal with the situation where the plist file or key do not exist.
use framework "Foundation"
use scripting additions
--write and read a path in a plist
writePlist("AutoFolder", "/Users/peavine/Documents/Auto/") --parameters are key name and value
# set autoPath to readPlist("AutoFolder") --parameter is key name
--write and read another path in the same plist
# writePlist("MedicalFolder", "/Users/peavine/Documents/Medical/")
# set medicalPath to readPlist("MedicalFolder") --parameter is key name
on readPlist(theKey)
set theDefaults to current application's NSUserDefaults's alloc()'s initWithSuiteName:"com.peavine.Test"
return theDefaults's objectForKey:theKey
end readPlist
on writePlist(theKey, theValue)
set theDefaults to current application's NSUserDefaults's alloc()'s initWithSuiteName:"com.peavine.Test"
theDefaults's setObject:theValue forKey:theKey
end writePlist
If I understand correctly, the author’s question is not about how to save and read a plist but rather where to store it.
I’ve tried using a specially designated folder for plist files in several locations. The locations that seem to be least problematic are:
In my home folder (eg ~/scriptPreferences), in the scripts folder where I keep all my Applescripts (eg ~/Documents/Scripts/scriptPreferences), in the Library (e.g. ~/Library/Preferences/scriptPreferences) or in the Library Scripts folder (~/Library/Scripts/scriptPreferences).
Whatever location is in use, I aways create the “scriptPreferences” folder, so that I know no other application will expect to use that folder.
I find it helpful to put a link to the “scriptPreferences” folder in the Finder’s Sidebar.
Thank you all for the responses, I have been tinkering with all of these and learning from them all, ASObjC is still beyond my skill I will admit that as I’m trying to get my head round AS as a first step in the hope of improving and using Swift as well as ASObjC some day.
Out of all of them peavines was the simplest to implement with using POSIX files and reading them back, to answer the questions that seem to have been floating about, it was not about the PLIST itself, I wanted to prompt a dialog box that would ask for a folder location (Select where to look for and store files), then to store that within the PLIST for simplicity of saving data together, then reading back the location in later runs so I’m not prompted multiple times for where the file is or other info.