use unicode_segmentation::UnicodeSegmentation;
#[derive(Debug, Clone)]
pub struct Value {
graphemes: Vec<String>,
}
impl Value {
pub fn new(string: &str) -> Self {
let graphemes = UnicodeSegmentation::graphemes(string, true)
.map(String::from)
.collect();
Self { graphemes }
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn len(&self) -> usize {
self.graphemes.len()
}
#[must_use]
pub fn previous_start_of_word(&self, index: usize) -> usize {
let previous_string = &self.graphemes[..index.min(self.graphemes.len())].concat();
UnicodeSegmentation::split_word_bound_indices(previous_string as &str)
.filter(|(_, word)| !word.trim_start().is_empty())
.next_back()
.map_or(0, |(i, previous_word)| {
index
- UnicodeSegmentation::graphemes(previous_word, true).count()
- UnicodeSegmentation::graphemes(
&previous_string[i + previous_word.len()..] as &str,
true,
)
.count()
})
}
#[must_use]
pub fn next_end_of_word(&self, index: usize) -> usize {
let next_string = &self.graphemes[index..].concat();
UnicodeSegmentation::split_word_bound_indices(next_string as &str)
.find(|(_, word)| !word.trim_start().is_empty())
.map_or(self.len(), |(i, next_word)| {
index
+ UnicodeSegmentation::graphemes(next_word, true).count()
+ UnicodeSegmentation::graphemes(&next_string[..i] as &str, true).count()
})
}
#[must_use]
pub fn select(&self, start: usize, end: usize) -> Self {
let graphemes = self.graphemes[start.min(self.len())..end.min(self.len())].to_vec();
Self { graphemes }
}
#[must_use]
pub fn until(&self, index: usize) -> Self {
let graphemes = self.graphemes[..index.min(self.len())].to_vec();
Self { graphemes }
}
pub fn insert(&mut self, index: usize, c: char) {
self.graphemes.insert(index, c.to_string());
self.graphemes = UnicodeSegmentation::graphemes(&self.to_string() as &str, true)
.map(String::from)
.collect();
}
pub fn insert_many(&mut self, index: usize, mut value: Value) {
let _ = self
.graphemes
.splice(index..index, value.graphemes.drain(..));
}
pub fn remove(&mut self, index: usize) {
let _ = self.graphemes.remove(index);
}
pub fn remove_many(&mut self, start: usize, end: usize) {
let _ = self.graphemes.splice(start..end, std::iter::empty());
}
#[must_use]
pub fn secure(&self) -> Self {
Self {
graphemes: std::iter::repeat(String::from("•"))
.take(self.graphemes.len())
.collect(),
}
}
}
impl ToString for Value {
fn to_string(&self) -> String {
self.graphemes.concat()
}
}