Skip to content

Commit c3b14f8

Browse files
authored
Add option to draw indentation lines (#8)
1 parent cc56589 commit c3b14f8

File tree

1 file changed

+130
-21
lines changed

1 file changed

+130
-21
lines changed

src/lib.rs

Lines changed: 130 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,44 @@ use tracing_subscriber::{
1616
registry::LookupSpan,
1717
};
1818

19+
const LINE_VERT: &str = "│";
20+
const LINE_HORIZ: &str = "─";
21+
const LINE_BRANCH: &str = "├";
22+
23+
#[derive(Debug)]
24+
struct Config {
25+
ansi: bool,
26+
indent_lines: bool,
27+
indent_amount: usize,
28+
}
29+
30+
impl Config {
31+
fn with_ansi(self, ansi: bool) -> Self {
32+
Self { ansi, ..self }
33+
}
34+
fn with_indent_lines(self, indent_lines: bool) -> Self {
35+
Self {
36+
indent_lines,
37+
..self
38+
}
39+
}
40+
}
41+
42+
impl Default for Config {
43+
fn default() -> Self {
44+
Self {
45+
ansi: true,
46+
indent_lines: false,
47+
indent_amount: 2,
48+
}
49+
}
50+
}
51+
1952
#[derive(Debug)]
2053
pub struct HierarchicalLayer {
2154
stdout: io::Stdout,
22-
indent_amount: usize,
23-
ansi: bool,
2455
bufs: Mutex<Buffers>,
56+
config: Config,
2557
}
2658

2759
#[derive(Debug)]
@@ -48,12 +80,13 @@ impl Buffers {
4880
self.indent_buf.clear();
4981
}
5082

51-
fn indent_current(&mut self, indent: usize, indent_amount: usize) {
83+
fn indent_current(&mut self, indent: usize, config: &Config) {
5284
indent_block(
5385
&mut self.current_buf,
5486
&mut self.indent_buf,
5587
indent,
56-
indent_amount,
88+
config.indent_amount,
89+
config.indent_lines,
5790
);
5891
self.current_buf.clear();
5992
}
@@ -102,9 +135,9 @@ impl<'a> Visit for FmtEvent<'a> {
102135
}
103136

104137
impl<'a> FmtEvent<'a> {
105-
fn finish(&mut self, indent: usize, indent_amount: usize) {
138+
fn finish(&mut self, indent: usize, config: &Config) {
106139
self.bufs.current_buf.push('\n');
107-
self.bufs.indent_current(indent, indent_amount);
140+
self.bufs.indent_current(indent, config);
108141
self.bufs.flush_indent_buf();
109142
}
110143
}
@@ -124,35 +157,111 @@ impl<'a> fmt::Display for ColorLevel<'a> {
124157
}
125158
}
126159

127-
fn indent_block(block: &mut String, buf: &mut String, indent: usize, indent_amount: usize) {
128-
let lines: Vec<_> = block.lines().collect();
160+
fn indent_block_with_lines(lines: &[&str], buf: &mut String, indent: usize, indent_amount: usize) {
129161
let indent_spaces = indent * indent_amount;
130-
buf.reserve(block.len() + (lines.len() * indent_spaces));
131-
let indent_str = String::from(" ").repeat(indent_spaces);
132-
for line in lines {
133-
buf.push_str(&indent_str);
162+
if lines.len() == 0 {
163+
return;
164+
} else if indent_spaces == 0 {
165+
for line in lines {
166+
buf.push_str(line);
167+
buf.push('\n');
168+
}
169+
return;
170+
}
171+
let mut s = String::with_capacity(indent_spaces);
172+
173+
// instead of using all spaces to indent, draw a vertical line at every indent level
174+
// up until the last indent
175+
for i in 0..(indent_spaces - indent_amount) {
176+
if i % indent_amount == 0 {
177+
s.push_str(LINE_VERT);
178+
} else {
179+
s.push(' ');
180+
}
181+
}
182+
183+
// draw branch
184+
buf.push_str(&s);
185+
buf.push_str(LINE_BRANCH);
186+
187+
// add `indent_amount - 1` horizontal lines before the span/event
188+
for _ in 0..(indent_amount - 1) {
189+
buf.push_str(LINE_HORIZ);
190+
}
191+
buf.push_str(&lines[0]);
192+
buf.push('\n');
193+
194+
// add the rest of the indentation, since we don't want to draw horizontal lines
195+
// for subsequent lines
196+
for i in 0..indent_amount {
197+
if i % indent_amount == 0 {
198+
s.push_str(LINE_VERT);
199+
} else {
200+
s.push(' ');
201+
}
202+
}
203+
204+
// add all of the actual content, with each line preceded by the indent string
205+
for line in &lines[1..] {
206+
buf.push_str(&s);
134207
buf.push_str(line);
135208
buf.push('\n');
136209
}
137210
}
138211

212+
fn indent_block(
213+
block: &mut String,
214+
buf: &mut String,
215+
indent: usize,
216+
indent_amount: usize,
217+
indent_lines: bool,
218+
) {
219+
let lines: Vec<&str> = block.lines().collect();
220+
let indent_spaces = indent * indent_amount;
221+
buf.reserve(block.len() + (lines.len() * indent_spaces));
222+
if indent_lines {
223+
indent_block_with_lines(&lines, buf, indent, indent_amount);
224+
} else {
225+
let indent_str = String::from(" ").repeat(indent_spaces);
226+
for line in lines {
227+
buf.push_str(&indent_str);
228+
buf.push_str(line);
229+
buf.push('\n');
230+
}
231+
}
232+
}
233+
139234
impl HierarchicalLayer {
140235
pub fn new(indent_amount: usize) -> Self {
141236
let ansi = atty::is(atty::Stream::Stdout);
142-
Self {
237+
let config = Config {
238+
ansi,
143239
indent_amount,
240+
..Default::default()
241+
};
242+
Self {
144243
stdout: io::stdout(),
145-
ansi,
146244
bufs: Mutex::new(Buffers::new()),
245+
config,
147246
}
148247
}
149248

150249
pub fn with_ansi(self, ansi: bool) -> Self {
151-
Self { ansi, ..self }
250+
Self {
251+
config: self.config.with_ansi(ansi),
252+
..self
253+
}
254+
}
255+
256+
pub fn with_indent_lines(self, indent_lines: bool) -> Self {
257+
Self {
258+
config: self.config.with_indent_lines(indent_lines),
259+
..self
260+
}
152261
}
153262

154263
fn styled(&self, style: Style, text: impl AsRef<str>) -> String {
155-
if self.ansi {
264+
if self.config.ansi {
156265
style.paint(text.as_ref()).to_string()
157266
} else {
158267
text.as_ref().to_string()
@@ -200,7 +309,7 @@ where
200309
let bufs = &mut *guard;
201310
let mut current_buf = &mut bufs.current_buf;
202311

203-
let indent = ctx.scope().count() - 1;
312+
let indent = ctx.scope().count().saturating_sub(1);
204313

205314
write!(
206315
current_buf,
@@ -223,7 +332,7 @@ where
223332
)
224333
.unwrap();
225334

226-
bufs.indent_current(indent, self.indent_amount);
335+
bufs.indent_current(indent, &self.config);
227336
bufs.flush_indent_buf();
228337
bufs.flush_current_buf(self.stdout.lock());
229338
}
@@ -271,7 +380,7 @@ where
271380
.expect("Unable to write to buffer");
272381
}
273382
let level = event.metadata().level();
274-
let level = if self.ansi {
383+
let level = if self.config.ansi {
275384
ColorLevel(level).to_string()
276385
} else {
277386
level.to_string()
@@ -282,9 +391,9 @@ where
282391
bufs: &mut bufs,
283392
};
284393
event.record(&mut visitor);
285-
visitor.finish(indent, self.indent_amount);
394+
visitor.finish(indent, &self.config);
286395
bufs.flush_current_buf(self.stdout.lock());
287396
}
288397

289-
fn on_close(&self, _id: Id, _ctx: Context<S>) {}
398+
fn on_exit(&self, _id: &Id, _ctx: Context<S>) {}
290399
}

0 commit comments

Comments
 (0)