Blocks
Blocks
Blocks are the foundation of Zazu plugins and are defined in the zazu.json
file in each plugin. Each one represents a step to be completed. Along the way,
each block passes a value from one block to the next. If they fork, each block
will get their own copy of the current value.
Blocks link to other blocks via connections. Once a blocks gets executed,
it’s connections will get executed after. You can link to both output and input
blocks. All blocks have connections unless the block explicitly mentions
otherwise.
All blocks can have the following properties:
idmixed: Unique identifier of the block, used for logging and connections.connectionsmixed[]: Blocks to execute if one of the results are chosen.typestring: Name of the block you wish to use.
Each unique block type can have it’s own properties, listed below with their descriptions.
If a block is missing a required argument, you will see an error in the Plugin
Debugger or in the logs in ~/.zazu/log/.
External Blocks
External blocks are ways of accessing Zazu plugins without using the Zazu search bar. These types of blocks are unique because they cannot be used as a connection.
{
"blocks": {
"external": [
// trigger blocks
]
}
}
Hotkey
When a user hits a specific set of keys, it can activate an input or output block of your plugin.
A hotkey can be overwritten in the user’s local configuration file.
hotkeystring: Key combination to use. [docs]
In this example you have a hotkey block named Inverse, when somebody hits that
hotkey it goes to the next block PlayPandora which is most likely a user
script.
[{
"id": "Inverse",
"type": "Hotkey",
"hotkey": "cmd+shift+o",
"connections": ["PlayPandora"]
}]
Service Script
Often a plugin will need to run jobs in the background for things like indexing files or checking the active application. This block allows you to run your script on a set interval. Your service is not guaranteed to run on the given interval.
NOTICE: The connections on this block will be ignored.
Variables defined in the configuration will be used as environment variables passed into the script.
intervalint: Milliseconds between the time we run the script. Must be>=100.scriptstring: Path to the node file to execute.
[{
"id": "Cache Packages",
"type": "ServiceScript",
"script": "cachePackages.js",
"interval": 100
}]
Below is an example of the Cache Packages block we defined earlier. It fetches
a JSON file from the internet and
store it in the plugin directory under the name packages.json.
The pluginContext is provided when your plugin is loaded, and the returned
function will be called as needed.
// cachePackages.js
const fs = require('fs')
const http = require('http')
const path = require('path')
module.exports = (pluginContext) => {
const packageUrl = 'http://zazuapp.org/api/packages.json'
const outputFile = path.join(pluginContext.cwd, 'packages.json')
return (env = {}) => {
return new Promise((resolve, reject) => {
http.get(packageUrl, (response) => {
const chunks = []
response.on('data', (chunk) => {
chunks.push(chunk.toString())
})
response.on('end', () => {
resolve(chunks.join(''))
})
})
}).then((data) => {
return fs.writeFileSync(outputFile, data)
})
}
}
Input Blocks
Input blocks are blocks that are the entry points to your plugin. These usually
return results to be displayed in Zazu. If a search becomes stales, all input
scripts should be able to handle a SIGKILL
{
"blocks": {
"input": [
// input blocks
]
}
}
Root Script
This allows you to execute a node script without a prefix.
scriptstring: Path to the node file to execute.debounceint: How long in milliseconds we should wait between calls, useful for resource intensive or slow running plugins. Defaults to100.
[{
"id": "Calculator",
"type": "RootScript",
"script": "calculator.js",
"debounce": 500,
"connections": ["Copy"]
}]
We call the export with the Plugin
Context, which should return an object
with two methods respondsTo and search.
The respondsTo method takes a query and asks the plugin if they are willing
to respond to that input.
The search method takes a query and env and returns a
Promise.
that resolves with results.
The pluginContext is provided when your plugin is loaded, and the returned
functions will be called as needed.
Variables defined in the configuration will be used as environment variables in the script call.
// calculator.js
module.exports = (pluginContext) => {
return {
respondsTo: (query, env = {}) => {
return query.match(/\d/)
},
search: (query, env = {}) => {
return new Promise((resolve, reject) => {
const value = eval(query)
resolve([
{
icon: 'fa-calculator',
title: value,
subtitle: 'Select item to copy the value to the clipboard.',
value: value,
}
])
})
},
}
}
Prefix Script
This allows you to execute a node script with a prefix.
prefixstring: Prefix to be used before user input.spaceboolean: If a space should be between the Prefix and the user input.argsstring: Specifies if you want arguments. Possibles values areRequired,OptionalandNone.scriptstring: Path to the node file to execute.debounceint: How long in milliseconds we should wait between calls, useful for resource intensive or slow running plugins. Defaults to100.
[{
"id": "Calculator",
"type": "PrefixScript",
"prefix": "calc",
"space": true,
"args": "Required",
"script": "calculator.js",
"debounce": 75,
"connections": ["Copy"]
}]
The node script needs to have a curried function that returns a promise. We call the export with the Plugin Context. The search function can accept a query and the environment variables, and it should return a Promise.
The pluginContext is provided when your plugin is loaded, and the returned
function will be called as needed.
Variables defined in the configuration will be used as environment variables in the script call.
// calculator.js
module.exports = (pluginContext) => {
return (query, env = {}) => {
return new Promise((resolve, reject) => {
const value = eval(query)
resolve([
{
icon: 'fa-calculator',
title: value,
subtitle: 'Select item to copy the value to the clipboard.',
value: value,
}
])
})
}
}
Keyword
Keyword blocks are a useful input block, if you don’t need input from the user. Once a user types in part of your keyword, it will display as a result the user can click on.
keywordstring: What the user input should match. Similar to thevaluein results.titlestring: Title of the result that will be displayed, similar to results.subtitlestring: Subtitle of the result that will be displayed, similar to results.iconstring: Font awesome or the relative path to an icon to be displayed next to the result.
[{
"id": "Play",
"type": "Keyword",
"keyword": "play",
"title": "Play Pandora",
"subtitle": "Click to play Pandora!",
"icon": "fa-play",
"connections": ["PlayPandora"]
}]
Output Blocks
Output blocks happen after an input block, these can do several things like call a script, or copy something to your clipboard.
Most of the special attributes allow you to use a variable {value} which will
be replaced with the current value of the result being passed around.
{
"blocks": {
"output": [
// output blocks
]
}
}
Copy To Clipboard
This block will copy the given input to the clipboard.
textstring: Text to be copied to the clipboard.
[{
"id": "Copy",
"type": "CopyToClipboard",
"text": "{value}"
}]
Open In Browser
Open up the value in the users default Browser.
urlstring: URL of the page you wish to open.
[{
"id": "Link",
"type": "OpenInBrowser",
"url": "{value}"
}]
Send Notification
Give the user a notification with a title and a message.
titlestring: Title of the notification.messagestring: Message of the notification.
[{
"id": "Notify",
"type": "SendNotification",
"title": "Hello world",
"message": "{value}"
}]
Preview
You can display large text in a preview window.
messagestring: Message to display in the window.
[{
"id": "Display",
"type": "Preview",
"message": "{value}"
}]
Open File
To open a file in the default application.
[{
"id": "Open",
"type": "OpenFile"
}]
Show File
To show a file in it’s folder.
[{
"id": "Show",
"type": "ShowFile"
}]
User Script
If you need to process or modify your state, this allows you to run any script on the current state being passed down.
scriptstring: Path to the node file to execute.
[{
"id": "Process",
"type": "UserScript",
"script": "process.js",
"connections": ["Copy"]
}]
In the example below we take in a unicode value and output the character that
corresponds to that unicode value using
String.fromCharCode.
The pluginContext is provided when your plugin is loaded, and the returned
function will be called as needed.
// process.js
module.exports = (pluginContext) => {
return (value, env = {}) => {
return new Promise((resolve, reject) => {
resolve(String.fromCharCode(value))
})
}
}
Reload Configuration
If a plugin is changing values inside of the ~/.zazurc.json file, it can often
be useful to tell Zazu to reload this configuration.
[{
"id": "Reload",
"type": "ReloadConfig"
}]
Play Sound
Playing a sound to alert the user, or signal an event is sometimes more useful then a Notification. This block allows you to play abritrary sounds inside of your plugin.
filestring: Path to the audio file you want Zazu to play. You can also add a{value}inside of this string to make it more dynamic.
[{
"id": "Play",
"type": "PlaySound",
"file": "beep.mp3"
}]