1use {
2 crate::{
3 compound_style::CompoundStyle,
4 errors::Result,
5 },
6 minimad::Alignment,
7};
8
9#[derive(Debug, Clone, Copy)]
10pub struct Spacing {
11 pub width: usize,
12 pub align: Alignment,
13}
14
15fn truncate(s: &str, max_chars: usize) -> &str {
16 match s.char_indices().nth(max_chars) {
17 None => s,
18 Some((idx, _)) => &s[..idx],
19 }
20}
21
22impl Spacing {
23 #[inline(always)]
26 pub const fn completions(
27 align: Alignment,
28 inner_width: usize,
29 outer_width: usize,
30 ) -> (usize, usize) {
31 if inner_width >= outer_width {
32 return (0, 0);
33 }
34 match align {
35 Alignment::Left | Alignment::Unspecified => (0, outer_width - inner_width),
36 Alignment::Center => {
37 let lp = (outer_width - inner_width) / 2;
38 (lp, outer_width - inner_width - lp)
39 }
40 Alignment::Right => (outer_width - inner_width, 0),
41 }
42 }
43 #[inline(always)]
44 pub const fn optional_completions(
45 align: Alignment,
46 inner_width: usize,
47 outer_width: Option<usize>,
48 ) -> (usize, usize) {
49 match outer_width {
50 Some(outer_width) => Spacing::completions(align, inner_width, outer_width),
51 None => (0, 0),
52 }
53 }
54 #[inline(always)]
55 pub const fn completions_for(&self, inner_width: usize) -> (usize, usize) {
56 Spacing::completions(self.align, inner_width, self.width)
57 }
58 pub fn write_counted_str<W>(
59 &self,
60 w: &mut W,
61 s: &str,
62 str_width: usize,
63 style: &CompoundStyle,
64 ) -> Result<()>
65 where
66 W: std::io::Write,
67 {
68 if str_width >= self.width {
69 let s = truncate(s, self.width);
71 style.queue_str(w, s)?;
72 } else {
73 let (lp, rp) = self.completions_for(str_width);
76 let mut con = String::new();
77 for _ in 0..lp {
78 con.push(' ');
79 }
80 con.push_str(s);
81 for _ in 0..rp {
82 con.push(' ');
83 }
84 style.queue(w, con)?;
85 }
86 Ok(())
87 }
88 pub fn write_str<W>(&self, w: &mut W, s: &str, style: &CompoundStyle) -> Result<()>
91 where
92 W: std::io::Write,
93 {
94 self.write_counted_str(w, s, s.chars().count(), style)
95 }
96}