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