use std::fmt::{Debug, Display, Result};
use get_size::GetSize;
use r3bl_rs_utils_core::*;
use serde::*;
use crate::*;
#[derive(Clone, PartialEq, Serialize, Deserialize, GetSize)]
pub struct EditorBuffer {
lines: Vec<UnicodeString>,
caret: Position,
scroll_offset: ScrollOffset,
lolcat: Lolcat,
}
mod constructor {
use super::*;
impl Default for EditorBuffer {
fn default() -> Self {
call_if_true!(DEBUG_TUI_MOD, {
log_no_err!(
DEBUG,
"🪙 {}",
"construct EditorBuffer { lines, caret, lolcat }"
);
});
Self {
lines: vec![UnicodeString::default()],
caret: Position::default(),
lolcat: Lolcat::default(),
scroll_offset: ScrollOffset::default(),
}
}
}
}
pub enum CaretKind {
Raw,
ScrollAdjusted,
}
pub mod access_and_mutate {
use super::*;
impl EditorBuffer {
pub fn len(&self) -> ChUnit { ch!(self.lines.len()) }
pub fn get_lines(&self) -> &Vec<UnicodeString> { &self.lines }
pub fn get_caret(&self, kind: CaretKind) -> Position {
match kind {
CaretKind::Raw => self.caret,
CaretKind::ScrollAdjusted => {
position! {
col: Self::calc_scroll_adj_caret_col(&self.caret, &self.scroll_offset),
row: Self::calc_scroll_adj_caret_row(&self.caret, &self.scroll_offset)
}
}
}
}
pub fn calc_scroll_adj_caret_row(caret: &Position, scroll_offset: &ScrollOffset) -> usize {
ch!(@to_usize caret.row + scroll_offset.row)
}
pub fn calc_scroll_adj_caret_col(caret: &Position, scroll_offset: &ScrollOffset) -> usize {
ch!(@to_usize caret.col + scroll_offset.col)
}
pub fn get_scroll_offset(&self) -> ScrollOffset { self.scroll_offset }
pub fn get_mut(
&mut self,
) -> (
/* lines */ &mut Vec<UnicodeString>,
/* caret */ &mut Position,
/* scroll_offset */ &mut ScrollOffset,
) {
(&mut self.lines, &mut self.caret, &mut self.scroll_offset)
}
}
}
impl EditorBuffer {
pub fn apply_editor_event<S, A>(
engine: &mut EditorRenderEngine,
buffer: &mut EditorBuffer,
editor_buffer_command: EditorBufferCommand,
_shared_tw_data: &SharedTWData,
_component_registry: &mut ComponentRegistry<S, A>,
_self_id: &str,
) where
S: Default + Display + Clone + PartialEq + Debug + Sync + Send,
A: Default + Display + Clone + Sync + Send,
{
match editor_buffer_command {
EditorBufferCommand::InsertChar(character) => {
mut_content::insert_str_at_caret(EditorArgsMut { buffer, engine }, &String::from(character))
}
EditorBufferCommand::InsertNewLine => {
mut_content::insert_new_line_at_caret(EditorArgsMut { buffer, engine });
}
EditorBufferCommand::Delete => {
mut_content::delete_at_caret(buffer, engine);
}
EditorBufferCommand::Backspace => {
mut_content::backspace_at_caret(buffer, engine);
}
EditorBufferCommand::MoveCaret(direction) => {
match direction {
CaretDirection::Left => move_caret::left(buffer, engine),
CaretDirection::Right => move_caret::right(buffer, engine),
CaretDirection::Up => move_caret::up(buffer, engine),
CaretDirection::Down => move_caret::down(buffer, engine),
};
}
EditorBufferCommand::InsertString(chunk) => {
mut_content::insert_str_at_caret(EditorArgsMut { buffer, engine }, &chunk)
}
EditorBufferCommand::Resize(_) => {
scroll::validate_scroll(EditorArgsMut { buffer, engine });
}
EditorBufferCommand::Home => {
move_caret::to_start_of_line(buffer, engine);
}
EditorBufferCommand::End => {
move_caret::to_end_of_line(buffer, engine);
}
EditorBufferCommand::PageDown => {
move_caret::page_down(buffer, engine);
}
EditorBufferCommand::PageUp => {
move_caret::page_up(buffer, engine);
}
};
}
pub fn apply_editor_events<S, A>(
engine: &mut EditorRenderEngine,
buffer: &mut EditorBuffer,
editor_event_vec: Vec<EditorBufferCommand>,
shared_tw_data: &SharedTWData,
component_registry: &mut ComponentRegistry<S, A>,
self_id: &str,
) where
S: Default + Display + Clone + PartialEq + Debug + Sync + Send,
A: Default + Display + Clone + Sync + Send,
{
for editor_event in editor_event_vec {
EditorBuffer::apply_editor_event(
engine,
buffer,
editor_event,
shared_tw_data,
component_registry,
self_id,
);
}
}
pub fn is_empty(&self) -> bool { self.lines.is_empty() }
}
mod debug_format_helpers {
use super::*;
impl Debug for EditorBuffer {
fn fmt(&self, f: &mut __private::Formatter<'_>) -> Result {
write! { f,
"\nEditorBuffer [ \n \
├ lines: {}, size: {}, \n \
├ caret: {:?}, \n \
└ lolcat: [{}, {}, {}, {}] \n]",
self.lines.len(), self.lines.get_heap_size(),
self.caret,
pretty_print_f64(self.lolcat.color_wheel_control.seed),
pretty_print_f64(self.lolcat.color_wheel_control.spread),
pretty_print_f64(self.lolcat.color_wheel_control.frequency),
self.lolcat.color_wheel_control.color_change_speed
}
}
}
fn pretty_print_f64(before: f64) -> f64 { f64::trunc(before * 100.0) / 100.0 }
}