Hi,
I understand that AppleScript doesn’t provide a direct means of getting the names of a record’s properties. I put together a handler that gets the job done, but it’s long and somewhat sluggish. I suspect the topic might have come up before, but I couldn’t find anything in the forums. Any suggestions on a more elegant solution to this problem would be much appreciated.
bmose
get_record_property_names({a:1, bb:"b", ccc:true, dddd:{1, 2, {1, 2, {1, 2}}}, eeeee:{f:{1, 2}, g:{h:1, i:2}}}) --> {"a","bb","ccc","dddd","eeeee"}
on get_record_property_names(the_record)
-- Initialize the result variable to an empty list
set names_of_record_properties to {}
-- Exit with an error if input parameter is not a record
if class of the_record is not record then error "Not a record"
try
-- Force the error message "Can't make {...record property names and values...} into type null."
the_record as null
on error error_message
-- Capture "...record property names and values..." from the error message
set current_string to text 13 thru -18 of error_message
end try
-- Parse the "...record property names and values..." string and extract its property names
repeat until current_string is ""
-- Capture the next property name (text up to but not including the first ":")
set name_of_current_record_property to text 1 thru ((offset of ":" in current_string) - 1) of current_string
-- Deblank the captured property name
repeat while name_of_current_record_property starts with space
set name_of_current_record_property to text 2 thru -1 of name_of_current_record_property
end repeat
repeat while name_of_current_record_property ends with space
set name_of_current_record_property to text 1 thru -2 of name_of_current_record_property
end repeat
-- Add the property name to the result list
set end of names_of_record_properties to name_of_current_record_property
try
-- Break the "...record property names and values..." string into fragments at each comma in the string (one of which will represent the end of the current property name:property value combination)
set {astid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ","}
set current_string_fragments to text items of current_string
set current_record_item_found to false
repeat with i from 1 to length of current_string_fragments
try
-- Use a "run script" macro to reconstruct progressively larger fragments of "...record property names and values..." from left to right until a valid property name:property value combination corresponding to the just saved property name is created
set s to "on run {the_record}"
set s to s & return & "if {" & ((items 1 thru i of current_string_fragments) as string) & "}'s " & name_of_current_record_property & " is the_record's " & name_of_current_record_property & " then return true"
set s to s & return & "return false"
set s to s & return & "end run"
set current_record_item_found to run script s with parameters {the_record}
end try
-- As soon as the appropriate property name:property value combination is created, exit the repeat loop
if current_record_item_found then exit repeat
end repeat
if current_record_item_found then
if i < (length of current_string_fragments) then
-- If there are more property name:property value entries left in the record (other than the current entry), reset the "...record property names and values..." string to just those remaining entries
set current_string to (items (i + 1) thru -1 of current_string_fragments) as string
else
-- Otherwise, quit processing the string
set current_string to ""
end if
set AppleScript's text item delimiters to astid
else
error
end if
on error
set AppleScript's text item delimiters to astid
-- Capture any errors occurring during extraction of property names
error "Problem parsing record names. The following residual string was not processed:" & return & return & current_string
end try
end repeat
-- Return the record's property names as a list of strings
return names_of_record_properties
end get_record_property_names