kutil_cli/debug/
context.rs1use super::{format::*, theme::*};
2
3use std::io::*;
4
5const INDENTATION: &str = " ";
6const BRANCH_CONTINUATION_LAST: &str = " ";
7const BRANCH_CONTINUATION_ONGOING: &str = "│ ";
8const BRANCH_CONTINUATION_ONGOING_THICK: &str = "┃ ";
9const BRANCH_CONTINUATION_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#[derive(Clone)]
26pub struct DebugContext<'own> {
27 pub theme: &'own Theme,
29
30 pub format: DebugFormat,
34
35 pub inline: bool,
39
40 pub separator: bool,
44
45 pub indentation: String,
47}
48
49impl<'own> DebugContext<'own> {
50 pub fn new(theme: &'own Theme) -> Self {
52 Self { theme, format: DebugFormat::default(), inline: false, separator: false, indentation: String::new() }
53 }
54
55 pub fn child(&self) -> Self {
59 Self {
60 theme: self.theme,
61 format: self.format.clone(),
62 inline: false,
63 separator: self.separator,
64 indentation: self.indentation.clone(),
65 }
66 }
67
68 pub fn with_theme(mut self, theme: &'own Theme) -> Self {
70 self.theme = theme;
71 self
72 }
73
74 pub fn with_format(mut self, format: DebugFormat) -> Self {
76 self.format = format;
77 self
78 }
79
80 pub fn with_inline(mut self, inline: bool) -> Self {
85 self.inline = inline;
86 self
87 }
88
89 pub fn with_separator(mut self, separator: bool) -> Self {
91 self.separator = separator;
92 self
93 }
94
95 pub fn increase_indentation(mut self) -> Self {
97 self.indentation = self.indentation + INDENTATION;
98 self
99 }
100
101 pub fn increase_indentation_branch(mut self, last: bool) -> Self {
103 if last {
104 self.indentation = self.indentation + BRANCH_CONTINUATION_LAST;
105 } else {
106 self.indentation = self.indentation + BRANCH_CONTINUATION_ONGOING;
107 }
108 self
109 }
110
111 pub fn increase_indentation_thick_branch(mut self, last: bool) -> Self {
113 if last {
114 self.indentation = self.indentation + BRANCH_CONTINUATION_LAST;
115 } else {
116 self.indentation = self.indentation + BRANCH_CONTINUATION_ONGOING_THICK;
117 }
118 self
119 }
120
121 pub fn increase_indentation_double_branch(mut self, last: bool) -> Self {
123 if last {
124 self.indentation = self.indentation + BRANCH_CONTINUATION_LAST;
125 } else {
126 self.indentation = self.indentation + BRANCH_CONTINUATION_ONGOING_DOUBLE;
127 }
128 self
129 }
130
131 pub fn separate<WriteT>(&self, writer: &mut WriteT) -> Result<()>
133 where
134 WriteT: Write,
135 {
136 match self.separator {
137 true => write!(writer, " "),
138 false => Ok(()),
139 }
140 }
141
142 pub fn indent<WriteT>(&self, writer: &mut WriteT) -> Result<()>
144 where
145 WriteT: Write,
146 {
147 write!(writer, "\n{}", self.theme.delimiter(&self.indentation))
148 }
149
150 pub fn indent_into<WriteT>(&self, writer: &mut WriteT, delimiter: &str) -> Result<()>
152 where
153 WriteT: Write,
154 {
155 write!(writer, "\n{}", self.theme.delimiter(format!("{}{}", self.indentation, delimiter)))
156 }
157
158 pub fn indent_into_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
160 where
161 WriteT: Write,
162 {
163 if last {
164 self.indent_into(writer, BRANCH_INTO_LAST)
165 } else {
166 self.indent_into(writer, BRANCH_INTO_ONGOING)
167 }
168 }
169
170 pub fn indent_into_thick_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
172 where
173 WriteT: Write,
174 {
175 if last {
176 self.indent_into(writer, BRANCH_INTO_LAST_THICK)
177 } else {
178 self.indent_into(writer, BRANCH_INTO_ONGOING_THICK)
179 }
180 }
181
182 pub fn indent_into_double_branch<WriteT>(&self, writer: &mut WriteT, last: bool) -> Result<()>
184 where
185 WriteT: Write,
186 {
187 if last {
188 self.indent_into(writer, BRANCH_INTO_LAST_DOUBLE)
189 } else {
190 self.indent_into(writer, BRANCH_INTO_ONGOING_DOUBLE)
191 }
192 }
193
194 pub fn separate_or_indent<WriteT>(&self, writer: &mut WriteT, first: bool) -> Result<()>
197 where
198 WriteT: Write,
199 {
200 if first && !self.inline {
201 self.separate(writer)
202 } else {
203 self.indent(writer)
204 }
205 }
206
207 pub fn separate_or_indent_into<WriteT>(&self, writer: &mut WriteT, delimiter: &str, first: bool) -> Result<()>
210 where
211 WriteT: Write,
212 {
213 if first && !self.inline {
214 self.separate(writer)?;
215 self.theme.write_delimiter(writer, delimiter)
216 } else {
217 self.indent_into(writer, delimiter)
218 }
219 }
220}