#![deny(missing_docs)]
use std::fs::OpenOptions;
use std::io::{self, Read, Write};
use clap::Parser;
use strip_ansi_escapes::Writer as StripAnsiWriter;
#[derive(Parser, Debug)]
#[clap(author, version)]
struct Cli {
files: Vec<String>,
#[clap(short, long)]
append: bool,
#[clap(long, parse(try_from_str), default_value_t = true)]
strip_ansi: bool,
#[clap(long = "bs", default_value_t = 8 * 1024)]
buffer_size: usize,
}
fn main() {
let cli = Cli::parse();
let stdin = io::stdin();
let mut stdin = stdin.lock();
let stdout = io::stdout();
let stdout = stdout.lock();
let mut outputs: Vec<_> = cli
.files
.iter()
.map(|fname| {
let f = OpenOptions::new()
.write(true)
.create(true)
.append(cli.append)
.truncate(!cli.append)
.open(fname)
.unwrap_or_else(|e| {
panic!("Unable to open file '{}': {}", fname, e);
});
if cli.strip_ansi {
Box::new(StripAnsiWriter::new(f)) as Box<dyn Write>
} else {
Box::new(f) as Box<dyn Write>
}
})
.collect();
outputs.push(Box::new(stdout));
let mut buf = vec![0; cli.buffer_size];
loop {
let bytes = stdin.read(&mut buf).expect("Unable to read from stdin");
if bytes == 0 {
break;
}
let buf = &buf[..bytes];
for output in &mut outputs {
output.write_all(buf).expect("Unable to write to output");
}
}
}