use std::fs::File;
use std::io::{self, IsTerminal, Write};
use malevich::{Frame, Plot};
use crate::args::{Args, CharsetChoice, ColorChoice, Output, PixelsChoice};
use crate::chart::Built;
pub fn apply_color(choice: ColorChoice) {
match choice {
ColorChoice::Never => unsafe { std::env::set_var("NO_COLOR", "1") },
ColorChoice::Always => unsafe {
std::env::remove_var("NO_COLOR");
std::env::set_var("CLICOLOR_FORCE", "1");
},
ColorChoice::Auto => {}
}
}
pub fn emit(args: &Args, built: &Built) -> io::Result<i32> {
match &args.output {
Output::Stderr => plot_to(io::stderr(), &built.plot, args)?,
Output::Stdout => plot_to(io::stdout(), &built.plot, args)?,
Output::File(path) => {
let file = File::create(path)?;
plot_to(file, &built.plot, args)?;
}
}
if built.unparsed > 0 && !args.quiet {
let noun = if built.unparsed == 1 {
"value"
} else {
"values"
};
eprintln!("{} {noun} could not be parsed", built.unparsed);
}
Ok(0)
}
fn plot_to<W: Write + IsTerminal>(mut dest: W, plot: &Plot<'_>, args: &Args) -> io::Result<()> {
let frame = frame_for(&dest, args);
let text = render(plot, &frame, args.pixels, dest.is_terminal());
dest.write_all(text.as_bytes())?;
dest.write_all(b"\n")?;
dest.flush()
}
pub(crate) fn frame_for<T: IsTerminal>(dest: &T, args: &Args) -> Frame {
let mut frame = Frame::detect_for(dest);
if let CharsetChoice::Fixed(charset) = args.charset {
frame.charset = charset;
}
if let Some(width) = args.width {
frame.width = width;
}
if let Some(height) = args.height {
frame.height = height;
}
frame
}
fn render(plot: &Plot<'_>, frame: &Frame, pixels: PixelsChoice, dest_is_terminal: bool) -> String {
match pixels {
PixelsChoice::Never => plot.render(frame),
PixelsChoice::Auto if dest_is_terminal => plot.render_best(frame),
PixelsChoice::Auto => plot.render(frame),
PixelsChoice::Always => plot.render_best(frame),
}
}