When I grab stderr using Stdio::piped(), I am able to get the contents of stderr, but any formatting is lost. I've attempted this using both a String and using a Vec<u8> and in both occasions, the formatting is stripped and plain text is returned to the terminal.
Rough version of the code. Full code available at command.rs
fn do_something(mut cmd: Command) {
let mut cmd = cmd.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let mut buffered_stderr = BufReader::new(cmd.stderr.take().unwrap());
let status = cmd.wait();
match status {
Err(e) => whatever(e),
Ok(status) => {
let stderr = io::stderr();
let mut handle = stderr.lock();
while buffered_stderr.read_line(&mut buffer).unwrap() > 0 {
let b = buffer.to_owned();
buffer.clear();
let _ = handle.write(b.as_bytes());
// more stuff here
}
}
}
}
Is there a way to maintain coloring in stderr?
Edit including a screenshot so we can stop talking about --color always
That's a feature of the command you are calling, as far as I know, so you'll probably have to convince the command that stderr is a terminal, and not actually piped. I don't know how that would be done, though.
After fixing the broken example I can see colors just fine with --color always. (On Fedora Linux)
use std::process::{Command, Stdio};
use std::io::BufReader;
use std::io::prelude::*;
use std::io;
fn do_something(mut cmd: Command) {
let mut cmd = cmd.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let mut buffered_stderr = BufReader::new(cmd.stderr.take().unwrap());
let status = cmd.wait();
match status {
Err(_) => panic!(),
Ok(_) => {
let stderr = io::stderr();
let mut handle = stderr.lock();
let mut buffer = String::new();
while buffered_stderr.read_line(&mut buffer).unwrap() > 0 {
let b = buffer.to_owned();
buffer.clear();
let _ = handle.write(b.as_bytes());
// more stuff here
}
}
}
}
fn main() {
let mut cmd = Command::new("rustc");
cmd.arg("--color").arg("always").arg("qwe.rs");
do_something(cmd);
}
A slight point of clarification: the pipe itself is not stripping the colors; the program you are invoking is detecting the pipe and choosing not to send colors. (On older versions of Windows there was no way to send color information on a pipe; Unix supports it but "programs that want to use color should check for pipes first" has been a cultural norm since forever).