py_executer_lib/
cmd.rs

1use colored::Colorize;
2use std::io::{BufRead, BufReader};
3use std::process;
4
5/// Stream the output of a child process to stdout and stderr,
6/// coloring any lines from stderr red.
7///
8/// The function takes a mutable reference to a `Child` process and
9/// returns an `ExitCode` indicating the exit status of the process.
10///
11/// The function will block until the child process has finished
12/// executing.
13///
14/// # Errors
15///
16/// If there is an error waiting for the child process to finish,
17/// an error message will be printed to stderr and the process will
18/// exit with a status code of 1.
19pub fn stream_output(mut child: process::Child) -> process::ExitCode {
20    let stdout = child.stdout.take().expect("Failed to capture stdout");
21    let stdout_reader = BufReader::new(stdout);
22    let stdout_lines = stdout_reader.lines();
23    let stderr = child.stderr.take().expect("Failed to capture stderr");
24    let stderr_reader = BufReader::new(stderr);
25    let stderr_lines = stderr_reader.lines();
26    let stdout_handle = std::thread::spawn(move || {
27        for line in stdout_lines {
28            if let Ok(line) = line {
29                println!("{}", line);
30            }
31        }
32    });
33    let stderr_handle = std::thread::spawn(move || {
34        for line in stderr_lines {
35            if let Ok(line) = line {
36                eprintln!("{}", line.red());
37            }
38        }
39    });
40    stdout_handle.join().unwrap();
41    stderr_handle.join().unwrap();
42    match child.wait() {
43        Ok(status) => {
44            if status.success() {
45                process::ExitCode::SUCCESS
46            } else {
47                process::ExitCode::FAILURE
48            }
49        }
50        Err(e) => {
51            eprintln!("Failed to wait for Python process: {}", e);
52            process::ExitCode::FAILURE
53        }
54    }
55}