1 // Code for creating styled buffers
3 use crate::snippet
::{Style, StyledString}
;
6 pub struct StyledBuffer
{
8 styles
: Vec
<Vec
<Style
>>,
12 pub fn new() -> StyledBuffer
{
13 StyledBuffer { text: vec![], styles: vec![] }
16 fn replace_tabs(&mut self) {
17 for (line_pos
, line
) in self.text
.iter_mut().enumerate() {
18 let mut tab_pos
= vec
![];
19 for (pos
, c
) in line
.iter().enumerate() {
24 // start with the tabs at the end of the line to replace them with 4 space chars
25 for pos
in tab_pos
.iter().rev() {
26 assert_eq
!(line
.remove(*pos
), '
\t'
);
27 // fix the position of the style to match up after replacing the tabs
28 let s
= self.styles
[line_pos
].remove(*pos
);
30 line
.insert(*pos
, ' '
);
31 self.styles
[line_pos
].insert(*pos
, s
);
37 pub fn render(&mut self) -> Vec
<Vec
<StyledString
>> {
38 let mut output
: Vec
<Vec
<StyledString
>> = vec
![];
39 let mut styled_vec
: Vec
<StyledString
> = vec
![];
41 // before we render, replace tabs with spaces
44 for (row
, row_style
) in self.text
.iter().zip(&self.styles
) {
45 let mut current_style
= Style
::NoStyle
;
46 let mut current_text
= String
::new();
48 for (&c
, &s
) in row
.iter().zip(row_style
) {
49 if s
!= current_style
{
50 if !current_text
.is_empty() {
51 styled_vec
.push(StyledString { text: current_text, style: current_style }
);
54 current_text
= String
::new();
58 if !current_text
.is_empty() {
59 styled_vec
.push(StyledString { text: current_text, style: current_style }
);
62 // We're done with the row, push and keep going
63 output
.push(styled_vec
);
71 fn ensure_lines(&mut self, line
: usize) {
72 while line
>= self.text
.len() {
73 self.text
.push(vec
![]);
74 self.styles
.push(vec
![]);
78 pub fn putc(&mut self, line
: usize, col
: usize, chr
: char, style
: Style
) {
79 self.ensure_lines(line
);
80 if col
< self.text
[line
].len() {
81 self.text
[line
][col
] = chr
;
82 self.styles
[line
][col
] = style
;
84 let mut i
= self.text
[line
].len();
86 self.text
[line
].push(' '
);
87 self.styles
[line
].push(Style
::NoStyle
);
90 self.text
[line
].push(chr
);
91 self.styles
[line
].push(style
);
95 pub fn puts(&mut self, line
: usize, col
: usize, string
: &str, style
: Style
) {
97 for c
in string
.chars() {
98 self.putc(line
, n
, c
, style
);
103 pub fn prepend(&mut self, line
: usize, string
: &str, style
: Style
) {
104 self.ensure_lines(line
);
105 let string_len
= string
.chars().count();
107 // Push the old content over to make room for new content
108 for _
in 0..string_len
{
109 self.styles
[line
].insert(0, Style
::NoStyle
);
110 self.text
[line
].insert(0, ' '
);
113 self.puts(line
, 0, string
, style
);
116 pub fn append(&mut self, line
: usize, string
: &str, style
: Style
) {
117 if line
>= self.text
.len() {
118 self.puts(line
, 0, string
, style
);
120 let col
= self.text
[line
].len();
121 self.puts(line
, col
, string
, style
);
125 pub fn num_lines(&self) -> usize {
129 pub fn set_style_range(
137 for col
in col_start
..col_end
{
138 self.set_style(line
, col
, style
, overwrite
);
142 pub fn set_style(&mut self, line
: usize, col
: usize, style
: Style
, overwrite
: bool
) {
143 if let Some(ref mut line
) = self.styles
.get_mut(line
) {
144 if let Some(s
) = line
.get_mut(col
) {
145 if *s
== Style
::NoStyle
|| *s
== Style
::Quotation
|| overwrite
{