Starts building a line editor

This commit is contained in:
Gregor Reitzenstein 2020-11-03 12:35:40 +01:00
parent d0440942b1
commit d074a551ad

View File

@ -1,34 +1,58 @@
use std::io; use std::{mem, io, thread};
use std::thread;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use linefeed::{Interface, ReadResult}; use termion::event::Key;
use linefeed::memory::MemoryTerminal; use termion::input::TermRead;
use futures::Stream; use futures::Stream;
use futures::ready;
use futures::channel::mpsc; use futures::channel::mpsc;
use futures::SinkExt; use futures::SinkExt;
pub struct Inputs { pub struct Inputs {
rx: mpsc::Receiver<String>, rx: mpsc::Receiver<Key>,
hndl: thread::JoinHandle<()>, hndl: thread::JoinHandle<()>,
cmd_line: String,
} }
impl Inputs { impl Inputs {
pub fn new(term: MemoryTerminal) -> Self { pub fn new() -> Self {
let (mut tx, rx) = mpsc::channel(64); let (mut tx, rx) = mpsc::channel(64);
let hndl = thread::spawn(move || { let hndl = thread::spawn(move || {
let stdin = io::stdin(); let stdin = io::stdin();
let mut reader = Interface::with_term("sute", term).unwrap(); let mut keys = stdin.keys();
reader.set_prompt("> ").unwrap(); for key in keys {
while let ReadResult::Input(line) = reader.read_line().unwrap() { let key = key.unwrap();
smol::block_on(tx.send(line)); smol::block_on(tx.send(key));
} }
}); });
Self { rx, hndl } Self {
rx: rx,
hndl: hndl,
cmd_line: String::new(),
}
}
pub fn get_line(&self) -> &str {
self.cmd_line.as_ref()
}
pub fn handle_key(&mut self, key: Key) -> Option<String> {
match key {
Key::Char('\n') => Some(mem::replace(&mut self.cmd_line, String::new())),
Key::Char(c) => {
self.cmd_line.push(c);
None
},
Key::Backspace => {
self.cmd_line.pop();
None
},
_ => None
}
} }
} }
@ -36,6 +60,14 @@ impl Stream for Inputs {
type Item = String; type Item = String;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
Pin::new(&mut self.rx).poll_next(cx) if let Some(key) = ready!(Pin::new(&mut self.rx).poll_next(cx)) {
if let Some(line) = self.handle_key(key) {
Poll::Ready(Some(line))
} else {
Poll::Pending
}
} else {
Poll::Pending
}
} }
} }