Skip to content
UrushiDocumentation

Configure text appearance

TextStyle describes the appearance of one text run. It has no padding, border, or dimensions; use Layout when the content needs a rectangle.

Capability Use it for Main API Behavior
Foreground and background Color text or the cells behind it foreground, background Accepts ANSI, ANSI 256, or RGB Color values
Attributes Emphasis and terminal text effects bold, dim, italic, underlined, blink, reverse, hide, strikethrough; add_attribute(s) Adds the selected attributes to the style
Underline style and color Single, double, curly, dotted, or dashed emphasis underline_style, underline_color, underline Shape and color are one underline value; unsupported forms may be narrowed by the renderer
OSC 8 hyperlink Give visible text a terminal link target hyperlink; Hyperlink::new Supporting terminals make the text clickable; other renderers keep the visible label
Hyperlink parameters Give an OSC 8 link an identifier or future terminal-defined metadata Hyperlink::parameter Parameters are emitted in insertion order and safely encoded
Resets Remove selected appearance from a reusable value reset_foreground, reset_background, reset_attributes, reset_underline, reset_hyperlink Returns that property to its unset/default state

TextStyle::new() starts with every field unset. Builders consume and return the value, so clone a reusable base before deriving variants.

This complete example prints three independently styled lines. It includes a background color so foreground and cell fill can be compared directly:

use std::io;
use urushi::{Color, TextStyle, View};
fn main() -> io::Result<()> {
urushi::println_view(&View::text(
"ready",
TextStyle::new().foreground(Color::GREEN).bold(),
))?;
urushi::println_view(&View::text(
"secondary",
TextStyle::new().dim().italic(),
))?;
urushi::println_view(&View::text(
"attention",
TextStyle::new()
.foreground(Color::BLACK)
.background(Color::YELLOW),
))
}
ready
secondary
attention

On a capable terminal, ready is green and bold; secondary is dim and italic; and attention uses contrasting foreground and background cells. The visible text remains the same when the destination supports fewer features. Use add_attribute(s) and remove_attribute(s) when working with explicit TextAttribute values instead of the convenience builders.

The remaining attribute builders affect a run as follows:

underlined  strikethrough  reverse
bold        dim            italic
blink       hidden: hidden text

blink requests terminal-controlled blinking, which this static preview does not animate. hide makes the graphemes invisible while they continue to occupy cells; the blank area after hidden: is therefore intentional.

underlined() selects a single underline in the foreground color. Set its shape or color independently when the terminal presentation needs more detail:

use urushi::{Align, Color, TextStyle, UnderlineStyle, View};
let view = View::column(Align::Left, [
("single", UnderlineStyle::Single),
("double", UnderlineStyle::Double),
("curly", UnderlineStyle::Curly),
("dotted", UnderlineStyle::Dotted),
("dashed", UnderlineStyle::Dashed),
].map(|(label, shape)| {
View::text(
label,
TextStyle::new()
.underline_style(shape)
.underline_color(Color::YELLOW),
)
}));
urushi::println_view(&view)?;
single
double
curly
dotted
dashed

The logical style retains the requested shape and color. The output renderer uses the underline features selected by its RenderSettings; terminal output derives those settings from detected capabilities.

Attach a URI directly for the ordinary case. Construct Hyperlink when the OSC 8 link also needs parameters such as id:

use std::io;
use urushi::{Color, Hyperlink, TextStyle, View};
fn main() -> io::Result<()> {
let target = Hyperlink::new("https://example.com/docs")
.parameter("id", "guide");
let view = View::text(
"Open documentation",
TextStyle::new()
.foreground(Color::CYAN)
.underlined()
.hyperlink(target),
);
urushi::println_view(&view)
}
Open documentation

When hyperlinks are supported, the renderer surrounds the visible label with an OSC 8 open and close sequence, so the terminal can make it clickable. When they are unsupported or disabled, the same label is rendered without those sequences. Color and underline capability selection is independent from hyperlink selection.

Hyperlink::new accepts any UTF-8 string; it does not parse or validate URL syntax. It percent-encodes control characters so the URI cannot terminate the OSC 8 sequence. parameter also percent-encodes the OSC 8 delimiters :, =, and ; in parameter names and values. Parameters remain open-ended because terminals currently define id and may define more keys later.

Use RenderSettings::hyperlinks(true) only when a serializer has already chosen hyperlink support. Ordinary terminal output should keep using println_view, which narrows the style to detected capabilities.

Reset builders remove only the named property. Other properties remain:

use urushi::{Color, TextStyle};
let linked = TextStyle::new()
.foreground(Color::CYAN)
.bold()
.underlined()
.hyperlink("https://example.com");
let plain_target = linked
.reset_foreground()
.reset_attributes()
.reset_underline()
.reset_hyperlink();
assert_eq!(plain_target, TextStyle::new());

The same reset is visible when a shared base style is used for two runs:

before reset
after reset

The corresponding reset_background builder removes a background color. These methods return the property to the same unset/default state used by TextStyle::new(); they do not retain a separate reset instruction.