Skip to content

Add a composable ratatui TUI to ppvm-cli#166

Open
david-pl wants to merge 20 commits into
david/42-circuit-componentfrom
david/cli-tui
Open

Add a composable ratatui TUI to ppvm-cli#166
david-pl wants to merge 20 commits into
david/42-circuit-componentfrom
david/cli-tui

Conversation

@david-pl

@david-pl david-pl commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a composable ratatui TUI to ppvm-cli. Bare ppvm launches a unified single-screen REPL + step-debugger; ppvm <file> opens a program paused at the first instruction. The existing run/dump/parse/debug subcommands are unchanged.

  • New library crate crates/ppvm-tui holds the terminal-agnostic pieces: an AppState owning a ppvm_vihaco::composite::PPVM, the command grammar, and four ratatui Widget view components (Program/State/Measurement-record/Command line).
  • ppvm-cli (bin) owns only terminal setup (RAII restore on panic) and the blocking event loop.
  • Composability: view components own no terminal and run no loop (impl Widget for &…View-style; handle_key(KeyEvent) -> bool), and deps are pinned to ratatui/crossterm 0.29.0 to match stellarscope so panels can dock together later.

Features

  • REPL: device N then gate ops (h 0, cnot 0 1, rx 0 0.5, measure 0, …); outcomes echo as => bits.
  • Debugger: :load, Enter = step, :c = continue to next breakpoint/end, :reset; authored breakpoints pause.
  • Breakpoint gate injection: at a breakpoint you can apply ad-hoc gates and resume — backed by making apply_circuit_instruction preserve the program counter (ppvm-vihaco).
  • Line editing + history: movable cursor (←/→, Home/End, insert/Backspace/Delete) drawn via the terminal cursor; ↑/↓ command history with a draft stash.
  • :help toggles a command-reference overlay (works in both modes).

Base branch

Targets david/42-circuit-component (not main) — this branch was cut from it and depends on its vihaco-circuit-isa work. The merge commit here also pulls in that branch's Add back eyre fix (a pre-existing derive-macro build breakage), so the branch compiles.

Design docs

  • Spec: docs/superpowers/specs/2026-07-01-cli-tui-design.md
  • Plan: docs/superpowers/plans/2026-07-01-cli-tui.md

Testing

  • cargo test --workspace — green (0 failures).
  • ppvm-tui: 36 tests (command grammar, REPL/debug state transitions, breakpoint injection resume, cursor/history editing, help toggle, TestBackend render checks).
  • clippy --all-targets clean.

Built TDD, task-by-task, with per-task + whole-branch review.

Draft: opened for review before it's ready to merge.

🤖 Generated with Claude Code

david-pl and others added 15 commits July 1, 2026 09:57
Unified single-screen TUI for `ppvm-cli`: bare `ppvm` launches a REPL +
step-debugger on one screen (program listing, tableau state via
state_string(), measurement record, command line). New `crates/ppvm-tui`
lib holds terminal-agnostic `Widget` components + AppState; `ppvm-cli`
owns only the terminal and event loop. Deps pinned to ratatui/crossterm
0.29 to match stellarscope so panels can dock together later. PauliSum
REPL backend deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fold gdb-style breakpoint injection into the design: at a breakpoint,
typed gate ops update the tableau/record and stepping resumes where it
paused. Requires one small engine change in ppvm-vihaco — a
pc/code-preserving injection method (save pc + code len, run the op,
truncate the appended op, restore pc). Removes the corresponding
deferred item from scope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Seven TDD tasks: engine pc-preserving injection (ppvm-vihaco); scaffold
ppvm-tui + CodeView; command grammar; AppState REPL dispatch + key
handling; program loading/stepping/breakpoint injection; ratatui widgets
+ composer; ppvm-cli wiring (optional subcommand launches the TUI).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Save/restore the program counter and code-vector length around
execute_single_instruction so a paused debugger's position is
byte-for-byte unchanged after injecting a gate at a breakpoint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…path

The previous implementation used `?` after execute_single_instruction,
which skipped the truncate + pc restore when the call returned Err,
leaving leaked appended ops and a wrong pc in the loaded program.
Now the restore runs unconditionally via a local `result` binding.

Also adds a test (apply_circuit_instruction_preserves_pc_and_code_on_error)
that exercises the error path and asserts both invariants hold.

Separately, moves the #[cfg(test)] mod tests block in ppvm-cli/src/main.rs
to after fn main() to fix the clippy::items_after_test_module lint under
--all-targets.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a movable edit cursor (Left/Right/Home/End, insert/Backspace/Delete
at the cursor) rendered via the terminal's own cursor
(Frame::set_cursor_position, offset past the shared CommandLine::PROMPT),
and Up/Down command history over submitted lines with an in-progress
draft stash and consecutive-duplicate skipping. All hand-rolled, no new
dependency, unit-tested without a terminal plus a TestBackend cursor
placement check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`:help` (aliases `:h`, `:?`) toggles a floating, centered overlay listing
the meta/debug commands and the full gate grammar. Implemented as a
render-time overlay driven by a `show_help` flag, so it works in both
REPL and debug modes without touching the key-handling model or the
composability contract. `:help` is also surfaced in the footer hint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://QuEraComputing.github.io/ppvm/pr-preview/pr-166/

Built to branch gh-pages at 2026-07-03 08:01 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

david-pl and others added 4 commits July 1, 2026 15:38
…ack on gate injection

Two state-leak fixes surfaced in review of the TUI:

- `new_device` now clears `self.module`, so switching to a REPL device
  forgets any previously loaded program. Otherwise `:reset` resurrected the
  old program instead of resetting the fresh device.
- `apply_circuit_instruction` now restores the CPU operand stack depth on
  every path, alongside the existing pc/code restore. `circuit.measure` /
  `circuit.trace` push a result onto the stack for bytecode to consume, and
  an errored gate can leave its consts behind; with no consumer during an
  injected gate, a stray operand would desync a resumed program's stack and
  grow a REPL session's stack without bound. The measurement record (a
  separate observer effect) is unaffected, so the REPL's `=> bits` echo
  still works.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`ppvm-tui` pulls in ratatui/crossterm, which target native terminals and
don't compile for wasm32-unknown-unknown (crossterm's `sys` module has no
browser-wasm backend). Exclude it from the browser-wasm workspace build
alongside `ppvm-cli` and `ppvm-python-native`; the reusable engine stays
covered via the library crates.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@david-pl david-pl marked this pull request as ready for review July 2, 2026 10:42
@david-pl david-pl requested a review from Roger-luo July 2, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant