use std::fmt::{Display, Formatter};
#[derive(Debug, PartialEq, Eq)]
pub enum MovementType {
Left,
Right,
Start,
End,
}
#[derive(Debug, Default)]
pub struct EditableString {
contents: Vec<char>,
cursor: usize,
_scratch: Vec<char>,
}
impl EditableString {
pub fn position(&self) -> usize {
self.cursor
}
pub fn cursor_at_end(&self) -> bool {
self.cursor == self.contents.len()
}
pub fn paste(&mut self, s: &str) -> bool {
if !s.is_empty() {
if self.cursor_at_end() {
self.contents.extend(s.chars());
self.cursor = self.contents.len();
} else {
self._scratch.clear();
self._scratch.extend(s.chars());
let extend_len = self._scratch.len();
self._scratch.extend(self.contents.drain(self.cursor..));
self.cursor += extend_len;
self.contents.append(&mut self._scratch);
}
true
} else {
false
}
}
pub fn insert(&mut self, ch: char) -> bool {
self.contents.insert(self.cursor, ch);
self.cursor += 1;
true
}
pub fn delete(&mut self) -> bool {
if self.cursor > 0 {
self.cursor -= 1;
self.contents.remove(self.cursor);
true
} else {
false
}
}
#[inline]
fn shift_to(&mut self, pos: usize) -> bool {
if pos <= self.contents.len() && self.cursor != pos {
self.cursor = pos;
true
} else {
false
}
}
#[inline]
pub fn shift(&mut self, st: MovementType) -> bool {
match st {
MovementType::Left => {
if self.cursor > 0 {
self.cursor -= 1;
true
} else {
false
}
}
MovementType::Right => self.shift_to(self.cursor + 1),
MovementType::Start => self.shift_to(0),
MovementType::End => self.shift_to(self.contents.len()),
}
}
}
impl Display for EditableString {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let content_str: String = self.contents.iter().collect();
content_str.fmt(f)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_edit() {
let mut editable = EditableString::default();
editable.insert('a');
editable.insert('b');
editable.insert('c');
editable.insert('d');
editable.shift(MovementType::Left);
editable.insert('1');
editable.insert('2');
editable.insert('3');
editable.shift(MovementType::Start);
editable.delete();
editable.insert('4');
editable.shift(MovementType::End);
editable.delete();
assert_eq!(&editable.to_string(), "4abc123");
}
}