I’m having an issue figuring out how to set a position property from a text string.
I have a plist that I have written the position of a Finder window to. When writing to the plist I converted the position property (that looked something like {900,900}) to a string (which looks something like “{900,900}”) to save it as text to the plist item.
I now want to pull the text from that plist item to use it to change the position of a window. But since it’s a string I have to find a way to convert it to a property??? This the bit that’s confusing me. I understand that it’s not working because the string I’m getting from the plist has quotes around it and I have to somehow find a way to remove the quotes so that the position property sees it as a valid value.
So, I tried many variations for compiling the value for the position so that it doesn’t have quotes but no matter what I do I can’t seem to figure it out.
Example script:
set thePosition to "{900,900}" --this is how it is returned from the plist
tell application "Finder"
set theTarget to ":Users:Shared:" as alias
set newWindow to make new Finder window to theTarget
set position of newWindow to thePosition --this is where it gets hairy because I have a quoted form of a value for a property position. and it shouldn't be quoted. and it's not really a quoted form, it's just text.
end tell
Thanks for look and I look forward to reading your posts.
Applications that read and store positions in property lists generally use two functions, NSPointFromString() and NSStringFromPoint(). To use them in AppleScript you need a suitable use framework statement, like this:
use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use scripting additions
set thePosition to "{900, 900}"
set thePos to current application's NSPointFromString(thePosition)
--> {x:900.0, y:900.0}
The result is a record, so you can ask for “x of thePos” or “y of thePos”.
You needn’t have. Your solution was somewhat more efficient performancewise.
set thePosition to "{900,900}" --this is how it is returned from the plist
set o to (offset of "," in thePosition)
set x to (text 2 thru (o - 1) of thePosition) as integer
set y to (text (o + 1) thru -2 of thePosition) as integer
set thePosition to {x, y}
--> {900, 900}
Thanks for all of the support. I ended up using Nigel’s method since it was the easiest but I tested everyone’s to see how they worked. (and they did…)
I’m very interested in Shane’s thought of using foundation “Framework.” I’ve used this once before but on a recommendation and I didn’t understand why I was using but after Shane posting about it I’ve grown a bit more curious about it and did some digging to find that you can use regular expressions (something I’ve been hunting for and can’t believe I never found this). I will definitely do more digging on this front.
tell application id ("com.apple.Finder")
tell (make new Finder window to continue ¬
path to shared documents folder)
set the position to words of "{900, 900}"
end tell
activate
end tell
The key part to highlight is:
words of "{900, 900}"
which works well in this case because the parts of the string you want to extract are clearly word-like, whilst the parts that aren’t needed happen to be non-word characters. It returns a list containing the two words, namely {“900”, “900”}. Despite being a list of strings rather than a list of numbers, AppleScript thankfully has a small amount of intuition about what to do and, somewhere along the lines, turns what it receives into the appropriate data type (which is of a class called point whose superclass is a list, but specifically a list containing precisely two numerical values). Explicitly:
Technically it’s not actually a subclass of list, but a type of its own (historically based on a QuickDraw point), although it usually gets converted to a list. But it has some limitations lists don’t have: integers only, and a limited range of values.
An alternative which demonstrates the potential speed advantage of text item delimiters:
set thePosition to "{900,900}"
set text item delimiters to {"{", ",", "}"}
set thePosition to {text item 2 of thePosition as integer, text item 3 of thePosition as integer}
set text item delimiters to ""
thePosition --> {900, 900}
Script Geek timings of the scripts in this thread:
Unfortunately, the method suggested by the CK (words of …) does not work for text without a space (like the OP has). Otherwise, it would be more efficient than the Peavine script.
But here’s another script that is at least 2.5 times faster than the Peavine script:
set thePosition to "{900,900}"
set text item delimiters to {"{", ",", "}"}
tell thePosition to set thePosition to {text item 2, text item 3}
set text item delimiters to "" -- optional
thePosition as point -- coercion at once --> {900, 900}