tracing_human_layer/
textwrap.rs

1//! Extensions and utilities for the [`textwrap`] crate.
2
3use std::borrow::Cow;
4
5use textwrap::Options;
6use textwrap::WordSeparator;
7use textwrap::WordSplitter;
8
9/// Get [`textwrap`] options with our settings.
10pub fn options<'a>() -> Options<'a> {
11    let opts = Options::with_termwidth()
12        .break_words(false)
13        .word_separator(WordSeparator::AsciiSpace)
14        .word_splitter(WordSplitter::NoHyphenation);
15
16    // In tests, the terminal is always 80 characters wide.
17    if cfg!(test) {
18        opts.with_width(80)
19    } else {
20        opts
21    }
22}
23
24/// Extension trait adding methods to [`textwrap::Options`]
25pub trait TextWrapOptionsExt {
26    /// Subtract from the current `width`.
27    fn subtract_width(self, decrease: usize) -> Self;
28
29    /// Set the `width` to wrap the text to.
30    fn with_width(self, width: usize) -> Self;
31
32    /// Wrap the given text into lines.
33    fn wrap<'s>(&self, text: &'s str) -> Vec<Cow<'s, str>>;
34
35    /// Wrap the given text into lines and return a `String`.
36    ///
37    /// Like [`Self::wrap`] but with the lines pre-joined.
38    fn fill(&self, text: &str) -> String;
39}
40
41impl<'a> TextWrapOptionsExt for Options<'a> {
42    fn subtract_width(mut self, decrease: usize) -> Self {
43        self.width -= decrease;
44        self
45    }
46
47    fn with_width(mut self, width: usize) -> Self {
48        self.width = width;
49        self
50    }
51
52    fn wrap<'s>(&self, text: &'s str) -> Vec<Cow<'s, str>> {
53        textwrap::wrap(text, self)
54    }
55
56    fn fill(&self, text: &str) -> String {
57        textwrap::fill(text, self)
58    }
59}