]> git.proxmox.com Git - rustc.git/blame - src/librustc_errors/styled_buffer.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / librustc_errors / styled_buffer.rs
CommitLineData
5bcae85e
SL
1// Code for creating styled buffers
2
9fa01778 3use crate::snippet::{Style, StyledString};
5bcae85e
SL
4
5#[derive(Debug)]
6pub struct StyledBuffer {
7 text: Vec<Vec<char>>,
8 styles: Vec<Vec<Style>>,
9}
10
11impl StyledBuffer {
12 pub fn new() -> StyledBuffer {
13 StyledBuffer {
14 text: vec![],
15 styles: vec![],
16 }
17 }
18
ea8adc8c 19 fn replace_tabs(&mut self) {
ff7c6d11
XL
20 for (line_pos, line) in self.text.iter_mut().enumerate() {
21 let mut tab_pos = vec![];
22 for (pos, c) in line.iter().enumerate() {
ea8adc8c 23 if *c == '\t' {
ff7c6d11
XL
24 tab_pos.push(pos);
25 }
26 }
27 // start with the tabs at the end of the line to replace them with 4 space chars
28 for pos in tab_pos.iter().rev() {
29 assert_eq!(line.remove(*pos), '\t');
30 // fix the position of the style to match up after replacing the tabs
31 let s = self.styles[line_pos].remove(*pos);
32 for _ in 0..4 {
33 line.insert(*pos, ' ');
34 self.styles[line_pos].insert(*pos, s);
5bcae85e
SL
35 }
36 }
37 }
38 }
39
40 pub fn render(&mut self) -> Vec<Vec<StyledString>> {
41 let mut output: Vec<Vec<StyledString>> = vec![];
42 let mut styled_vec: Vec<StyledString> = vec![];
43
ea8adc8c
XL
44 // before we render, replace tabs with spaces
45 self.replace_tabs();
5bcae85e
SL
46
47 for (row, row_style) in self.text.iter().zip(&self.styles) {
48 let mut current_style = Style::NoStyle;
49 let mut current_text = String::new();
50
51 for (&c, &s) in row.iter().zip(row_style) {
52 if s != current_style {
53 if !current_text.is_empty() {
54 styled_vec.push(StyledString {
55 text: current_text,
56 style: current_style,
57 });
58 }
59 current_style = s;
60 current_text = String::new();
61 }
62 current_text.push(c);
63 }
64 if !current_text.is_empty() {
65 styled_vec.push(StyledString {
66 text: current_text,
67 style: current_style,
68 });
69 }
70
71 // We're done with the row, push and keep going
72 output.push(styled_vec);
73
74 styled_vec = vec![];
75 }
76
77 output
78 }
79
80 fn ensure_lines(&mut self, line: usize) {
81 while line >= self.text.len() {
82 self.text.push(vec![]);
83 self.styles.push(vec![]);
84 }
85 }
86
87 pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
88 self.ensure_lines(line);
89 if col < self.text[line].len() {
90 self.text[line][col] = chr;
91 self.styles[line][col] = style;
92 } else {
93 let mut i = self.text[line].len();
94 while i < col {
95 self.text[line].push(' ');
96 self.styles[line].push(Style::NoStyle);
97 i += 1;
98 }
99 self.text[line].push(chr);
100 self.styles[line].push(style);
101 }
102 }
103
104 pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
105 let mut n = col;
106 for c in string.chars() {
107 self.putc(line, n, c, style);
108 n += 1;
109 }
110 }
111
5bcae85e
SL
112 pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
113 self.ensure_lines(line);
114 let string_len = string.len();
115
116 // Push the old content over to make room for new content
117 for _ in 0..string_len {
118 self.styles[line].insert(0, Style::NoStyle);
119 self.text[line].insert(0, ' ');
120 }
121
122 self.puts(line, 0, string, style);
123 }
124
125 pub fn append(&mut self, line: usize, string: &str, style: Style) {
126 if line >= self.text.len() {
127 self.puts(line, 0, string, style);
128 } else {
129 let col = self.text[line].len();
130 self.puts(line, col, string, style);
131 }
132 }
133
134 pub fn num_lines(&self) -> usize {
135 self.text.len()
136 }
2c00a5a8
XL
137
138 pub fn set_style_range(&mut self,
139 line: usize,
140 col_start: usize,
141 col_end: usize,
142 style: Style,
143 overwrite: bool) {
144 for col in col_start..col_end {
145 self.set_style(line, col, style, overwrite);
146 }
147 }
148
149 pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
150 if let Some(ref mut line) = self.styles.get_mut(line) {
151 if let Some(s) = line.get_mut(col) {
152 if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
153 *s = style;
154 }
155 }
156 }
157 }
5bcae85e 158}