summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2020-03-14 18:22:18 -0400
committerJiayi Zhao <jeff.no.zhao@gmail.com>2020-03-14 18:22:18 -0400
commit5606fe301d0c23b7ea98f9da2a60f9f431d8a3b9 (patch)
tree9ce09bb4100b3f12480f6db2eb951ec48e9795b4
parent032258fcd42761719561a43e52c1a264b92cf067 (diff)
rework input event thread handling
- this fixes issues where joshuto steals the inputs of terminal applications
-rw-r--r--src/run.rs2
-rw-r--r--src/ui/widgets/tui_menu.rs29
-rw-r--r--src/ui/widgets/tui_prompt.rs6
-rw-r--r--src/ui/widgets/tui_textfield.rs138
-rw-r--r--src/util/event.rs44
5 files changed, 123 insertions, 96 deletions
diff --git a/src/run.rs b/src/run.rs
index b6b03c8..0291a34 100644
--- a/src/run.rs
+++ b/src/run.rs
@@ -98,6 +98,7 @@ pub fn run(config_t: JoshutoConfig, keymap_t: JoshutoCommandMapping) -> std::io:
}
}
}
+ context.events.flush();
}
}
let mut view = TuiView::new(&context);
@@ -109,6 +110,5 @@ pub fn run(config_t: JoshutoConfig, keymap_t: JoshutoCommandMapping) -> std::io:
}
}
}
- eprintln!("{:#?}", context.message_queue);
Ok(())
}
diff --git a/src/ui/widgets/tui_menu.rs b/src/ui/widgets/tui_menu.rs
index 5f628cc..4088d6d 100644
--- a/src/ui/widgets/tui_menu.rs
+++ b/src/ui/widgets/tui_menu.rs
@@ -32,6 +32,7 @@ impl TuiCommandMenu {
) -> Option<&'a Box<dyn JoshutoCommand>> {
let mut map: &JoshutoCommandMapping = &m;
let terminal = backend.terminal_mut();
+ context.events.flush();
loop {
terminal.draw(|mut frame| {
@@ -73,20 +74,26 @@ impl TuiCommandMenu {
TuiMenu::new(&display_str).render(&mut frame, menu_rect);
}
});
+
if let Ok(event) = context.events.next() {
match event {
- Event::Input(Key::Esc) => {
- return None;
- }
- Event::Input(key) => match map.get(&key) {
- Some(CommandKeybind::SimpleKeybind(s)) => {
- return Some(s);
+ Event::Input(key) => {
+ match key {
+ Key::Esc => return None,
+ key => {
+ match map.get(&key) {
+ Some(CommandKeybind::SimpleKeybind(s)) => {
+ return Some(s);
+ }
+ Some(CommandKeybind::CompositeKeybind(m)) => {
+ map = m;
+ }
+ None => return None,
+ }
+ }
}
- Some(CommandKeybind::CompositeKeybind(m)) => {
- map = m;
- }
- None => return None,
- },
+ context.events.flush();
+ }
_ => {}
}
}
diff --git a/src/ui/widgets/tui_prompt.rs b/src/ui/widgets/tui_prompt.rs
index dd947a9..1f4826f 100644
--- a/src/ui/widgets/tui_prompt.rs
+++ b/src/ui/widgets/tui_prompt.rs
@@ -21,6 +21,8 @@ impl<'a> TuiPrompt<'a> {
pub fn get_key(&mut self, backend: &mut TuiBackend, context: &JoshutoContext) -> Key {
let terminal = backend.terminal_mut();
+
+ context.events.flush();
loop {
terminal.draw(|mut frame| {
let f_size = frame.size();
@@ -52,7 +54,9 @@ impl<'a> TuiPrompt<'a> {
if let Ok(event) = context.events.next() {
match event {
- Event::Input(key) => return key,
+ Event::Input(key) => {
+ return key;
+ }
_ => {}
};
}
diff --git a/src/ui/widgets/tui_textfield.rs b/src/ui/widgets/tui_textfield.rs
index 602fa5d..c663b95 100644
--- a/src/ui/widgets/tui_textfield.rs
+++ b/src/ui/widgets/tui_textfield.rs
@@ -64,6 +64,8 @@ impl<'a> TuiTextField<'a> {
backend: &mut TuiBackend,
context: &JoshutoContext,
) -> Option<String> {
+ context.events.flush();
+
let mut line_buffer = line_buffer::LineBuffer::with_capacity(255);
let completer = FilenameCompleter::new();
@@ -140,74 +142,80 @@ impl<'a> TuiTextField<'a> {
if let Ok(event) = context.events.next() {
match event {
- Event::Input(Key::Backspace) => {
- if line_buffer.backspace(1) {
- completion_tracker.take();
- }
- }
- Event::Input(Key::Left) => {
- if line_buffer.move_backward(1) {
- completion_tracker.take();
- }
- }
- Event::Input(Key::Right) => {
- if line_buffer.move_forward(1) {
- completion_tracker.take();
- }
- }
- Event::Input(Key::Delete) => {
- if line_buffer.delete(1).is_some() {
- completion_tracker.take();
- }
- }
- Event::Input(Key::Home) => {
- line_buffer.move_home();
- completion_tracker.take();
- }
- Event::Input(Key::End) => {
- line_buffer.move_end();
- completion_tracker.take();
- }
- Event::Input(Key::Up) => {}
- Event::Input(Key::Down) => {}
- Event::Input(Key::Esc) => {
- terminal.hide_cursor();
- return None;
- }
- Event::Input(Key::Char('\t')) => {
- if completion_tracker.is_none() {
- let res =
- completer.complete_path(line_buffer.as_str(), line_buffer.pos());
- if let Ok((pos, mut candidates)) = res {
- candidates.sort_by(|x, y| {
- x.display()
- .partial_cmp(y.display())
- .unwrap_or(std::cmp::Ordering::Less)
- });
- let ct = CompletionTracker::new(
- pos,
- candidates,
- String::from(line_buffer.as_str()),
- );
- completion_tracker = Some(ct);
+ Event::Input(key) => {
+ match key {
+ Key::Backspace => {
+ if line_buffer.backspace(1) {
+ completion_tracker.take();
+ }
}
- }
-
- if let Some(ref mut s) = completion_tracker {
- if s.index < s.candidates.len() {
- let candidate = &s.candidates[s.index];
- completer.update(&mut line_buffer, s.pos, candidate.replacement());
- s.index += 1;
+ Key::Left => {
+ if line_buffer.move_backward(1) {
+ completion_tracker.take();
+ }
}
+ Key::Right => {
+ if line_buffer.move_forward(1) {
+ completion_tracker.take();
+ }
+ }
+ Key::Delete => {
+ if line_buffer.delete(1).is_some() {
+ completion_tracker.take();
+ }
+ }
+ Key::Home => {
+ line_buffer.move_home();
+ completion_tracker.take();
+ }
+ Key::End => {
+ line_buffer.move_end();
+ completion_tracker.take();
+ }
+ Key::Up => {}
+ Key::Down => {}
+ Key::Esc => {
+ terminal.hide_cursor();
+ return None;
+ }
+ Key::Char('\t') => {
+ if completion_tracker.is_none() {
+ let res =
+ completer.complete_path(line_buffer.as_str(), line_buffer.pos());
+ if let Ok((pos, mut candidates)) = res {
+ candidates.sort_by(|x, y| {
+ x.display()
+ .partial_cmp(y.display())
+ .unwrap_or(std::cmp::Ordering::Less)
+ });
+ let ct = CompletionTracker::new(
+ pos,
+ candidates,
+ String::from(line_buffer.as_str()),
+ );
+ completion_tracker = Some(ct);
+ }
+ }
+
+ if let Some(ref mut s) = completion_tracker {
+ if s.index < s.candidates.len() {
+ let candidate = &s.candidates[s.index];
+ completer.update(&mut line_buffer, s.pos, candidate.display());
+ s.index += 1;
+ }
+ }
+ }
+ Key::Char('\n') => {
+ break;
+ }
+ Key::Char(c) => {
+ if line_buffer.insert(c, 1).is_some() {
+ completion_tracker.take();
+ }
+ }
+ _ => {}
}
- }
- Event::Input(Key::Char('\n')) => {
- break;
- }
- Event::Input(Key::Char(c)) => {
- if line_buffer.insert(c, 1).is_some() {
- completion_tracker.take();
- }
+ context.events.flush();
}
_ => {}
};
diff --git a/src/util/event.rs b/src/util/event.rs
index 5a76702..9ec41f7 100644
--- a/src/util/event.rs
+++ b/src/util/event.rs
@@ -27,7 +27,7 @@ pub struct Events {
prefix: &'static str,
pub event_tx: mpsc::Sender<Event>,
event_rx: mpsc::Receiver<Event>,
- pub sync_tx: mpsc::SyncSender<()>,
+ pub input_tx: mpsc::SyncSender<()>,
// fileio_handle: thread::JoinHandle<()>,
}
@@ -41,7 +41,7 @@ impl Events {
}
pub fn with_config(prefix: &'static str) -> Self {
- let (sync_tx, sync_rx) = mpsc::sync_channel(1);
+ let (input_tx, input_rx) = mpsc::sync_channel(1);
let (event_tx, event_rx) = mpsc::channel();
{
@@ -49,16 +49,26 @@ impl Events {
thread::spawn(move || {
let stdin = io::stdin();
let mut keys = stdin.keys();
- while let Ok(_) = sync_rx.recv() {
- if let Some(evt) = keys.next() {
- match evt {
- Ok(key) => {
- if let Err(e) = event_tx.send(Event::Input(key)) {
- eprintln!("[{}] Input thread send err: {:#?}", prefix, e);
- return;
- }
+ match keys.next() {
+ Some(key) => match key {
+ Ok(key) => {
+ if let Err(e) = event_tx.send(Event::Input(key)) {
+ eprintln!("[{}] Input thread send err: {:#?}", prefix, e);
+ return;
+ }
+ }
+ _ => return,
+ }
+ _ => return,
+ }
+
+ while let Ok(_) = input_rx.recv() {
+ if let Some(key) = keys.next() {
+ if let Ok(key) = key {
+ if let Err(e) = event_tx.send(Event::Input(key)) {
+ eprintln!("[{}] Input thread send err: {:#?}", prefix, e);
+ return;
}
- _ => {}
}
}
}
@@ -68,19 +78,17 @@ impl Events {
Events {
event_tx,
event_rx,
- sync_tx,
+ input_tx,
prefix,
}
}
pub fn next(&self) -> Result<Event, mpsc::RecvError> {
- self.sync_tx.try_send(());
let event = self.event_rx.recv()?;
Ok(event)
}
- /*
- pub fn flush(&self) {
- self.sync_rx.try_recv();
- }
- */
+
+ pub fn flush(&self) {
+ self.input_tx.send(());
+ }
}