From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_errors/src/styled_buffer.rs | 151 +++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 compiler/rustc_errors/src/styled_buffer.rs (limited to 'compiler/rustc_errors/src/styled_buffer.rs') diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs new file mode 100644 index 000000000..9abdb5fc9 --- /dev/null +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -0,0 +1,151 @@ +// Code for creating styled buffers + +use crate::snippet::{Style, StyledString}; + +#[derive(Debug)] +pub struct StyledBuffer { + lines: Vec>, +} + +#[derive(Debug, Clone)] +struct StyledChar { + chr: char, + style: Style, +} + +impl StyledChar { + const SPACE: Self = StyledChar::new(' ', Style::NoStyle); + + const fn new(chr: char, style: Style) -> Self { + StyledChar { chr, style } + } +} + +impl StyledBuffer { + pub fn new() -> StyledBuffer { + StyledBuffer { lines: vec![] } + } + + /// Returns content of `StyledBuffer` split by lines and line styles + pub fn render(&self) -> Vec> { + // Tabs are assumed to have been replaced by spaces in calling code. + debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); + + let mut output: Vec> = vec![]; + let mut styled_vec: Vec = vec![]; + + for styled_line in &self.lines { + let mut current_style = Style::NoStyle; + let mut current_text = String::new(); + + for sc in styled_line { + if sc.style != current_style { + if !current_text.is_empty() { + styled_vec.push(StyledString { text: current_text, style: current_style }); + } + current_style = sc.style; + current_text = String::new(); + } + current_text.push(sc.chr); + } + if !current_text.is_empty() { + styled_vec.push(StyledString { text: current_text, style: current_style }); + } + + // We're done with the row, push and keep going + output.push(styled_vec); + + styled_vec = vec![]; + } + + output + } + + fn ensure_lines(&mut self, line: usize) { + if line >= self.lines.len() { + self.lines.resize(line + 1, Vec::new()); + } + } + + /// Sets `chr` with `style` for given `line`, `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. + pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { + self.ensure_lines(line); + if col >= self.lines[line].len() { + self.lines[line].resize(col + 1, StyledChar::SPACE); + } + self.lines[line][col] = StyledChar::new(chr, style); + } + + /// Sets `string` with `style` for given `line`, starting from `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. + pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { + let mut n = col; + for c in string.chars() { + self.putc(line, n, c, style); + n += 1; + } + } + + /// For given `line` inserts `string` with `style` before old content of that line, + /// adding lines if needed + pub fn prepend(&mut self, line: usize, string: &str, style: Style) { + self.ensure_lines(line); + let string_len = string.chars().count(); + + if !self.lines[line].is_empty() { + // Push the old content over to make room for new content + for _ in 0..string_len { + self.lines[line].insert(0, StyledChar::SPACE); + } + } + + self.puts(line, 0, string, style); + } + + /// For given `line` inserts `string` with `style` after old content of that line, + /// adding lines if needed + pub fn append(&mut self, line: usize, string: &str, style: Style) { + if line >= self.lines.len() { + self.puts(line, 0, string, style); + } else { + let col = self.lines[line].len(); + self.puts(line, col, string, style); + } + } + + pub fn num_lines(&self) -> usize { + self.lines.len() + } + + /// Set `style` for `line`, `col_start..col_end` range if: + /// 1. That line and column range exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` + pub fn set_style_range( + &mut self, + line: usize, + col_start: usize, + col_end: usize, + style: Style, + overwrite: bool, + ) { + for col in col_start..col_end { + self.set_style(line, col, style, overwrite); + } + } + + /// Set `style` for `line`, `col` if: + /// 1. That line and column exist in `StyledBuffer` + /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` + pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { + if let Some(ref mut line) = self.lines.get_mut(line) { + if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { + if overwrite || *s == Style::NoStyle || *s == Style::Quotation { + *s = style; + } + } + } + } +} -- cgit v1.2.3