layered_nlp/ll_line/
display.rs1use super::*;
2use unicode_width::UnicodeWidthStr;
3
4pub struct LLLineDisplay<'a> {
5 ll_line: &'a LLLine,
6 include_attrs: Vec<(LRange, String)>,
7}
8
9impl<'a> std::fmt::Display for LLLineDisplay<'a> {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 const SPACE_PADDING: usize = 2;
35 let mut token_idx_to_start_display_char_idx = Vec::new();
36 let mut token_idx_to_end_display_char_idx = Vec::new();
37 let mut opening_line = String::new();
39 {
40 let mut is_first = true;
42 for ll_token in self.ll_line.ll_tokens.iter() {
43 if is_first {
44 is_first = false;
45 } else {
46 opening_line.extend(std::iter::repeat(' ').take(SPACE_PADDING));
47 }
48
49 token_idx_to_start_display_char_idx.push(UnicodeWidthStr::width(&*opening_line));
50
51 match &ll_token.token {
52 LToken::Text(text, _) => {
53 opening_line.push_str(&text);
54 }
55 LToken::Value { .. } => {
56 write!(&mut opening_line, "<>")?;
57 }
58 }
59
60 token_idx_to_end_display_char_idx.push(UnicodeWidthStr::width(&*opening_line));
61 }
62 }
63
64 f.write_str(&opening_line)?;
65
66 for ((starts_at_token_idx, ends_at_token_idx), debug_value) in self.include_attrs.iter() {
70 f.write_char('\n')?;
71
72 let start_char_idx = token_idx_to_start_display_char_idx[*starts_at_token_idx];
73 for _ in 0..start_char_idx {
74 f.write_char(' ')?;
75 }
76
77 f.write_char('╰')?;
78
79 let end_char_idx = token_idx_to_end_display_char_idx[*ends_at_token_idx];
80 let char_len = end_char_idx - start_char_idx;
81 for _ in (start_char_idx + 1)..end_char_idx.saturating_sub(1) {
82 f.write_char('─')?;
83 }
84
85 if char_len > 1 {
86 f.write_char('╯')?;
87 }
88
89 f.write_str(&debug_value)?;
90 }
91
92 Ok(())
93 }
94}
95
96impl<'a> LLLineDisplay<'a> {
97 pub fn new(ll_line: &'a LLLine) -> Self {
98 LLLineDisplay {
99 ll_line,
100 include_attrs: Vec::new(),
101 }
102 }
103 pub fn include<T: 'static + std::fmt::Debug>(&mut self) {
105 for ll_range in self.ll_line.attrs.ranges.get::<T>() {
106 for debug_value in self
107 .ll_line
108 .attrs
109 .values
110 .get(ll_range)
111 .into_iter()
112 .flat_map(|type_bucket| type_bucket.get_debug::<T>())
113 .rev()
114 {
115 self.include_attrs.push((*ll_range, debug_value));
116 }
117 }
118 }
119 pub fn with<T: 'static + std::fmt::Debug>(mut self) -> Self {
121 self.include::<T>();
122 self
123 }
124}