1use crossterm::{cursor::*, execute, queue, style::*, terminal::*};
4use std::{collections::VecDeque, fmt::Display, io::Write};
5
6use super::error::{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 write!(w, "{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 begin: &'a str,
30 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 pub fn undraw<W: Write>(&self, w: &mut W) -> ReplResult<()> {
49 let Self { head, .. } = self;
50 match head.iter().copied().filter(is_newline).count() {
51 0 => write!(w, "\x1b[0G"),
52 lines => write!(w, "\x1b[{}F", lines),
53 }?;
54 queue!(w, Clear(ClearType::FromCursorDown))?;
55 Ok(())
57 }
58
59 pub fn redraw<W: Write>(&self, w: &mut W) -> ReplResult<()> {
61 let Self { head, tail, color, begin, again } = self;
62 write!(w, "{color}{begin}\x1b[0m ")?;
63 for c in head {
65 match c {
66 '\n' => write!(w, "\r\n{color}{again}\x1b[0m "),
67 _ => w.write_all({ *c as u32 }.to_le_bytes().as_slice()),
68 }?
69 }
70 execute!(w, SavePosition)?;
72 for c in tail {
74 match c {
75 '\n' => write!(w, "\r\n{color}{again}\x1b[0m "),
76 _ => write!(w, "{c}"),
77 }?
78 }
79 execute!(w, RestorePosition)?;
81 Ok(())
82 }
83
84 pub fn prompt<W: Write>(&self, w: &mut W) -> ReplResult<()> {
87 let Self { head, color, begin, again, .. } = self;
88 queue!(
89 w,
90 MoveToColumn(0),
91 Print(color),
92 Print(if head.is_empty() { begin } else { again }),
93 ResetColor,
94 Print(' '),
95 )?;
96 Ok(())
97 }
98
99 pub fn print_head<W: Write>(&self, w: &mut W) -> ReplResult<()> {
101 self.prompt(w)?;
102 write_chars(
103 self.head.iter().skip(
104 self.head
105 .iter()
106 .rposition(is_newline)
107 .unwrap_or(self.head.len())
108 + 1,
109 ),
110 w,
111 )?;
112 Ok(())
113 }
114
115 pub fn print_err<W: Write>(&self, w: &mut W, err: impl Display) -> ReplResult<()> {
116 queue!(
117 w,
118 SavePosition,
119 Clear(ClearType::UntilNewLine),
120 Print(err),
121 RestorePosition
122 )?;
123 Ok(())
124 }
125
126 pub fn print_tail<W: Write>(&self, w: &mut W) -> ReplResult<()> {
128 let Self { tail, .. } = self;
129 queue!(w, SavePosition, Clear(ClearType::UntilNewLine))?;
130 write_chars(tail.iter().take_while(|&c| !is_newline(c)), w)?;
131 queue!(w, RestorePosition)?;
132 Ok(())
133 }
134
135 pub fn push<W: Write>(&mut self, c: char, w: &mut W) -> ReplResult<()> {
137 if self.tail.is_empty() {
140 self.head.push_back(c);
141 match c {
142 '\n' => {
143 write!(w, "\r\n")?;
144 self.print_head(w)?;
145 }
146 c => {
147 queue!(w, Print(c))?;
148 }
149 };
150 return Ok(());
151 }
152
153 if '\n' == c {
154 self.undraw(w)?;
155 }
156 self.head.push_back(c);
157 match c {
158 '\n' => self.redraw(w)?,
159 _ => {
160 write!(w, "{c}")?;
161 self.print_tail(w)?;
162 }
163 }
164 Ok(())
165 }
166
167 pub fn pop<W: Write>(&mut self, w: &mut W) -> ReplResult<Option<char>> {
169 if let Some('\n') = self.head.back() {
170 self.undraw(w)?;
171 }
172 let c = self.head.pop_back();
173 match c {
175 Some('\n') => self.redraw(w)?,
176 Some(_) => {
177 queue!(w, MoveLeft(1), Print(' '), MoveLeft(1))?;
179 self.print_tail(w)?;
180 }
181 None => {}
182 }
183 Ok(c)
184 }
185
186 pub fn extend<T: IntoIterator<Item = char>, W: Write>(
188 &mut self,
189 iter: T,
190 w: &mut W,
191 ) -> ReplResult<()> {
192 for c in iter {
193 self.push(c, w)?;
194 }
195 Ok(())
196 }
197
198 pub fn restore(&mut self, s: &str) {
200 self.clear();
201 self.head.extend(s.chars())
202 }
203
204 pub fn clear(&mut self) {
206 self.head.clear();
207 self.tail.clear();
208 }
209
210 pub fn delete<W: Write>(&mut self, w: &mut W) -> ReplResult<char> {
212 match self.tail.front() {
213 Some('\n') => {
214 self.undraw(w)?;
215 let out = self.tail.pop_front();
216 self.redraw(w)?;
217 out
218 }
219 _ => {
220 let out = self.tail.pop_front();
221 self.print_tail(w)?;
222 out
223 }
224 }
225 .ok_or(Error::EndOfInput)
226 }
227
228 pub fn erase_word<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
231 while self.pop(w)?.filter(|c| !c.is_whitespace()).is_some() {}
232 Ok(())
233 }
234
235 pub fn len(&self) -> usize {
237 self.head.len() + self.tail.len()
238 }
239
240 pub fn at_start(&self) -> bool {
242 self.head.is_empty()
243 }
244 pub fn at_end(&self) -> bool {
246 self.tail.is_empty()
247 }
248
249 pub fn is_empty(&self) -> bool {
251 self.at_start() && self.at_end()
252 }
253
254 pub fn ends_with(&self, iter: impl DoubleEndedIterator<Item = char>) -> bool {
256 let mut iter = iter.rev();
257 let mut head = self.head.iter().rev();
258 loop {
259 match (iter.next(), head.next()) {
260 (None, _) => break true,
261 (Some(_), None) => break false,
262 (Some(a), Some(b)) if a != *b => break false,
263 (Some(_), Some(_)) => continue,
264 }
265 }
266 }
267
268 pub fn cursor_back<W: Write>(&mut self, steps: usize, w: &mut W) -> ReplResult<()> {
270 for _ in 0..steps {
271 if let Some('\n') = self.head.back() {
272 self.undraw(w)?;
273 }
274 let Some(c) = self.head.pop_back() else {
275 return Ok(());
276 };
277 self.tail.push_front(c);
278 match c {
279 '\n' => self.redraw(w)?,
280 _ => queue!(w, MoveLeft(1))?,
281 }
282 }
283 Ok(())
284 }
285
286 pub fn cursor_forward<W: Write>(&mut self, steps: usize, w: &mut W) -> ReplResult<()> {
288 for _ in 0..steps {
289 if let Some('\n') = self.tail.front() {
290 self.undraw(w)?
291 }
292 let Some(c) = self.tail.pop_front() else {
293 return Ok(());
294 };
295 self.head.push_back(c);
296 match c {
297 '\n' => self.redraw(w)?,
298 _ => queue!(w, MoveRight(1))?,
299 }
300 }
301 Ok(())
302 }
303
304 pub fn home<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
306 loop {
307 match self.head.back() {
308 Some('\n') | None => break Ok(()),
309 Some(_) => self.cursor_back(1, w)?,
310 }
311 }
312 }
313
314 pub fn end<W: Write>(&mut self, w: &mut W) -> ReplResult<()> {
316 loop {
317 match self.tail.front() {
318 Some('\n') | None => break Ok(()),
319 Some(_) => self.cursor_forward(1, w)?,
320 }
321 }
322 }
323}
324
325impl<'e> IntoIterator for &'e Editor<'_> {
326 type Item = &'e char;
327 type IntoIter = std::iter::Chain<
328 std::collections::vec_deque::Iter<'e, char>,
329 std::collections::vec_deque::Iter<'e, char>,
330 >;
331 fn into_iter(self) -> Self::IntoIter {
332 self.head.iter().chain(self.tail.iter())
333 }
334}
335
336impl Display for Editor<'_> {
337 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
338 use std::fmt::Write;
339 for c in self.iter() {
340 f.write_char(*c)?;
341 }
342 Ok(())
343 }
344}