1use async_std::sync::Arc;
4use std::fmt;
5use std::slice::Iter;
6use std::time::Instant;
7use unicode_segmentation::UnicodeSegmentation;
8
9pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
10
11#[derive(Debug, Clone)]
17pub struct Prompt {
18 query: Vec<char>,
19 cursor: usize,
20 timestamp: Instant,
21}
22
23impl Prompt {
24 pub fn add(&mut self, ch: char) {
25 self.query.insert(self.cursor, ch);
26 self.cursor += 1;
27 self.refresh();
28 }
29
30 pub fn backspace(&mut self) -> bool {
31 if self.cursor > 0 {
32 self.cursor -= 1;
33 self.query.remove(self.cursor);
34 self.refresh();
35
36 return true;
37 }
38
39 false
40 }
41
42 pub fn clear(&mut self) {
43 self.query.clear();
44 self.cursor = 0;
45 self.refresh();
46 }
47
48 pub fn left(&mut self) {
49 if self.cursor > 0 {
50 self.cursor -= 1;
51 }
52 }
53
54 pub fn right(&mut self) {
55 if self.cursor < self.len() {
56 self.cursor += 1;
57 }
58 }
59
60 pub fn cursor_at_end(&mut self) {
61 self.cursor = self.len();
62 }
63
64 pub fn cursor_at_start(&mut self) {
65 self.cursor = 0;
66 }
67
68 pub fn cursor_until_end(&self) -> usize {
69 if self.len() < self.cursor {
70 0
71 } else {
72 self.len() - self.cursor
73 }
74 }
75
76 pub fn as_string(&self) -> String {
77 self.query.iter().collect()
78 }
79
80 pub fn timestamp(&self) -> Instant {
81 self.timestamp
82 }
83
84 pub fn len(&self) -> usize {
85 self.query.len()
86 }
87
88 pub fn is_empty(&self) -> bool {
89 self.query.is_empty()
90 }
91
92 pub fn refresh(&mut self) {
93 self.timestamp = Instant::now();
94 }
95}
96
97impl From<&String> for Prompt {
98 fn from(string: &String) -> Self {
99 let query = string.chars().collect::<Vec<char>>();
100 let cursor = query.len();
101
102 Self {
103 query,
104 cursor,
105 ..Default::default()
106 }
107 }
108}
109
110impl Default for Prompt {
111 fn default() -> Self {
112 Self {
113 timestamp: Instant::now(),
114 cursor: 0,
115 query: vec![],
116 }
117 }
118}
119
120pub type Text = Arc<Letters>;
122
123#[derive(Debug, Clone)]
125pub struct TextBuilder;
126
127impl TextBuilder {
128 pub fn build(string: &str) -> Text {
129 let text: Letters = string.into();
130
131 Arc::new(text)
132 }
133}
134
135#[derive(Debug, Clone)]
143pub struct Letters {
144 string: String,
145 graphemes: Vec<String>,
146 graphemes_lw: Vec<String>,
147}
148
149impl Letters {
150 pub fn new(string: String) -> Self {
151 let graphemes = string.graphemes(true).map(String::from).collect::<Vec<_>>();
152
153 let graphemes_lw = graphemes
154 .iter()
155 .map(|s| s.to_lowercase())
156 .collect::<Vec<_>>();
157
158 Self {
159 string,
160 graphemes,
161 graphemes_lw,
162 }
163 }
164
165 pub fn len(&self) -> usize {
166 self.graphemes.len()
167 }
168
169 pub fn last_index(&self) -> usize {
170 let len = self.len();
171
172 if len == 0 {
173 0
174 } else {
175 len - 1
176 }
177 }
178
179 pub fn grapheme_at(&self, index: usize) -> &'_ str {
180 &self.graphemes[index]
181 }
182
183 pub fn lowercase_grapheme_at(&self, index: usize) -> &'_ str {
184 &self.graphemes_lw[index]
185 }
186
187 pub fn iter(&self) -> Iter<'_, String> {
188 self.graphemes.iter()
189 }
190
191 pub fn lowercase_iter(&self) -> Iter<'_, String> {
192 self.graphemes_lw.iter()
193 }
194
195 pub fn is_empty(&self) -> bool {
196 self.string.is_empty()
197 }
198}
199
200impl From<&str> for Letters {
201 fn from(string: &str) -> Self {
202 Self::new(String::from(string))
203 }
204}
205
206impl From<String> for Letters {
207 fn from(string: String) -> Self {
208 Self::new(string)
209 }
210}
211
212impl fmt::Display for Letters {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(f, "{}", self.string)
215 }
216}