How can I loop through the results of an AppleScript to find the variables that have a boolean value of 1?
I'm using Applescript with Pashua: Native macOS dialogs for scripting languages. I'm using checkboxes in the dialog box, and I can get the output of those as a result in the script editor, i.e., when cat
and cat 2
are checked, I get:
{cat:"1", cat4:"0", cat2:"1", cat3:"0"}
But what I need to do is loop through the checkboxes to find only those that have been toggled to 1, and I don't know where to start.
How can I loop through all categories - cat, cat2, cat3, cat4, etc. - in the result, find only those that are boolean 1, and then output those in one variable, separated by a comma.
I.e. using this script result
{cat:"1", cat4:"0", cat2:"1", cat3:"0"}
how can I loop through and get a variable that has a value of:
cat1, cat2
This is the script that generates the dialog box and the checkboxes:
tell application "Finder" to set thisFolder to (container of (path to me)) as text -- get the folder path
try
set thePath to alias (thisFolder & "Pashua.scpt")
set pashuaBinding to load script thePath
tell pashuaBinding
try
set dialogConfiguration to my getDialogConfiguration() -- configure the dialog
set dialogResult to showDialog(dialogConfiguration, "") -- show the dialog
end try
end tell
end try
on getDialogConfiguration() -- return the configuration string
return "
# Add category checkboxes
txtcats.type = text
txtcats.default = Categories
cat.rely = -18
cat.type = checkbox
cat.label = Category 1
cat2.type = checkbox
cat2.label = Category 2
cat3.type = checkbox
cat3.label = Category 3
cat4.type = checkbox
cat4.label = Category 4
"
end getDialogConfiguration
AppleScript records
are a poorly implemented construct, appearing to emulate what is referred to in some languages as an associative array, but doing a half-arsed job of it.
What are referred to as properties
in a record
, i.e. cat
, cat4
, etc. in your case, aren't things that can be referenced indirectly, therefore it isn't possible to read them as values and store them in a variable through which you could access the record item associated with that property.
In other words, one cannot do any of these:
set R to {cat:"1", cat4:"0", cat2:"1", cat3:"0"}
set item_name to cat # Error: the variable cat is not defined
return item_name of R
set item_name to "cat"
return item_name of R # Error: can't get item_name of {cat:"1", ...}
set item_name to a reference to cat
return item_name of R # [ As above ]
You can, of course, do this:
set item_value to cat of R
but that requires you already hold an awareness of the property
name "cat"
.
The simplest way to get around this problem is to cast the AppleScript record
into a different data type of another language that gives you full access to the associative relationship between the paired entries.
Your two options are Objective-C , and JavaScript:
AppleScript-ObjC
AppleScript records
bridge to what Objective-C and many other languages refer to as dictionaries
, which are—for all intents and purposes to us—the same as associative arrays (they differ under the hood in how data is stored and accessed, but this makes little difference to us).
We need to transform the AppleScript record
into an Objective-C NSDictionary
class object, then we can search through its keys (what was referred to above as properties) and values indiscriminately:
use framework "Foundation"
property this : a reference to the current application
property NSDictionary : a reference to NSDictionary of this
set R to {cat:"1", cat4:"0", cat2:"1", cat3:"0"} # Swap in the return value of your script
set D to NSDictionary's dictionaryWithDictionary:R
return (D's allKeysForObject:"1") as list
--> {"cat", "cat2"}
If you want to stick this in a function to use to search for some arbitrary value in some arbitrary record
, then:
on keys from R as record given data:V : missing value
local R, V
script
use framework "Foundation"
property this : a reference to current application
property nil : a reference to missing value
property dict : a reference to NSDictionary of this
property object : R
property value : V
on fn()
tell (dict's dictionaryWithDictionary:object)
if value = nil then return ¬
allKeys() as list
allKeysForObject_(value) as list
end tell
end fn
end script
result's fn()
end keys
Then:
return the keys from {cat:"1", cat4:"0", cat2:"1", cat3:"0"}
will return {"cat", "cat4", "cat2", "cat3" }
, i.e. all the keys, and
return the keys from {cat:"1", cat4:"0", cat2:"1", cat3:"0"} given data:"0"
will return only the ones who are associated with the value "0"
.