use crate::db::config::Config;
use ratatui::style::{Color, Style};
use ratatui::text::Span;
use std::str::FromStr;
pub trait CursorState {
fn get_text(&self) -> &str;
fn get_text_mut(&mut self) -> &mut String;
fn get_cursor_pos(&self) -> usize;
fn set_cursor_pos(&mut self, pos: usize);
fn add_char(&mut self, c: char) {
let char_pos = self.get_cursor_pos();
let chars: Vec<char> = self.get_text().chars().collect();
let byte_pos = if char_pos == 0 {
0
} else if char_pos >= chars.len() {
self.get_text().len()
} else {
chars[..char_pos].iter().map(|c| c.len_utf8()).sum()
};
self.get_text_mut().insert(byte_pos, c);
self.set_cursor_pos(char_pos + 1);
}
fn remove_char_before_cursor(&mut self) {
let char_pos = self.get_cursor_pos();
if char_pos > 0 {
let chars: Vec<char> = self.get_text().chars().collect();
let byte_pos = chars[..char_pos - 1].iter().map(|c| c.len_utf8()).sum();
self.get_text_mut().remove(byte_pos);
self.set_cursor_pos(char_pos - 1);
}
}
fn delete_char_after_cursor(&mut self) {
let pos = self.get_cursor_pos();
let text_len = self.get_text().chars().count();
if pos < text_len {
let mut chars: Vec<char> = self.get_text().chars().collect();
chars.remove(pos);
*self.get_text_mut() = chars.into_iter().collect();
}
}
fn move_cursor_left(&mut self) {
let pos = self.get_cursor_pos();
if pos > 0 {
self.set_cursor_pos(pos - 1);
}
}
fn move_cursor_right(&mut self) {
let pos = self.get_cursor_pos();
let text_len = self.get_text().chars().count();
if pos < text_len {
self.set_cursor_pos(pos + 1);
}
}
fn move_cursor_to_start(&mut self) {
self.set_cursor_pos(0);
}
fn move_cursor_to_end(&mut self) {
let text_len = self.get_text().chars().count();
self.set_cursor_pos(text_len);
}
fn clear(&mut self) {
self.get_text_mut().clear();
self.set_cursor_pos(0);
}
fn create_cursor_text_spans(&self, config: Config) -> Vec<Span<'static>> {
let fg = config.foreground();
let bg = config.background();
let text = self.get_text();
let cursor_pos = self.get_cursor_pos();
let chars: Vec<char> = text.chars().collect();
let text_len = chars.len();
let safe_cursor_pos = cursor_pos.min(text_len);
let text_before: String = chars[..safe_cursor_pos].iter().collect();
let cursor_char = if safe_cursor_pos >= text_len {
"█".to_string()
} else {
chars[safe_cursor_pos].to_string()
};
let text_after: String = if safe_cursor_pos >= text_len {
String::new()
} else {
chars[(safe_cursor_pos + 1)..].iter().collect()
};
vec![
Span::styled(
text_before,
Style::default().fg(Color::from_str(fg).unwrap()),
),
if cursor_char == "█" {
Span::styled(
cursor_char,
Style::default()
.fg(Color::from_str(fg).unwrap())
.bg(Color::from_str(bg).unwrap()),
)
} else {
Span::styled(
cursor_char,
Style::default()
.fg(Color::from_str(bg).unwrap())
.bg(Color::from_str(fg).unwrap()),
)
},
Span::styled(
text_after,
Style::default().fg(Color::from_str(fg).unwrap()),
),
]
}
}