1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
extern crate ansi_term;
use std::f64::consts::PI;
use std::io::{self, Stdout, Write};
use ansi_term::Color;
pub struct Colors<W> {
wrapped: W,
spread: f64,
frequency: f64,
seed: f64,
}
pub fn stdout() -> Colors<Stdout> {
Colors::new(io::stdout())
}
impl<W> Colors<W> {
pub fn new(wrapped: W) -> Self {
Self::configure(wrapped, 3.0, 0.1, 0.0)
}
pub fn configure(wrapped: W, spread: f64, frequency: f64, seed: f64) -> Self {
Self {
wrapped,
spread,
frequency,
seed,
}
}
fn color(&mut self, seed: f64) -> Color {
let i = self.frequency * seed / self.spread;
let red = i.sin() * 127.00 + 128.00;
let green = (i + (PI * 2.00 / 3.00)).sin() * 127.00 + 128.00;
let blue = (i + (PI * 4.00 / 3.00)).sin() * 127.00 + 128.00;
Color::RGB(red as u8, green as u8, blue as u8)
}
}
impl<W: Write> Write for Colors<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
for line in ::std::str::from_utf8(buf).unwrap().lines() {
let mut seed = self.seed;
for c in line.chars() {
seed += 1.0;
let mut s = String::with_capacity(1);
s.push(c);
let color = self.color(seed);
write!(&mut self.wrapped, "{}", color.paint(s))?
}
write!(&mut self.wrapped, "\n")?;
}
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
self.wrapped.flush()
}
}
#[cfg(test)]
mod tests {
use super::{stdout, Colors};
use ansi_term::Color;
use std::io::{self, Write};
#[test]
fn colors_colors() {
assert_eq!(Colors::new(io::sink()).color(0.0), Color::RGB(128, 237, 18))
}
#[test]
fn colors_writes() {
assert!(write!(&mut Colors::new(Vec::new()), "hello").is_ok());
}
#[test]
fn stdout_convenience() {
assert!(write!(&mut stdout(), "hello").is_ok());
}
}