]>
Commit | Line | Data |
---|---|---|
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 | ||
13 | use snippet::{Style, StyledString}; | |
14 | ||
15 | #[derive(Debug)] | |
16 | pub struct StyledBuffer { | |
17 | text: Vec<Vec<char>>, | |
18 | styles: Vec<Vec<Style>>, | |
19 | } | |
20 | ||
21 | impl 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 | } |