egui_sgr 0.2.1

A Rust library that converts ASCII/ANSI escape sequence color models into colored text in egui
Documentation
# egui_sgr Architecture

`egui_sgr` is organized around one pipeline:

```text
bytes / str -> vte parser -> ANSI style spans -> egui rendering
```

The crate intentionally does not emulate a terminal screen. It linearizes
visible text, interprets SGR style changes, strips non-rendered control
sequences, and maps the result into egui types.

## API Layers

- `ansi_to_spans` and `ansi_bytes_to_spans` are the semantic parse layer. They
  are useful for tests, custom renderers, and callers that want to cache parsed
  ANSI output independently from an egui theme.
- `spans_to_layout_job` is the egui render layer. It turns semantic spans into
  one `egui::text::LayoutJob`, preserving byte ranges and text layout as a
  single egui widget.
- `ansi_to_layout_job` and `ansi_bytes_to_layout_job` are convenience APIs that
  compose parse and render in one call.
- `AnsiStreamParser` is the synchronous streaming parser. It preserves style,
  incomplete escape sequences, and incomplete UTF-8 between chunks.
- `AnsiSpanBuffer` accumulates streaming output and can render the accumulated
  spans to a `LayoutJob`.
- `AnsiParser`, `ColoredText`, and `ansi_to_rich_text` are compatibility APIs
  for existing users and simple segmented rendering.

## Module Responsibilities

- `model`: public ANSI model types such as `AnsiSpan`, `AnsiStyle`, and
  `AnsiColor`.
- `theme`: egui color/theme mapping, including xterm and legacy palettes.
- `sgr`: SGR parameter interpretation and style-state transitions.
- `parser`: `vte::Parser` integration and streaming state.
- `egui_render`: conversion from ANSI spans into `LayoutJob`, `RichText`, and
  legacy `ColoredText`.
- `color_models`: legacy helper functions retained for compatibility.

## Rendering Policy

`LayoutJob` is the primary output because ANSI text is usually one logical
string with multiple styles inside it. Splitting that into many `RichText`
labels changes wrapping and layout behavior. `RichText` remains available for
compatibility and simpler use cases.

Some ANSI semantics are richer than egui's current text format. Curly, dotted,
and dashed underline styles are preserved in `AnsiSpan`, but all underline
variants render as an egui underline stroke.

## Streaming Policy

Streaming input is byte-oriented. This allows callers to feed process output,
PTY output, network logs, or async chunks without pre-splitting valid UTF-8.
`vte` handles partial UTF-8 and escape state between `push_bytes` calls.

`AnsiStreamParser::push_bytes` returns only spans produced by that call.
`AnsiSpanBuffer` is the higher-level helper for callers that want a growing
renderable buffer.

## Performance Policy

The parser uses `vte` instead of regex scanning so it can process incremental
byte streams and avoid reparsing partial escape sequences. The render layer
uses `LayoutJob::append`, letting egui maintain correct UTF-8 byte ranges.

Performance-sensitive paths are covered by Criterion benchmarks:

```sh
cargo bench --bench ansi
```

The benchmark suite covers one-shot parsing, one-shot `LayoutJob` rendering,
chunked streaming parse, and chunked streaming buffer rendering.

## Compatibility Policy

The 0.2 API is additive over the 0.1 compatibility surface:

- Existing `AnsiParser::parse(&str) -> Vec<ColoredText>` remains one-shot and
  resets style state for every call.
- Existing `ansi_to_rich_text` remains available and uses the legacy palette.
- New code should prefer `LayoutJob` APIs for egui rendering.

## Quality Gates

Before publishing, run:

```sh
cargo fmt -- --check
cargo check --all-targets
cargo test --all-targets
cargo test --doc
cargo clippy --all-targets --all-features -- -D warnings
cargo bench --bench ansi --no-run
cargo doc --no-deps --all-features
cargo package --allow-dirty
```