ribbon.wz
May 14, 2026 ยท View on GitHub
Formatted text ribbons for WezTerm.
Ribbon builds wezterm.format() item lists with a small chainable API. Use it
for status bars, tab titles, command hints, separators, and other places where a
terminal UI needs short colored text segments.
- Append or prepend colored text segments
- Use WezTerm ANSI color names or arbitrary color strings
- Apply attributes by name, alias, or grouped alias
- Reset attributes after each segment with atomic mode
- Process text with stripping, transforms, and max-length truncation
- Configure validation and lightweight internal logging
Installation
local wezterm = require "wezterm"
-- from git
local ribbon = wezterm.plugin.require "https://github.com/sravioli/ribbon.wz"
-- from a local checkout
local ribbon = wezterm.plugin.require("file:///" .. wezterm.config_dir .. "/plugins/ribbon.wz")
Ribbon loads warp.wz automatically for
table helpers used by its configuration layer.
Usage
ribbon.setup {
atomic = true,
attribute_aliases = {
strong = { "Bold", "Single" },
},
}
local title = ribbon:new "TabTitle"
title
:append("Blue", "White", " 1 ", "Bold")
:append("Black", "Silver", " shell ", "strong")
return title:format()
Both constructor styles are supported:
local a = ribbon:new "StatusBar"
local b = ribbon.new "StatusBar"
Configuration
setup() deep-merges your options with Ribbon defaults. Tables are merged by
key, while array-like tables replace the previous value. You usually only set
the fields you care about.
ribbon.setup {
log = {
enabled = true,
threshold = "WARN",
},
defaults = {
foreground = nil,
background = nil,
attributes = {
Bold = { Intensity = "Bold" },
Italic = { Italic = true },
None = "ResetAttributes",
},
colors = {
Black = true,
White = true,
Blue = true,
},
},
attribute_aliases = {
b = "Bold",
i = "Italic",
highlight = { "Bold", "Single" },
},
validate_attributes = true,
strict_mode = false,
text = {
strip = false,
max_length = nil,
transform = nil,
},
atomic = false,
}
log
Ribbon has its own small logger and does not require log.wz.
log = {
enabled = true,
threshold = "WARN",
}
enabled = false silences Ribbon. threshold accepts "DEBUG", "INFO",
"WARN", "ERROR", or a numeric level. The old layout option log.sinks is
accepted for compatibility, but Ribbon does not use it.
defaults.foreground and defaults.background
These are fallback colors for segments that do not pass a foreground or
background to append() / prepend().
ribbon.setup {
defaults = {
foreground = "White",
background = "#1f2335",
},
}
local cell = ribbon:new "Cell"
cell:append(nil, nil, " text ")
In that example, the segment uses White as the foreground and #1f2335 as the
background. If no fallback is configured, Ribbon uses "none".
defaults.colors
defaults.colors tells Ribbon which color names should be emitted as WezTerm
ANSI colors.
defaults = {
colors = {
Black = true,
White = true,
Blue = true,
},
}
When a color is present in this table, Ribbon emits:
{ Foreground = { AnsiColor = "Blue" } }
Other strings are emitted as literal colors:
{ Foreground = { Color = "#7aa2f7" } }
That means terminal palette colors and literal color strings can live in the same ribbon.
defaults.attributes
defaults.attributes is the registry of attributes Ribbon knows how to emit. It
is not a list of attributes applied to every segment.
defaults = {
attributes = {
None = "ResetAttributes",
Bold = { Intensity = "Bold" },
Italic = { Italic = true },
Single = { Underline = "Single" },
},
}
Passing "Bold" to append() looks up defaults.attributes.Bold and emits the
matching WezTerm format item. Passing "None" emits ResetAttributes.
You can add project-specific names:
ribbon.setup {
defaults = {
attributes = {
Alert = { Intensity = "Bold" },
},
},
}
local cell = ribbon:new "Cell"
cell:append("Red", "White", " warning ", "Alert")
Because setup() deep-merges tables, adding Alert keeps the built-in
attributes unless you replace the whole table with an array-like value.
attribute_aliases
Aliases are shortcuts for one attribute or a small group of attributes.
attribute_aliases = {
b = "Bold",
i = "Italic",
highlight = { "Bold", "Single" },
}
These calls are equivalent:
cell:append("Blue", "White", " title ", "b")
cell:append("Blue", "White", " title ", "Bold")
Grouped aliases are expanded in order:
cell:append("Blue", "White", " title ", "highlight")
That applies Bold, then Single.
validate_attributes and strict_mode
By default, Ribbon validates attribute names. If an attribute cannot be emitted, Ribbon logs the problem but keeps loading the config.
ribbon.setup {
validate_attributes = true,
strict_mode = false,
}
With validate_attributes = true, Ribbon warns when you pass a name that is not
in defaults.attributes or attribute_aliases. With strict_mode = true, that
warning becomes an error.
You can set validate_attributes = false if you want the older permissive
behavior.
text
Text processing runs in this order:
- Strip leading and trailing whitespace when
strip = true. - Run
transform(text)when a transform function is configured. - Truncate to
max_lengthand append...when the processed text is too long.
ribbon.setup {
text = {
strip = true,
max_length = 10,
transform = function(text)
return text:upper()
end,
},
}
With that config, " shell " becomes "SHELL". A longer string such as
" powershell " becomes "POWERSHEL...".
atomic
Atomic mode inserts ResetAttributes after each text segment.
ribbon.setup {
atomic = true,
}
Use it when a segment should not leak bold, italic, underline, or other attributes into the next segment. You can override it per instance:
local global_default = ribbon:new "GlobalDefault"
local always_atomic = ribbon:new("AlwaysAtomic", true)
local never_atomic = ribbon:new("NeverAtomic", false)
API
ribbon.setup(opts)
Configures Ribbon and returns the active config table.
ribbon:new(name, atomic) / ribbon.new(name, atomic)
Creates a Ribbon instance. name is used in log messages. atomic overrides the
global atomic setting for that instance.
Ribbon:append(background, foreground, text, attributes)
Adds a segment to the end of the ribbon.
Ribbon:prepend(background, foreground, text, attributes)
Adds a segment to the beginning of the ribbon.
Ribbon:append_items(items)
Appends one raw wezterm.format() item, or an array of items, without applying
Ribbon color, attribute, text, or atomic processing.
title:append_items {
{ Foreground = { Color = "#57A143" } },
{ Text = "nvim" },
"ResetAttributes",
}
Ribbon:prepend_items(items)
Prepends one raw wezterm.format() item, or an array of items, while preserving
the order you pass in.
Ribbon:clear()
Removes all format items from the instance and returns it, so the same Ribbon can be reused.
Ribbon:reset_attributes()
Appends a ResetAttributes marker manually.
Ribbon:format()
Returns the rendered string from wezterm.format().
Ribbon:debug(formatted)
Logs either the raw format-item table or the rendered string.
Ribbon:items()
Returns the raw format-item table. This is mainly useful in tests or advanced renderers.
License
Code is licensed under the GNU General Public License v3. Documentation is licensed under the terms in LICENSE-DOCS.