Requirements
You should check for these binaries to be installed on your system before continuing. Here is a sample output of an example to help you test these out.
$ node --version
v10.16.0
$ npm --version
6.9.0
$ i3 --version
i3 version 4.17 (2019-08-03) © 2009 Michael Stapelberg and contributors
Usage
Create a directory
$ mkdir my-i3bar
Go into that directory
$ cd my-i3bar
Initialize a new NPM project
$ npm init --yes
Install the "@i3bar/core"
package
$ npm install --save-dev @i3bar/core
Create the main script
$ touch main.js
Open the main script with your favorite editor (here, VIM)
$ vim main.js
Import the "@i3bar/core"
utilities
"use strict";
const { I3bar, I3Block } = require("@i3bar/core");
Create a new bar instance
const bar = new I3bar();
Create a new block
const block = new I3Block({ full_text: "Hello, i3!" });
Add the block to the bar
bar.addBlock(block);
Add a refresh time to the bar
bar.setSecondsBetweenRefreshes(5);
Start the bar
bar.start();
Open the i3 configuration file
$ vim ~/.config/i3/config
Update the bar command
bar {
status_command node /path/to/my-i3bar/main.js
}
Reload the bar
$ i3 reload
API
Create a new bar
const { I3Bar } = require("@i3bar/core");
const bar = new I3Bar();
Enable events
const { I3Bar } = require("@i3bar/core");
const bar = new I3Bar();
bar.enableEvents();
This is required for listening to the bar events.
Listen to bar events
const { I3Bar, I3Block } = require("@i3bar/core");
const bar = new I3Bar();
const block = new I3Block({ full_text: "volume", name: "volume" });
bar.addBlock(block);
bar.enableEvents();
bar.on("leftClick", function(blockName, modifiers) {
if (blockName === "volume") {
//...
} else if (blockName === "brightness" && modifiers.includes("Shift")) {
//...
}
});
bar.on("rightClick", function(blockName, modifiers) {
//...
});
bar.on("middleClick", function(blockName, modifiers) {
//...
});
bar.on("mouseWheelDown", function(blockName, modifiers) {
//...
});
bar.on("mouseWheelUp", function(blockName, modifiers) {
//...
});
blockName
is a string containing the "name"
of the block where the event occured, while modifiers
is an array containing the modifiers attached to the event like "Shift"
or "Control"
Set the refresh time between each updates of the bar
const { I3Bar } = require("@i3bar/core");
const bar = new I3Bar();
bar.setSecondsBetweenRefreshes(5);
If you need to refresh the bar often, try not to set this value too low as this will increase your CPU usage. Instead, use events and timers in Node.js (see FAQ).
Add a block to the bar
const { I3Bar, I3Block } = require("@i3bar/core");
const bar = new I3Bar();
const block = new I3Block({ full_text: "" });
bar.addBlock(block);
Manually trigger an update of the bar
const { I3Bar} = require("@i3bar/core");
const bar = new I3Bar();
bar.render();
Start the bar
const { I3Bar } = require("@i3bar/core");
const bar = new I3Bar();
bar.start();
Create a block
const { I3Block } = require("@i3bar/core");
const block = new I3Block({ full_text: "" });
Add a block with a dynamic text
const { I3Block } = require("@i3bar/core");
function getText() {
return "";
}
async function getTextAsync() {
return "";
}
function getTextPromise() {
return new Promise(function(resolve) {
resolve("");
});
}
const block1 = new I3Block({ full_text: getText });
const block2 = new I3Block({ full_text: getTextAsync });
const block3 = new I3Block({ full_text: getTextPromise });
Update the block manually
const { I3Block } = require("@i3bar/core");
const block = new I3Block({ full_text: "loading..." });
block.update("full_text", "loaded");
FAQ
How to add dynamic values for the "full_text"
property?
Using a function
function getTime() {
const date = new Date();
return `${date.getHours().toString().padStart(2. "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
}
const block = new I3Block({ full_text: getTime });
Using an asynchronous function
const { promisify } = require("util");
const { exec } = require("child_process");
const execute = promisify(exec);
async function getBattery(command) {
try {
const battery = await execute("cat /sys/class/power_supply/BAT0/capacity");
return battery.stdout.trim() + "%";
} catch {
return "??%";
}
}
const block = new I3Block({ full_text: getBattery });
Using the built-in update()
method
Note that this is the prefered method as it does not block the main thread.
const { exec } = require("child_process");
const block = new I3Block({ full_text: "" });
exec("xbacklight -get", function(exception, output, error) {
if (!exception && !error) {
block.update("full_text", `${output.trim()}%`);
bar.render();
}
});
Using setInterval()
to update on a different interval than the bar
const { get } = require("https");
const block = new I3Block({ full_text: "" });
const TEN_MINUTES = 1000 * 60 * 10;
function updateWeather() {
get("https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22", function(response) {
response.on("data", function() {
const weather = JSON.parse(data);
block.update("full_text", `${weather.main.temp}°F`);
});
});
}
updateWeather();
setInterval(updateWeather, TEN_MINUTES);
How to update the bar on events?
const { exec } = require("child_process");
const { promisify } = require("util");
const execute = promisify(exec);
async function getBrightness() {
try {
const brightness = await execute("xbacklight -get");
return `${Math.floor(brightness.stdout)}%`;
} catch {
return "??%";
}
}
const block = new I3Block({ full_text: getBrightness, name: "brightness" });
bar.on("leftClick", async function(blockName) {
if (blockName === "brightness") {
try {
await execute("xbacklight -set $(( $(xbacklight -get) + 1 ))");
bar.render();
} catch {}
}
});
bar.enableEvents();
Events available are: "leftClick"
, "rightClick"
, "middleClick"
, "mouseWheelUp"
& "mouseWheelDown"
How to use modifiers with events?
bar.on("leftClick", async function(blockName, modifiers) {
if (blockName === "brightness" && modifiers.includes("Shift")) {
//...
}
});