AppleScript_ The Definitive Guide - Matt Neuburg [245]
end tell
end updateInterface
Now comes the clever part (Example 27-10). We want main.applescript to receive, among its parameters, the updated value of the example text field, as this is the lame command to be sent along to the Terminal. These parameters are supplied as a record whose items are based on the parameters listed in Info.plist. That's why we created the exampleText parameter in Info.plist—to make it appear in the parameters record. In addition, we have implemented the update parameters event handler, whose purpose is exactly to give us a chance to modify the values in the parameters record. This event handler will be called just before the workflow runs; the record containing the parameters arrives under the name theParameters. So we update the interface one last time, and then we modify the exampleText item of theParameters and hand back the modified record.
Example 27-10. Passing a parameter to main.applescript
on update parameters theObject parameters theParameters
updateInterface( )
set |exampleText| of theParameters to (content of text field "example" of theView)
return theParameters
end update parameters
Now we are ready for main.applescript (Example 27-11). This script contains just one event handler, the run handler , which has been created for us. It takes two parameters: input, which is the output from the previous step in the workflow, and parameters, which contains the bound values from the interface along with the modifications made in our update parameters handler. We assume that input is a list of aliases; we convert these aliases to POSIX pathnames. We extract the exampleText item from the parameters record; this is the lame command the user wants us to perform. Now we form a shell command that will loop through each POSIX pathname in turn and hand it to our lame command. (The shell is assumed to be bash.) We send this shell command to the Terminal for execution. The Terminal will execute this command asynchronously (we have specified that are ignoring application responses), so our handler will end immediately; we must return something to serve as our action's output, even though the action produces no meaningful output, so on the principle of doing least harm we return the same list we received as input.
Example 27-11. The action's main script
on run {input, parameters}
set myInput to (input as list)
set L to {}
repeat with anAlias in input
set end of L to quoted form of POSIX path of anAlias
end repeat
set text item delimiters to space
set theFiles to L as string
set s to "arr=(" & theFiles & "); "
set s to s & "for i in \"${arr[@]}\"; "
set s to s & "do echo /usr/local/bin/" & |exampleText| of parameters & space
set s to s & "\"$i\" \"${i%\\.*}.mp3\"; done"
ignoring application responses
tell application "Terminal" to do script s
end ignoring
return input
end run
The really cool part is that, because we have allowed it in Info.plist, the user can now choose "Show Action When Run" to display our action's interface in a workflow at runtime (Figure 27-8).
Figure 27-8. Choosing to show the action's interface at runtime
This gives the user maximum flexibility. Let's say, for example, that the user creates a workflow consisting of just our LAME Encode action, with "Show Action When Run" checked, and saves it as a Finder plug-in. This means that in the Finder this workflow will appear as a contextual menu item. The user can select some sound files in the Finder and, using the contextual menu, run this workflow. Our action's interface will appear as a dialog in the Finder! (See Figure 27-9.) The user can then specify the desired settings and continue with the workflow; the files will be converted to MP3 format, with feedback in the Terminal. This illustrates my point about an Automator action having just enough interface.
Figure 27-9. Our Automator action at work
Cocoa Scripting
Adding scriptability to an application that you write has been, in the past, not a task for the faint of heart. An 'aete'-format dictionary is difficult