rustc_errors/
styled_buffer.rs
1use crate::snippet::{Style, StyledString};
4
5#[derive(Debug)]
6pub(crate) struct StyledBuffer {
7 lines: Vec<Vec<StyledChar>>,
8}
9
10#[derive(Debug, Clone)]
11struct StyledChar {
12 chr: char,
13 style: Style,
14}
15
16impl StyledChar {
17 const SPACE: Self = StyledChar::new(' ', Style::NoStyle);
18
19 const fn new(chr: char, style: Style) -> Self {
20 StyledChar { chr, style }
21 }
22}
23
24impl StyledBuffer {
25 pub(crate) fn new() -> StyledBuffer {
26 StyledBuffer { lines: vec![] }
27 }
28
29 pub(crate) fn render(&self) -> Vec<Vec<StyledString>> {
31 debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t')));
33
34 let mut output: Vec<Vec<StyledString>> = vec![];
35 let mut styled_vec: Vec<StyledString> = vec![];
36
37 for styled_line in &self.lines {
38 let mut current_style = Style::NoStyle;
39 let mut current_text = String::new();
40
41 for sc in styled_line {
42 if sc.style != current_style {
43 if !current_text.is_empty() {
44 styled_vec.push(StyledString { text: current_text, style: current_style });
45 }
46 current_style = sc.style;
47 current_text = String::new();
48 }
49 current_text.push(sc.chr);
50 }
51 if !current_text.is_empty() {
52 styled_vec.push(StyledString { text: current_text, style: current_style });
53 }
54
55 output.push(styled_vec);
57
58 styled_vec = vec![];
59 }
60
61 output
62 }
63
64 fn ensure_lines(&mut self, line: usize) {
65 if line >= self.lines.len() {
66 self.lines.resize(line + 1, Vec::new());
67 }
68 }
69
70 pub(crate) fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
74 self.ensure_lines(line);
75 if col >= self.lines[line].len() {
76 self.lines[line].resize(col + 1, StyledChar::SPACE);
77 }
78 self.lines[line][col] = StyledChar::new(chr, style);
79 }
80
81 pub(crate) fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
85 let mut n = col;
86 for c in string.chars() {
87 self.putc(line, n, c, style);
88 n += 1;
89 }
90 }
91
92 pub(crate) fn prepend(&mut self, line: usize, string: &str, style: Style) {
95 self.ensure_lines(line);
96 let string_len = string.chars().count();
97
98 if !self.lines[line].is_empty() {
99 for _ in 0..string_len {
101 self.lines[line].insert(0, StyledChar::SPACE);
102 }
103 }
104
105 self.puts(line, 0, string, style);
106 }
107
108 pub(crate) fn append(&mut self, line: usize, string: &str, style: Style) {
111 if line >= self.lines.len() {
112 self.puts(line, 0, string, style);
113 } else {
114 let col = self.lines[line].len();
115 self.puts(line, col, string, style);
116 }
117 }
118
119 pub(crate) fn num_lines(&self) -> usize {
120 self.lines.len()
121 }
122
123 pub(crate) fn set_style_range(
127 &mut self,
128 line: usize,
129 col_start: usize,
130 col_end: usize,
131 style: Style,
132 overwrite: bool,
133 ) {
134 for col in col_start..col_end {
135 self.set_style(line, col, style, overwrite);
136 }
137 }
138
139 fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
143 if let Some(ref mut line) = self.lines.get_mut(line) {
144 if let Some(StyledChar { style: s, .. }) = line.get_mut(col) {
145 if overwrite || matches!(s, Style::NoStyle | Style::Quotation) {
146 *s = style;
147 }
148 }
149 }
150 }
151}