Your prescription for increased productivity and profitability
In creating a script for InDesign that will require the user to choose an item from a list, a number of methods an be used in AppleScript. The demonstration script below has CHOOSE FROM LIST as part of the getNameFromList() handler. The script assumes that document presets have been created with a Web or Mobile label if not print intent. (See previous blog post.)
set presetPrompt to "Select preset for new document" try set myList to getPresets(1) -- set presetName to getNameFromList(myList, presetPrompt) on error errStr display alert ("Error: " & errStr) end try (*Returns list of names for document presets having intnet designated by list index*) on getPresets(intentIndex) tell application "Adobe InDesign CC 2019" if intentIndex is 1 then set fullList to (name of document presets where intent is print intent) set fullList to rest of fullList else if intentIndex is 2 then set fullList to (name of document presets where label is "Web") else if intentIndex is 3 then set fullList to (name of document presets where label is "Mobile") end if end tell return fullList end getPresets (*dialog for user to select item from list*) on getNameFromList(theList, thePrompt) set userChoice to choose from list theList with prompt thePrompt if userChoice is not false then return item 1 of userChoice else error "User cancelled" end if end getNameFromList
For AppleScript a collection of items is represented by a list. You might want to think of a list as a box: the box can be empty, or it can contain any number of items. An empty list is represented by a pair of curly brackets. In InDesign, if no selection is made in the open document, the following will return an empty list.
tell application "Adobe InDesign CC 2019" set mySelection to selection end tell mySelection --result is {}
A script creates a list by assigning a variable to a pair of empty braces.
set myList to {}
A script can create a list with any number of items by placing the items, separated by commas within the curly brackets. In AppleScript these items can be of different types.
set myList to {1, 2, "cherry", "vanilla", 1.4} set myClass to class of item 2 of myList --result is integer
Try this code with different values for the item index number.
A script can add items to a list by using the syntax end.
set myList to {} set end of myList to "chocolate" set end of myList to "vanilla" myList --result is {"chocolate", "vanila"}
You can also use beginning to add an item to a list:
set myList to {} set end of myList to "chocolate" set beginning of myList to "vanilla" myList --result is {"vanilla", "chocolate"}
As in above, using end of or beginning of is the most efficient way to add an item to a list You can also add an item to a list using the concatenation operator (&).
set myList to {"cherry"} set myList to myList & {"chocolate"} myList --result is {"cherry", "chocolate"}
Another way of adding items to a list is to use the concatenation (&) operator.
set myList to {} set mList to myList & 123 --result is {123}
Interestingly, the concatenation operation can be used to add a number of items to a list.
set myList to {} set mList to myList & 1 & 2 & 3 --result is {1, 2, 3}
The concatenation operator can even be used to create a list with list items.
set myList to 1 & 2 & 3 myList --result is {1,2,3}
A list can contain another list. This is known as a list of lists. To add a list to another list, use end or beginning. In the following the list {4, 5, 6} is added as a list.
set myList to {1, 2, 3} set end of myList to {4, 5, 6} myList --result is {1, 2, 3, {4, 5, 6}}
Be careful. When using the concatenation operator to add a list to a list, the items in the added list are added as items, not as a list.
set myList to {1, 2, 3} set myList to myList & {4, 5, 6} myList --result is {1, 2 ,3, 4, 5, 6}
The individual items in a list are defined by their position within the list.
set myList to {"cherry", "vanilla", "chocolate"} set myChoice to item 3 of myList myChoice --result is "chocolate"
Notice that item positions in a list (indexes) begins with 1, not 0 as in other languages such as JavaScript.
In AppleScript other references can be used to target items within the list. These include: last, first, middle, and some.: For the myChoice variable in the code above, instead of item 3 try one of the following:
first item of myList --result is "cherry"
last item of myList --result is "chocolate"
middle item of myList --result is "vanilla"
It is well to note that if there is an even number of items in the list “middle’ will return the item to the left of center.
set myList to {"cherry", "vanilla", "caramel", "chocolate"} set myChoice to middle item of myList myChoice--returns "vanilla"
And, just for fun (or randomness), a script can use some to return an item from a list.
set myList to {"cherry", "vanilla", "caramel", "chocolate"} set myChoice to some item of myList myChoice --result is any item in the list
Finally, you can get a range of items in a list by using the thru operator.
set myList to {"cherry", "vanilla", "caramel", "chocolate"} set myItems to items 2 thru 3 of myList myItems --result is { "vanilla", "caramel"}
Using the range technique shown above is the principal way to remove an item, or items, from a list.
set myList to {"cherry", "vanilla", "caramel", "chocolate", "mint"} set myList to items 1 thru 2 of myList & items 4 thru (length of myList) of myList myList --result is {"cherry", "vanilla", "chocolate", "mint"}
To remove items from the end of a list, you can use a negative index value with the thru operator.
set myList to {"cherry", "vanilla", "caramel", "chocolate", "mint"} set myList to items 1 thru -2 of myList --result is {"cherry" "vanilla", "caramel", "chocolate"}
To remove the first item from a list, rest can be used.
set myList to {"cherry", "vanilla", "caramel", "chocolate", "mint"} set myList to rest of myList --result is {"vanilla", "caramel", "chocolate", "mint"}
The number of items in a list is returned using the length property of the list.
set myList to {"cherry", "vanilla", "caramel", "chocolate", "mint"} set myNumber to length of myList --result is 5
The rest of a list is all of its items with exception of the first item.
set myList to {"cherry", "vanilla", "caramel", "chocolate", "mint"} set myList to rest of myList myList --result is {"vanilla", "caramel", "chocolate", "mint"}
In addition to properties length and rest, reverse returns the list in reverse order (what else?).
set myList to {1, 3, 5, 7, 9} set myList to reverse of myList myList --result is {9, 7, 5, 3, 1}
To find an item within a list a repeat with is often used.
set myChoice to "chocolate" set myList to {"cherry", "vanilla", "caramel", "chocolate", "mint"} repeat with i from 1 to length of myList if item i of myList is myChoice then set myItem to i exit repeat end if end repeat myChoice & " is item " & myItem & " of the list." --result is "chocolate is item 4 of the list"
Instead, the rest property of a list can be used. It is most advantageous when doing a search within a very long list. The reason is that the list to parse becomes shorter with each iteration.
set myChoice to "chocolate" set myCount to 0 set myList to {"cherry", "vanilla", "caramel", "chocolate", "mint"} repeat while myList is not {} set thisItem to item 1 of myList if thisItem is myChoice then set thisCount to myCount + 1 exit repeat end if set myCount to myCount + 1 set myList to rest of myList end repeat set myString to "" & myChoice & " is item " & thisCount & " of the list items" myString --result is "chocolate is item 4 of the list items"
Working with items in a list can pose a few problems when working with InDesign. For the following it will be assumed that a selected text frame in InDesign’s open document has a number of paragraphs the first three of which begin with the words “One”, “Two”, and “Three” respectively. A script to change the first letter of the sequential paragraphs will demonstrate.
In reading through the code below, one would think that the script would work.
tell application "Adobe InDesign CC 2019" set selList to selection if selList is not {} and class of item 1 of selList is text frame then set frameRef to item 1 of selList tell frameRef set theCount to count of paragraphs repeat with i from 1 to theCount set thisParagraph to paragraph i set point size of character 1 of word 1 of thisParagraph to "24 pt" end repeat end tell end if end tell selList --Will return value of selList or force error
Instead, the result of the error reads “Can’t set size of \”O\” to 24…
The problem is the value of the variable thisParagraph is the text of the paragraph, not a reference to the paragraph object.
To fix this, change the offending line (the one that establishes the value of the variable thisParagraph) to read:
set thisParagraph to (a reference to paragraph i)
Run the script. The first character of each paragraph is changed without an error.
Alternatively, you could write the script to repeat the list using a reference to the item itself:
tell application "Adobe InDesign CC 2019" set selList to selection if selList is not {} and class of item 1 of selList is text frame then set frameRef to item 1 of selList tell frameRef set theList to a reference to every paragraph repeat with eachItem in theList set point size of character 1 of eachItem to "24 pt" end repeat end tell end if end tell
In this example, the value of the variable eachItem takes on the value of the next item in the list until the list is empty.
Understanding how to work with lists is fundamental with AppleScript as it provides a wealth of ways to automate objects in the operating system as well as items in applications such as Adobe InDesign. Next week, we dive a little deeper into working with lists and lists of lists.