// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Code for creating styled buffers use snippet::{Style, StyledString}; #[derive(Debug)] pub struct StyledBuffer { text: Vec>, styles: Vec>, } impl StyledBuffer { pub fn new() -> StyledBuffer { StyledBuffer { text: vec![], styles: vec![], } } pub fn copy_tabs(&mut self, row: usize) { if row < self.text.len() { for i in row + 1..self.text.len() { for j in 0..self.text[i].len() { if self.text[row].len() > j && self.text[row][j] == '\t' && self.text[i][j] == ' ' { self.text[i][j] = '\t'; } } } } } pub fn render(&mut self) -> Vec> { let mut output: Vec> = vec![]; let mut styled_vec: Vec = vec![]; // before we render, do a little patch-up work to support tabs self.copy_tabs(3); for (row, row_style) in self.text.iter().zip(&self.styles) { let mut current_style = Style::NoStyle; let mut current_text = String::new(); for (&c, &s) in row.iter().zip(row_style) { if s != current_style { if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style, }); } current_style = s; current_text = String::new(); } current_text.push(c); } 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) { while line >= self.text.len() { self.text.push(vec![]); self.styles.push(vec![]); } } pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); if col < self.text[line].len() { self.text[line][col] = chr; self.styles[line][col] = style; } else { let mut i = self.text[line].len(); while i < col { self.text[line].push(' '); self.styles[line].push(Style::NoStyle); i += 1; } self.text[line].push(chr); self.styles[line].push(style); } } 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; } } pub fn set_style(&mut self, line: usize, col: usize, style: Style) { if self.styles.len() > line && self.styles[line].len() > col { self.styles[line][col] = style; } } pub fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); let string_len = string.len(); // Push the old content over to make room for new content for _ in 0..string_len { self.styles[line].insert(0, Style::NoStyle); self.text[line].insert(0, ' '); } self.puts(line, 0, string, style); } pub fn append(&mut self, line: usize, string: &str, style: Style) { if line >= self.text.len() { self.puts(line, 0, string, style); } else { let col = self.text[line].len(); self.puts(line, col, string, style); } } pub fn num_lines(&self) -> usize { self.text.len() } }