Given that the items to be sorted are all strings, they can be concatenated to form part of the JS code string:
{"skip item (22)", "item (33)", "item (100)", "item (011)", "item (skip item)"}
sort_(result) --> {"item (011)", "item (33)", "item (100)"}
to sort:(L as list)
set my text item delimiters to character id 0
run script "`" & L & "`.split('\\x00')
.filter(x => x.match(/[0-9]/) && !(
x.match(/skip item/i)))
.sort((a,b) => a.match(/[0-9]+/)
- b.match(/[0-9]+/));
" in "JavaScript"
end sort:
The key aspect of this script is the joining together of a list of a strings using a nul byte (character id 0
), as this wouldn’t ordinarily be a character that features in conventional strings: where they most often appear are as a marker delimiting special segments of a string in which specific byte positions or ranges are allocated for specific pieces of information. This is precisely the function they’ll be serving here, by delimiting the boundaries between distinct items in the original list, which will be passed into the JXA code as a single string.
Thus, after setting the text item delimiters
to character id 0
, it is safe to perform this operation with L
(the list of string items):
"`" & L & "`.split(..."
This implicitly coerces L
from a list
into a string
, performing serial concatenations of all of its items with the nul byte as described above. In the JavaScript code, this string is enclosed inside a pair of back-ticks, i.e. `․․․`
, which allows for the possibility of multi-line string items that might feature in the original list. However, it would require that any occurrence of a back-tick character in any of the string items be encoded before being sent through. If multi-line strings are not a consideration, it would be better to do this instead:
quoted form of (L as text) & ".split(..."
After passing the string representation of the original list through to the JXA environment, it needs to be converted from a string back into separate items housed within a native Array
-prototype object. The items were originally joined using the nul byte (character id 0
), so the string now needs to be split at every occurrence of a nul byte (which, in JavaScript, is expressed as the hexadecimal escaped form \x00
—this will need to be double-escaped, of course), i.e.:
"`" & L & "`.split('\\x00')
or, if preferred:
quoted form of (L as text) & ".split('\\x00')"
The remainder of the JXA code acts upon the array to sort it using the custom callback function, which is by no means the best example of such a function here, but it sufficiently handles and correctly sorts the test items supplied, returning a JavaScript array, which conveniently gets converted back into an AppleScript list upon completion of run script
command.