swc_common/errors/
styled_buffer.rs1use super::snippet::{Style, StyledString};
14
15#[derive(Debug)]
16pub struct StyledBuffer {
17 text: Vec<Vec<char>>,
18 styles: Vec<Vec<Style>>,
19}
20
21impl StyledBuffer {
22 pub fn new() -> StyledBuffer {
23 StyledBuffer {
24 text: Vec::new(),
25 styles: Vec::new(),
26 }
27 }
28
29 fn replace_tabs(&mut self) {
30 for (line_pos, line) in self.text.iter_mut().enumerate() {
31 let mut tab_pos = Vec::new();
32 for (pos, c) in line.iter().enumerate() {
33 if *c == '\t' {
34 tab_pos.push(pos);
35 }
36 }
37 for pos in tab_pos.iter().rev() {
39 assert_eq!(line.remove(*pos), '\t');
40 let s = self.styles[line_pos].remove(*pos);
42 for _ in 0..4 {
43 line.insert(*pos, ' ');
44 self.styles[line_pos].insert(*pos, s);
45 }
46 }
47 }
48 }
49
50 pub fn render(&mut self) -> Vec<Vec<StyledString>> {
51 let mut output: Vec<Vec<StyledString>> = Vec::new();
52 let mut styled_vec: Vec<StyledString> = Vec::new();
53
54 self.replace_tabs();
56
57 for (row, row_style) in self.text.iter().zip(&self.styles) {
58 let mut current_style = Style::NoStyle;
59 let mut current_text = String::new();
60
61 for (&c, &s) in row.iter().zip(row_style) {
62 if s != current_style {
63 if !current_text.is_empty() {
64 styled_vec.push(StyledString {
65 text: current_text,
66 style: current_style,
67 });
68 }
69 current_style = s;
70 current_text = String::new();
71 }
72 current_text.push(c);
73 }
74 if !current_text.is_empty() {
75 styled_vec.push(StyledString {
76 text: current_text,
77 style: current_style,
78 });
79 }
80
81 output.push(styled_vec);
83
84 styled_vec = Vec::new();
85 }
86
87 output
88 }
89
90 fn ensure_lines(&mut self, line: usize) {
91 while line >= self.text.len() {
92 self.text.push(Vec::new());
93 self.styles.push(Vec::new());
94 }
95 }
96
97 pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
98 self.ensure_lines(line);
99 if col < self.text[line].len() {
100 self.text[line][col] = chr;
101 self.styles[line][col] = style;
102 } else {
103 let mut i = self.text[line].len();
104 while i < col {
105 self.text[line].push(' ');
106 self.styles[line].push(Style::NoStyle);
107 i += 1;
108 }
109 self.text[line].push(chr);
110 self.styles[line].push(style);
111 }
112 }
113
114 pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
115 let mut n = col;
116 for c in string.chars() {
117 self.putc(line, n, c, style);
118 n += 1;
119 }
120 }
121
122 pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
123 self.ensure_lines(line);
124 let string_len = string.len();
125
126 for _ in 0..string_len {
128 self.styles[line].insert(0, Style::NoStyle);
129 self.text[line].insert(0, ' ');
130 }
131
132 self.puts(line, 0, string, style);
133 }
134
135 pub fn append(&mut self, line: usize, string: &str, style: Style) {
136 if line >= self.text.len() {
137 self.puts(line, 0, string, style);
138 } else {
139 let col = self.text[line].len();
140 self.puts(line, col, string, style);
141 }
142 }
143
144 pub fn num_lines(&self) -> usize {
145 self.text.len()
146 }
147
148 pub fn set_style_range(
149 &mut self,
150 line: usize,
151 col_start: usize,
152 col_end: usize,
153 style: Style,
154 overwrite: bool,
155 ) {
156 for col in col_start..col_end {
157 self.set_style(line, col, style, overwrite);
158 }
159 }
160
161 pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
162 if let Some(ref mut line) = self.styles.get_mut(line) {
163 if let Some(s) = line.get_mut(col) {
164 if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
165 *s = style;
166 }
167 }
168 }
169 }
170}