1use crate::formatter::get_length;
4use std::fmt;
5use std::fmt::Write;
6
7pub struct PaddingEntry {
8 pub text: String,
9 pub width: usize,
10 pub alignment: Alignment,
11}
12
13pub enum Alignment {
14 Left,
15 Center,
16 Right,
17}
18
19pub fn align(
20 entries: &Vec<PaddingEntry>,
21 max_width: usize,
22 pad_char: char,
23 mut func: impl FnMut(String) -> fmt::Result,
24) -> fmt::Result {
25 let mut offset = 0;
26 let mut line = String::new();
27 for entry in entries {
28 let text = &entry.text;
29 let length = get_length(text);
30 if length > entry.width {
31 offset += length - entry.width;
32 line.push_str(text);
33 } else {
34 let mut padding_size = entry.width - length;
35
36 let offset_amount = offset.clamp(0, padding_size);
38 offset -= offset_amount;
39 padding_size -= offset_amount;
40
41 let padding = pad_char.to_string().repeat(padding_size);
42 match entry.alignment {
43 Alignment::Left => {
44 write!(&mut line, "{text}{padding}")?;
45 }
46 Alignment::Center => {
47 let (left_padding, right_padding) = padding.split_at(padding.len() / 2);
48 write!(&mut line, "{left_padding}{text}{right_padding}")?;
49 }
50 Alignment::Right => {
51 write!(&mut line, "{padding}{text}")?;
52 }
53 }
54 }
55 }
56
57 if get_length(&line) > max_width {
58 let mut line_builder = String::new();
59 for ch in line.chars() {
60 line_builder.push(ch);
61 if get_length(&line_builder) >= max_width {
62 func(line_builder)?;
63 line_builder = String::new();
64 }
65 }
66
67 if !line_builder.is_empty() {
68 func(line_builder)?;
69 }
70 } else {
71 func(line)?;
72 }
73
74 Ok(())
75}