Skip to content

Commit 75e1331

Browse files
authored
Rollup merge of rust-lang#84235 - klensy:styled-buffer, r=lcnr
refactor StyledBuffer Refactors StyledBuffer `text` and `styles` fields content into StyledChar and touches some other stuff.
2 parents 06f0adb + 8ebd811 commit 75e1331

File tree

1 file changed

+55
-35
lines changed

1 file changed

+55
-35
lines changed

compiler/rustc_errors/src/styled_buffer.rs

+55-35
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,52 @@
11
// Code for creating styled buffers
22

33
use crate::snippet::{Style, StyledString};
4-
use std::iter;
54

65
#[derive(Debug)]
76
pub struct StyledBuffer {
8-
text: Vec<Vec<char>>,
9-
styles: Vec<Vec<Style>>,
7+
lines: Vec<Vec<StyledChar>>,
8+
}
9+
10+
#[derive(Debug, Clone)]
11+
struct StyledChar {
12+
chr: char,
13+
style: Style,
14+
}
15+
16+
impl StyledChar {
17+
const SPACE: Self = StyledChar::new(' ', Style::NoStyle);
18+
19+
const fn new(chr: char, style: Style) -> Self {
20+
StyledChar { chr, style }
21+
}
1022
}
1123

1224
impl StyledBuffer {
1325
pub fn new() -> StyledBuffer {
14-
StyledBuffer { text: vec![], styles: vec![] }
26+
StyledBuffer { lines: vec![] }
1527
}
1628

29+
/// Returns content of `StyledBuffer` splitted by lines and line styles
1730
pub fn render(&self) -> Vec<Vec<StyledString>> {
1831
// Tabs are assumed to have been replaced by spaces in calling code.
19-
debug_assert!(self.text.iter().all(|r| !r.contains(&'\t')));
32+
debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t')));
2033

2134
let mut output: Vec<Vec<StyledString>> = vec![];
2235
let mut styled_vec: Vec<StyledString> = vec![];
2336

24-
for (row, row_style) in iter::zip(&self.text, &self.styles) {
37+
for styled_line in &self.lines {
2538
let mut current_style = Style::NoStyle;
2639
let mut current_text = String::new();
2740

28-
for (&c, &s) in iter::zip(row, row_style) {
29-
if s != current_style {
41+
for sc in styled_line {
42+
if sc.style != current_style {
3043
if !current_text.is_empty() {
3144
styled_vec.push(StyledString { text: current_text, style: current_style });
3245
}
33-
current_style = s;
46+
current_style = sc.style;
3447
current_text = String::new();
3548
}
36-
current_text.push(c);
49+
current_text.push(sc.chr);
3750
}
3851
if !current_text.is_empty() {
3952
styled_vec.push(StyledString { text: current_text, style: current_style });
@@ -49,29 +62,25 @@ impl StyledBuffer {
4962
}
5063

5164
fn ensure_lines(&mut self, line: usize) {
52-
while line >= self.text.len() {
53-
self.text.push(vec![]);
54-
self.styles.push(vec![]);
65+
if line >= self.lines.len() {
66+
self.lines.resize(line + 1, Vec::new());
5567
}
5668
}
5769

70+
/// Sets `chr` with `style` for given `line`, `col`.
71+
/// If `line` does not exist in our buffer, adds empty lines up to the given
72+
/// and fills the last line with unstyled whitespace.
5873
pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
5974
self.ensure_lines(line);
60-
if col < self.text[line].len() {
61-
self.text[line][col] = chr;
62-
self.styles[line][col] = style;
63-
} else {
64-
let mut i = self.text[line].len();
65-
while i < col {
66-
self.text[line].push(' ');
67-
self.styles[line].push(Style::NoStyle);
68-
i += 1;
69-
}
70-
self.text[line].push(chr);
71-
self.styles[line].push(style);
75+
if col >= self.lines[line].len() {
76+
self.lines[line].resize(col + 1, StyledChar::SPACE);
7277
}
78+
self.lines[line][col] = StyledChar::new(chr, style);
7379
}
7480

81+
/// Sets `string` with `style` for given `line`, starting from `col`.
82+
/// If `line` does not exist in our buffer, adds empty lines up to the given
83+
/// and fills the last line with unstyled whitespace.
7584
pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
7685
let mut n = col;
7786
for c in string.chars() {
@@ -80,32 +89,40 @@ impl StyledBuffer {
8089
}
8190
}
8291

92+
/// For given `line` inserts `string` with `style` before old content of that line,
93+
/// adding lines if needed
8394
pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
8495
self.ensure_lines(line);
8596
let string_len = string.chars().count();
8697

87-
// Push the old content over to make room for new content
88-
for _ in 0..string_len {
89-
self.styles[line].insert(0, Style::NoStyle);
90-
self.text[line].insert(0, ' ');
98+
if !self.lines[line].is_empty() {
99+
// Push the old content over to make room for new content
100+
for _ in 0..string_len {
101+
self.lines[line].insert(0, StyledChar::SPACE);
102+
}
91103
}
92104

93105
self.puts(line, 0, string, style);
94106
}
95107

108+
/// For given `line` inserts `string` with `style` after old content of that line,
109+
/// adding lines if needed
96110
pub fn append(&mut self, line: usize, string: &str, style: Style) {
97-
if line >= self.text.len() {
111+
if line >= self.lines.len() {
98112
self.puts(line, 0, string, style);
99113
} else {
100-
let col = self.text[line].len();
114+
let col = self.lines[line].len();
101115
self.puts(line, col, string, style);
102116
}
103117
}
104118

105119
pub fn num_lines(&self) -> usize {
106-
self.text.len()
120+
self.lines.len()
107121
}
108122

123+
/// Set `style` for `line`, `col_start..col_end` range if:
124+
/// 1. That line and column range exist in `StyledBuffer`
125+
/// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation`
109126
pub fn set_style_range(
110127
&mut self,
111128
line: usize,
@@ -119,10 +136,13 @@ impl StyledBuffer {
119136
}
120137
}
121138

139+
/// Set `style` for `line`, `col` if:
140+
/// 1. That line and column exist in `StyledBuffer`
141+
/// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation`
122142
pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
123-
if let Some(ref mut line) = self.styles.get_mut(line) {
124-
if let Some(s) = line.get_mut(col) {
125-
if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
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 || *s == Style::NoStyle || *s == Style::Quotation {
126146
*s = style;
127147
}
128148
}

0 commit comments

Comments
 (0)