As I see, Standard Additions’s choose from list has other one lake too. The following script instead of choose 2 items “test2”, selects only the 1st “test2”:
set aList to {"test1", "test2", "test3", "test2"}
set anItem to (choose from list aList default items {"test2"}) as string
Up to a point, that’s right, because only a single selection’s allowed unless you specify ‘with multiple selections allowed’. But even then, and with two "test2"s in the default items, only the first is selected.
use scripting additions
use script "Myriad Tables Lib" version "1.0.10"
set aList to {"item 1", "item 2", "Item 3", "item 2"}
set theResult to display table with data aList initially selected rows {2, 4} with multiple selections allowed
return rows selected of theResult
Myriad Tables Lib is great, I’m using it for some things.
But if you want a clunky workaround in pure Applescript for some reason, I came across this issue a long time ago (before Myriad Tables) and I solved it this way:
set originalData to {"item 1", "item 2", "Item 3", "item 2", "item 6", "item 7"}
set displayData to {}
set choiceCount to count of originalData
repeat with i from 1 to choiceCount
set newEntry to "#" & i & ". " & item i of originalData
set displayData to displayData & newEntry
end repeat
set resultChoice to item 1 of (choose from list displayData)
repeat with i from 1 to choiceCount
if item i of displayData is resultChoice then set resultIndex to i
end repeat
return resultIndex
Here’s a variation of t.spoon’s workaround if you want the items to be displayed in the dialog window without an entry number prefix. The “trick” is to mark each entry’s index in the dialog window with a prefix string of zero-width space characters equal in number to the entry’s index in the list (and then to return the original, not the prefixed, versions of the chosen items.) All instances of a default item will be pre-selected, unlike choose from list’s current behavior. If multiple selections are allowed, results will be returned as lists; otherwise, results will be returned as non-list values. If an empty selection is allowed and no selection is made, results will be returned as empty lists.
set aList to {"item 1", "item 2", "Item 3", "item 2", "item 6", "", "item 7"}
set defaultItems to {"item 2"}
set multipleSelectionsAllowed to true -- or false
set emptySelectionAllowed to true -- or false
set zeroWidthSpace to character id 8203
tell defaultItems to if its class ≠ list then set defaultItems to {it}
set currPrefix to ""
set {modifiedList, modifiedDefaultItems} to {{}, {}}
repeat with currItem in aList
set currPrefix to currPrefix & zeroWidthSpace
tell (currPrefix & currItem)
set end of modifiedList to it
if ({currItem's contents} is in defaultItems) and (multipleSelectionsAllowed or (modifiedDefaultItems = {})) then set end of modifiedDefaultItems to it
end tell
end repeat
set modifiedChosenItems to (choose from list modifiedList default items modifiedDefaultItems multiple selections allowed multipleSelectionsAllowed empty selection allowed emptySelectionAllowed)
if modifiedChosenItems = false then error number -128
set {chosenItems, chosenIndices} to {{}, {}}
repeat with currModifiedChosenItem in modifiedChosenItems
set i to 0
repeat with currId in (get currModifiedChosenItem's id)
if currId's contents ≠ 8203 then exit repeat
set i to i + 1
end repeat
set {end of chosenItems, end of chosenIndices} to {aList's item i, i}
end repeat
if not multipleSelectionsAllowed and (chosenItems's length = 1) then set {chosenItems, chosenIndices} to {chosenItems's item 1, chosenIndices's item 1}
return {chosenItems, chosenIndices}
— as long as none of the original items begin with that character themselves, of course.
It won’t make a lot of difference, but you could perhaps lose the inner repeat towards the end by using TIDs:
-- (Existing script up to 'if modifiedChosenItems = false then error number -128')
set {chosenItems, chosenIndices} to {{}, {}}
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to (character id 8203)
repeat with currModifiedChosenItem in modifiedChosenItems
set i to (count currModifiedChosenItem) - (count currModifiedChosenItem's last text item)
set {end of chosenItems, end of chosenIndices} to {aList's item i, i}
end repeat
set AppleScript's text item delimiters to astid
if not multipleSelectionsAllowed and (chosenItems's length = 1) then set {chosenItems, chosenIndices} to {chosenItems's item 1, chosenIndices's item 1}
return {chosenItems, chosenIndices}
That’s a nice, compact way of counting the number of leading marker characters. Thanks. (It too depends on the zero-width space character not being present in the original list items.)
I wrote my own, simpler version, using ideas from bmose and t.spoon. I believe, it is little more clear and little better:
set aList to {"test1", "test2", "test3", "test2", "", 5}
set {zeroWidthSpace, modifList, indexesList, chosenItemsList} to {"", {}, {}, {}}
repeat with anItem in aList
set zeroWidthSpace to zeroWidthSpace & character id 8203
set end of modifList to zeroWidthSpace & anItem
end repeat
set aChoice to (choose from list modifList default items {modifList's item 2, modifList's item 4} ¬
with multiple selections allowed and empty selection allowed)
if aChoice is false then return
repeat with i from 1 to count of aChoice
set {anItem, anIndex} to {item i of aChoice, 1}
set aLength to count of anItem
repeat until (anIndex = aLength) or (character (anIndex + 1) of anItem is not (character id 8203))
set anIndex to anIndex + 1
end repeat
set end of indexesList to anIndex
set end of chosenItemsList to item anIndex of aList
end repeat
return {chosenItemsList, indexesList}
Modified version allowing empty string in the original list.
set aList to {"test1", "test2", "test3", "test2", "", 5}
set {zeroWidthSpace, modifList, indexesList, chosenItemsList} to {"", {}, {}, {}}
repeat with anItem in aList
set zeroWidthSpace to zeroWidthSpace & character id 8203
set end of modifList to zeroWidthSpace & character id 8204 & anItem
end repeat
set aChoice to (choose from list modifList default items {modifList's item 2, modifList's item 4} ¬
with multiple selections allowed)
if aChoice is false then return
repeat with anItem in aChoice
set anIndex to (offset of character id 8204 in anItem) - 1
set end of indexesList to anIndex
set end of chosenItemsList to item anIndex of aList
end repeat
return {chosenItemsList, indexesList}
I removed " and empty selection allowed" because, as far as I know, as there is a default selection we can’t select nothing.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mercredi 4 décembre 2019 12:03:18
set aList to {"test1", "test2", "test3", "test2", "", 5}
set {zeroWidthSpace, modifList, indexesList, chosenItemsList} to {"", {}, {}, {}}
repeat with anItem in aList
set zeroWidthSpace to zeroWidthSpace & character id 8203
set end of modifList to zeroWidthSpace & character id 8204 & anItem
end repeat
set tag to character id 8203 & character id 8204
set aChoice to (choose from list modifList default items {modifList's item 2, modifList's item 4} ¬
with multiple selections allowed)
if aChoice is false then return
repeat with anItem in aChoice
set anIndex to offset of tag in anItem
set end of indexesList to anIndex
set end of chosenItemsList to item anIndex of aList # Corrected according to Nigel Garvey's comment
end repeat
return {chosenItemsList, indexesList}
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mercredi 4 décembre 2019 16:37:51
Using two separate zero-width characters not only makes the extraction of list item indices straightforward but also allows a list item to begin with a zero-width space character (rare though that case may be!) and yet still be indexed properly.
Somebody wrote this (over ten years or more before ?). It is very simple one.
set aList to {"red", "blue", "green", "white"}
set aMes to "Select Color"
set aRes to retItemFromListByItemNo(aList, aMes) of me
on retItemFromListByItemNo(aList, aMes)
set aRes to choose from list aList with prompt aMes
if aRes = false then return 0
set aRes to contents of item 1 of aRes
set hitNum to 1
repeat with i in aList
set j to contents of i
if j is equal to aRes then
exit repeat
end if
set hitNum to hitNum + 1
end repeat
return hitNum
end retItemFromListByItemNo
“return type” parameter have two enums. " item contents" returns the actual data item like {“Red”, “Yellow”}. “item numbers” returns the item index like {1,2}.
As I see, it defers from Shane’s choose from list, since it is segmented choose from list.
Both of you are the best as you take AppleScript automation to the next, highest level. I love to delve into your solutions, they are better than any programming book.