Repeat with i in a plist array

Hi,
I’m trying to write a script to change one or two values of two or three array items in “com.apple.finder.plist”. There is a menu for the options and that’s all done. This is just a test script to change one value of one array item. There may be easier ways of doing it but It does work well:


set plistFolder to path to preferences folder as Unicode text
-- make a plist test file by duplicating "com.apple.finder.plist" 
tell application "Finder"
	set plistFile to (duplicate (plistFolder & "com.apple.finder.plist")) as string
end tell
display dialog plistFile -- just for testing
tell application "System Events"
	tell property list file plistFile
		tell contents
			set col_ExLVS_StVS to (property list item "columns" of property list item "ExtendedListViewSettings" of ¬
				property list item "StandardViewSettings")
			(*the property list item "columns" is an array of 10 items numbered from 0 to 9, where I need to change ¬
			the value of the array item with the "identifier" = "label". By default this is the item numbered 5 ¬
			but in fact being item 6 in the array. So I use (5 + 1) for clarity - at least for me*) ;)
			set col_id to the value of property list item "identifier" of property list item (5 + 1) of col_ExLVS_StVS
			set col_vis to the value of property list item "visible" of property list item (5 + 1) of col_ExLVS_StVS -- just for testing
			set the value of property list item "visible" of property list item (5 + 1) of col_ExLVS_StVS to false
			set col_vis_new to the value of property list item "visible" of property list item (5 + 1) of col_ExLVS_StVS -- just for testing
		end tell
	end tell
end tell
-- the following lines are just for testing
display dialog ((col_id as string) & ", " & col_vis as string) & ", " & col_vis_new as string
tell application "Finder" to open file plistFile -- open with the default app, in my case it is Xcode

However, I discovered that some :mad: users have changed the order of the array items, and thus hard coding the item number fails. What I need in this example is to cycle through the array items to find the item with the value of property list item “identifier” = “label”.
This is one of the many things I’ve tried and failed dismally and where I need your help disparately :frowning:


set plistFolder to path to preferences folder as Unicode text
-- make a plist test file by duplicating "com.apple.finder.plist" 
tell application "Finder"
	set plistFile to (duplicate (plistFolder & "com.apple.finder.plist")) as string
end tell
display dialog plistFile -- just for testing
tell application "System Events"
	tell property list file plistFile
		tell contents
			set col_ExLVS_StVS to (property list item "columns" of property list item "ExtendedListViewSettings" of property list item ¬
				"StandardViewSettings")
			repeat with i in col_ExLVS_StVS
				-- This fails with "label" highlighted & the error message "can't make item 1 of . to integer"
				if the value of property list item "identifier" of property list item i of col_ExLVS_StVS is "label" then
					set col_id to the value of property list item "identifier" of property list item i of col_ExLVS_StVS
					set col_vis to the value of property list item "visible" of property list item i of col_ExLVS_StVS -- just for testing
					set the value of property list item "visible" of property list item i of col_ExLVS_StVS to true
					set col_vis_new to the value of property list item "visible" of property list item i of col_ExLVS_StVS -- just for testing
				end if
			end repeat
		end tell
	end tell
end tell
-- the following lines are just for testing
display dialog ((col_id as string) & ", " & col_vis as string) & ", " & col_vis_new as string
tell application "Finder" to open file plistFile -- open with the default app, in my case it is Xcode

Please, can a charitable soul help me with this repeat coding. I’ll be forever grateful :slight_smile:

Just in case you have no direct access to the xml form of the “com.apple.finder.plist”, I include here the relevant part of the xml file.
I know, I know that this all is exceedingly long but I’m disparate :frowning:


set PLIST_File to "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
<dict>
	...
	<key>StandardViewSettings</key>
	<dict>
		<key>ExtendedListViewSettings</key>
		<dict>
			<key>calculateAllSizes</key>
			<true/>
			<key>columns</key>
			<array>
				<dict>
					<key>ascending</key>
					<true/>
					<key>identifier</key>
					<string>name</string>
					<key>visible</key>
					<true/>
					<key>width</key>
					<integer>300</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<false/>
					<key>identifier</key>
					<string>dateModified</string>
					<key>visible</key>
					<true/>
					<key>width</key>
					<integer>130</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<false/>
					<key>identifier</key>
					<string>dateCreated</string>
					<key>visible</key>
					<false/>
					<key>width</key>
					<integer>130</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<false/>
					<key>identifier</key>
					<string>size</string>
					<key>visible</key>
					<true/>
					<key>width</key>
					<integer>80</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<true/>
					<key>identifier</key>
					<string>kind</string>
					<key>visible</key>
					<false/>
					<key>width</key>
					<integer>150</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<true/>
					<key>identifier</key>
					<string>label</string>
					<key>visible</key>
					<true/>
					<key>width</key>
					<integer>70</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<true/>
					<key>identifier</key>
					<string>version</string>
					<key>visible</key>
					<false/>
					<key>width</key>
					<integer>70</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<true/>
					<key>identifier</key>
					<string>comments</string>
					<key>visible</key>
					<false/>
					<key>width</key>
					<integer>100</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<false/>
					<key>identifier</key>
					<string>dateLastOpened</string>
					<key>visible</key>
					<false/>
					<key>width</key>
					<integer>130</integer>
				</dict>
				<dict>
					<key>ascending</key>
					<false/>
					<key>identifier</key>
					<string>dateAdded</string>
					<key>visible</key>
					<false/>
					<key>width</key>
					<integer>130</integer>
				</dict>
			</array>
			<key>iconSize</key>
			<real>16</real>
			<key>scrollPositionX</key>
			<real>0.0</real>
			<key>scrollPositionY</key>
			<real>0.0</real>
			<key>showIconPreview</key>
			<true/>
			<key>sortColumn</key>
			<string>name</string>
			<key>textSize</key>
			<real>10</real>
			<key>useRelativeDates</key>
			<true/>
			<key>viewOptionsVersion</key>
			<integer>0</integer>
		</dict>
		<key>IconViewSettings</key>
		...
		<key>ListViewSettings</key>
		...
 		<key>SettingsType</key>
		<string>StandardViewSettings</string>
   </dict>
</plist>
"

Cheers,
Chris

You can use filters in property list suite so you don’t need repeat loops. Because my StandardViewSettings only contains dictionaries my example code shows it with another array.


set plistFolder to path to preferences folder as Unicode text
tell application "System Events"
	tell property list file (plistFolder & "com.apple.finder.plist")
		tell contents
			return every property list item of property list item "SlicesRootAttributes" whose value = "kMDItemKind"
		end tell
	end tell
end tell

Thanks DJ, but unfortunately the “com.apple.finder.plist” gets longer the longer it is used. On top of it, there are a great many keys with the same name and function nested under ‘root’ keys with different LIst View functions. Here is the list of ‘root’ keys from my survey of 31 Macs with ML 10.8.2:

“FK_StandardViewSettings”
“PackageViewSettings”
“SearchViewSettings”
“StandardViewSettings”
“TrashViewSettings”
Each of the 5 ‘root’ keys have two sub-keys relevant to List Views, each of different class:
“ExtendedListViewSettings”
“columns” ”> class = array of 10 items of class = dictionary, each with an identical group of 4 items
“ListViewSettings”
“columns” ”> class = dictionary of 9 items of class = dictionary

From all that, I need to change only the “ExtendedListViewSettings” and “ListViewSettings” keys of the “StandardViewSettings” key. I can’t touch the others.

Unfortunately, I’m not familiar with how to apply and use filters for deeply nested array items. Could you (or another charitable soul) help me with such an example?

All I’d need to work out the rest, is an example of the coding for changing the value of the “visibility” key corresponding to the “identifier” key value of “label” of the “columns” array of the “ExtendedListViewSettings” key of the “StandardViewSettings”.

Cheers,
Chris

Of course I can/will, something like this:

set plistFolder to path to preferences folder as Unicode text
tell application "System Events"
   tell property list file (plistFolder & "com.apple.finder.plist")
       tell contents
           return every property list item of property list item "columns" of property list item "ExtendedListViewSettings" of property list item "StandardViewSettings" whose value = "label"
       end tell
   end tell
end tell

p.s. Because my property list file contains dictionaries I can’t test it.

Hi DJ,
Yesterday, I sent you a more detailed email vie the MacScripter emailer. Did you receive it?
I’m trying to send you a copy of my test file “com.apple.finder.2.plist”

The script above doesn’t seem to work when arrays are involved. It simply returns an empty list.
I think this is because the property list item “column” doesn’t have a property list item whose value is “label”.
The property list item “column” has the class = array and the value = 10 ordered objects, numbered from 0 to 9.
Each array object has the class = dictionary and the value = 4 key/value pairs; one of the 4 keys is “identities” and the value = the name of a list view column ”> we need to find the array object with the “identities” value = “label”.
Once the correct array object is found, return all 4 key/value pairs.

This code from my first script works because I know the specific array object number, which contains the property list item “identifier” with the value ‘label’:


set plistFolder to path to preferences folder as Unicode text
set plisFile to plistFolder & "com.apple.finder.plist"
tell application "System Events"
	tell property list file plistFile
		tell contents
			set col_ExLVS_StVS to (property list item "columns" of property list item "ExtendedListViewSettings" of property list item "StandardViewSettings")
			set the value of property list item "visible" of property list item (5 + 1) of col_ExLVS_StVS to false
		end tell
	end tell
end tell

As I said earlier, the array order can change and thus hard coding a number is not an option.

Unfortunately, :frowning: I can’t work out how to convert that to a filter to check each sequentially numbered array object to find the one containing the item “identities” with the value “label” and then return all properties found in that array object. Help is badly needed.

Cheers, Chris

I just had one of those light bulb flash moments from cartoons :D.
This script does work with the arrays without knowing the array item number :cool:


set plistFolder to path to preferences folder as Unicode text
-- make a plist test file by duplicating "com.apple.finder.plist" 
tell application "Finder"
	set plistFile to (duplicate (plistFolder & "com.apple.finder.plist")) as string
end tell
tell application "System Events"
	tell property list file plistFile
		tell contents
			set col_ExLVS_StVS to (property list item "columns" of property list item "ExtendedListViewSettings" of property list item "StandardViewSettings")
			repeat with i from 1 to 10
				set array_i to i
				set col_id to the value of property list item "identifier" of property list item array_i of col_ExLVS_StVS
				if col_id is "label" then
					set col_vis to the value of property list item "visible" of property list item array_i of col_ExLVS_StVS -- just for testing
					set the value of property list item "visible" of property list item array_i of col_ExLVS_StVS to false
					set col_vis_new to the value of property list item "visible" of property list item array_i of col_ExLVS_StVS -- just for testing
					exit repeat
				end if
			end repeat
		end tell
	end tell
end tell
-- the following lines are just for testing
display dialog ("array item " & i & ", " & (col_id as string) & ", " & col_vis as string) & ", " & col_vis_new as string
tell application "Finder" to open file plistFile -- open with the default app, in my case it is Xcode

I’ll use this for the time being,
DJ, thanks for your help but, I’d still love to learn how to do this using filters, if you find a solution for dealing with arrays.

Cheers,
Chris

Great that you’ve solved it. For the record, I’ve replied to your mail