1use crossterm::{cursor::*, queue, style::*, terminal::*};
4use std::{collections::VecDeque, fmt::Display, io::Write};
5
6use super::error::ReplResult;
7
8fn is_newline(c: &char) -> bool {
9 *c == '\n'
10}
11
12fn write_chars<'a, W: Write>(
13 c: impl IntoIterator<Item = &'a char>,
14 w: &mut W,
15) -> std::io::Result<()> {
16 for c in c {
17 queue!(w, Print(c))?;
18 }
19 Ok(())
20}
21
22#[derive(Clone, Debug)]
24pub struct Editor<'a> {
25 head: VecDeque<char>,
26 tail: VecDeque<char>,
27
28 pub color: &'a str,
29 pub begin: &'a str,
30 pub again: &'a str,
31}
32
33impl<'a> Editor<'a> {
34 pub fn new(color: &'a str, begin: &'a str, again: &'a str) -> Self {
36 Self { head: Default::default(), tail: Default::default(), color, begin, again }
37 }
38
39 pub fn iter(&self) -> impl Iterator<Item = &char> {
41 let Self { head, tail, .. } = self;
42 head.iter().chain(tail.iter())
43 }
44
45 fn putchar<W: Write>(&self, c: char, w: &mut W) -> ReplResult<()> {
46 let Self { color, again, .. } = self;
47 match c {
48 '\n' => queue!(
49 w,
50 Print('\n'),
51 MoveToColumn(0),
52 Print(color),
53 Print(again),
54 Print(ResetColor)
55 ),
56 c => queue!(w, Print(c)),
57 }?;
58 Ok(())
59 }
60
61 pub fn redraw_head<W: Write>(&self, w: &mut W) -> ReplResult<()> {
62 let Self { head, color, begin, .. } = self;
63 match head.iter().copied().filter(is_newline).count() {
64 0 => queue!(w, MoveToColumn(0)),
65 n => queue!(w, MoveUp(n as u16)),
66 }?;
67
68 queue!(w, Print(color), Print(begin), Print(ResetColor))?;
69 for c in head {
70 self.putchar(*c, w)?;
71 }
72 Ok(())
73 }
74
75 pub fn redraw_tail<W: Write>(&self, w: &mut W) -> ReplResult<()> {
76 let Self { tail, .. } = self;
77 queue!(w, SavePosition, Clear(ClearType::FromCursorDown))?;
78 for c in tail {
79 self.putchar(*c, w)?;
80 }
81 queue!(w, RestorePosition)?;
82 Ok(())
83 }
84
85 pub fn print_head<W: Write>(&self, w: &mut W) -> ReplResult<()> {
87 let Self { head, color, begin, again, .. } = self;
88 let nl = self.head.iter().rposition(is_newline).map(|n| n + 1);
89 let prompt = if nl.is_some() { again } else { begin };
90
91 queue!(w, MoveToColumn(0), Print(color), Print(prompt), ResetColor)?;
92
93 write_chars(head.iter().skip(nl.unwrap_or(0)), w)?;
94 Ok(())
95 }
96
97 pub fn print_tail<W: Write>(&self, w: &mut W) -> ReplResult<()> {
99 let Self { tail, .. } = self;
100 queue!(w, SavePosition, Clear(ClearType::UntilNewLine))?;
101 write_chars(tail.iter().take_while(|&c| !is_newline(c)), w)?;
102 queue!(w, RestorePosition)?;
103 Ok(())
104 }
105
106 pub fn print_err<W: Write>(&self, err: impl Display, w: &mut W) -> ReplResult<()> {
107 queue!(
108 w,
109 SavePosition,
110 Clear(ClearType::UntilNewLine),
111 Print(err),
112 RestorePosition
113 )?;
114 Ok(())
115 }
116
117 pub fn push<W: Write>(&mut self, c: char, w: &mut W) -> ReplResult<()> {
119 self.head.push_back(c);
120 queue!(w, Clear(ClearType::UntilNewLine))?;
121 self.putchar(c, w)?;
122 match c {
123 '\n' => self.redraw_tail(w),
124 _ => self.print_tail(w),
125 }
126 }
127
128 pub fn pop<W: Write>(&mut self, w: &mut W) -> ReplResult<Option<char>> {
130 let c = self.head.pop_back();
131
132 match c {
133 None => return Ok(None),
134 Some('\n') => {
135 queue!(w, MoveToPreviousLine(1))?;
136 self.print_head(w)?;
137 self.redraw_tail(w)?;
138 }
139 Some(_) => {
140 queue!(w, MoveLeft(1), Clear(ClearType::UntilNewLine))?;
141 self.print_tail(w)?;
142 }
143 }
144
145 Ok(c)
146 }
147
148 pub fn delete<W: Write>(&mut self, w: &mut W) -> ReplResult<Option<char>> {
150 let c = self.tail.pop_front();
151 match c {
152 Some('\n') => self.redraw_tail(w)?,
153 _ => self.print_tail(w)?,
154 }
155 Ok(c)
156 }
157
158 pub fn extend<T: IntoIterator<Item = char>, W: Write>(
160 &mut self,
161 iter: T,
162 w: &mut W,
163 ) -> ReplResult<()> {
164 for c in iter {
165 self.push(c, w)?;
166 }
167 Ok(())
168 }
169
170 pub fn restore<W: Write>(&mut self, s: &str, w: &mut W) -> ReplResult<()> {
172 match self.head.iter().copied().filter(is_newline).count() {
173 0 => queue!(w, MoveToColumn(0), Clear(ClearType::FromCursorDown))?,
174 n => queue!(w, MoveUp(n as u16), Clear(ClearType::FromCursorDown))?,
175 };
176 self.clear();
177 self.print_head(w)?;
178 self.extend(s.chars(), w)
179 }
180
181 pub fn clear(&mut self) {
183 self.head.clear();
184 self.tail.clear();
185 }
186
187 pub fn erase_word<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
190 while self.pop(w)?.filter(|c| !c.is_whitespace()).is_some() {}
191 Ok(())
192 }
193
194 pub fn len(&self) -> usize {
196 self.head.len() + self.tail.len()
197 }
198
199 pub fn at_start(&self) -> bool {
201 self.head.is_empty()
202 }
203
204 pub fn at_end(&self) -> bool {
206 self.tail.is_empty()
207 }
208
209 pub fn at_line_start(&self) -> bool {
211 matches!(self.head.back(), None | Some('\n'))
212 }
213
214 pub fn at_line_end(&self) -> bool {
216 matches!(self.tail.front(), None | Some('\n'))
217 }
218
219 pub fn at_word_start(&self) -> bool {
221 self.head
222 .back()
223 .copied()
224 .map(|c| c.is_alphanumeric() || c == '\n')
225 .unwrap_or(true)
226 }
227
228 pub fn at_word_end(&self) -> bool {
230 self.tail
231 .front()
232 .copied()
233 .map(|c| c.is_alphanumeric() || c == '\n')
234 .unwrap_or(true)
235 }
236
237 pub fn is_empty(&self) -> bool {
239 self.at_start() && self.at_end()
240 }
241
242 pub fn ends_with(&self, iter: impl DoubleEndedIterator<Item = char>) -> bool {
244 let mut iter = iter.rev();
245 let mut head = self.head.iter().rev();
246 loop {
247 match (iter.next(), head.next()) {
248 (None, _) => break true,
249 (Some(_), None) => break false,
250 (Some(a), Some(b)) if a != *b => break false,
251 (Some(_), Some(_)) => continue,
252 }
253 }
254 }
255
256 pub fn cursor_back<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
258 let Some(c) = self.head.pop_back() else {
259 return Ok(());
260 };
261
262 self.tail.push_front(c);
263 match c {
264 '\n' => {
265 queue!(w, MoveToPreviousLine(1))?;
266 self.print_head(w)
267 }
268 _ => queue!(w, MoveLeft(1)).map_err(Into::into),
269 }
270 }
271
272 pub fn cursor_forward<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
274 let Some(c) = self.tail.pop_front() else {
275 return Ok(());
276 };
277
278 self.head.push_back(c);
279 match c {
280 '\n' => {
281 queue!(w, MoveToNextLine(1))?;
282 self.print_head(w)
283 }
284 _ => queue!(w, MoveRight(1)).map_err(Into::into),
285 }
286 }
287
288 pub fn cursor_up<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
290 let mut len = self.head.len();
292 self.cursor_line_start(w)?;
293 len -= self.head.len();
294
295 if self.at_start() {
296 return Ok(());
297 }
298
299 self.cursor_back(w)?;
300 self.cursor_line_start(w)?;
301
302 while 0 < len && !self.at_line_end() {
303 self.cursor_forward(w)?;
304 len -= 1;
305 }
306
307 Ok(())
308 }
309
310 pub fn cursor_down<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
312 let mut len = self.head.iter().rev().take_while(|&&c| c != '\n').count();
313
314 self.cursor_line_end(w)?;
315 self.cursor_forward(w)?;
316
317 while 0 < len && !self.at_line_end() {
318 self.cursor_forward(w)?;
319 len -= 1;
320 }
321
322 Ok(())
323 }
324
325 pub fn cursor_line_start<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
327 while !self.at_line_start() {
328 self.cursor_back(w)?
329 }
330 Ok(())
331 }
332
333 pub fn cursor_line_end<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
335 while !self.at_line_end() {
336 self.cursor_forward(w)?
337 }
338 Ok(())
339 }
340
341 pub fn cursor_word_back<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
343 let target = self.at_word_start();
344 self.cursor_back(w)?;
345 while self.at_word_start() == target && !self.at_start() {
346 self.cursor_back(w)?
347 }
348 Ok(())
349 }
350
351 pub fn cursor_word_forward<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
353 let target = self.at_word_end();
354 self.cursor_forward(w)?;
355 while self.at_word_end() == target && !self.at_end() {
356 self.cursor_forward(w)?
357 }
358 Ok(())
359 }
360
361 pub fn cursor_start<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
363 while !self.at_start() {
364 self.cursor_back(w)?
365 }
366 Ok(())
367 }
368
369 pub fn cursor_end<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
371 while !self.at_end() {
372 self.cursor_forward(w)?
373 }
374 Ok(())
375 }
376}
377
378impl<'e> IntoIterator for &'e Editor<'_> {
379 type Item = &'e char;
380 type IntoIter = std::iter::Chain<
381 std::collections::vec_deque::Iter<'e, char>,
382 std::collections::vec_deque::Iter<'e, char>,
383 >;
384 fn into_iter(self) -> Self::IntoIter {
385 self.head.iter().chain(self.tail.iter())
386 }
387}
388
389impl Display for Editor<'_> {
390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
391 use std::fmt::Write;
392 for c in self.iter() {
393 f.write_char(*c)?;
394 }
395 Ok(())
396 }
397}