cargo-llvm-cov 0.1.11

Cargo subcommand to easily use LLVM source-based code coverage (-Z instrument-coverage).
use std::{
    io::Write,
    sync::atomic::{AtomicBool, AtomicU8, Ordering::Relaxed},
};

use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};

use crate::cli::Coloring;

static COLORING: AtomicU8 = AtomicU8::new(AUTO);

const AUTO: u8 = Coloring::Auto as _;
const ALWAYS: u8 = Coloring::Always as _;
const NEVER: u8 = Coloring::Never as _;

pub(crate) fn set_coloring(coloring: &mut Option<Coloring>) {
    let mut color = coloring.unwrap_or(Coloring::Auto);
    if color == Coloring::Auto && !atty::is(atty::Stream::Stderr) {
        *coloring = Some(Coloring::Never);
        color = Coloring::Never;
    }
    COLORING.store(color as _, Relaxed);
}

fn coloring() -> ColorChoice {
    match COLORING.load(Relaxed) {
        AUTO => ColorChoice::Auto,
        ALWAYS => ColorChoice::Always,
        NEVER => ColorChoice::Never,
        _ => unreachable!(),
    }
}

static QUIET: AtomicBool = AtomicBool::new(false);

pub(crate) fn set_quiet(quiet: bool) {
    QUIET.store(quiet, Relaxed);
}

pub(crate) fn quiet() -> bool {
    QUIET.load(Relaxed)
}

pub(crate) fn print_inner(status: &str, color: Option<Color>, justified: bool) -> StandardStream {
    let mut stream = StandardStream::stderr(coloring());
    let _ = stream.set_color(ColorSpec::new().set_bold(true).set_fg(color));
    if justified {
        let _ = write!(stream, "{:>12}", status);
    } else {
        let _ = write!(stream, "{}", status);
        let _ = stream.set_color(ColorSpec::new().set_bold(true));
        let _ = write!(stream, ":");
    }
    let _ = stream.reset();
    let _ = write!(stream, " ");
    stream
}

macro_rules! error {
    ($($msg:expr),* $(,)?) => {{
        use std::io::Write;
        let mut stream = crate::term::print_inner("error", Some(termcolor::Color::Red), false);
        let _ = writeln!(stream, $($msg),*);
    }};
}

macro_rules! warn {
    ($($msg:expr),* $(,)?) => {{
        use std::io::Write;
        let mut stream = crate::term::print_inner("warning", Some(termcolor::Color::Yellow), false);
        let _ = writeln!(stream, $($msg),*);
    }};
}

macro_rules! info {
    ($($msg:expr),* $(,)?) => {{
        use std::io::Write;
        let mut stream = crate::term::print_inner("info", None, false);
        let _ = writeln!(stream, $($msg),*);
    }};
}

macro_rules! status {
    ($status:expr, $($msg:expr),* $(,)?) => {{
        use std::io::Write;
        if !crate::term::quiet() {
            let mut stream = crate::term::print_inner($status, Some(termcolor::Color::Cyan), true);
            let _ = writeln!(stream, $($msg),*);
        }
    }};
}