mirror of
https://github.com/asciinema/asciinema.git
synced 2025-12-15 19:28:00 +01:00
Use avt's TextCollector to make TextEncoder incremental
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -135,8 +135,8 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "avt"
|
||||
version = "0.8.3"
|
||||
source = "git+https://github.com/asciinema/avt?tag=v0.8.3#28aed2b5a65a4ff07344fd6bc51b8ccb8542389c"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/asciinema/avt?tag=v0.9.0#4e086767d775b149f3fb92bae9b5d94a96f9b358"
|
||||
dependencies = [
|
||||
"rgb",
|
||||
"serde",
|
||||
|
||||
@@ -25,4 +25,4 @@ config = { version = "0.13.4", default-features = false, features = ["toml", "in
|
||||
which = "5.0.0"
|
||||
tempfile = "3.9.0"
|
||||
scraper = { version = "0.15.0", default-features = false }
|
||||
avt = { git = "https://github.com/asciinema/avt", tag = "v0.8.3" }
|
||||
avt = { git = "https://github.com/asciinema/avt", tag = "v0.9.0" }
|
||||
|
||||
@@ -60,7 +60,7 @@ impl Cli {
|
||||
))),
|
||||
|
||||
Format::Raw => Ok(Box::new(encoder::RawEncoder::new(file, false))),
|
||||
Format::Txt => Ok(Box::new(encoder::TxtEncoder::new(file))),
|
||||
Format::Txt => Ok(Box::new(encoder::TextEncoder::new(file))),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ impl Cli {
|
||||
}
|
||||
|
||||
Format::Raw => Ok(Box::new(encoder::RawEncoder::new(file, append))),
|
||||
Format::Txt => Ok(Box::new(encoder::TxtEncoder::new(file))),
|
||||
Format::Txt => Ok(Box::new(encoder::TextEncoder::new(file))),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ mod txt;
|
||||
pub use asciicast::AsciicastEncoder;
|
||||
pub use asciicast::Metadata;
|
||||
pub use raw::RawEncoder;
|
||||
pub use txt::TxtEncoder;
|
||||
pub use txt::TextEncoder;
|
||||
|
||||
use crate::asciicast::Event;
|
||||
use crate::recorder;
|
||||
|
||||
@@ -1,70 +1,67 @@
|
||||
use crate::asciicast::{Event, EventData};
|
||||
use crate::tty;
|
||||
use avt::util::{TextCollector, TextCollectorOutput};
|
||||
use std::io::{self, Write};
|
||||
|
||||
pub struct TxtEncoder<W> {
|
||||
writer: W,
|
||||
vt: Option<avt::Vt>,
|
||||
pub struct TextEncoder<W: Write> {
|
||||
writer: Option<W>,
|
||||
collector: Option<TextCollector<TextWriter<W>>>,
|
||||
}
|
||||
|
||||
impl<W> TxtEncoder<W> {
|
||||
impl<W: Write> TextEncoder<W> {
|
||||
pub fn new(writer: W) -> Self {
|
||||
TxtEncoder { writer, vt: None }
|
||||
TextEncoder {
|
||||
writer: Some(writer),
|
||||
collector: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> super::Encoder for TxtEncoder<W> {
|
||||
impl<W: Write> super::Encoder for TextEncoder<W> {
|
||||
fn start(&mut self, _timestamp: Option<u64>, tty_size: &tty::TtySize) -> io::Result<()> {
|
||||
let vt = avt::Vt::builder()
|
||||
.size(tty_size.0 as usize, tty_size.1 as usize)
|
||||
.resizable(true)
|
||||
.scrollback_limit(100)
|
||||
.build();
|
||||
|
||||
self.vt = Some(vt);
|
||||
self.collector = Some(TextCollector::new(
|
||||
vt,
|
||||
TextWriter(self.writer.take().unwrap()),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn event(&mut self, event: &Event) -> io::Result<()> {
|
||||
use EventData::*;
|
||||
|
||||
match &event.data {
|
||||
EventData::Output(data) => {
|
||||
self.vt.as_mut().unwrap().feed_str(data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
EventData::Resize(cols, rows) => {
|
||||
self.vt
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.feed_str(&format!("\x1b[8;{rows};{cols}t"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Output(data) => self.collector.as_mut().unwrap().feed_str(data),
|
||||
Resize(cols, rows) => self.collector.as_mut().unwrap().resize(*cols, *rows),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(&mut self) -> io::Result<()> {
|
||||
let mut text = self.vt.as_ref().unwrap().text();
|
||||
self.collector.as_mut().unwrap().flush()
|
||||
}
|
||||
}
|
||||
|
||||
while !text.is_empty() && text[text.len() - 1].is_empty() {
|
||||
text.truncate(text.len() - 1);
|
||||
}
|
||||
struct TextWriter<W: Write>(W);
|
||||
|
||||
for line in text {
|
||||
self.writer.write_all(line.as_bytes())?;
|
||||
self.writer.write_all(b"\n")?;
|
||||
}
|
||||
impl<W: Write> TextCollectorOutput for TextWriter<W> {
|
||||
type Error = io::Error;
|
||||
|
||||
Ok(())
|
||||
fn push(&mut self, line: String) -> Result<(), Self::Error> {
|
||||
self.0.write_all(line.as_bytes())?;
|
||||
self.0.write_all(b"\n")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::TxtEncoder;
|
||||
use super::TextEncoder;
|
||||
use crate::asciicast::Event;
|
||||
use crate::encoder::Encoder;
|
||||
use crate::tty::TtySize;
|
||||
@@ -72,7 +69,7 @@ mod test {
|
||||
#[test]
|
||||
fn encoder_impl() {
|
||||
let mut out: Vec<u8> = Vec::new();
|
||||
let mut enc = TxtEncoder::new(&mut out);
|
||||
let mut enc = TextEncoder::new(&mut out);
|
||||
|
||||
enc.start(None, &TtySize(3, 1)).unwrap();
|
||||
enc.event(&Event::output(0, b"he\x1b[1mllo\r\n")).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user