ultraviolet 0.6.0
ultraviolet: ^0.6.0 copied to clipboard
Core cell/buffer/style types for terminal rendering.
Ultraviolet #
ultraviolet is a high-performance terminal rendering/runtime package for Dart.
It provides the low-level primitives you need to build interactive terminal
applications: screen buffers, styled cells, diff-based rendering, typed input
events, and terminal capability handling.
Features #
- Cell/buffer-based rendering model
- High-performance diff renderer (
UvTerminalRenderer) - Typed keyboard/mouse/focus/resize events
- Style + color primitives (
UvStyle,UvColor) - Per-cell diff policies (
normal,skip,alwaysUpdate,forcedWidth) - ANSI helpers (
Ansi) and renderer-level ANSI sequences (UvAnsi) - Terminal capability detection
- Image protocol support (Kitty, iTerm2, Sixel, fallback drawables)
Installation #
From pub.dev:
dart pub add ultraviolet
Workspace usage:
dependencies:
ultraviolet:
Git dependency usage:
dependencies:
ultraviolet:
git:
url: https://github.com/kingwill101/artisanal.git
path: pkgs/ultraviolet
Quick Start #
import 'package:ultraviolet/ultraviolet.dart';
Future<void> main() async {
final terminal = Terminal();
await terminal.start();
try {
terminal.enterAltScreen();
terminal.hideCursor();
terminal.setCell(2, 1, Cell(content: 'U'));
terminal.setCell(3, 1, Cell(content: 'V'));
terminal.draw();
await for (final event in terminal.events) {
if (event is KeyEvent && event.matchString('q', 'esc', 'ctrl+c')) {
break;
}
}
} finally {
terminal.showCursor();
terminal.exitAltScreen();
await terminal.stop();
}
}
Demo Captures #
Every example in pkgs/ultraviolet/example/ has a VHS recording
regenerated from the tapes in pkgs/ultraviolet/example/.vhs/:
task uv-demos # compiles each example, then records all GIFs into assets/
3D & raytracing #
Raycast maze (example/raycast_maze.dart):

SDF raymarcher (example/sdf_raymarcher.dart):

Path tracer (example/path_tracer.dart):

Simulations #
Conway's Game of Life (example/conway_life.dart):

Metaballs / marching squares (example/metaballs_marching_squares.dart):

Boids swarm (example/boids_swarm.dart):

N-body gravity (example/nbody_gravity.dart):

Network topology (example/network_topology_sim.dart):

Wave function collapse (example/wave_function_collapse.dart):

Games & interactive #
Pong (example/pong.dart):

Mouse drawing (example/draw.dart):

Effects & shaders #
Shader toy (example/terminal_shader_toy.dart):

Post effects (example/effects.dart):

TV test pattern (example/tv.dart):

Layout & UI #
Layout (example/layout.dart):

Splits (example/splits.dart):

Hello world (example/main.dart, example/helloworld.dart):


Alternate screen toggle (example/altscreen.dart):

Space (example/space.dart):

Terminal demo (example/uv_demo.dart):

Image protocols (example/image.dart, example/uv_graphics_parity.dart):


File pager (example/bat.dart):

Panic recovery (example/panic.dart):

Prepend line (example/prependline.dart):

Performance Tips #
- Prefer incremental updates over full-screen redraws.
- For resize-heavy or animation-heavy apps, consider:
terminal.setScrollOptim(false)terminal.setSynchronizedOutput(true)
API Surface #
Terminal
Runtime entrypoint: lifecycle, event stream, capability queries, and drawing.Buffer
2D grid of cells representing screen state for a frame.Cell
A single rendered glyph plus style/link metadata.UvStyle/UvColor
Text attributes and color model for foreground/background styling.UvPaintPolicyShared foreground/background, palette, reverse, faint, and conceal resolution for native raster, webCanvasTerminalRenderer, and Flutter painting. Setforeground,background, an optional 16- or 256-entrypalette, andfaintMixonce when those backends must agree.UvTerminalRenderer
Diff-based renderer that minimizes terminal output between frames.KittyImage/ITerm2Image/SixelImage— Raw protocol encoders exported bypackage:ultraviolet/rendering.dart.Ansi/UvAnsi
ANSI escape sequence helpers (Ansi) and UV renderer ANSI controls (UvAnsi).Eventtypes (KeyEvent,MouseEvent,WindowSizeEvent, etc.)
Typed input and terminal-state events fromterminal.events.
Small How-Tos #
For a narrower dependency surface, import the focused entrypoint matching the layer you use:
import 'package:ultraviolet/core.dart'; // cells, buffers, layout
import 'package:ultraviolet/input.dart'; // events and decoding
import 'package:ultraviolet/rendering.dart'; // diff renderer and effects
import 'package:ultraviolet/terminal.dart'; // terminal lifecycle
import 'package:ultraviolet/unicode.dart'; // graphemes and cell widths
Non-ANSI backends can share one color policy:
import 'package:ultraviolet/core.dart';
import 'package:ultraviolet/web.dart';
final policy = UvPaintPolicy(
foreground: const UvRgb(204, 204, 204),
background: const UvRgb(0, 0, 0),
);
final canvas = CanvasTerminalRenderer(paintPolicy: policy);
The native raster renderer exposes the equivalent values through
RasterRenderOptions; Flutter accepts the policy directly. This aligns cell
color/attribute resolution; it does not make glyph pixels identical. Font
hinting, antialiasing, and the selected font can still differ.
All five entrypoints are browser-safe. The umbrella
package:ultraviolet/ultraviolet.dart remains available when an application
needs APIs from several layers. package:ultraviolet/uv.dart exposes the
complete low-level UV surface for compatibility consumers.
Write ANSI sequences directly:
import 'dart:io';
import 'package:ultraviolet/ultraviolet.dart';
stdout.write(Ansi.clearScreen);
stdout.write(Ansi.cursorTo(1, 1));
stdout.write('${Ansi.bold}Ultraviolet${Ansi.reset}');
Draw a styled label:
terminal.setCell(
2,
2,
Cell(
content: 'H',
style: const UvStyle(
fg: UvColor.rgb(255, 210, 120),
attrs: Attr.bold,
),
),
);
terminal.setCell(3, 2, Cell(content: 'i'));
terminal.draw();
Control exceptional diff behavior on a cell:
terminal.setCell(
0,
0,
Cell(content: '•', diffOption: CellDiffOption.alwaysUpdate),
);
Use CellDiffOption.skip for terminal cells owned by an external renderer and
CellDiffOption.forcedWidth(width) for escape-sequence-backed content whose
display width cannot be inferred from its text. Ordinary cells should keep the
default CellDiffOption.normal fast path.
Fill an area:
final panel = rect(0, 0, 20, 6);
terminal.fillArea(
Cell(content: ' ', style: const UvStyle(bg: UvColor.rgb(24, 32, 48))),
panel,
);
terminal.draw();
Handle resize safely:
await for (final event in terminal.events) {
if (event is WindowSizeEvent) {
terminal.resize(event.width, event.height);
terminal.clearScreen();
terminal.draw();
}
}
Run a simple animation loop:
final timer = Timer.periodic(const Duration(milliseconds: 33), (_) {
// update state
terminal.clear();
// redraw frame
terminal.draw();
});
Pick best image protocol automatically:
final drawable = terminal.bestImageDrawableForTerminal(
image,
columns: 40,
rows: 20,
);
drawable.draw(terminal, rect(2, 2, 40, 20));
terminal.draw();
Use synchronized output for heavy redraws:
terminal.setScrollOptim(false);
terminal.setSynchronizedOutput(true);
Examples #
See:
pkgs/ultraviolet/example/