Marwes / combine

A parser combinator library for Rust
https://docs.rs/combine/*/combine/
MIT License
1.29k stars 93 forks source link

Parse `std::process::Child` stdout #354

Open AustinScola opened 1 year ago

AustinScola commented 1 year ago

Hi,

I am developing a TUI program and one of the features is that I can open vim for any file. The problem is that vim outputs some ANSI escape codes that I would like to strip out (the enable and disable alternative screen codes). I'm trying to use combine to do so but am running into some difficulty and was wondering if I could get some guidance.

Here is what I current have:

I can't seem to get this approach to compile b/c of some lifetime errors. Is this the right approach or is there a better way to do this w/ combine?

Here is a snippet of the code I described above:

let command_stdout: ChildStdout = child.stdout.take().unwrap();
let mut reader: BufReader<ChildStdout> = BufReader::new(command_stdout);
let mut buffer: [u8; 1] = [0; 1];

let mut stdout = io::stdout().lock();
let mut parser = any_partial_state(ansi_escaped_text::parser());
let mut parser_state = AnyPartialState::default();
let mut length: usize;
loop {
    length = {
        reader.read(&mut buffer).unwrap()
    };
    if length == 0 {
        break;
    }

    #[cfg(feature = "logging")]
    debug!("Got output {:?} from vim.", &buffer[..length]);

    // Parse the text so that we can strip out the ANSI escape codes for enabling and
    // disabling the alternative screen.
    let mut stream = PartialStream(&buffer[..]);
    let parsed_text = parser.parse_with_state(&mut stream, &mut parser_state);
    match parsed_text {
        Ok(ansi_escaped_text) => {
            match ansi_escaped_text {
                ANSIEscapedText::ANSIEscapeCode(ansi_escape_code) => {
                    match ansi_escape_code {
                        ANSIEscapeCode::EnableAlternativeScreen => {
                            #[cfg(feature = "logging")]
                            debug!("Stripping enable alternative screen ANSI escape code from vim's output.");
                        },
                        ANSIEscapeCode::DisableAlternativeScreen => {
                            #[cfg(feature = "logging")]
                            debug!("Stripping disable alternative screen ANSI escape code from vim's output.");
                        }
                    }
                },
                ANSIEscapedText::Character(character) => {
                    stdout.write(&[character]).unwrap();
                    stdout.flush().unwrap();
                }
            };
        },
        #[cfg(feature = "logging")]
        Err(error) => {
            error!("Failed to parse ANSI escaped text: {:?}", error);
        },
        #[cfg(not(feature = "logging"))]
        Err(_) => {},
    };
}