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.
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.
11 // Code for creating styled buffers
13 use snippet::{Style, StyledString};
16 pub struct StyledBuffer {
18 styles: Vec<Vec<Style>>,
22 pub fn new() -> StyledBuffer {
29 fn replace_tabs(&mut self) {
30 for (line_pos, line) in self.text.iter_mut().enumerate() {
31 let mut tab_pos = vec![];
32 for (pos, c) in line.iter().enumerate() {
37 // start with the tabs at the end of the line to replace them with 4 space chars
38 for pos in tab_pos.iter().rev() {
39 assert_eq!(line.remove(*pos), '\t');
40 // fix the position of the style to match up after replacing the tabs
41 let s = self.styles[line_pos].remove(*pos);
43 line.insert(*pos, ' ');
44 self.styles[line_pos].insert(*pos, s);
50 pub fn render(&mut self) -> Vec<Vec<StyledString>> {
51 let mut output: Vec<Vec<StyledString>> = vec![];
52 let mut styled_vec: Vec<StyledString> = vec![];
54 // before we render, replace tabs with spaces
57 for (row, row_style) in self.text.iter().zip(&self.styles) {
58 let mut current_style = Style::NoStyle;
59 let mut current_text = String::new();
61 for (&c, &s) in row.iter().zip(row_style) {
62 if s != current_style {
63 if !current_text.is_empty() {
64 styled_vec.push(StyledString {
70 current_text = String::new();
74 if !current_text.is_empty() {
75 styled_vec.push(StyledString {
81 // We're done with the row, push and keep going
82 output.push(styled_vec);
90 fn ensure_lines(&mut self, line: usize) {
91 while line >= self.text.len() {
92 self.text.push(vec![]);
93 self.styles.push(vec![]);
97 pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
98 self.ensure_lines(line);
99 if col < self.text[line].len() {
100 self.text[line][col] = chr;
101 self.styles[line][col] = style;
103 let mut i = self.text[line].len();
105 self.text[line].push(' ');
106 self.styles[line].push(Style::NoStyle);
109 self.text[line].push(chr);
110 self.styles[line].push(style);
114 pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
116 for c in string.chars() {
117 self.putc(line, n, c, style);
122 pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
123 self.ensure_lines(line);
124 let string_len = string.len();
126 // Push the old content over to make room for new content
127 for _ in 0..string_len {
128 self.styles[line].insert(0, Style::NoStyle);
129 self.text[line].insert(0, ' ');
132 self.puts(line, 0, string, style);
135 pub fn append(&mut self, line: usize, string: &str, style: Style) {
136 if line >= self.text.len() {
137 self.puts(line, 0, string, style);
139 let col = self.text[line].len();
140 self.puts(line, col, string, style);
144 pub fn num_lines(&self) -> usize {
148 pub fn set_style_range(&mut self,
154 for col in col_start..col_end {
155 self.set_style(line, col, style, overwrite);
159 pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
160 if let Some(ref mut line) = self.styles.get_mut(line) {
161 if let Some(s) = line.get_mut(col) {
162 if *s == Style::NoStyle || *s == Style::Quotation || overwrite {