1use super::*;
2
3#[derive(Clone, Copy, Debug)]
5pub enum StreamType {
6 Stdout,
8 Stderr,
10}
11
12pub trait StreamAwareFmt: Sized {
18 #[cfg(not(feature = "concolor"))]
19 #[doc(hidden)]
20 fn color_enabled_for(_: StreamType) -> bool {
21 true
22 }
23
24 fn fg<C: Into<Option<Color>>>(self, color: C, stream: StreamType) -> Foreground<Self> {
26 if Self::color_enabled_for(stream) { Foreground(self, color.into()) } else { Foreground(self, None) }
27 }
28
29 fn bg<C: Into<Option<Color>>>(self, color: C, stream: StreamType) -> Background<Self> {
31 if Self::color_enabled_for(stream) { Background(self, color.into()) } else { Background(self, None) }
32 }
33}
34
35impl<T: Display> StreamAwareFmt for T {}
36
37pub trait Console: Sized {
45 fn fg<C: Into<Option<Color>>>(self, color: C) -> Foreground<Self>
47 where
48 Self: Display,
49 {
50 if cfg!(feature = "concolor") {
51 StreamAwareFmt::fg(self, color, StreamType::Stderr)
52 }
53 else {
54 Foreground(self, color.into())
55 }
56 }
57
58 fn bg<C: Into<Option<Color>>>(self, color: C) -> Background<Self>
60 where
61 Self: Display,
62 {
63 if cfg!(feature = "concolor") {
64 StreamAwareFmt::bg(self, color, StreamType::Stdout)
65 }
66 else {
67 Background(self, color.into())
68 }
69 }
70}
71
72impl<T: Display> Console for T {}
73
74#[derive(Copy, Clone, Debug)]
75pub struct Foreground<T>(T, Option<Color>);
76impl<T: Display> Display for Foreground<T> {
77 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
78 if let Some(col) = self.1 { write!(f, "{}", Paint::new(&self.0).fg(col)) } else { write!(f, "{}", self.0) }
79 }
80}
81
82#[derive(Copy, Clone, Debug)]
83pub struct Background<T>(T, Option<Color>);
84impl<T: Display> Display for Background<T> {
85 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
86 if let Some(col) = self.1 { write!(f, "{}", Paint::new(&self.0).bg(col)) } else { write!(f, "{}", self.0) }
87 }
88}
89
90pub struct Palette {
92 state: [u16; 3],
93 min_brightness: f32,
94}
95
96impl Default for Palette {
97 fn default() -> Self {
98 Self::from_state([30000, 15000, 35000], 0.5)
99 }
100}
101
102impl Palette {
103 pub fn from_state(state: [u16; 3], min_brightness: f32) -> Self {
107 Self { state, min_brightness: min_brightness.max(0.0).min(1.0) }
108 }
109
110 pub fn new() -> Self {
112 Self::default()
113 }
114
115 pub fn random(&mut self) -> Color {
117 for i in 0..3 {
118 self.state[i] = (self.state[i] as usize).wrapping_add(40503 * (i * 4 + 1130)) as u16;
120 }
121 Color::Fixed(
122 16 + ((self.state[2] as f32 / 65535.0 * (1.0 - self.min_brightness) + self.min_brightness) * 5.0
123 + (self.state[1] as f32 / 65535.0 * (1.0 - self.min_brightness) + self.min_brightness) * 30.0
124 + (self.state[0] as f32 / 65535.0 * (1.0 - self.min_brightness) + self.min_brightness) * 180.0)
125 as u8,
126 )
127 }
128}