use std::{fmt, path::PathBuf};
use anyhow::Error;
use serde::{Deserialize, Serialize};
pub use yansi::Color;
use yansi::Paint;
#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct Context {
pub version: String,
pub config_file: PathBuf,
pub config_dir: PathBuf,
pub cache_dir: PathBuf,
pub data_dir: PathBuf,
pub bin_dir: PathBuf,
#[serde(skip)]
pub lock_file: PathBuf,
#[serde(skip)]
pub verbosity: Verbosity,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
pub enum Verbosity {
Quiet,
Normal,
Verbose,
}
impl Default for Verbosity {
fn default() -> Self {
Self::Normal
}
}
impl Context {
pub fn log_header(&self, prefix: &str, msg: impl fmt::Display) {
if self.verbosity >= Verbosity::Normal {
self.log_header_impl(prefix, msg);
}
}
pub fn log_header_v(&self, prefix: &str, msg: impl fmt::Display) {
if self.verbosity >= Verbosity::Verbose {
self.log_header_impl(prefix, msg);
}
}
fn log_header_impl(&self, prefix: &str, msg: impl fmt::Display) {
eprintln!("{} {}", Paint::magenta(prefix).bold(), msg);
}
pub fn log_status(&self, prefix: &str, msg: impl fmt::Display) {
if self.verbosity >= Verbosity::Normal {
self.log_impl(Color::Cyan, prefix, msg);
}
}
pub fn log_status_v(&self, prefix: &str, msg: impl fmt::Display) {
if self.verbosity >= Verbosity::Verbose {
self.log_impl(Color::Cyan, prefix, msg);
}
}
pub fn log_warning(&self, prefix: &str, msg: impl fmt::Display) {
if self.verbosity >= Verbosity::Normal {
self.log_impl(Color::Yellow, prefix, msg);
}
}
pub fn log_warning_v(&self, prefix: &str, msg: impl fmt::Display) {
if self.verbosity >= Verbosity::Verbose {
self.log_impl(Color::Yellow, prefix, msg);
}
}
fn log_impl(&self, color: Color, prefix: &str, msg: impl fmt::Display) {
eprintln!(
"{} {}",
Paint::new(format!("{prefix: >12}")).fg(color).bold(),
msg
);
}
}
pub fn log_error(err: &Error) {
let pretty = prettyify_error(err);
eprintln!("\n{} {}", Paint::red("error:").bold(), pretty);
}
pub fn log_error_as_warning(err: &Error) {
let pretty = prettyify_error(err);
eprintln!("\n{} {}", Paint::yellow("warning:").bold(), pretty);
}
fn prettyify_error(err: &Error) -> String {
err.chain()
.map(|c| c.to_string())
.collect::<Vec<_>>()
.join("\n due to: ")
}