Skip to content
UrushiDocumentation

Rendering behavior

Renderer-neutral view pipelineSemantic data and a theme are composed by a presentation into a View. Resolve applies an available area to produce a ResolvedView. Render applies output settings and serializes the result.Data + Themesemantic inputPresentationcomposeViewlayout intentResolvedViewstyled cellsStringplain / ANSIresolve(available)render(settings)

View is renderer-neutral. ResolvedView is a rectangular collection of styled graphemes plus reported anchor rectangles. RenderSettings selects which terminal styling features may reach ANSI output.

Semantic components are lowered into View by concrete presentations before this pipeline begins. The resolver does not know whether a primitive tree came from a list, table, tree, CLI summary, or application-specific component.

Value Meaning
Available::NONE No width or height bound
Available::columns(n) Width is limited to n cells
Adapter-derived area Width and height come from the target rectangle

measure is intrinsic resolution under Available::NONE. try_measure returns layout errors for content that requires a finite extent.

The free resolve function is the ordinary stateless path. Keep a Resolver when a host evaluates successive immutable view snapshots and wants to reuse unchanged materialized subtree output:

use urushi::{Available, Resolver, TextStyle, View, resolve};
let mut resolver = Resolver::new();
let available = Available::size(80, 24);
let first_view = View::text("status: loading", TextStyle::new());
let next_view = View::text("status: ready", TextStyle::new().bold());
let _first = resolver.resolve(&first_view, available)?;
let next = resolver.resolve(&next_view, available)?;
assert_eq!(next, resolve(&next_view, available)?);

Resolver::resolve has the same observable result as resolve. The current View and Available area remain the complete layout input. Changed content or settled layout invalidates the affected retained artifact; moving a Viewport can reuse unchanged child output. Call clear() to discard all retained evaluation state.

RenderSettings controls these axes independently:

  • color level: none, ANSI 16, ANSI 256, or true color;
  • text attributes;
  • supported underline styles;
  • underline colors; and
  • OSC 8 hyperlinks.

RenderSettings::default() enables none of these features and produces plain text. RenderSettings::from(capabilities) selects the detected maximum. RenderSettings::all() preserves all logical features and is intended for a serializer whose input is already known to be supported.

Unsupported features are narrowed at render time:

  • true colors are quantized to the selected color level;
  • unsupported text attributes are removed;
  • unsupported underline shapes are removed;
  • underline colors fall back to the foreground when disabled; and
  • hyperlinks are omitted when unavailable.

The logical TextStyle and View values are unchanged, so the same values can be rendered again for a different destination.

The standard-stream helpers detect terminal width and capabilities. A non-terminal destination uses Available::NONE and default plain RenderSettings. See Output behavior for the stdout, stderr, redirection, and NO_COLOR rules.

The TUI runtime uses the same resolution pass through a different output boundary:

Full-screen rendering boundaryApplication view produces an Urushi View. The renderer resolves it and writes styled graphemes through a borrowed Frame. Screen owns Urushi cell buffers, diffing, and transactional terminal output.Applicationview(&Model)Viewrenderer-neutralRendererresolve + drawURUSHI-TUIScreen::drawborrowed FrameCommandWriterterminal outputScreen owns frame history and commits only after output succeeds.

urushi-tui-app resolves the application’s view and writes its styled graphemes through a borrowed urushi_tui::Frame. The concrete urushi_tui::Screen owns working and committed buffers, computes changed cells, lowers them to backend-independent urushi_terminal::Command values, and commits the new baseline only after output and flush succeed.

urushi_tui_app::run(app) assembles the application runtime and production terminal integration. Runtime::new(app) exposes its configurable executor, clock, physical terminal backend, and session options. Ratatui participates only when a caller separately selects urushi-adapter-ratatui.

The separate Ratatui adapter serves an application that already owns its Ratatui terminal and event loop. It does not serialize ANSI. It maps resolved Urushi styles to Ratatui cells and writes within the supplied Rect. ANSI escape sequences in text are not interpreted.