When writing AppleScript in Automator, what is the significance of "input" and "parameters"?

When one adds a "Run AppleScript" action to a file in Automator.app (e.g., a workflow, application, or service), the following default code is presented:

on run {input, parameters}

    (* Your script goes here *)

    return input
end run

What is the significance of input and parameters? That is to say,

  • Where does the AppleScript code get these variables from?

  • To where exactly does the AppleScript return the input to?

  • How might these variables be ideally employed in an AppleScript application/service? Examples are appreciated.


Solution 1:

I'll try to answer my own question, making use of the relevant documentation1 provided by @user3439894 in a comment on my question.

Where does the AppleScript code get these variables from?

input:

The input parameter contains (in most instances) the output of the previous action in the workflow.

The data type of input is list.

To display the contents of input in Automator's corresponding "Results" pane for that specific action, simply use:

return input

parameters:

The parameters parameter contains the settings made in the action’s user interface.

The data type of parameters is reco (i.e., a record object).

Here is an overview of the reco type2:

This type is used as the type of the properties property for the item class, and the type of the with properties parameters of the duplicate and make commands.

To display the contents of parameters in Automator's corresponding "Results" pane for that specific action, simply use:

return parameters

What, specifically, does parameters contain?

I was curious what exactly is meant by, "settings made in the action’s user interface," so I took a look at the contents of parameters. I learned that, unlike input, parameters only contains information about that specific action, not any information regarding the preceding action.

By using the following line of code,

display dialog length of parameters

I also discovered that the number of properties in parameters for a "Run AppleScript" action in Automator is three.

They are:

|temporary items path|:

where |temporary items path| is followed by the file path of the temporary folder created to store temporary data that may be created by the currently running "Run AppleScript" action. This folder is necessarily created upon run, even if the code does not create any temporary data. After the "Run AppleScript" action has completed, this folder and its parent folder are immediately deleted.

  • Note that |temporary items path| differs from (path to temporary items).

    • return POSIX path of (path to temporary items) produces:

      • "/private/var/folders/p9/q_5_fbld7qzdmz6htfqjcxhw0000gn/T/TemporaryItems/"

    • return |temporary items path| of parameters produces:

      • "/var/folders/p9/q_5_fbld7qzdmz6htfqjcxhw0000gn/T/1BD6446F-5501-42E5-A002-29588DFF8BD8/1/com.apple.Automator.RunScript"

    • While both folders reside within the "T" folder, the difference between these two folders is that the |temporary items path| folder, as well as its parent folder, are deleted upon completion of the "Run AppleScript" action (i.e., this folder is action-specific), while the path to temporary items folder is never deleted and can be viewed even when the AppleScript is not running.

ignoresInput:

where ignoresInput is either true or false, depending on whether the "Ignore this action's input" box found in the Options tab beneath that action in Automator is either ticked or unchecked.

source:

where source contains the unabridged AppleScript code of that "Run AppleScript" action.

How does one read the contents of parameters within an AppleScript?

Since the type of parameters is not list, one cannot simply:

set firstParameter to item 1 of parameters

as this will produce an error. But, you can convert parameters to a list object:

set parametersInListFormat to (parameters as list)

Then, you'll be able to execute something like this:

set individualItemFrom_parametersInListFormat to ""

repeat with individualItemFrom_parametersInListFormat in parametersInListFormat
    display dialog individualItemFrom_parametersInListFormat
end repeat

Alternatively, you can skip the conversion to a list and read the contents of parameters simply like so1:

set item1 to |temporary items path| of parameters
set item2 to |ignoresInput| of parameters
set item3 to source of parameters

To where exactly does the AppleScript return the input to?

The input of the current action is sent to the next action as that action's input.

More info on the return statement3:

A return statement exits a handler and optionally returns a specified value. Execution continues at the place in the script where the handler was called.

If a handler does not include a return statement, AppleScript returns the value returned by the last statement. If the last statement doesn’t return a value, AppleScript returns nothing.

When AppleScript has finished executing a handler (that is, when it executes a return statement or the last statement in the handler), it passes control to the place in the script immediately after the place where the handler was called. If a handler call is part of an expression, AppleScript uses the value returned by the handler to evaluate the expression.


How might these variables be ideally employed in an AppleScript application/service?

Now that I better understand the positional parameters of input and parameters, it is easier for me to imagine their practical value.

input:

The value of input is conspicuous and the possibilities for its implementation are immeasurable.

One very basic application would be if you want to pass a string of text that a user enters in a dialog box via an "Ask for Text" action to the next action, a "Run AppleScript" action that writes this string to file. Here is what this might look like:

Sample Automator Workflow


parameters:

Given that parameters is limited to that specific action and does not contain any data from previous actions, and the data that it does contain isn't necessarily relevant, it is much less useful and flexible than input. I can visualize the need for |temporary items path|, but I am unable to do so for the other two properties.

Here is an example of how one might need to reference |temporary items path| in their AppleScript:

  • Say that one wanted an Automator application to display to the user the dimensions of a web image.

    • The user could use |temporary items path| as a location to store that image, so that the code could operate on it. Then, upon completion, since the user does not need or want the image saved to disk, the AppleScript would automatically delete that image (or, more specifically, the AppleScript would automatically delete the folder that contains the folder that contains that image).

    • Here is how this might be implemented:

      on run {input, parameters}
      
          set theURLofImage to "https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/se/se-logo.png"
          set tempFolderThatIsAutomaticallyDeletedAfterRun to |temporary items path| of parameters
          set filename to "StackExchangeLogo.png"
          set fullFilepath to tempFolderThatIsAutomaticallyDeletedAfterRun & "/" & filename
      
      
      
          -- Saving image from internet to disk.
          -- From: http://stackoverflow.com/a/21491446/7138483    
          do shell script "curl -f " & theURLofImage & " -o " & fullFilepath
      
      
      
          -- Figuring out the dimensions of the saved image.
          -- From: https://www.macosxautomation.com/applescript/imageevents/01.html
          try
              tell application "Image Events"
                  launch
                  set this_image to open fullFilepath
                  -- Extract the properties record.
                  set the props_rec to the properties of this_image
                  -- Purge the open image data.
                  close this_image
                  -- Extract the property value from the record.
                  copy (dimensions of props_rec) to {x, y}
                  set the image_info to "Dimensions of " & filename & ": " & "" & x & " x " & y
              end tell
              display dialog image_info
          on error error_message
              display dialog error_message
          end try
      
          return input
      end run
      
  • Also, one might want to monitor the size of the |temporary items path| folder, to impose a limitation, so that if its size surpasses a certain value, an error is presented to the user.

In terms of how |ignoresInput| might be used, one could change the |ignoresInput| setting mid-code, with the following line:

set |ignoresInput| of parameters to true

One might want to arrange their code so that if the input meets or does not meet some condition, then the input should be ignored. For example:

if item 1 of input > 10 then
        set |ignoresInput| of parameters to true
end if

But, even if one did want to make sure that the input was only utilized if its contents met some condition, one could accomplish this same effect without having to read or alter the |ignoresInput| value; instead, one could simply declare their own boolean value for this purpose. So, I still think that the applicability of the |ignoresInput| parameter is questionable.

Similarly, I can't think of any particularly compelling reasons why one would need to read or modify the source parameter of their AppleScript while it runs.


What else?

One area of confusion for me still exists.

I still don't understand why Apple, in its documentation, advises against not returning anything in an AppleScript1:

The template code finally returns input as its output; your action should always return something as output, even if it what [sic] is given it as input.

What's the harm of removing the return statement from one's AppleScript, if one does not need it?

If someone familiar with AppleScript methodology can address this matter for me, please drop a comment.

It is possible that I am misinterpreting the sentence.

I am interpreting this sentence to mean:

"When writing your code, you should always make sure to include a return statement somewhere in your code."

But, the sentence could potentially mean instead:

"If you put a return statement in your code, that return statement is designed to always return something. If you don't assign anything to input, then the code will simply return the same input that it received."

The ambiguity revolves around the original intent of the word, should, and whether the should is meant to act as a recommendation for the user writing an AppleScript, or whether, by should, they meant will.


Sources for passages included in this answer:

1.Automator Programming Guide - The Structure of the on run Command Handler

2.Cocoa Scripting Guide - Built-in Support for Basic AppleScript Types

3.AppleScript Language Guide - Handler Reference