Skip to main content

Crate abstracttui_graph

Crate abstracttui_graph 

Source
Expand description

§abstracttui-graph

Graph auto-layout for AbstractTUI: the layout half of the diagram lane (backlog 0440), an ADR-0004 sibling crate built on core’s public API only.

§The one contract

Every layout pass is GraphDesc -> Layout: nodes with cell sizes and edges in, per-node positions/ranks, per-edge waypoint polylines, a bounding box and honesty markers out. Consumers select the ALGORITHM, never a different data contract:

  • layered — sugiyama-lite, the workflow/DAG path (v1).
  • force — bounded seeded force placement, the knowledge-graph path (v1.5).
  • grid — labeled near-square placement, the honest fallback.

§Honesty markers

A layout never lies about degradation: cycle-broken edges are marked (EdgeLayout::broken, Layout::broken_edges), and Layout::fallback names every degradation that occurred (node cap exceeded, duplicate node ids dropped, unresolvable edges skipped, grid placement). None means the requested algorithm ran cleanly.

§Determinism

Same graph + same options = identical Layout, golden-test-pinned. No map-iteration order leaks into results, every tiebreak is input order, and float arithmetic sticks to IEEE-exact operations (+ - * / sqrt, no transcendentals), so goldens hold across platforms.

§Bounds

Everything is bounded: crossing-reduction sweeps (LayeredOpts::sweeps, default 4), the layered node cap (LayeredOpts::node_cap, default 512, past which the grid fallback engages with a label), and the force iteration budget (ForceOpts::budget, default 256, freezing earlier on settle). The force pass is an act, not an animation: run it on demand, cache the Layout, re-render from the cache (zero idle cost is the caller’s story and the engine’s rule).

use abstracttui_graph::{layered, GraphDesc, LayeredOpts};

let desc = GraphDesc::new()
    .node("fetch", 9, 3)
    .node("build", 9, 3)
    .node("test", 8, 3)
    .edge("fetch", "build")
    .edge("build", "test");
let layout = layered(&desc, &LayeredOpts::default());
assert_eq!(layout.node("fetch").unwrap().rank, 0);
assert_eq!(layout.node("test").unwrap().rank, 2);
assert!(layout.fallback.is_none(), "clean run, no degradation");

Re-exports§

pub use desc::Direction;
pub use desc::EdgeDesc;
pub use desc::GraphDesc;
pub use desc::NodeDesc;
pub use layout::force;
pub use layout::grid;
pub use layout::layered;
pub use layout::EdgeLayout;
pub use layout::ForceOpts;
pub use layout::IterationBudget;
pub use layout::LayeredOpts;
pub use layout::Layout;
pub use layout::NodeLayout;
pub use view::GraphAlgo;
pub use view::GraphStyle;
pub use view::GraphView;

Modules§

desc
The input half of the crate’s one data contract: GraphDesc.
dump
Plain-ASCII layout dumps: a debugging aid, not a renderer.
layout
Layout passes and the output half of the crate contract: Layout.
view
GraphView: read-only rendering of a Layout (the view half of backlog 0440).

Structs§

Point
Rect
Size