scrin 0.1.75

A terminal UI toolkit with panes, widgets, overlays, animations, and Aisling-powered effects/loaders.
Documentation

scrin

Made by KnottDynamics.

scrin is a Rust terminal UI toolkit for building polished command-line interfaces without Ratatui. It provides Scrin-native buffers, colors, layout, styled text, widgets, panes, overlays, command palettes, status bars, input routing, terminal lifecycle helpers, and animation utilities.

Scrin also ships with Aisling-powered effects and loaders. The aisling crate is baked in as a first-class dependency, and Scrin adapts Aisling frames into Scrin buffers so animated text effects and progress loaders can live beside normal widgets.

Install

[dependencies]
scrin = "0.1.75"

Why Scrin

  • Scrin-native terminal rendering with no Ratatui dependency.
  • Composable widgets for blocks, paragraphs, lists, tables, tabs, charts, gauges, markdown output, forms, popups, toggles, and more.
  • App structure primitives for panes, overlays, modals, toasts, status bars, command palettes, event routing, scrolling, and text expansion.
  • Rich terminal text with spans, lines, wrapping, scrolling, alignment, colors, and modifiers.
  • Aisling integration for cinematic effects and loaders rendered directly into Scrin buffers.
  • Demos and scripts that exercise widgets, overlays, Aisling effects, loaders, and a full Scrin shell showcase.

Draw A Widget

use scrin::core::buffer::Buffer;
use scrin::core::color::Color;
use scrin::core::rect::Rect;
use scrin::widgets::block::{Block, BorderStyle};
use scrin::widgets::paragraph::Paragraph;
use scrin::widgets::Widget;

let mut buffer = Buffer::new(48, 8);
buffer.fill(Rect::new(0, 0, 48, 8), ' ', Color::WHITE, None);

let block = Block::new("scrin").with_borders(BorderStyle::Rounded);
block.render(&mut buffer, Rect::new(0, 0, 48, 8));

let text = Paragraph::new("Scrin renders terminal UI from its own buffer model.");
text.render(&mut buffer, Rect::new(2, 2, 44, 4));

Use The Terminal API

Terminal::draw builds a frame, renders into Scrin's back buffer, and presents a diff to the terminal. The diff presenter repositions for separated dirty runs on the same row and handles wide-glyph continuation cells.

use scrin::terminal::{Terminal, TerminalOptions};
use scrin::widgets::block::{Block, BorderStyle};
use scrin::widgets::Widget;

let mut terminal = Terminal::init_with(TerminalOptions::default())?;

terminal.draw(|frame| {
    let area = frame.area();
    let block = Block::new("app").with_borders(BorderStyle::Rounded);
    block.render(frame.buffer(), area);
})?;

terminal.restore()?;
# Ok::<(), std::io::Error>(())

For dense animation or integrations that prefer repainting every cell, Terminal::draw_full and Terminal::present_full are available.

Aisling Effects

Scrin exposes Aisling through scrin::effects. You can select an Aisling EffectKind, tune the effect with Scrin colors and sizing, and render the current Aisling frame into any Scrin Buffer area.

use scrin::core::buffer::Buffer;
use scrin::core::color::Color;
use scrin::core::rect::Rect;
use scrin::effects::{EffectKind, EffectPlayer};

let mut buffer = Buffer::new(64, 8);

let mut effect = EffectPlayer::new(EffectKind::Matrix, "Scrin + Aisling")
    .with_size(64, 8)
    .with_duration(32)
    .with_seed(7)
    .with_accent(Color::rgb(88, 166, 255));

effect.render_to_buffer(&mut buffer, Rect::new(0, 0, 64, 8));
effect.advance();

Useful effect APIs:

  • EffectPlayer::new(kind, text) creates an Aisling-backed text effect.
  • EffectPlayer::with_config(kind, text, config) accepts an Aisling EffectConfig re-exported from scrin::effects.
  • with_size, with_duration, with_seed, with_accent, and with_gradient_colors tune how the effect is generated and mapped.
  • render_to_buffer and render_frame_to_buffer copy Aisling frame cells into a Scrin buffer region.
  • get_ansi_string returns Aisling's raw ANSI frame when you want standalone effect output.
  • EffectPlayer::all_kinds() returns every EffectKind available in the baked Aisling version.

Aisling Loaders

Loaders are also Aisling-backed. Scrin maps loader frames into buffers and keeps progress helpers on LoaderPlayer.

use scrin::core::buffer::Buffer;
use scrin::core::color::Color;
use scrin::core::rect::Rect;
use scrin::effects::{LoaderKind, LoaderPlayer};

let mut buffer = Buffer::new(52, 5);

let loader = LoaderPlayer::new(LoaderKind::Bar)
    .with_size(52, 5)
    .with_label("indexing".to_string())
    .with_unit("files")
    .with_fraction(true)
    .with_accent(Color::rgb(255, 128, 64));

let progress = LoaderPlayer::progress_from_counts(42, 100);
loader.render(8, progress, &mut buffer, Rect::new(0, 0, 52, 5));

Useful loader APIs:

  • LoaderPlayer::new(kind) creates an Aisling-backed loader.
  • LoaderPlayer::with_config(kind, config) accepts an Aisling LoaderConfig re-exported from scrin::effects.
  • with_size, with_label, with_unit, with_fraction, with_accent, and with_gradient_colors tune the loader presentation.
  • render(tick, progress, buffer, area) draws the current loader frame into a Scrin buffer.
  • get_ansi_string(tick, progress) returns the raw ANSI loader frame.
  • progress_from_counts and progress_from_fraction create Aisling progress values without importing Aisling directly.
  • LoaderPlayer::all_kinds() returns every LoaderKind available in the baked Aisling version.

Modules

  • scrin::core: Buffer, Cell, Color, Gradient, and Rect.
  • scrin::layout: horizontal and vertical layout constraints.
  • scrin::widgets: blocks, paragraphs, rich text, lists, tables, forms, charts, gauges, markdown output, popups, toggles, scrollbars, and clearing helpers.
  • scrin::terminal: raw-mode setup, frame drawing, diff/full presenters, cursor control, mouse capture, bracketed paste, and restore-once lifecycle.
  • scrin::effects: Aisling-backed EffectPlayer, LoaderPlayer, effect kinds, loader kinds, progress, and config types.
  • scrin::panes, scrin::overlays, scrin::command_palette, scrin::status_bar, and scrin::input: higher-level application structure.
  • scrin::sanitize: display-width-safe terminal string helpers.

Demos

Run demos with the scripts in scripts/:

scripts/demo_widgets
scripts/demo_overlays
scripts/demo_scrin_shell
scripts/demo_toggle_exotic
scripts/demo_aisling
scripts/demo_loaders
scripts/demo_aisling_story

The Aisling story demo is the broadest visual smoke test: it walks the available effect inventory and rotates through loader systems using the Aisling bridge.

Publishing Notes

The crate is intended to publish cleanly to crates.io and build on docs.rs. The package excludes generated target/** artifacts and includes source, examples, tests, scripts, and this README.

Recommended pre-publish checks:

cargo fmt
cargo check
cargo check --examples
cargo test
cargo doc --no-deps
cargo publish --dry-run --allow-dirty