]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_errors/src/styled_buffer.rs
Rollup merge of #82214 - est31:no_to_string, r=oli-obk
[rust.git] / compiler / rustc_errors / src / styled_buffer.rs
1 // Code for creating styled buffers
2
3 use crate::snippet::{Style, StyledString};
4
5 #[derive(Debug)]
6 pub struct StyledBuffer {
7     text: Vec<Vec<char>>,
8     styles: Vec<Vec<Style>>,
9 }
10
11 impl StyledBuffer {
12     pub fn new() -> StyledBuffer {
13         StyledBuffer { text: vec![], styles: vec![] }
14     }
15
16     pub fn render(&self) -> Vec<Vec<StyledString>> {
17         // Tabs are assumed to have been replaced by spaces in calling code.
18         debug_assert!(self.text.iter().all(|r| !r.contains(&'\t')));
19
20         let mut output: Vec<Vec<StyledString>> = vec![];
21         let mut styled_vec: Vec<StyledString> = vec![];
22
23         for (row, row_style) in self.text.iter().zip(&self.styles) {
24             let mut current_style = Style::NoStyle;
25             let mut current_text = String::new();
26
27             for (&c, &s) in row.iter().zip(row_style) {
28                 if s != current_style {
29                     if !current_text.is_empty() {
30                         styled_vec.push(StyledString { text: current_text, style: current_style });
31                     }
32                     current_style = s;
33                     current_text = String::new();
34                 }
35                 current_text.push(c);
36             }
37             if !current_text.is_empty() {
38                 styled_vec.push(StyledString { text: current_text, style: current_style });
39             }
40
41             // We're done with the row, push and keep going
42             output.push(styled_vec);
43
44             styled_vec = vec![];
45         }
46
47         output
48     }
49
50     fn ensure_lines(&mut self, line: usize) {
51         while line >= self.text.len() {
52             self.text.push(vec![]);
53             self.styles.push(vec![]);
54         }
55     }
56
57     pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
58         self.ensure_lines(line);
59         if col < self.text[line].len() {
60             self.text[line][col] = chr;
61             self.styles[line][col] = style;
62         } else {
63             let mut i = self.text[line].len();
64             while i < col {
65                 self.text[line].push(' ');
66                 self.styles[line].push(Style::NoStyle);
67                 i += 1;
68             }
69             self.text[line].push(chr);
70             self.styles[line].push(style);
71         }
72     }
73
74     pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
75         let mut n = col;
76         for c in string.chars() {
77             self.putc(line, n, c, style);
78             n += 1;
79         }
80     }
81
82     pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
83         self.ensure_lines(line);
84         let string_len = string.chars().count();
85
86         // Push the old content over to make room for new content
87         for _ in 0..string_len {
88             self.styles[line].insert(0, Style::NoStyle);
89             self.text[line].insert(0, ' ');
90         }
91
92         self.puts(line, 0, string, style);
93     }
94
95     pub fn append(&mut self, line: usize, string: &str, style: Style) {
96         if line >= self.text.len() {
97             self.puts(line, 0, string, style);
98         } else {
99             let col = self.text[line].len();
100             self.puts(line, col, string, style);
101         }
102     }
103
104     pub fn num_lines(&self) -> usize {
105         self.text.len()
106     }
107
108     pub fn set_style_range(
109         &mut self,
110         line: usize,
111         col_start: usize,
112         col_end: usize,
113         style: Style,
114         overwrite: bool,
115     ) {
116         for col in col_start..col_end {
117             self.set_style(line, col, style, overwrite);
118         }
119     }
120
121     pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
122         if let Some(ref mut line) = self.styles.get_mut(line) {
123             if let Some(s) = line.get_mut(col) {
124                 if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
125                     *s = style;
126                 }
127             }
128         }
129     }
130 }