Cairo
Allows you to render custom content using the Lua and the Cairo drawing library. This is an advanced feature which provides a powerful escape hatch, allowing you to fetch data and render anything using an embedded scripting environment.
Scripts are automatically hot-reloaded.

Example
let { $config_dir = ".config/ironbar" $cairo = { type = "cairo" path = "$config_dir/clock.lua" frequency = 100 width = 300 height = 300 }} in { center = [ $cairo ]}{ "center": [ { "type": "cairo", "path": "$config_dir/clock.lua", "frequency": 100, "width": 300, "height": 300 } ]}center: - type: cairo path: $config_dir/clock.lua frequency: 100 width: 300 height: 300[[center]]type = "cairo"path = "$config_dir/clock.lua"frequency = 100width = 300height = 300Configuration
Type:
cairo
pathRequired
Section titled “pathRequired”The path to the Lua script to load. This can be absolute, or relative to the working directory.
The script must contain the entry draw function.
Type: string
Default:
frequency
Section titled “frequency”The number of milliseconds between each draw call.
Type: integer (uint64)
Default: 200
The canvas width in pixels.
Type: integer (uint32)
Default: 42
height
Section titled “height”The canvas height in pixels.
Type: integer (uint32)
Default: 42
Script
Every script must return a function or callable table with three parameters:
- Cairo context (required)
- Width of the drawing area (can be omitted)
- Height of the drawing area (can be omitted)
Outside of this, you can do whatever you like.
The full lua stdlib is available, and you can load in additional system packages as desired.
Additionally there is basic access to the ironbar via the ironbar global:
ironbar.config_dir: Absolute path to the configuration directory. This can be used for relative file imports, e.g.:local_module = dofile(ironbar.config_dir .. "local_mod.lua")`ironbar:log_debug(msg),ironbar:log_info(msg),ironbar:log_warn(msg),ironbar:log_error(msg): Write a log message.ironbar:unixtime(): Returns high-resolution unixtime (stdlib only offers second-resolution). Will return a table:secs: Seconds since unix-epoch with fractionssubsec_millis: Sub-second milliseconds as integersubsec_micros: Sub-second microseconds as integer
ironbar:var_get(key): Get an ironbar variable, e.g.memory_free = ironbar:var_get("sysinfo.memory_free")ironbar:var_list(namespace): Get all variables of a namespace as table (non-recursive), e.g.:memory_free = ironbar:var_list("sysinfo")["memory_free"]
Basic examples, which draw a red square
- As anonymous function:
return function(cr)cr:set_source_rgb(1.0, 0.0, 0.0)cr:paint()end
- As local function:
local function draw_square(cr)cr:set_source_rgb(1.0, 0.0, 0.0)cr:paint()endreturn draw_square
- As callable table (also using width and height):
local square = {}function square:draw(cr, width, height)cr:set_source_rgb(1.0, 0.0, 0.0)cr:rectangle(0, 0, width, height)cr:fill()endsetmetatable(square, {__call = function(o, cr, width, height)return o:draw(cr, width, height)end,})return square
A longer example, used to create the clock in the image at the top of the page, is shown below:
Circle clock
local function draw_clock(cr, width, height) local center_x = width / 2 local center_y = height / 2 local radius = math.min(width, height) / 2 - 20
local date_table = os.date("*t")
local hours = date_table["hour"] local minutes = date_table["min"] local seconds = date_table["sec"] local ms = ironbar:unixtime().subsec_millis / 1000
local label_seconds = seconds seconds = seconds + ms
local hours_str = tostring(hours) if string.len(hours_str) == 1 then hours_str = "0" .. hours_str end
local minutes_str = tostring(minutes) if string.len(minutes_str) == 1 then minutes_str = "0" .. minutes_str end
local seconds_str = tostring(label_seconds) if string.len(seconds_str) == 1 then seconds_str = "0" .. seconds_str end
local font_size = radius / 5.5
cr:set_source_rgb(1.0, 1.0, 1.0)
cr:move_to(center_x - font_size * 2.5 + 10, center_y + font_size / 2.5) cr:set_font_size(font_size) cr:show_text(hours_str .. ':' .. minutes_str .. ':' .. seconds_str) cr:stroke()
if hours > 12 then hours = hours - 12 end
local line_width = radius / 8 local start_angle = -math.pi / 2
local end_angle = start_angle + ((hours + minutes / 60 + seconds / 3600) / 12) * 2 * math.pi cr:set_line_width(line_width) cr:arc(center_x, center_y, radius, start_angle, end_angle) cr:stroke()
end_angle = start_angle + ((minutes + seconds / 60) / 60) * 2 * math.pi cr:set_line_width(line_width) cr:arc(center_x, center_y, radius * 0.8, start_angle, end_angle) cr:stroke()
if seconds == 0 then seconds = 60 end
end_angle = start_angle + (seconds / 60) * 2 * math.pi cr:set_line_width(line_width) cr:arc(center_x, center_y, radius * 0.6, start_angle, end_angle) cr:stroke()
return 0end
return draw_clockInitialization
You can optionally create an init.lua file in your config directory.
Any code in here will be executed once, on bar startup.
As variables and functions are global by default in Lua, this provides a mechanism for sharing code between multiple modules.
Styling
| Selector | Description |
|---|---|
.cairo | Cairo widget container. |
For more information on styling, please see the styling guide.