3013a54c78
Modern terminals (iTerm2, Terminal.app 13+, Ghostty, Kitty, WezTerm,
Alacritty, recent gnome-terminal/konsole) make a URL clickable when it's
wrapped in:
\x1b]8;;TARGET\x1b\\LABEL\x1b]8;;\x1b\\
Terminals that don't understand the sequence simply render the visible
LABEL and ignore the escape, so emitting OSC 8 is a strict UX upgrade
for supporting terminals and a no-op for the rest.
### What's wired
- New `crates/tui/src/tui/osc8.rs` module with `wrap_link(target, label)`,
`strip_into(s, &mut out)`, and a process-wide `ENABLED` AtomicBool that
defaults to `true`.
- `markdown_render::render_line_with_links` now wraps recognized URLs
(`http(s)://…`) in OSC 8 when the runtime flag is on. Display width is
computed from the bare URL — the escapes are zero-width on supporting
terminals.
- `ui_text::line_to_string` and `line_to_plain` strip OSC 8 wrappers when
the span content contains an escape, so selection / clipboard output
carries clean URLs and not the raw escape codes.
- `[tui] osc8_links: bool` config (default `true`) added to `TuiConfig`,
documented in `docs/CONFIGURATION.md`, and surfaced in
`config.example.toml`. `run_tui` applies it at startup.
### Tests
- 7 unit tests in `osc8::tests` covering wrap, strip-with-ESC-terminator,
strip-with-BEL-terminator, plain passthrough, mixed escapes, default
state, and round-trip set/unset.
- 2 markdown_render tests proving URLs in paragraph blocks emit the OSC 8
wrapper when enabled and emit plain text when disabled.
- 2 ui_text tests proving `line_to_plain` strips OSC 8 wrappers from spans
and passes plain spans through unchanged.
Tests that touch the global ENABLED flag serialize through a static
Mutex inside the test module so cargo's parallel runner can't observe a
torn read.
### Verification
cargo fmt --all -- --check ✓
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings ✓
cargo test --workspace --all-features --locked ✓ (1820 + supporting; was 1809)
Closes #498
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>