cosmic/widget/text_input/
value.rs
1use unicode_segmentation::UnicodeSegmentation;
6
7#[derive(Default, Debug, Clone, PartialEq)]
12pub struct Value {
13 graphemes: Vec<String>,
14}
15
16impl Value {
17 pub fn new(string: &str) -> Self {
19 let graphemes = UnicodeSegmentation::graphemes(string, true)
20 .map(String::from)
21 .collect();
22
23 Self { graphemes }
24 }
25
26 #[must_use]
30 #[inline]
31 pub fn is_empty(&self) -> bool {
32 self.len() == 0
33 }
34
35 #[must_use]
37 #[inline]
38 pub fn len(&self) -> usize {
39 self.graphemes.len()
40 }
41
42 #[must_use]
45 pub fn previous_start_of_word(&self, index: usize) -> usize {
46 let previous_string = &self.graphemes[..index.min(self.graphemes.len())].concat();
47
48 UnicodeSegmentation::split_word_bound_indices(previous_string as &str)
49 .filter(|(_, word)| !word.trim_start().is_empty())
50 .next_back()
51 .map_or(0, |(i, previous_word)| {
52 index
53 - UnicodeSegmentation::graphemes(previous_word, true).count()
54 - UnicodeSegmentation::graphemes(
55 &previous_string[i + previous_word.len()..] as &str,
56 true,
57 )
58 .count()
59 })
60 }
61
62 #[must_use]
65 pub fn next_end_of_word(&self, index: usize) -> usize {
66 let next_string = &self.graphemes[index..].concat();
67
68 UnicodeSegmentation::split_word_bound_indices(next_string as &str)
69 .find(|(_, word)| !word.trim_start().is_empty())
70 .map_or(self.len(), |(i, next_word)| {
71 index
72 + UnicodeSegmentation::graphemes(next_word, true).count()
73 + UnicodeSegmentation::graphemes(&next_string[..i] as &str, true).count()
74 })
75 }
76
77 #[must_use]
80 #[inline]
81 pub fn select(&self, start: usize, end: usize) -> Self {
82 let graphemes = self.graphemes[start.min(self.len())..end.min(self.len())].to_vec();
83
84 Self { graphemes }
85 }
86
87 #[must_use]
90 #[inline]
91 pub fn until(&self, index: usize) -> Self {
92 let graphemes = self.graphemes[..index.min(self.len())].to_vec();
93
94 Self { graphemes }
95 }
96
97 #[inline]
99 pub fn insert(&mut self, index: usize, c: char) {
100 self.graphemes.insert(index, c.to_string());
101
102 self.graphemes = UnicodeSegmentation::graphemes(&self.to_string() as &str, true)
103 .map(String::from)
104 .collect();
105 }
106
107 #[inline]
109 pub fn insert_many(&mut self, index: usize, mut value: Value) {
110 let _ = self
111 .graphemes
112 .splice(index..index, value.graphemes.drain(..));
113 }
114
115 #[inline]
117 pub fn remove(&mut self, index: usize) {
118 let _ = self.graphemes.remove(index);
119 }
120
121 #[inline]
123 pub fn remove_many(&mut self, start: usize, end: usize) {
124 let _ = self.graphemes.splice(start..end, std::iter::empty());
125 }
126
127 #[must_use]
130 pub fn secure(&self) -> Self {
131 Self {
132 graphemes: std::iter::repeat(String::from("•"))
133 .take(self.graphemes.len())
134 .collect(),
135 }
136 }
137}
138
139impl ToString for Value {
140 #[inline]
141 fn to_string(&self) -> String {
142 self.graphemes.concat()
143 }
144}