unicode_border/
lib.rs

1/// `TextBorderOptions` is a structure used to specify the configuration for text borders.
2///
3/// # Fields
4///
5/// * `border_char` - The character used to create the border.
6/// * `border_thickness` - A tuple specifying the border thickness in the order (left, top, right, bottom).
7/// * `margin_thickness` - A tuple specifying the margin thickness in the order (left, top, right, bottom).
8/// * `prevent_trim` - A boolean flag indicating whether to prevent trimming whitespace from the message.
9///
10/// # Examples
11///
12/// ```
13/// let options = TextBorderOptions {
14///     border_char: '#',
15///     border_thickness: (2, 2, 2, 2),
16///     margin_thickness: (1, 1, 1, 1),
17///     prevent_trim: true,
18/// };
19/// ```
20pub struct TextBorderOptions {
21    border_char: char,
22    border_thickness: (usize, usize, usize, usize),
23    margin_thickness: (usize, usize, usize, usize),
24    prevent_trim: bool,
25}
26
27impl Default for TextBorderOptions {
28    fn default() -> Self {
29        Self {
30            border_char: '*',
31            border_thickness: (1, 1, 1, 1),
32            margin_thickness: (0, 0, 0, 0),
33            prevent_trim: false,
34        }
35    }
36}
37
38impl TextBorderOptions {
39    fn create_border_line(&self, message: &str) -> String {
40        self.border_char.to_string().repeat(
41            message.len()
42                + self.border_thickness.0
43                + self.border_thickness.2
44                + self.margin_thickness.0
45                + self.margin_thickness.2,
46        )
47    }
48
49    fn create_margin_line(&self, message: &str) -> String {
50        format!(
51            "{}{}{}",
52            self.border_char.to_string().repeat(self.border_thickness.0),
53            " ".repeat(message.len() + self.margin_thickness.0 + self.margin_thickness.2),
54            self.border_char.to_string().repeat(self.border_thickness.2)
55        )
56    }
57
58    fn create_message_line(&self, message: &str) -> String {
59        format!(
60            "{}{}{}{}{}",
61            self.border_char.to_string().repeat(self.border_thickness.0),
62            " ".repeat(self.margin_thickness.0),
63            message,
64            " ".repeat(self.margin_thickness.2),
65            self.border_char.to_string().repeat(self.border_thickness.2)
66        )
67    }
68}
69
70/// Creates a string containing the input message, surrounded by a border and margin
71/// as specified by the provided `TextBorderOptions`.
72///
73/// # Arguments
74///
75/// * `message` - The message (`&str`) to be surrounded by a border.
76/// * `options` - An optional `TextBorderOptions` instance specifying the border and margin
77///               configurations. If `None`, default options are used.
78///
79/// # Returns
80///
81/// * A `String` containing the input message surrounded by the specified border and margin.
82///
83/// # Examples
84///
85/// ```
86/// let message = "Hello, World!";
87///
88/// let options = TextBorderOptions {
89///     border_char: '#',
90///     border_thickness: (2, 2, 2, 2),
91///     margin_thickness: (1, 1, 1, 1),
92///     prevent_trim: true,
93/// };
94///
95/// let bordered_text = create_text_border(message, Some(options));
96/// println!("{}", bordered_text);
97/// ```
98pub fn create_text_border(message: &str, options: Option<TextBorderOptions>) -> String {
99    let opts = options.unwrap_or_default();
100
101    let output_message = if opts.prevent_trim {
102        message.to_string()
103    } else {
104        message.trim().to_string()
105    };
106
107    let horizontal_border = opts.create_border_line(&output_message);
108    let margin_line = opts.create_margin_line(&output_message);
109
110    let mut bordered_message = Vec::new();
111
112    bordered_message.extend(vec![horizontal_border.clone(); opts.border_thickness.1]);
113    bordered_message.extend(vec![margin_line.clone(); opts.margin_thickness.1]);
114
115    bordered_message.push(opts.create_message_line(&output_message));
116
117    bordered_message.extend(vec![margin_line.clone(); opts.margin_thickness.3]);
118    bordered_message.extend(vec![horizontal_border; opts.border_thickness.3]);
119
120    bordered_message.join("\n")
121}