use super::*;
use yansi::Paint;
pub struct Characters {
pub hbar: char,
pub vbar: char,
pub xbar: char,
pub vbar_break: char,
pub vbar_gap: char,
pub uarrow: char,
pub rarrow: char,
pub ltop: char,
pub mtop: char,
pub rtop: char,
pub lbot: char,
pub rbot: char,
pub mbot: char,
pub lbox: char,
pub rbox: char,
pub lcross: char,
pub rcross: char,
pub underbar: char,
pub underline: char,
}
impl Characters {
pub fn unicode() -> Self {
Self {
hbar: '─',
vbar: '│',
xbar: '┼',
vbar_break: '┆',
vbar_gap: '┆',
uarrow: '🭯',
rarrow: '▶',
ltop: '╭',
mtop: '┬',
rtop: '╮',
lbot: '╰',
mbot: '┴',
rbot: '╯',
lbox: '[',
rbox: ']',
lcross: '├',
rcross: '┤',
underbar: '┬',
underline: '─',
}
}
pub fn ascii() -> Self {
Self {
hbar: '-',
vbar: '|',
xbar: '+',
vbar_break: '*',
vbar_gap: ':',
uarrow: '^',
rarrow: '>',
ltop: ',',
mtop: 'v',
rtop: '.',
lbot: '`',
mbot: '^',
rbot: '\'',
lbox: '[',
rbox: ']',
lcross: '|',
rcross: '|',
underbar: '|',
underline: '^',
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum StreamType {
Stdout,
Stderr,
}
#[cfg(feature = "concolor")]
impl From<StreamType> for concolor::Stream {
fn from(s: StreamType) -> Self {
match s {
StreamType::Stdout => concolor::Stream::Stdout,
StreamType::Stderr => concolor::Stream::Stderr,
}
}
}
pub trait StreamAwareFmt: Sized {
#[cfg(feature = "concolor")]
fn color_enabled_for(s: StreamType) -> bool {
concolor::get(s.into()).color()
}
#[cfg(not(feature = "concolor"))]
#[doc(hidden)]
fn color_enabled_for(_: StreamType) -> bool {
true
}
fn fg<C: Into<Option<Color>>>(self, color: C, stream: StreamType) -> Foreground<Self> {
if Self::color_enabled_for(stream) { Foreground(self, color.into()) } else { Foreground(self, None) }
}
fn bg<C: Into<Option<Color>>>(self, color: C, stream: StreamType) -> Background<Self> {
if Self::color_enabled_for(stream) { Background(self, color.into()) } else { Background(self, None) }
}
}
impl<T: Display> StreamAwareFmt for T {}
pub trait Fmt: Sized {
fn fg<C: Into<Option<Color>>>(self, color: C) -> Foreground<Self>
where
Self: Display,
{
if cfg!(feature = "concolor") {
StreamAwareFmt::fg(self, color, StreamType::Stderr)
}
else {
Foreground(self, color.into())
}
}
fn bg<C: Into<Option<Color>>>(self, color: C) -> Background<Self>
where
Self: Display,
{
if cfg!(feature = "concolor") {
StreamAwareFmt::bg(self, color, StreamType::Stdout)
}
else {
Background(self, color.into())
}
}
}
impl<T: Display> Fmt for T {}
#[cfg(any(feature = "concolor", doc))]
pub trait StdoutFmt: StreamAwareFmt {
fn fg<C: Into<Option<Color>>>(self, color: C) -> Foreground<Self> {
StreamAwareFmt::fg(self, color, StreamType::Stdout)
}
fn bg<C: Into<Option<Color>>>(self, color: C) -> Background<Self> {
StreamAwareFmt::bg(self, color, StreamType::Stdout)
}
}
#[cfg(feature = "concolor")]
impl<T: Display> StdoutFmt for T {}
#[derive(Copy, Clone, Debug)]
pub struct Foreground<T>(T, Option<Color>);
impl<T: Display> Display for Foreground<T> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
if let Some(col) = self.1 { write!(f, "{}", Paint::new(&self.0).fg(col)) } else { write!(f, "{}", self.0) }
}
}
#[derive(Copy, Clone, Debug)]
pub struct Background<T>(T, Option<Color>);
impl<T: Display> Display for Background<T> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
if let Some(col) = self.1 { write!(f, "{}", Paint::new(&self.0).bg(col)) } else { write!(f, "{}", self.0) }
}
}
pub struct ColorGenerator {
state: [u16; 3],
min_brightness: f32,
}
impl Default for ColorGenerator {
fn default() -> Self {
Self::from_state([30000, 15000, 35000], 0.5)
}
}
impl ColorGenerator {
pub fn from_state(state: [u16; 3], min_brightness: f32) -> Self {
Self { state, min_brightness: min_brightness.max(0.0).min(1.0) }
}
pub fn new() -> Self {
Self::default()
}
pub fn next(&mut self) -> Color {
for i in 0..3 {
self.state[i] = (self.state[i] as usize).wrapping_add(40503 * (i * 4 + 1130)) as u16;
}
Color::Fixed(
16 + ((self.state[2] as f32 / 65535.0 * (1.0 - self.min_brightness) + self.min_brightness) * 5.0
+ (self.state[1] as f32 / 65535.0 * (1.0 - self.min_brightness) + self.min_brightness) * 30.0
+ (self.state[0] as f32 / 65535.0 * (1.0 - self.min_brightness) + self.min_brightness) * 180.0)
as u8,
)
}
}