retroglyph-core 0.7.1

A 2D pseudographic terminal library -- core types, no backend
Documentation
//! retroglyph-core: the `no_std`-compatible foundation of retroglyph.
//!
//! Grid, tile, style, color, text, terminal, and event types, plus the
//! [`Output`](crate::backend::Output)/[`Input`](crate::backend::Input)/[`Cursor`](crate::backend::Cursor) backend
//! facets (bundled together as [`Backend`](crate::backend::Backend)) and the dependency-free
//! [`Headless`](crate::backend::Headless) test backend, and the `App`/`Flow`/`Frame` game loop contract.
//! Platform backends (`retroglyph-crossterm`, `retroglyph-software`) and drawing helpers
//! (`retroglyph-ui`) are separate crates that depend on this one.
//!
//! # Features
//!
//! <!-- gen-features:start -->
//! 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`](crate::grid::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`](crate::color::Color), [`Style`](crate::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`](crate::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`](crate::grid::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`](crate::app::App) against
//! [`Headless`](crate::backend::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.
//! <!-- gen-features:end -->
//!
//! # Architecture
//!
//! [`Terminal<B>`](crate::terminal::Terminal) owns a double-buffered [`Grid`](crate::grid::Grid) and the
//! [`Backend`](crate::backend::Backend) lifecycle (resize, present, events), diffing each frame drawn through
//! [`Surface`](crate::surface::Surface) against the previous one so only changed cells reach the
//! [`Backend`](crate::backend::Backend). `B` is the only thing that changes between a headless test and a real
//! window or terminal: [`Headless`](crate::backend::Headless) here, `Crossterm` (retroglyph-crossterm) for a
//! real TTY, `SoftwareRenderer`/`GlRenderer`/`WgpuRenderer` for a window or browser tab. See
//! <https://main.retroglyph.dev/book/explanation/architecture.html> for the full data-flow diagram
//! and how those backends compare.
//!
//! See `examples/headless.rs` (`cargo run -p retroglyph-core --example
//! headless`) for the smallest possible use of [`Headless`](crate::backend::Headless), depending on
//! nothing but this crate.
#![cfg_attr(not(feature = "std"), no_std)]
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/crates-lurey-io/retroglyph/main/docs/public/assets/logo.svg"
)]
#![doc(
    html_favicon_url = "https://raw.githubusercontent.com/crates-lurey-io/retroglyph/main/docs/public/assets/logo.svg"
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
// A `pub mod` line's own outer doc comment and its target module's inner `//!` doc concatenate
// into one rendered page, but intra-doc links in that combined block resolve against the scope
// where the *outer* comment lives (this file, the crate root) rather than the module's own scope.
// Every module doc below that also carries an outer doc comment on its `pub mod` line therefore
// needs fully qualified links even for types the module defines itself, which then reads as
// "redundant" from the module file's own point of view. Rather than track that split per link,
// every intra-doc link in this crate is fully qualified and this lint is off crate-wide.
#![allow(rustdoc::redundant_explicit_links)]
extern crate alloc;

// A float backend is not optional (retroglyph#903): the separable `BlendMode` channel math
// dispatches through `crate::math`, which has nothing to dispatch *to* without one, and
// `Color`'s color-space conversions go through `gem/space`, which needs `gem/std` or `gem/libm`
// for the same reason. Failing here names the two features that fix it, ahead of the same build
// failing as an unresolved `libm::` path inside `math.rs` or inside `gem::space`'s own
// `compile_error!`.
#[cfg(not(any(feature = "std", feature = "libm")))]
compile_error!("retroglyph-core needs a float backend: enable `std` or `libm`.");

// Compile the code blocks in this crate's own README as doctests so its quick start is
// type-checked on every test run and cannot silently rot. The `cfg(doctest)` gate keeps this out
// of the rendered crate documentation: see `retroglyph-crossterm`'s matching include for the
// same pattern applied to the workspace root README.
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
struct ReadmeDoctests;

/// The `App`-driven game loop.
pub mod app;
// See the `too_long_first_doc_paragraph` comment above `animate`: same noisy-lint mis-attribution,
// here because this module's own first doc paragraph grew past the threshold once its intra-doc
// links became fully qualified (retroglyph#1035).
#[allow(clippy::too_long_first_doc_paragraph)]
/// Pluggable rendering backends.
pub mod backend;
pub mod color;
// See the `too_long_first_doc_paragraph` comment above `animate`: same noisy-lint mis-attribution.
#[allow(clippy::too_long_first_doc_paragraph)]
/// Which diagnostics a build compiles in.
pub mod dev;
pub mod event;
// See the `too_long_first_doc_paragraph` comment above `animate`: same noisy-lint mis-attribution.
#[allow(clippy::too_long_first_doc_paragraph)]
/// `FrameClock`/`FrameStats` accumulators for the `App`/`Frame` game loop.
pub mod frames;
pub mod grid;
pub mod layout;
// `pub` so `retroglyph-ui` can share this crate's one std-or-libm dispatch point instead of
// vendoring its own copy, `#[doc(hidden)]` so that sharing costs no public API surface:
// `cargo-semver-checks` ignores hidden items (see the module's own doc comment for the traps that
// come with that). Never add a `pub use` that re-exports its contents through a non-hidden path,
// and never `#[deprecated]` it, both of which would make it public API again despite the hiding.
#[doc(hidden)]
pub mod math;
// See the `too_long_first_doc_paragraph` comment above `animate`: same noisy-lint mis-attribution.
#[allow(clippy::too_long_first_doc_paragraph)]
/// The one grid-drawing primitive: an area-clipped, single-layer view over a [`Grid`](crate::grid::Grid).
pub mod surface;
#[allow(clippy::too_long_first_doc_paragraph)]
/// Border, gridline, and partial-block `char` data shared by widgets and backends.
pub mod symbols;
pub mod terminal;
// See the `too_long_first_doc_paragraph` comment above `animate`: same noisy-lint mis-attribution.
#[allow(clippy::too_long_first_doc_paragraph)]
/// Headless test harness driving an `App` with synthetic input.
#[cfg(feature = "testing")]
pub mod testing;
pub mod text;
/// The atomic drawable unit (glyph, style, sub-cell offsets).
pub mod tile;

// No root re-exports below this line by design (retroglyph#1035): every public item lives at its
// module path, matching `ratatui-core`. `dev_only!` (`dev.rs`) and `spans!` (`text.rs`) still
// resolve at the crate root regardless, since `#[macro_export]` always places a macro there; that's
// a macro-export constraint, not a re-export choice.