term_transcript/term/
mod.rs

1use std::{borrow::Cow, fmt::Write as WriteStr};
2
3use termcolor::NoColor;
4
5use crate::{
6    utils::{normalize_newlines, WriteAdapter},
7    TermError,
8};
9
10mod parser;
11#[cfg(test)]
12mod tests;
13
14pub(crate) use self::parser::TermOutputParser;
15
16/// Marker trait for supported types of terminal output.
17pub trait TermOutput: Clone + Send + Sync + 'static {}
18
19/// Output captured from the terminal.
20#[derive(Debug, Clone)]
21pub struct Captured(String);
22
23impl AsRef<str> for Captured {
24    fn as_ref(&self) -> &str {
25        &self.0
26    }
27}
28
29impl From<String> for Captured {
30    fn from(raw: String) -> Self {
31        // Normalize newlines to `\n`.
32        Self(match normalize_newlines(&raw) {
33            Cow::Owned(normalized) => normalized,
34            Cow::Borrowed(_) => raw,
35        })
36    }
37}
38
39impl Captured {
40    fn write_as_plaintext(&self, output: &mut dyn WriteStr) -> Result<(), TermError> {
41        let mut plaintext_writer = NoColor::new(WriteAdapter::new(output));
42        TermOutputParser::new(&mut plaintext_writer).parse(self.0.as_bytes())
43    }
44
45    /// Converts this terminal output to plaintext.
46    ///
47    /// # Errors
48    ///
49    /// Returns an error if there was an issue processing output.
50    pub fn to_plaintext(&self) -> Result<String, TermError> {
51        let mut output = String::with_capacity(self.0.len());
52        self.write_as_plaintext(&mut output)?;
53        Ok(output)
54    }
55}
56
57impl TermOutput for Captured {}