Skip to content

Bars

A bar is a render function registered under a name. Place it with a bar leaf whose name is that registry name:

rune.ui.bar("clock", function(width)
return os.date("%H:%M")
end)
rune.ui.layout({
type = "column",
children = {
{ type = "pane", name = "output", border = "none" },
{ type = "bar", name = "clock" },
{ type = "input" },
{ type = "bar", name = "status" },
},
})

Rune calls active renderers every 250ms, or immediately after rune.ui.refresh_bars(). A bar displays only when the tree contains a leaf with type = "bar" and its registered name, the bar is enabled, its renderer produces visible content, and every ancestor region is visible. A same-named pane is a separate resource and never substitutes for the bar.

The callback receives the full terminal width, even in a narrower layout slot. Strings are clipped to that slot. Return { left = ..., center = ..., right = ... } to let Rune align fields within the assigned width. Keep content compact when the bar may appear in a sidebar.

Return a string, or a table with any of left, center, and right:

return { left = "HP 312/340", right = "LIVE" }

Style freely with rune.style. Bars render one row and default to automatic size in a column, so they take one row when they contain text. In a row, the omitted width is 1fr. Returning "" or nil, disabling the bar, or removing it makes its leaf take no space; its siblings reclaim the space.

A vitals bar fed by GMCP, with a full walkthrough in the HP bar cookbook:

local vitals = {}
rune.gmcp.subscribe("Char")
rune.gmcp.on("Char.Vitals", function(data)
vitals = data
rune.ui.refresh_bars()
end)
rune.ui.bar("vitals", function(width)
if not vitals.hp then return "" end
return string.format("HP %s/%s SP %s/%s",
vitals.hp, vitals.maxhp, vitals.sp, vitals.maxsp)
end)

Keep renderers cheap. Store or precompute data in the event that changes it, then format the current snapshot in the bar callback.

The default status bar is registered by the core scripts under the name status. Its leaf is { type = "bar", name = "status" }. Registering your own renderer under status replaces it completely. The default renderer also shows tab-completion matches and the Ctrl+C quit warning, so a replacement takes those over too.

Use rune.bars.disable, enable, toggle, and remove with the registered name. toggle returns true when the bar exists and false for an unknown name. The full list is in the API reference. /bars lists every bar with its state, group, and registration location.

A renderer that errors three times in a row is quarantined. Re-registering its name gives it a fresh start.

Bar registration and enabled state survive layout replacement. /reload rebuilds the Lua registry, so scripts register bars again with fresh enabled and failure state. Region visibility is separate placement state; replacing or reloading a layout resets regions to their declared hidden values.

Related: rune.ui reference, Layout & UI, Panes