diff --git a/src/cmd/rec.rs b/src/cmd/rec.rs index 027d62f..377e075 100644 --- a/src/cmd/rec.rs +++ b/src/cmd/rec.rs @@ -1,4 +1,3 @@ -use crate::format; use crate::format::{asciicast, raw}; use crate::locale; use crate::pty; @@ -89,7 +88,7 @@ impl Cli { .truncate(overwrite) .open(&self.filename)?; - let writer: Box = if self.raw { + let writer: Box = if self.raw { Box::new(raw::Writer::new(file)) } else { let time_offset = if append { @@ -105,10 +104,12 @@ impl Cli { writer, append, self.stdin, - self.idle_time_limit, - self.command.clone(), - self.title, - capture_env(&self.env), + recorder::Metadata { + idle_time_limit: self.idle_time_limit, + command: self.command.clone(), + title: self.title, + env: capture_env(&self.env), + }, ); let exec_command = build_exec_command(self.command); diff --git a/src/format.rs b/src/format.rs index c971b69..cd7f37c 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,20 +1,2 @@ pub mod asciicast; pub mod raw; -use std::{collections::HashMap, io}; - -pub trait Writer { - fn header(&mut self, header: &Header) -> io::Result<()>; - fn output(&mut self, time: u64, data: &[u8]) -> io::Result<()>; - fn input(&mut self, time: u64, data: &[u8]) -> io::Result<()>; - fn resize(&mut self, time: u64, size: (u16, u16)) -> io::Result<()>; -} - -pub struct Header { - pub cols: u16, - pub rows: u16, - pub timestamp: Option, - pub idle_time_limit: Option, - pub command: Option, - pub title: Option, - pub env: HashMap, -} diff --git a/src/format/asciicast.rs b/src/format/asciicast.rs index 2ec29c8..471c6c1 100644 --- a/src/format/asciicast.rs +++ b/src/format/asciicast.rs @@ -1,3 +1,4 @@ +use crate::recorder; use anyhow::Result; use serde::{Deserialize, Deserializer}; use std::collections::HashMap; @@ -63,12 +64,16 @@ where } } -impl super::Writer for Writer +impl recorder::EventWriter for Writer where W: Write, { - fn header(&mut self, header: &super::Header) -> io::Result<()> { - self.write_header(&header.into()) + fn start(&mut self, header: &recorder::Header, append: bool) -> io::Result<()> { + if append { + Ok(()) + } else { + self.write_header(&header.into()) + } } fn output(&mut self, time: u64, data: &[u8]) -> io::Result<()> { @@ -267,7 +272,7 @@ fn format_time(time: u64) -> String { format!("{}.{:0>6}", time / 1_000_000, time % 1_000_000) } -impl From<&Header> for super::Header { +impl From<&Header> for recorder::Header { fn from(header: &Header) -> Self { Self { cols: header.width, @@ -281,8 +286,8 @@ impl From<&Header> for super::Header { } } -impl From<&super::Header> for Header { - fn from(header: &super::Header) -> Self { +impl From<&recorder::Header> for Header { + fn from(header: &recorder::Header) -> Self { Self { width: header.cols, height: header.rows, diff --git a/src/format/raw.rs b/src/format/raw.rs index 48ca011..77cf1a0 100644 --- a/src/format/raw.rs +++ b/src/format/raw.rs @@ -1,3 +1,4 @@ +use crate::recorder; use std::io::{self, Write}; pub struct Writer { @@ -10,9 +11,13 @@ impl Writer { } } -impl super::Writer for Writer { - fn header(&mut self, header: &super::Header) -> io::Result<()> { - write!(self.writer, "\x1b[8;{};{}t", header.rows, header.cols) +impl recorder::EventWriter for Writer { + fn start(&mut self, header: &recorder::Header, append: bool) -> io::Result<()> { + if append { + Ok(()) + } else { + write!(self.writer, "\x1b[8;{};{}t", header.rows, header.cols) + } } fn output(&mut self, _time: u64, data: &[u8]) -> io::Result<()> { diff --git a/src/recorder.rs b/src/recorder.rs index 7ff0b00..26d24e4 100644 --- a/src/recorder.rs +++ b/src/recorder.rs @@ -1,4 +1,3 @@ -use crate::format; use crate::pty; use std::collections::HashMap; use std::io; @@ -7,19 +6,40 @@ use std::thread; use std::time::{Instant, SystemTime, UNIX_EPOCH}; pub struct Recorder { - writer: Option>, + writer: Option>, start_time: Instant, append: bool, record_input: bool, - idle_time_limit: Option, - command: Option, - title: Option, - env: HashMap, + metadata: Metadata, sender: mpsc::Sender, receiver: Option>, handle: Option, } +pub trait EventWriter { + fn start(&mut self, header: &Header, append: bool) -> io::Result<()>; + fn output(&mut self, time: u64, data: &[u8]) -> io::Result<()>; + fn input(&mut self, time: u64, data: &[u8]) -> io::Result<()>; + fn resize(&mut self, time: u64, size: (u16, u16)) -> io::Result<()>; +} + +pub struct Header { + pub cols: u16, + pub rows: u16, + pub timestamp: Option, + pub idle_time_limit: Option, + pub command: Option, + pub title: Option, + pub env: HashMap, +} + +pub struct Metadata { + pub idle_time_limit: Option, + pub command: Option, + pub title: Option, + pub env: HashMap, +} + enum Message { Output(u64, Vec), Input(u64, Vec), @@ -30,13 +50,10 @@ struct JoinHandle(Option>); impl Recorder { pub fn new( - writer: Box, + writer: Box, append: bool, record_input: bool, - idle_time_limit: Option, - command: Option, - title: Option, - env: HashMap, + metadata: Metadata, ) -> Self { let (sender, receiver) = mpsc::channel(); @@ -45,10 +62,7 @@ impl Recorder { start_time: Instant::now(), append, record_input, - idle_time_limit, - command, - title, - env, + metadata, sender, receiver: Some(receiver), handle: None, @@ -70,19 +84,17 @@ impl pty::Recorder for Recorder { let mut writer = self.writer.take().unwrap(); let receiver = self.receiver.take().unwrap(); - if !self.append { - let header = format::Header { - cols: size.0, - rows: size.1, - timestamp: Some(timestamp), - idle_time_limit: self.idle_time_limit, - command: self.command.clone(), - title: self.title.clone(), - env: self.env.clone(), - }; + let header = Header { + cols: size.0, + rows: size.1, + timestamp: Some(timestamp), + idle_time_limit: self.metadata.idle_time_limit, + command: self.metadata.command.clone(), + title: self.metadata.title.clone(), + env: self.metadata.env.clone(), + }; - writer.header(&header)?; - } + writer.start(&header, self.append)?; let handle = thread::spawn(move || { for msg in receiver {