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 ) 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 external AppleScripts:
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 external AppleScripts:
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 successful. 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.
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 “Pixel width,” and the second item in the list, item 2 of inputAttributes , is the attribute “Pixel height.”
Therefore, to use these attributes in your script, you can 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
—- Use width and height as needed
if width is equal to height then
…
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