kutil_cli/debug/
prefix.rs

1use {
2    owo_colors::*,
3    std::{fmt, io::*},
4};
5
6const BRANCH_NEST_LAST: &str = "  ";
7const BRANCH_NEST_ONGOING: &str = "│ ";
8const BRANCH_NEST_ONGOING_THICK: &str = "┃ ";
9const BRANCH_NEST_ONGOING_DOUBLE: &str = "║ ";
10const BRANCH_INTO_LAST: &str = "└─";
11const BRANCH_INTO_LAST_THICK: &str = "┗━";
12const BRANCH_INTO_LAST_DOUBLE: &str = "╚═";
13const BRANCH_INTO_ONGOING: &str = "├─";
14const BRANCH_INTO_ONGOING_THICK: &str = "┣━";
15const BRANCH_INTO_ONGOING_DOUBLE: &str = "╠═";
16
17//
18// DebugPrefix
19//
20
21/// Debug prefix.
22///
23/// Utility for implementing multi-line [Debuggable](super::debuggable::Debuggable) output
24/// in a nested horizontal tree-like structure.
25#[derive(Clone, Default, Debug)]
26pub struct DebugPrefix {
27    prefix: String,
28    style: Style,
29}
30
31impl DebugPrefix {
32    /// Constructor.
33    pub fn new(style: Style) -> Self {
34        Self { prefix: String::new(), style }
35    }
36
37    /// Clone and add a custom suffix.
38    pub fn with(&self, suffix: &str) -> Self {
39        let mut prefix = self.prefix.clone();
40        prefix += suffix;
41        Self { prefix, style: self.style }
42    }
43
44    /// Clone and add a branch-style suffix.
45    pub fn with_branch(&self, last: bool) -> Self {
46        if last {
47            self.with(BRANCH_NEST_LAST)
48        } else {
49            self.with(BRANCH_NEST_ONGOING)
50        }
51    }
52
53    /// Clone and add a thick branch-style suffix.
54    pub fn with_thick_branch(&self, last: bool) -> Self {
55        if last {
56            self.with(BRANCH_NEST_LAST)
57        } else {
58            self.with(BRANCH_NEST_ONGOING_THICK)
59        }
60    }
61
62    /// Clone and add a double branch-style suffix.
63    pub fn with_double_branch(&self, last: bool) -> Self {
64        if last {
65            self.with(BRANCH_NEST_LAST)
66        } else {
67            self.with(BRANCH_NEST_ONGOING_DOUBLE)
68        }
69    }
70
71    /// Write a newline plus this prefix.
72    pub fn write<WriteT>(&self, writer: &mut WriteT) -> Result<()>
73    where
74        WriteT: Write,
75    {
76        write!(writer, "\n{}", self.prefix.style(self.style))
77    }
78
79    /// If first is false, write a newline plus this prefix.
80    pub fn conditional_write<WriteT>(&self, writer: &mut WriteT, first: bool) -> Result<()>
81    where
82        WriteT: Write,
83    {
84        if first {
85            Ok(())
86        } else {
87            self.write(writer)
88        }
89    }
90
91    /// Write a newline plus this prefix. Then write a custom suffix.
92    pub fn write_with<WriteT>(&self, writer: &mut WriteT, suffix: &str) -> Result<()>
93    where
94        WriteT: Write,
95    {
96        write!(writer, "\n{}", format!("{}{}", self.prefix, suffix).style(self.style))
97    }
98
99    /// If first is false, write a newline plus this prefix. Then write a custom suffix.
100    /// The custom suffix is *always* written.
101    pub fn conditional_write_with<WriteT>(&self, writer: &mut WriteT, suffix: &str, first: bool) -> Result<()>
102    where
103        WriteT: Write,
104    {
105        if first {
106            write!(writer, "{}", suffix.style(self.style))
107        } else {
108            self.write_with(writer, suffix)
109        }
110    }
111
112    /// Write a newline plus this prefix plus a branch-style suffix.
113    pub fn write_with_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
114    where
115        WriteT: Write,
116    {
117        if last {
118            self.write_with(writer, BRANCH_INTO_LAST)
119        } else {
120            self.write_with(writer, BRANCH_INTO_ONGOING)
121        }
122    }
123
124    /// Write a newline plus this prefix plus a thick branch-style suffix.
125    pub fn write_with_thick_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
126    where
127        WriteT: Write,
128    {
129        if last {
130            self.write_with(writer, BRANCH_INTO_LAST_THICK)
131        } else {
132            self.write_with(writer, BRANCH_INTO_ONGOING_THICK)
133        }
134    }
135
136    /// Write a newline plus this prefix plus a double branch-style suffix.
137    pub fn write_with_double_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
138    where
139        WriteT: Write,
140    {
141        if last {
142            self.write_with(writer, BRANCH_INTO_LAST_DOUBLE)
143        } else {
144            self.write_with(writer, BRANCH_INTO_ONGOING_DOUBLE)
145        }
146    }
147}
148
149impl fmt::Display for DebugPrefix {
150    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
151        fmt::Display::fmt(&self.prefix, formatter)
152    }
153}