feat(play): add spacebar pause/resume during playback#279
Conversation
Co-authored-by: ibigbug <543405+ibigbug@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds interactive pause/resume to the play command so users can pause playback with the space bar instead of aborting with Ctrl+C.
Changes:
- Introduces a shared pause state (
Arc<(Mutex<bool>, Condvar)>) toggled by a stdin-reader thread. - Implements Windows raw-ish console mode (disable line/echo) to detect space without requiring Enter; non-Windows reads in cooked mode.
- Replaces the single sleep with an interruptible “remaining time” loop that supports pausing mid-delay.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot check the review comments |
Co-authored-by: ibigbug <543405+ibigbug@users.noreply.github.com>
Addressed all the review feedback in e3f9cec:
|
|
@copilot resolve conflicts |
Co-authored-by: ibigbug <543405+ibigbug@users.noreply.github.com>
Resolved in 72424f9. The branch now includes all changes from upstream
All pause/resume functionality and the earlier review-comment fixes are preserved on top. |
|
@codex[agent] resolve conflicts |
Co-authored-by: ibigbug <543405+ibigbug@users.noreply.github.com>
Co-authored-by: ibigbug <543405+ibigbug@users.noreply.github.com>
Co-authored-by: ibigbug <543405+ibigbug@users.noreply.github.com>
Conflicts resolved by rebasing onto origin/main and updating the branch (9cdf0c3). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let line_data: Vec<LineItem> = match serde_json::from_str(&content) { | ||
| Ok(data) => data, | ||
| Err(e) => { | ||
| eprintln!("corrupt record data: {}", e); | ||
| exit(1); |
There was a problem hiding this comment.
testdata/play.txt currently contains a trailing blank line (27th line). With the new stricter parsing, an empty line will hit serde_json::from_str and cause an immediate exit(1). Please skip empty/whitespace-only lines when iterating session events (e.g., loop until a non-empty line or EOF) so playback/tests don’t fail on harmless trailing newlines.
| // Spawn a thread that reads stdin and toggles pause when space is pressed. | ||
| // Console mode is already configured by the main thread above. | ||
| thread::spawn(move || { | ||
| #[cfg(windows)] | ||
| unsafe { |
There was a problem hiding this comment.
On Windows, the stdin reader thread is spawned unconditionally, even when GetConsoleMode fails and you log that “space-to-pause is disabled”. This can lead to a leaked/background thread blocked in ReadFile (especially in tests or when stdin is redirected) and contradicts the warning. Consider only spawning the reader thread when pause support is actually enabled (e.g., gate on stdin_restore.is_some()), and add a shutdown signal / join to avoid accumulating threads if Play::execute() is called multiple times in-process.
| // Restore the original console mode now that playback is done. | ||
| #[cfg(windows)] | ||
| unsafe { | ||
| if let Some((handle_val, mode_val)) = stdin_restore { | ||
| SetConsoleMode(HANDLE(handle_val as _), CONSOLE_MODE(mode_val)).ok(); |
There was a problem hiding this comment.
Console mode restoration happens only at the end of execute(). If playback panics (e.g., write_all(...).unwrap() or flush().unwrap()), the console can be left in the modified “raw” mode. Consider using an RAII guard (Drop impl) to restore the original console mode reliably on all exit paths, and handle/propagate any SetConsoleMode failures instead of silently ignoring them.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if let Ok(header) = serde_json::from_str::<RecordHeader>(&first_line) { | ||
| // v2 format: header on first line, events on subsequent lines | ||
| Session { | ||
| header, | ||
| line_iter: SessionLineSource::File(line_iter), | ||
| } |
There was a problem hiding this comment.
Session format detection treats any JSON object that deserializes into RecordHeader as v2, without validating the version field. A v1 recording that includes a timestamp (or any v2-like header with version: 1) would be misclassified as v2, and playback would then read no events (since v1 has no subsequent event lines). Consider checking header.version == 2 (or otherwise explicitly validating v2) before selecting the v2 parsing path, and falling back to v1 parsing when version == 1.
|
@claude[agent] address comments and update pr title and description properly |
- Skip empty/whitespace-only lines in v2 format parsing - Only spawn stdin reader thread on Windows when pause is enabled - Add RAII guard (ConsoleGuard) for reliable console mode restoration - Validate version field (must be 2) when detecting v2 format - Extract v1 format parsing into helper method to reduce duplication Co-authored-by: ibigbug <543405+ibigbug@users.noreply.github.com>
Addressed all review comments in 1a23b13:
PR description has been updated with the implementation checklist. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot resolve conflict and fix PR title and body |
…reader/from_url, fix version validation and empty-line handling Co-authored-by: ibigbug <543405+ibigbug@users.noreply.github.com>
Resolved in 8203792. The branch is now up to date with main and includes all changes from
PR title and description updated to reflect the full scope of changes. |
|
@claude[agent] resolve conflict and keep PR title unchanged |
…yback-feature # Conflicts: # src/commands/play.rs
Resolved in 3432917. Successfully merged the latest changes from main, including:
All merge conflicts in src/commands/play.rs have been resolved while preserving the pause/resume functionality and all previous review fixes (empty-line skipping, version validation, ConsoleGuard RAII, etc.) |
|
@copilot change the PR title and body properly |
wait_interruptiblehelper withArc<(Mutex<bool>, Condvar)>)ConsoleGuardRAII struct for reliable console mode restore; reader thread only spawned when raw mode succeedsis_terminal()check to avoid consuming piped input in CI/scripted environmentsplay.txt)header.version == 2test_wait_interruptible_no_pause,test_wait_interruptible_pause_and_resume,test_is_url,test_normalize_url_asciinemaOriginal prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.