]> git.proxmox.com Git - rustc.git/blame - src/librustc_errors/styled_buffer.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / librustc_errors / styled_buffer.rs
CommitLineData
5bcae85e
SL
1// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11// Code for creating styled buffers
12
13use snippet::{Style, StyledString};
14
15#[derive(Debug)]
16pub struct StyledBuffer {
17 text: Vec<Vec<char>>,
18 styles: Vec<Vec<Style>>,
19}
20
21impl StyledBuffer {
22 pub fn new() -> StyledBuffer {
23 StyledBuffer {
24 text: vec![],
25 styles: vec![],
26 }
27 }
28
29 pub fn copy_tabs(&mut self, row: usize) {
30 if row < self.text.len() {
c30ab7b3 31 for i in row + 1..self.text.len() {
5bcae85e 32 for j in 0..self.text[i].len() {
c30ab7b3 33 if self.text[row].len() > j && self.text[row][j] == '\t' &&
5bcae85e
SL
34 self.text[i][j] == ' ' {
35 self.text[i][j] = '\t';
36 }
37 }
38 }
39 }
40 }
41
42 pub fn render(&mut self) -> Vec<Vec<StyledString>> {
43 let mut output: Vec<Vec<StyledString>> = vec![];
44 let mut styled_vec: Vec<StyledString> = vec![];
45
c30ab7b3 46 // before we render, do a little patch-up work to support tabs
5bcae85e
SL
47 self.copy_tabs(3);
48
49 for (row, row_style) in self.text.iter().zip(&self.styles) {
50 let mut current_style = Style::NoStyle;
51 let mut current_text = String::new();
52
53 for (&c, &s) in row.iter().zip(row_style) {
54 if s != current_style {
55 if !current_text.is_empty() {
56 styled_vec.push(StyledString {
57 text: current_text,
58 style: current_style,
59 });
60 }
61 current_style = s;
62 current_text = String::new();
63 }
64 current_text.push(c);
65 }
66 if !current_text.is_empty() {
67 styled_vec.push(StyledString {
68 text: current_text,
69 style: current_style,
70 });
71 }
72
73 // We're done with the row, push and keep going
74 output.push(styled_vec);
75
76 styled_vec = vec![];
77 }
78
79 output
80 }
81
82 fn ensure_lines(&mut self, line: usize) {
83 while line >= self.text.len() {
84 self.text.push(vec![]);
85 self.styles.push(vec![]);
86 }
87 }
88
89 pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
90 self.ensure_lines(line);
91 if col < self.text[line].len() {
92 self.text[line][col] = chr;
93 self.styles[line][col] = style;
94 } else {
95 let mut i = self.text[line].len();
96 while i < col {
97 self.text[line].push(' ');
98 self.styles[line].push(Style::NoStyle);
99 i += 1;
100 }
101 self.text[line].push(chr);
102 self.styles[line].push(style);
103 }
104 }
105
106 pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
107 let mut n = col;
108 for c in string.chars() {
109 self.putc(line, n, c, style);
110 n += 1;
111 }
112 }
113
114 pub fn set_style(&mut self, line: usize, col: usize, style: Style) {
115 if self.styles.len() > line && self.styles[line].len() > col {
116 self.styles[line][col] = style;
117 }
118 }
119
120 pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
121 self.ensure_lines(line);
122 let string_len = string.len();
123
124 // Push the old content over to make room for new content
125 for _ in 0..string_len {
126 self.styles[line].insert(0, Style::NoStyle);
127 self.text[line].insert(0, ' ');
128 }
129
130 self.puts(line, 0, string, style);
131 }
132
133 pub fn append(&mut self, line: usize, string: &str, style: Style) {
134 if line >= self.text.len() {
135 self.puts(line, 0, string, style);
136 } else {
137 let col = self.text[line].len();
138 self.puts(line, col, string, style);
139 }
140 }
141
142 pub fn num_lines(&self) -> usize {
143 self.text.len()
144 }
145}