retroglyph-core 0.6.0

A 2D pseudographic terminal library -- core types, no backend
Documentation

retroglyph-core

crates.io docs.rs coverage license

The no_std-compatible foundation of retroglyph: grid, tile, style, color, text, terminal, and event types, plus the Backend trait and a dependency-free Headless test backend. Platform backends (retroglyph-crossterm, retroglyph-software) and drawing helpers (retroglyph-ui) are separate crates that depend on this one.

Quick start

cargo add retroglyph-core
# fn main() -> Result<(), core::convert::Infallible> {
use retroglyph_core::backend::Headless;
use retroglyph_core::color::{Color, Style};
use retroglyph_core::terminal::Terminal;

let mut term = Terminal::new(Headless::new(80, 24));
term.draw(|s| s.put((5, 5), '@', Style::new().fg(Color::GREEN)))?;
# Ok(())
# }

Headless never touches a real terminal or window, so this runs anywhere: including this README's own doctest (see src/lib.rs's #[cfg(doctest)] include). For a real backend, add retroglyph-crossterm or retroglyph-software and see the workspace README's quick start.

See docs.rs for the full API, or the workspace README for the crate list and a real backend quick start.

Grid, drawing, and double buffering

Grid holds up to 256 layers, each cell carrying a glyph, foreground/background color, and sub-cell pixel offsets; layer 0 is always allocated, layers 1+ are allocated on first write, so a single-layer game pays zero overhead. See the grid module docs for the full layering/compositing model.

Draw through Surface (handed out by Terminal::draw/Terminal::surface): place characters with put(), print strings with print(), or style a whole run at once with with_style(). See the surface module docs. Terminal::present() diffs the current frame against the previous one and forwards only the changed cells to the backend; pixel backends request full frames instead, since sub-cell offsets can leave orphaned pixels behind otherwise. Terminal::retain_layer() skips both that diff and the app's own redraw for one layer for the next frame, for content (e.g. a scrolled map) that's known unchanged.

This crate is no_std-compatible: disable the std feature and enable libm instead (also requires an allocator). Useful for embedded or kernel-space roguelikes; see the std and libm features below.

Features

Default features: egc, std.

dev

⚪ Optional.

Forces BuildMode::Dev on in a build that would otherwise resolve to Release.

Can be used so an optimized build still reports development diagnostics (see the dev module).

egc

🟢 Enabled by default.

Enables grapheme-cluster-aware text handling (via unicode-segmentation) for EGC-correct cell diffing and layout.

libm

⚪ Optional.

Uses libm's software float implementation (roundf/fmaf/sinf/cosf/powf) for the separable BlendMode channel math, via this crate's own math shim -- the no_std side of that split. See std below for the alternative that prefers the platform's own float intrinsics when available; a build needs exactly one of the two.

serde

⚪ Optional.

Adds Serialize/Deserialize impls for Color, Style, Size, Offset, and (via ixy) Pos/Rect, so a config file can round-trip a saved camera position, window geometry, sub-cell pixel offset, or theme color.

Color serializes through its Display/FromStr round trip (e.g. "bright-red", "#ff8000") rather than a derived structural form, so hand-edited TOML/JSON stays legible.

std

🟢 Enabled by default.

Enables gem/std and alpha-blend/std, and uses std's float intrinsics (via this crate's math shim) instead of libm's software implementation for the separable BlendMode channel math.

Disabling this feature (--no-default-features) builds this crate no_std, and then needs libm above as the float backend instead: see the crate-level compile_error! in src/lib.rs.

testing

⚪ Optional.

Enables testing's TestHarness, which drives an App against Headless for tests, with synthetic input queuing and frame-settling helpers.

Test-only surface, no_std + alloc compatible, off by default so it never ships in a release build by accident.