I’m trying to write preferences to a Plist which contain a space character. I’ve found a way to do this with the following code but it seems overly complex. Is there a simpler and more effective way of doing this?
property thePlist : (path to preferences folder as Unicode text) & "testapp.preferences"
property pathPlist : ""
property newString : ""
property charName : ""
tell application "Finder"
set pathPlist to POSIX path of thePlist
end tell
writeDefault("Name", "My Name")
display dialog readDefault("Name")
on readDefault(nameP)
set valueP to do shell script "defaults read " & pathPlist & space & nameP
set charName to every character of valueP
set newString to ""
repeat with charsRef in charName
if contents of charsRef is "_" then
set newString to newString & space
else
set newString to newString & charsRef
end if
end repeat
return newString
end readDefault
on writeDefault(nameP, valueP)
set charName to every character of valueP
set newString to ""
repeat with charsRef in charName
if contents of charsRef is space then
set newString to newString & "_"
else
set newString to newString & charsRef
end if
end repeat
set valueP to newString
do shell script "defaults write " & pathPlist & " " & nameP & " " & valueP
end writeDefault
“the simplest and most effective way” is to avoid spaces in the value
Alternatively you can use AppleScript’s text item delimiters to “convert” the string
property thePlist : (path to preferences folder as Unicode text) & "testapp.preferences"
property pathPlist : ""
set pathPlist to quoted form of POSIX path of thePlist
writeDefault("Name", "My Name")
display dialog readDefault("Name")
on readDefault(nameP)
set valueP to do shell script "defaults read " & pathPlist & space & nameP
return convertString(valueP, "_", space)
end readDefault
on writeDefault(nameP, valueP)
set valueP to convertString(valueP, space, "_")
do shell script "defaults write " & pathPlist & " " & nameP & " " & valueP
end writeDefault
on convertString(valueP, f, t)
set {TID, text item delimiters} to {text item delimiters, f}
set valueP to text items of valueP
set text item delimiters to t
set valueP to valueP as text
set text item delimiters to TID
return valueP
end convertString
It would be easier to use a subroutine with AppleScript’s text item delimiters and call it from your other subroutines. Something like this:
set t to "My Name"
set t to ReplaceText(t, space, "_")
--
on ReplaceText(t, s, r)
set utid to AppleScript's text item delimiters
set AppleScript's text item delimiters to s
set temp_list to text items of t
set AppleScript's text item delimiters to r
set temp_text to temp_list as string
set AppleScript's text item delimiters to utid
return temp_text
end ReplaceText
Edited: and btw, I pretty sure you can have spaces in keys. When you write to the plist use quotes:
do shell script “defaults write ~/Desktop/some.domain ‘some key’ ‘some string’”
Unfortunately it creates an error in ASS when one of the values is not a string but, for example, a boolean.
In AppleScript I can solve this easily by checking for class is string:
on ReplaceText(t, s, r)
if class of t is string then
set utid to AppleScript's text item delimiters
set AppleScript's text item delimiters to s
set temp_list to text items of t
set AppleScript's text item delimiters to r
set temp_text to temp_list as string
set AppleScript's text item delimiters to utid
return temp_text
else
return t
end if
end ReplaceText
If I run the same code in ASS this doesn’t work…
Oddly, if I ask for the class of a string value it returns with a number (display dialog class of t >> 1413830740). Unfortunately the following adaptation doesn’t work. The same is true for Stefan’s method. I can solve this in my app by separating the handling of the different classes of variables but am still curious if it can be solved more directly…
on ReplaceText(t, s, r)
if class of t is 1413830740 then
set utid to AppleScript's text item delimiters
set AppleScript's text item delimiters to s
set temp_list to text items of t
set AppleScript's text item delimiters to r
set temp_text to temp_list as string
set AppleScript's text item delimiters to utid
return temp_text
else
return t
end if
end ReplaceText
on ReplaceText(t, s, r)
set valClass to (class of t) as string
if valClass is "string" then
set utid to AppleScript's text item delimiters
set AppleScript's text item delimiters to s
set temp_list to text items of t
set AppleScript's text item delimiters to r
set temp_text to temp_list as string
set AppleScript's text item delimiters to utid
return temp_text
else
return t
end if
end ReplaceText