pub enum View {
Text(StyledText),
Block(BlockStyle, Option<BlockTitle>, Box<View>),
Row(VerticalAlign, Vec<View>),
Column(Align, Vec<View>),
Grid(GridStyle, Vec<Vec<View>>),
Canvas(Canvas),
Viewport(Viewport, Box<View>),
AnchorBlock(Key, BlockStyle, Option<BlockTitle>, Box<View>),
}Expand description
A fully composed, renderer-neutral terminal view.
A view tree combines text, boxes, linear and grid layout, and finite Canvas drawing surfaces. Every node resolves to a rectangle, so a bordered block or Canvas composes inside a row the same way a word does. An anchor is a box that also reports where its content landed, for a caller that draws there something this crate does not produce.
Components return a View; output adapters resolve it once
(resolve) and serialize the resulting
ResolvedView.
use urushi::{Align, BlockStyle, Border, TextStyle, VerticalAlign, View, measure};
let badge = View::block(
BlockStyle::new().border(Border::ROUNDED),
View::text("ok", TextStyle::new()),
);
let row = View::row(VerticalAlign::Center, [View::text("status: ", TextStyle::new()), badge]);
assert_eq!(measure(&row).height(), 3);Variants§
Text(StyledText)
One text flow whose grapheme-aligned segments carry complete styles. Source tabs are replaced under its layout policy before measurement; escape sequences and cursor movement remain invalid.
Block(BlockStyle, Option<BlockTitle>, Box<View>)
One BlockStyle and optional BlockTitle around exactly one child.
Row(VerticalAlign, Vec<View>)
Children placed side by side, aligned vertically.
Column(Align, Vec<View>)
Children stacked, aligned horizontally.
Grid(GridStyle, Vec<Vec<View>>)
A rectangle of cells sharing one width per column.
Every row holds the same number of cells: a grid has no style to fill an invented one with, so whatever composes it supplies the empty cell. Debug builds panic on a ragged grid; release builds resolve a missing cell as an empty view.
Canvas(Canvas)
A finite free-positioned drawing surface.
Viewport(Viewport, Box<View>)
One child projected from local content coordinates into a finite area.
AnchorBlock(Key, BlockStyle, Option<BlockTitle>, Box<View>)
Implementations§
Source§impl View
impl View
Sourcepub fn text(text: impl Into<String>, style: TextStyle) -> Self
pub fn text(text: impl Into<String>, style: TextStyle) -> Self
Creates a text leaf.
The text may contain newline and horizontal tab. Tabs use the default
four-space layout policy; construct a StyledText to select another
policy. Escape sequences and cursor movement break the contract and
panic during construction in every build profile. Raw ANSI is not a
valid Text payload.
Sourcepub const fn styled_text(text: StyledText) -> Self
pub const fn styled_text(text: StyledText) -> Self
Creates a text leaf carrying multiple styled segments in one flow.
Sourcepub fn block(style: BlockStyle, child: Self) -> Self
pub fn block(style: BlockStyle, child: Self) -> Self
Wraps one child in a block.
Sourcepub fn titled_block(
style: BlockStyle,
title: impl Into<BlockTitle>,
child: Self,
) -> Self
pub fn titled_block( style: BlockStyle, title: impl Into<BlockTitle>, child: Self, ) -> Self
Wraps one child in a block with a styled title in its top border.
The title participates in automatic width demand but never increases the box past an explicit or available width. It is clipped without wrapping when the top edge is narrower than its text and padding.
use urushi::{BlockStyle, Border, View, measure};
let panel = View::titled_block(
BlockStyle::new().border(Border::NORMAL),
"Files",
View::empty(),
);
assert_eq!(measure(&panel).width(), 9);§Panics
Panics when style has no top border edge.
Sourcepub fn row(
align: VerticalAlign,
children: impl IntoIterator<Item = Self>,
) -> Self
pub fn row( align: VerticalAlign, children: impl IntoIterator<Item = Self>, ) -> Self
Places children side by side.
Sourcepub fn column(align: Align, children: impl IntoIterator<Item = Self>) -> Self
pub fn column(align: Align, children: impl IntoIterator<Item = Self>) -> Self
Stacks children.
Sourcepub fn anchor_block(key: impl Into<Key>, style: BlockStyle, child: Self) -> Self
pub fn anchor_block(key: impl Into<Key>, style: BlockStyle, child: Self) -> Self
Wraps one child in a block that reports where its content landed.
An anchor carries no geometry of its own: it is a block, so its size is
whatever style and its content decide, by the rules every other block
follows. What the key adds is a report — an
AnchoredRect of the rectangle inside the frame
— for a caller that draws there something this crate does not produce.
The key is opaque here; this crate never looks at what belongs in the region. One key names one region: two anchors carrying the same key are a contract violation, which debug builds assert.
use urushi::{Available, BlockStyle, Length, View, resolve};
// A region for a foreign renderer: the box states the size, and the
// empty content resolves to the blanks a backend without one draws.
let chart = View::anchor_block(
"chart",
BlockStyle::new().width(Length::Cells(20)).height(Length::Cells(8)),
View::empty(),
);
let resolved = resolve(&chart, Available::NONE).unwrap();
let region = resolved.anchor("chart").expect("the anchor resolved");
assert_eq!((region.width(), region.height()), (20, 8));Sourcepub fn titled_anchor_block(
key: impl Into<Key>,
style: BlockStyle,
title: impl Into<BlockTitle>,
child: Self,
) -> Self
pub fn titled_anchor_block( key: impl Into<Key>, style: BlockStyle, title: impl Into<BlockTitle>, child: Self, ) -> Self
Wraps one child in a titled block and reports its content rectangle.
Geometry and title behavior are identical to titled_block;
the key adds only the same report as anchor_block.
§Panics
Panics when style has no top border edge.
Sourcepub fn anchor(key: impl Into<Key>) -> Self
pub fn anchor(key: impl Into<Key>) -> Self
Creates an anchor with no box around it: an empty region, named.
This is the cursor case of anchor_block. The
region covers no cells, so it changes no layout and draws nothing; what
the caller reads is its origin.
use urushi::{Available, TextStyle, VerticalAlign, View, resolve};
let prompt = View::row(
VerticalAlign::Top,
[View::text("> ", TextStyle::new()), View::anchor("cursor")],
);
let resolved = resolve(&prompt, Available::NONE).unwrap();
let cursor = resolved.anchor("cursor").expect("the anchor resolved");
assert_eq!((cursor.x(), cursor.y()), (2, 0));
assert!(cursor.is_empty());Sourcepub fn grid<R>(style: GridStyle, rows: impl IntoIterator<Item = R>) -> Selfwhere
R: IntoIterator<Item = Self>,
pub fn grid<R>(style: GridStyle, rows: impl IntoIterator<Item = R>) -> Selfwhere
R: IntoIterator<Item = Self>,
Lines cells up in shared columns.
Every row must hold the same number of cells; see View::Grid.
Sourcepub const fn canvas(canvas: Canvas) -> Self
pub const fn canvas(canvas: Canvas) -> Self
Creates a finite drawing surface from ordered, owned items.