1use std::{
46 collections::VecDeque,
47 io::{self, stdout, Stdout, Write},
48 ops::DerefMut,
49 pin::Pin,
50 task::{Context, Poll},
51};
52
53use crossterm::{
54 event::EventStream,
55 terminal::{self, disable_raw_mode, Clear},
56 QueueableCommand,
57};
58use futures_util::{pin_mut, ready, select, AsyncWrite, FutureExt, StreamExt};
59use thingbuf::mpsc::{errors::TrySendError, Receiver, Sender};
60use thiserror::Error;
61
62mod history;
63mod line;
64use history::History;
65use line::LineState;
66
67#[derive(Debug, Error)]
70pub enum ReadlineError {
71 #[error(transparent)]
73 IO(#[from] io::Error),
74
75 #[error("line writers closed")]
78 Closed,
79}
80
81#[derive(Debug)]
83pub enum ReadlineEvent {
84 Line(String),
86 Eof,
88 Interrupted,
90}
91
92#[pin_project::pin_project]
103pub struct SharedWriter {
104 #[pin]
105 buffer: Vec<u8>,
106 sender: Sender<Vec<u8>>,
107}
108impl Clone for SharedWriter {
109 fn clone(&self) -> Self {
110 Self {
111 buffer: Vec::new(),
112 sender: self.sender.clone(),
113 }
114 }
115}
116impl AsyncWrite for SharedWriter {
117 fn poll_write(
118 self: Pin<&mut Self>,
119 cx: &mut Context<'_>,
120 buf: &[u8],
121 ) -> Poll<io::Result<usize>> {
122 let mut this = self.project();
123 this.buffer.extend_from_slice(buf);
124 if this.buffer.ends_with(b"\n") {
125 let fut = this.sender.send_ref();
126 pin_mut!(fut);
127 let mut send_buf = ready!(fut.poll_unpin(cx)).map_err(|_| {
128 io::Error::new(io::ErrorKind::Other, "thingbuf receiver has closed")
129 })?;
130 std::mem::swap(send_buf.deref_mut(), &mut this.buffer);
132 this.buffer.clear();
133 Poll::Ready(Ok(buf.len()))
134 } else {
135 Poll::Ready(Ok(buf.len()))
136 }
137 }
138 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
139 let mut this = self.project();
140 let fut = this.sender.send_ref();
141 pin_mut!(fut);
142 let mut send_buf = ready!(fut.poll_unpin(cx))
143 .map_err(|_| io::Error::new(io::ErrorKind::Other, "thingbuf receiver has closed"))?;
144 std::mem::swap(send_buf.deref_mut(), &mut this.buffer);
146 this.buffer.clear();
147 Poll::Ready(Ok(()))
148 }
149 fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
150 Poll::Ready(Ok(()))
151 }
152}
153impl io::Write for SharedWriter {
154 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
155 self.buffer.extend_from_slice(buf);
156 if self.buffer.ends_with(b"\n") {
157 match self.sender.try_send_ref() {
158 Ok(mut send_buf) => {
159 std::mem::swap(send_buf.deref_mut(), &mut self.buffer);
160 self.buffer.clear();
161 }
162 Err(TrySendError::Full(_)) => return Err(io::ErrorKind::WouldBlock.into()),
163 _ => {
164 return Err(io::Error::new(
165 io::ErrorKind::Other,
166 "thingbuf receiver has closed",
167 ));
168 }
169 }
170 }
171 Ok(buf.len())
172 }
173 fn flush(&mut self) -> io::Result<()> {
174 Ok(())
175 }
176}
177
178pub struct Readline {
189 raw_term: Stdout,
190 event_stream: EventStream, line_receiver: Receiver<Vec<u8>>,
192 line: LineState, }
194
195impl Readline {
196 pub fn new(prompt: String) -> Result<(Self, SharedWriter), ReadlineError> {
199 let (sender, line_receiver) = thingbuf::mpsc::channel(500);
200 terminal::enable_raw_mode()?;
201
202 let line = LineState::new(prompt, terminal::size()?);
203
204 let mut readline = Readline {
205 raw_term: stdout(),
206 event_stream: EventStream::new(),
207 line_receiver,
208 line,
209 };
210 readline.line.render(&mut readline.raw_term)?;
211 readline.raw_term.queue(terminal::EnableLineWrap)?;
212 readline.raw_term.flush()?;
213 Ok((
214 readline,
215 SharedWriter {
216 sender,
217 buffer: Vec::new(),
218 },
219 ))
220 }
221
222 pub fn update_prompt(&mut self, prompt: &str) -> Result<(), ReadlineError> {
224 self.line.update_prompt(prompt, &mut self.raw_term)?;
225 Ok(())
226 }
227
228 pub fn clear(&mut self) -> Result<(), ReadlineError> {
230 self.raw_term.queue(Clear(terminal::ClearType::All))?;
231 self.line.clear_and_render(&mut self.raw_term)?;
232 self.raw_term.flush()?;
233 Ok(())
234 }
235
236 pub fn set_max_history(&mut self, max_size: usize) {
238 self.line.history.set_max_size(max_size);
239 }
240
241 pub fn should_print_line_on(&mut self, enter: bool, control_c: bool) {
254 self.line.should_print_line_on_enter = enter;
255 self.line.should_print_line_on_control_c = control_c;
256 }
257
258 pub fn flush(&mut self) -> Result<(), ReadlineError> {
260 while let Ok(buf) = self.line_receiver.try_recv_ref() {
261 self.line.print_data(&buf, &mut self.raw_term)?;
262 }
263 self.line.clear(&mut self.raw_term)?;
264 self.raw_term.flush()?;
265 Ok(())
266 }
267
268 pub async fn readline(&mut self) -> Result<ReadlineEvent, ReadlineError> {
271 loop {
272 select! {
273 event = self.event_stream.next().fuse() => match event {
274 Some(Ok(event)) => {
275 match self.line.handle_event(event, &mut self.raw_term) {
276 Ok(Some(event)) => {
277 self.raw_term.flush()?;
278 return Result::<_, ReadlineError>::Ok(event)
279 },
280 Err(e) => return Err(e),
281 Ok(None) => self.raw_term.flush()?,
282 }
283 }
284 Some(Err(e)) => return Err(e.into()),
285 None => {},
286 },
287 result = self.line_receiver.recv_ref().fuse() => match result {
288 Some(buf) => {
289 self.line.print_data(&buf, &mut self.raw_term)?;
290 self.raw_term.flush()?;
291 },
292 None => return Err(ReadlineError::Closed),
293 },
294 }
295 }
296 }
297
298 pub fn add_history_entry(&mut self, entry: String) -> Option<()> {
300 self.line.history.add_entry(entry);
301 Some(())
303 }
304
305 pub fn get_history_entries(&self) -> &VecDeque<String> {
307 self.line.history.get_entries()
308 }
309
310 pub fn set_history_entries(&mut self, entries: impl IntoIterator<Item = String>) {
312 self.line.history.set_entries(entries);
313 }
314
315 pub fn clear_history(&mut self) {
317 self.set_history_entries([]);
318 }
319}
320
321impl Drop for Readline {
322 fn drop(&mut self) {
323 let _ = disable_raw_mode();
324 }
325}