use super::TextCursor;
pub fn replace_selection(text: &mut String, cursor: &mut TextCursor, s: &str) {
let mut chars: Vec<char> = text.chars().collect();
delete_selection(&mut chars, cursor);
cursor.anchor = None;
let mut at = cursor.pos.min(chars.len());
for ch in s.chars() {
chars.insert(at, ch);
at += 1;
}
cursor.pos = at;
*text = chars.into_iter().collect();
}
pub fn insert_str(text: &mut String, cursor: &mut TextCursor, to_insert: &str) {
replace_selection(text, cursor, to_insert);
}
#[must_use]
pub fn selected_text(text: &str, cursor: &TextCursor) -> Option<String> {
let (start, end) = cursor.selection()?;
let chars: Vec<char> = text.chars().collect();
let end = end.min(chars.len());
let start = start.min(end);
Some(chars[start..end].iter().collect())
}
pub(super) fn delete_range(
chars: &mut Vec<char>,
cursor: &mut TextCursor,
start: usize,
end: usize,
) {
let start = start.min(chars.len());
let end = end.min(chars.len());
if start >= end {
return;
}
chars.drain(start..end);
cursor.pos = start;
cursor.anchor = None;
}
pub(crate) fn move_caret(cursor: &mut TextCursor, to: usize, extend: bool) {
if extend {
cursor.anchor.get_or_insert(cursor.pos);
} else {
cursor.anchor = None;
}
cursor.pos = to;
}
pub(crate) fn insert_char(
chars: &mut Vec<char>,
cursor: &mut TextCursor,
ch: char,
max_len: Option<usize>,
) {
delete_selection(chars, cursor);
if max_len.is_some_and(|max| chars.len() >= max) {
return;
}
chars.insert(cursor.pos, ch);
cursor.pos += 1;
cursor.anchor = None;
}
pub(crate) fn backspace(chars: &mut Vec<char>, cursor: &mut TextCursor) {
if delete_selection(chars, cursor) {
return;
}
if cursor.pos > 0 {
chars.remove(cursor.pos - 1);
cursor.pos -= 1;
}
}
pub(crate) fn delete_forward(chars: &mut Vec<char>, cursor: &mut TextCursor) {
if delete_selection(chars, cursor) {
return;
}
if cursor.pos < chars.len() {
chars.remove(cursor.pos);
}
}
pub(crate) fn delete_selection(
chars: &mut Vec<char>,
cursor: &mut TextCursor,
) -> bool {
let Some((start, end)) = cursor.selection() else {
return false;
};
chars.drain(start..end);
cursor.pos = start;
cursor.anchor = None;
true
}