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
126
127
128
129
#![doc = include_str ! ("../examples/custom_fetch.rs")]
use std::{default::Default, fmt::Write};
use image::DynamicImage;
use onefetch_ascii::AsciiArt;
use onefetch_image::get_best_backend;
use owo_colors::{AnsiColors, DynColors};
pub use punfetch_derive::Render;
pub use crate::distros::Distro;
mod distros;
pub mod info;
pub trait Render {
fn render(&self, color: DynColors) -> Vec<String>;
}
impl Render for Vec<String> {
fn render(&self, _: DynColors) -> Vec<String> {
self.to_owned()
}
}
impl Render for String {
fn render(&self, _: DynColors) -> Vec<String> {
vec![self.to_owned()]
}
}
pub struct Printer<'a> {
pub color: DynColors,
pub info: Vec<Box<dyn Render + 'a>>,
pub ascii: Option<AsciiArt<'a>>,
pub image: Option<DynamicImage>,
}
impl<'a> Default for Printer<'a> {
fn default() -> Self {
Self {
color: DynColors::Ansi(AnsiColors::Default),
info: Vec::new(),
ascii: None,
image: None,
}
}
}
impl<'a> Printer<'a> {
#[inline]
pub fn with_image(&mut self, image: DynamicImage) {
self.image = Some(image);
}
#[inline]
pub fn with_ascii(&mut self, ascii: AsciiArt<'a>) {
self.ascii = Some(ascii);
}
#[inline]
pub fn with_color(&mut self, color: DynColors) {
self.color = color;
}
#[inline]
pub fn with_info<R: Render + 'a>(&mut self, info: R) {
self.info.push(Box::new(info));
}
#[inline]
pub fn render(&mut self) {
let mut buf = String::new();
let color = self.color;
let lines = self.info.iter().flat_map(|i| i.render(color)).collect();
if let Some((image, backend)) = self
.image
.as_ref()
.and_then(|img| get_best_backend().map(|backend| (img, backend)))
{
buf.push_str(backend.add_image(lines, image, 32).unwrap().as_str());
} else if let Some(ref mut art) = &mut self.ascii {
let padding = art.width();
let mut lines = lines.iter();
loop {
match (art.next(), lines.next()) {
(Some(art), Some(line)) => {
writeln!(buf, " {art} {line}")
}
(Some(art), None) => writeln!(buf, " {art}"),
(None, Some(line)) => writeln!(buf, " {} {line}", " ".repeat(padding)),
(None, None) => {
writeln!(buf).expect("failed to write to buffer");
break;
}
}
.expect("failed to write to buffer");
}
} else {
for line in lines.iter() {
writeln!(buf, "{line}").expect("failed to write to buffer");
}
writeln!(buf).expect("failed to write to buffer");
}
print!("{buf}")
}
}