Using AppleScript or JavaScript

Hazel rules can use AppleScript or JavaScript in either of two ways: to provide logic for a condition (the “Passes AppleScript” or “Passes JavaScript” attribute), or to perform an action when a rule matches (the “Run AppleScript” or “Run JavaScript” action). If you need to accomplish a task that Hazel’s conditions or actions alone don’t cover, AppleScript or JavaScript may provide a solution.

Note: Other than the fact that the two languages have different syntax, their overall capabilities within Hazel are essentially the same.

- AppleScript/JavaScript in conditions: AppleScript or JavaScript can also enable you to construct even more elaborate logical tests than Hazel natively offers with nested conditions . In addition, although Hazel can examine almost any attribute of a file or folder inside the watched folder, it can’t check the state of something elsewhere on your Mac—but AppleScript or JavaScript can. For example, you could write a script that checks for conditions such as the following:

⁃ The number of messages in my Inbox is greater than 100.

⁃ I have a certain URL open in a Safari tab.

⁃ The amount of free space on my disk is less than 10 GB.

⁃ I’m connected to the library’s free Wi-Fi network.

- AppleScript/JavaScript in actions: Similarly, while Hazel can move, copy, rename, and tag files and folders (among other actions), there are many tasks you might want to accomplish that Hazel can’t perform without a bit of help (in this case, from AppleScript or JavaScript). For example:

⁃ Sending an email message

⁃ Inserting a value into a specific cell in an Excel or Numbers spreadsheet

⁃ Opening a webpage

⁃ Performing mathematical calculations

Embedded vs. External AppleScripts/JavaScripts

Hazel can run AppleScripts or JavaScripts in either of two ways:

- Embedded: You can type (or paste) your script directly into your Hazel rule. To do this, choose “Passes AppleScript”/“Passes JavaScript” as the attribute for a condition, or “Run AppleScript”/“Run JavaScript” for an action, and then click the Edit Script icon. Enter your script in the popover that appears (as illustrated below), optionally click the Build button to verify your syntax, and click the X icon when you’re done. Embedded scripts are stored with your rules and therefore do not need to be transferred separately when copying, moving, sharing, or syncing your rules.

- External: If your AppleScript or JavaScript already exists as a standalone script ( .scpt or .js ) file, you can simply point Hazel to that script. To do this, choose “Passes AppleScript”/“Passes JavaScript” as the attribute for a condition, or “Run AppleScript”/“Run JavaScript” for an action, choose “Other” from the second pop-up menu, navigate to the file on disk, and click “Open.” Because external scripts are stored separately from Hazel rules, they must be transferred separately when copying, moving, sharing, or syncing rules to another Mac.

AppleScript/JavaScript in Rule Conditions

You can use AppleScript or JavaScript to supply custom logic for a rule condition. The primary requirement is that your script return true or false (as a value or a record/object—see “Returning Values from the Script” below).

Keep in mind that because rule conditions are evaluated frequently, you should make sure your script runs quickly. Time-consuming scripts will greatly decrease Hazel’s performance. In addition, the script must not modify any files or folders underneath the folder Hazel is monitoring, as that can result in a loop in which Hazel never stops processing the folder.

Passing Values to the Script

The variable theFile carries an alias to the file or folder currently being processed, which Hazel passes to the script.

For embedded scripts, no handler (AppleScript) or function (JavaScript) is needed. For external scripts, Hazel requires a handler (AppleScript) or function (JavaScript) called hazelMatchFile . The handler or function takes two arguments— theFile (as described just above) and inputAttributes , a list of input attribute values (see the section just ahead on Input Attributes ) .

Below is a template you can use for AppleScript:

on hazelMatchFile(theFile, inputAttributes)

-- Add your logic here.

-- 'theFile' is an alias to the file that matched.

-- 'inputAttributes' is an AppleScript list of the values of any attributes you told Hazel to pass in.

-- Be sure to return true or false (or optionally a record) to indicate whether the file passes this script.

end hazelMatchFile

And here is the corresponding JavaScript template:

function hazelMatchFile(theFile, inputAttributes)

{

-- Add your logic here.

-- 'theFile' is an alias to the file that matched.

-- 'inputAttributes' is a JavaScript array of the values of any attributes you told Hazel to pass in.

-- Be sure to return true or false (or optionally an object) to indicate whether the file passes this script

}

Returning Values from the Script

To tell Hazel whether the file or folder being processed matches your condition, have your script return true or false . For example:

-- your supporting code here

if (your logical test here)

return true

else

return false

end if

You can optionally return a record (AppleScript) or an object (JavaScript) instead of true or false . This method allows your script to send values back to Hazel. An AppleScript record looks something like this:

{key1:value1, key2:value2,…}

Currently, Hazel recognizes the following keys:

- hazelPassesScript: This is the same as returning true or false by itself: the hazelPassesScript key tells Hazel whether the file passes the script or not. For example, the following two AppleScript fragments do the same thing.

  Returning a true/false value (AppleScript):

  -- your supporting code here

  if (your logical test here)

  return true

  else

  return false

  end if

  Returning a record (AppleScript):

  -- your supporting code here

  if (your logical test here)

  return {hazelPassesScript:true}

  else

  return {hazelPassesScript:false}

  end if

- hazelOutputAttributes: A list (AppleScript) or array (JavaScript) of values for the custom attributes this script exports. The values must be in the order as you specify in the interface. See the section below on Custom Attributes . Here’s an example in AppleScript:

  -- your supporting code here

  set color to "blue"

  set flavor to "raspberry"

  return {hazelPassesScript:true, hazelOutputAttributes:(color,flavor)}

AppleScript/JavaScript in Rule Actions

You can also use an AppleScript or JavaScript as the “Run AppleScript”/“Run JavaScript” action.

Passing Values to the Script

The variable theFile carries an alias to the file or folder that matched the rule, which Hazel passes to the script.

For embedded scripts, no handler (AppleScript) or function (JavaScript) is needed. For external scripts, Hazel requires a handler (AppleScript) or function (JavaScript) called hazelProcessFile . The handler or function takes two arguments— theFile (as described just above) and inputAtttributes , a list/array of input attribute values (see the section just ahead on Input Attributes ) .

Below is a template you can use for AppleScript:

on hazelProcessFile(theFile, inputAttributes)

-- Add your logic here.

-- 'theFile' is an alias to the file that matched.

-- 'inputAttributes' is an AppleScript list of the values of any attributes you told Hazel to pass in.

-- Be sure to throw errors if you do not want Hazel to consider this action to have run successfully.

end hazelProcessFile

And here is the corresponding JavaScript template:

function hazelProcessFile(theFile, inputAttributes)

{

-- Add your logic here.

-- 'theFile' is an alias to the file that matched.

-- 'inputAttributes' is a JavaScript array of the values of any attributes you told Hazel to pass in.

-- Be sure to throw errors if you do not want Hazel to consider this action to have run successfully.

}

Returning Values from the Script

Your script can optionally return a record (AppleScript) or object (JavaScript). (If your script returns anything besides a record/object, that value is ignored.) This method allows your script to send values back to Hazel. An AppleScript record looks something like this:

{key1:value1, key2:value2,…}

Currently, Hazel recognizes the following keys (of which your record/object can contain any or all):

- hazelStop: If set to true, instructs Hazel to stop processing. Subsequent actions for this rule do not run, and Hazel considers the rule as a whole to have been unsuccessful. You can use this to stop a rule from continuing based on what button a user clicks in a dialog, for example. Hazel will not try to run this rule again.

- hazelSwitchFile: If set to a valid file, Hazel applies subsequent actions to that file. You can use this to retarget what file Hazel is acting on, such as switching to the parent folder. Or, if the script transforms the file into a new one, you can point this at the new file.

- hazelOutputAttributes : A list of values for the custom attributes this script exports (just as in rule conditions). The values must be in the order as you specify in the interface. See the section below on Custom Attributes .

So, an AppleScript’s return line may look something like this:

return {hazelStop:false, hazelSwitchFile:myFile, hazelOutputAttributes:(color,flavor)}

Reporting Errors

If you want the script to terminate un successfully, you must throw an error (AppleScript—see Apple’s page Working with Errors in the AppleScript Language Guide) or an exception (JavaScript). If the script encounters an error/exception, Hazel considers the rule as a whole to have been unsuccessful, and will try to run the rule again later. If the script does not throw an error/exception, Hazel considers the script to have been successful regardless of what is returned.

Input Attributes

An AppleScript or JavaScript can take a list of input attribute values as its second argument. This enables you to pass most of Hazel’s built-in attributes, as well as any Spotlight attribute or any custom attribute you defined earlier in the rule, to your script for further processing.

To specify these attributes for an external script, click the Edit Script icon in the AppleScript/JavaScript condition or action. For an embedded script, first click the Edit Script icon, and then click the Custom Tokens icon in the script editor popover.

On the left side of this popover, you can specify which attributes to pass into your script. To add an attribute, click the plus button and choose an attribute from the pop-up menu; repeat as needed to add more attributes. (The pop-up menu also includes any custom attributes that were defined earlier in the rule.)

The second ( inputAttributes ) argument that Hazel passes to your script automatically is a list of attributes, in the order they were defined in the popover above. So in this example, the first item in the list, item 1 of inputAttributes , is the attribute “Extension,” and the second item in the list, item 2 of inputAttributes , is the attribute “Kind.”

Therefore, to use these attributes in your script, you must assign variables to the relevant list/array items. Here’s how you might do it in AppleScript:

set width to item 1 of inputAttributes

set height to item 2 of inputAttributes

if width is equal to height then

return {hazelOutputAttributes:{"

Custom Attributes

Just as you can pass attributes into a script, you can also export custom attributes defined by your script. Once you’ve done so, those custom attributes become available for patterns in conditions or actions that after the condition or action in which you exported them.

To make these attributes accessible to your rule, from an external script, click the Edit Script icon in the AppleScript/JavaScript condition or action. For an embedded script, first click the Edit Script icon, and then click the Custom Tokens icon in the script editor popover.

On the right side of this popover, you can add the names of any custom attributes your script exports. To add an attribute, click the plus button and choose “New Text Attribute” or “New Date Attribute” from the pop-up menu. Select the newly added attribute, press Return, and type a name for it. Repeat the process as needed to add more attributes.

The order of the values you return in the script using the hazelOutputAttributes list should match the order of the attributes you define here. For example, in the image above, the custom attributes are “color” and “flavor,” so an AppleScript would need to contain something like this:

set color to "blue"

set flavor to "raspberry"

return {hazelOutputAttributes:(color,flavor)}

These values will then be substituted wherever the attribute is used (in conditions or actions later in the rule).

SEE ALSO

Using Automator

Using Shell Scripts