use super::style::Style;
pub struct StyledBuffer {
buffer: Vec<char>,
styles: Vec<Style>,
cursor_position: usize,
}
impl Default for StyledBuffer {
fn default() -> Self {
Self {
buffer: vec![],
styles: vec![],
cursor_position: 0,
}
}
}
impl From<&str> for StyledBuffer {
fn from(value: &str) -> Self {
let mut styled_buffer = StyledBuffer::default();
styled_buffer.insert_string(value);
styled_buffer
}
}
impl StyledBuffer {
pub fn insert_char(&mut self, ch: char) {
self.buffer.insert(self.cursor_position, ch);
self.styles.insert(self.cursor_position, Style::default());
self.move_char_right();
}
pub fn insert_styled_char(&mut self, ch: char, style: Style) {
self.buffer.insert(self.cursor_position, ch);
self.styles.insert(self.cursor_position, style);
self.move_char_right();
}
pub fn insert_string(&mut self, str: &str) {
for ch in str.chars() {
self.insert_char(ch);
}
}
pub fn insert_styled_string(&mut self, str: &str, style: Style) {
for ch in str.chars() {
self.insert_styled_char(ch, style.clone());
}
}
pub fn move_char_right(&mut self) {
if self.cursor_position < self.len() {
self.cursor_position += 1;
}
}
pub fn move_char_left(&mut self) {
if self.cursor_position > 0 {
self.cursor_position -= 1;
}
}
pub fn move_word_right(&mut self) {
while self.cursor_position < self.len() {
if self.buffer[self.cursor_position].is_whitespace() {
if self.cursor_position != self.len() {
self.cursor_position += 1;
}
return;
}
self.cursor_position += 1;
}
}
pub fn move_word_left(&mut self) {
self.cursor_position = usize::min(self.cursor_position, self.len() - 1);
if self.cursor_position != 0 {
self.cursor_position -= 1;
}
while 0 != self.cursor_position {
if self.buffer[self.cursor_position].is_whitespace() {
self.cursor_position -= 1;
continue;
}
break;
}
while 0 != self.cursor_position {
if self.buffer[self.cursor_position].is_whitespace() {
if self.cursor_position + 1 < self.len() {
self.cursor_position += 1;
}
return;
}
self.cursor_position -= 1;
}
}
pub fn move_to_start(&mut self) {
self.cursor_position = 0;
}
pub fn move_to_end(&mut self) {
self.cursor_position = self.buffer.len();
}
pub fn delete_right_char(&mut self) {
if self.cursor_position + 1 < self.buffer.len() {
self.buffer.remove(self.cursor_position + 1);
self.styles.remove(self.cursor_position + 1);
}
}
pub fn delete_left_char(&mut self) {
if self.cursor_position > 0 {
self.cursor_position -= 1;
self.buffer.remove(self.cursor_position);
self.styles.remove(self.cursor_position);
}
}
pub fn delete_range(&mut self, from: usize, to: usize) {
if to <= self.len() {
self.buffer.drain(from..to);
self.styles.drain(from..to);
self.cursor_position = from;
}
}
pub fn buffer(&mut self) -> &Vec<char> {
&self.buffer
}
pub fn literal(&self) -> String {
let literal: &String = &self.buffer.clone().into_iter().collect();
literal.to_string()
}
pub fn char_at(&self, position: usize) -> Option<char> {
Some(self.buffer[position])
}
pub fn sub_string(&self, start: usize, end: usize) -> Option<String> {
if start < end && end <= self.len() {
let slice: String = self.buffer[start..end].iter().clone().collect();
return Some(slice);
}
None
}
pub fn last_alphabetic_keyword(&self) -> Option<String> {
let mut keyword = String::new();
for c in self.buffer.iter().rev() {
if c.is_alphabetic() {
keyword.insert(0, *c);
continue;
}
break;
}
if keyword.is_empty() {
None
} else {
Some(keyword)
}
}
pub fn styles(&self) -> &Vec<Style> {
&self.styles
}
pub fn set_styles(&mut self, styles: &mut Vec<Style>) {
if self.len() == styles.len() {
self.styles.clear();
self.styles.append(styles);
}
}
pub fn style_char(&mut self, position: usize, style: Style) {
self.styles[position] = style;
}
pub fn style_range(&mut self, start: usize, end: usize, style: Style) {
let max = std::cmp::min(end, self.styles.len());
for i in start..max {
self.styles[i] = style.clone();
}
}
pub fn style_all(&mut self, style: Style) {
for i in 0..self.len() {
self.styles[i] = style.clone();
}
}
pub fn reset_styles(&mut self) {
for i in 0..self.styles.len() {
self.styles[i] = Style::default();
}
}
pub fn clear(&mut self) {
self.buffer = vec![];
self.styles = vec![];
self.cursor_position = 0;
}
pub fn set_position(&mut self, pos: usize) {
self.cursor_position = pos;
}
pub fn position(&self) -> usize {
self.cursor_position
}
pub fn is_cursor_at_the_end(&self) -> bool {
self.cursor_position == self.len()
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
}