Add support for play -r.

The new -r or --resize option causes asciinema to send CSI 8 ; width ; height t
for "r" commands in the asciicast. This causes the terminal window to resize as
it did during the recording. It also sets the size initially. Resizing is off by
default for backward compatibility.
This commit is contained in:
George Nachman
2024-09-19 10:02:43 -07:00
committed by Marcin Kulik
parent 6132e4d8d6
commit 5ec65c9a29
3 changed files with 37 additions and 3 deletions

View File

@@ -124,6 +124,10 @@ pub struct Play {
/// Automatically pause on markers /// Automatically pause on markers
#[arg(short = 'm', long)] #[arg(short = 'm', long)]
pub pause_on_markers: bool, pub pause_on_markers: bool,
/// Resize terminal window with control sequences.
#[arg(short = 'r', long)]
pub resize: bool,
} }
#[derive(Debug, Args)] #[derive(Debug, Args)]

View File

@@ -30,6 +30,7 @@ impl cli::Play {
idle_time_limit, idle_time_limit,
self.pause_on_markers, self.pause_on_markers,
&keys, &keys,
self.resize,
)?; )?;
if !self.loop_ || !ended { if !self.loop_ || !ended {

View File

@@ -35,13 +35,21 @@ pub fn play(
idle_time_limit: Option<f64>, idle_time_limit: Option<f64>,
pause_on_markers: bool, pause_on_markers: bool,
keys: &KeyBindings, keys: &KeyBindings,
enable_resize: bool,
) -> Result<bool> { ) -> Result<bool> {
let initial_cols = recording.header.cols;
let initial_rows = recording.header.rows;
let mut events = open_recording(recording, speed, idle_time_limit)?; let mut events = open_recording(recording, speed, idle_time_limit)?;
let mut stdout = io::stdout(); let mut stdout = io::stdout();
let mut epoch = Instant::now(); let mut epoch = Instant::now();
let mut pause_elapsed_time: Option<u64> = None; let mut pause_elapsed_time: Option<u64> = None;
let mut next_event = events.next().transpose()?; let mut next_event = events.next().transpose()?;
// Send initial resize sequence if enabled and dimensions are available
if enable_resize {
send_resize_sequence(&mut stdout, initial_cols, initial_rows)?;
}
while let Some(Event { time, data }) = &next_event { while let Some(Event { time, data }) = &next_event {
if let Some(pet) = pause_elapsed_time { if let Some(pet) = pause_elapsed_time {
if let Some(input) = read_input(&mut tty, 1_000_000)? { if let Some(input) = read_input(&mut tty, 1_000_000)? {
@@ -56,9 +64,15 @@ pub fn play(
} else if keys.step.as_ref().is_some_and(|k| k == &input) { } else if keys.step.as_ref().is_some_and(|k| k == &input) {
pause_elapsed_time = Some(*time); pause_elapsed_time = Some(*time);
if let EventData::Output(data) = data { match data {
stdout.write_all(data.as_bytes())?; EventData::Output(data) => {
stdout.flush()?; stdout.write_all(data.as_bytes())?;
stdout.flush()?;
}
EventData::Resize(cols, rows) if enable_resize => {
send_resize_sequence(&mut stdout, *cols, *rows)?;
}
_ => {}
} }
next_event = events.next().transpose()?; next_event = events.next().transpose()?;
@@ -76,6 +90,10 @@ pub fn play(
break; break;
} }
EventData::Resize(cols, rows) if enable_resize => {
send_resize_sequence(&mut stdout, cols, rows)?;
}
_ => {} _ => {}
} }
} }
@@ -110,6 +128,10 @@ pub fn play(
stdout.write_all(data.as_bytes())?; stdout.write_all(data.as_bytes())?;
} }
EventData::Resize(cols, rows) if enable_resize => {
send_resize_sequence(&mut stdout, *cols, *rows)?;
}
EventData::Marker(_) => { EventData::Marker(_) => {
if pause_on_markers { if pause_on_markers {
pause_elapsed_time = Some(*time); pause_elapsed_time = Some(*time);
@@ -129,6 +151,13 @@ pub fn play(
Ok(true) Ok(true)
} }
fn send_resize_sequence(stdout: &mut impl Write, cols: u16, rows: u16) -> io::Result<()> {
let resize_sequence = format!("\x1b[8;{};{}t", rows, cols);
stdout.write_all(resize_sequence.as_bytes())?;
stdout.flush()?;
Ok(())
}
fn open_recording( fn open_recording(
recording: asciicast::Asciicast<'_>, recording: asciicast::Asciicast<'_>,
speed: f64, speed: f64,