1pub mod components;
2pub mod views;
3
4use iocraft::prelude::*;
5
6pub fn render_lines(lines: Vec<String>, no_color: bool) -> String {
7 let mut element = element! {
8 View(flex_direction: FlexDirection::Column) {
9 #(lines.into_iter().map(|line| element! { Text(content: line, wrap: TextWrap::NoWrap) }))
10 }
11 };
12
13 render_element_to_string(&mut element, no_color)
14}
15
16pub fn indent_lines(lines: Vec<String>, spaces: usize) -> Vec<String> {
17 let prefix = " ".repeat(spaces);
18 lines
19 .into_iter()
20 .map(|line| {
21 if line.is_empty() {
22 line
23 } else {
24 format!("{}{}", prefix, line)
25 }
26 })
27 .collect()
28}
29
30pub fn render_element_to_string<E: ElementExt>(element: &mut E, no_color: bool) -> String {
31 let canvas = element.render(None);
32 let mut bytes = Vec::new();
33 if no_color {
34 canvas
35 .write(&mut bytes)
36 .expect("writing iocraft canvas should not fail");
37 } else {
38 canvas
39 .write_ansi(&mut bytes)
40 .expect("writing ANSI iocraft canvas should not fail");
41 }
42
43 let s = String::from_utf8(bytes).expect("iocraft output should be UTF-8");
44 let s = s.replace("\u{1b}[K", "");
45 let mut lines = s
46 .split('\n')
47 .map(|line| line.trim_end_matches(' ').to_string())
48 .collect::<Vec<_>>();
49
50 while lines.last().map(|line| line.is_empty()).unwrap_or(false) {
51 lines.pop();
52 }
53
54 lines.join("\n")
55}