summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-02-28 18:43:11 +0100
committerrabite <rabite@posteo.de>2019-02-28 18:48:37 +0100
commit06817602a8559e8c214c7f68d804ee1d7d9ffd77 (patch)
treeab3672a6f7f43c478ff8783f4d8a99d5a05e487a
parentfd67621dee25990cca67766865ec3e991b5bf11e (diff)
view exec'd processes status/output
-rw-r--r--src/fail.rs4
-rw-r--r--src/file_browser.rs49
-rw-r--r--src/hbox.rs6
-rw-r--r--src/listview.rs11
-rw-r--r--src/main.rs3
-rw-r--r--src/miller_columns.rs3
-rw-r--r--src/minibuffer.rs5
-rw-r--r--src/preview.rs6
-rw-r--r--src/proclist.rs250
-rw-r--r--src/tabview.rs4
-rw-r--r--src/textview.rs6
-rw-r--r--src/widget.rs62
-rw-r--r--src/window.rs61
13 files changed, 399 insertions, 71 deletions
diff --git a/src/fail.rs b/src/fail.rs
index 3e85e11..02287f9 100644
--- a/src/fail.rs
+++ b/src/fail.rs
@@ -32,7 +32,9 @@ pub enum HError {
#[fail(display = "No widget found")]
NoWidgetError,
#[fail(display = "Path: {:?} not in this directory: {:?}", path, dir)]
- WrongDirectoryError{ path: PathBuf, dir: PathBuf }
+ WrongDirectoryError{ path: PathBuf, dir: PathBuf },
+ #[fail(display = "Widget finnished")]
+ PopupFinnished,
}
impl From<std::io::Error> for HError {
diff --git a/src/file_browser.rs b/src/file_browser.rs
index 31e15da..a950f0a 100644
--- a/src/file_browser.rs
+++ b/src/file_browser.rs
@@ -17,6 +17,7 @@ use crate::tabview::{TabView, Tabbable};
use crate::preview::WillBeWidget;
use crate::fail::{HResult, HError};
use crate::window::{Events, send_event};
+use crate::proclist::ProcView;
@@ -25,12 +26,17 @@ pub struct FileBrowser {
pub cwd: File,
watcher: INotifyWatcher,
watches: Vec<PathBuf>,
- dir_events: Arc<Mutex<Vec<DebouncedEvent>>>
+ dir_events: Arc<Mutex<Vec<DebouncedEvent>>>,
+ proc_view: Arc<Mutex<ProcView>>,
}
impl Tabbable for TabView<FileBrowser> {
fn new_tab(&mut self) {
- let tab = FileBrowser::new().unwrap();
+ let mut tab = FileBrowser::new().unwrap();
+
+ let proc_view = self.active_tab_().proc_view.clone();
+ tab.proc_view = proc_view;
+
self.push_widget(tab);
self.active += 1;
}
@@ -71,7 +77,7 @@ impl Tabbable for TabView<FileBrowser> {
.collect::<Vec<_>>();
self.widgets[self.active].exec_cmd(tab_dirs).ok();
}
- _ => self.active_tab_mut().on_key(key)
+ _ => { self.active_tab_mut().on_key(key).ok(); }
}
}
}
@@ -125,11 +131,15 @@ impl FileBrowser {
let watcher = INotifyWatcher::new(tx_watch, Duration::from_secs(2)).unwrap();
watch_dir(rx_watch, dir_events.clone());
+ let mut proc_view = ProcView::new();
+ proc_view.set_coordinates(&coords);
+
Ok(FileBrowser { columns: miller,
cwd: cwd,
watcher: watcher,
watches: vec![],
- dir_events: dir_events })
+ dir_events: dir_events,
+ proc_view: Arc::new(Mutex::new(proc_view)) })
}
pub fn enter_dir(&mut self) -> HResult<()> {
@@ -250,7 +260,7 @@ impl FileBrowser {
self.watches.push(left_dir.path);
}
if let Some(preview_dir) = preview_dir {
- if !watched_dirs.contains(&preview_dir) {
+ if !watched_dirs.contains(&preview_dir) && preview_dir.is_dir() {
self.watcher.watch(&preview_dir, RecursiveMode::NonRecursive).unwrap();
self.watches.push(preview_dir);
}
@@ -380,21 +390,8 @@ impl FileBrowser {
cmd = cmd.replace(&tab_identifier, &tab_path);
}
- let status = std::process::Command::new("sh")
- .arg("-c")
- .arg(&cmd)
- .status();
- let mut bufout = std::io::BufWriter::new(std::io::stdout());
- write!(bufout, "{}{}",
- termion::style::Reset,
- termion::clear::All).unwrap();
-
- match status {
- Ok(status) => self.show_status(&format!("\"{}\" exited with {}",
- cmd, status)),
- Err(err) => self.show_status(&format!("Can't run this \"{}\": {}",
- cmd, err)),
- }
+ self.proc_view.lock()?.run_proc(&cmd)?;
+
Ok(())
}
}
@@ -404,7 +401,8 @@ impl Widget for FileBrowser {
&self.columns.coordinates
}
fn set_coordinates(&mut self, coordinates: &Coordinates) {
- self.columns.coordinates = coordinates.clone();
+ self.columns.set_coordinates(coordinates);
+ self.proc_view.lock().unwrap().set_coordinates(coordinates);
self.refresh();
}
fn render_header(&self) -> String {
@@ -467,15 +465,20 @@ impl Widget for FileBrowser {
}
}
- fn on_key(&mut self, key: Key) {
+ fn on_key(&mut self, key: Key) -> HResult<()> {
match key {
Key::Char('/') => { self.turbo_cd().ok(); },
Key::Char('Q') => { self.quit_with_dir().ok(); },
Key::Right | Key::Char('f') => { self.enter_dir().ok(); },
Key::Left | Key::Char('b') => { self.go_back().ok(); },
- _ => self.columns.get_main_widget_mut().unwrap().on_key(key),
+ Key::Char('w') => {
+ self.proc_view.lock()?.popup().ok();
+ }
+ ,
+ _ => { self.columns.get_main_widget_mut()?.on_key(key).ok(); },
}
self.update_preview().ok();
+ Ok(())
}
}
diff --git a/src/hbox.rs b/src/hbox.rs
index 23c580b..7e27656 100644
--- a/src/hbox.rs
+++ b/src/hbox.rs
@@ -2,6 +2,7 @@ use termion::event::{Event};
use crate::widget::Widget;
use crate::coordinates::{Coordinates, Size, Position};
+use crate::fail::HResult;
#[derive(PartialEq)]
pub struct HBox<T: Widget> {
@@ -106,7 +107,8 @@ impl<T> Widget for HBox<T> where T: Widget + PartialEq {
self.coordinates = coordinates.clone();
self.refresh();
}
- fn on_event(&mut self, event: Event) {
- self.widgets.last_mut().unwrap().on_event(event);
+ fn on_event(&mut self, event: Event) -> HResult<()> {
+ self.widgets.last_mut()?.on_event(event).ok();
+ Ok(())
}
}
diff --git a/src/listview.rs b/src/listview.rs
index 19e806a..0a25dca 100644
--- a/src/listview.rs
+++ b/src/listview.rs
@@ -90,7 +90,7 @@ where
view
}
- fn move_up(&mut self) {
+ pub fn move_up(&mut self) {
if self.selection == 0 {
return;
}
@@ -102,11 +102,11 @@ where
self.selection -= 1;
self.seeking = false;
}
- fn move_down(&mut self) {
+ pub fn move_down(&mut self) {
let lines = self.lines;
let y_size = self.coordinates.ysize() as usize;
- if self.selection == lines - 1 {
+ if self.lines == 0 || self.selection == lines - 1 {
return;
}
@@ -379,7 +379,7 @@ impl<T> Widget for ListView<T> where ListView<T>: Listable {
fn refresh(&mut self) {
self.on_refresh();
self.lines = self.len();
- if self.selection >= self.lines {
+ if self.selection >= self.lines && self.selection != 0 {
self.selection -= 1;
}
self.buffer = self.render();
@@ -418,7 +418,8 @@ impl<T> Widget for ListView<T> where ListView<T>: Listable {
format!("{} files", self.len())
}
- fn on_key(&mut self, key: Key) {
+ fn on_key(&mut self, key: Key) -> HResult<()> {
Listable::on_key(self, key);
+ Ok(())
}
}
diff --git a/src/main.rs b/src/main.rs
index ea5f92c..09d05d9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -40,6 +40,9 @@ mod tabview;
mod async_widget;
mod fail;
mod minibuffer;
+mod proclist;
+
+
use window::Window;
diff --git a/src/miller_columns.rs b/src/miller_columns.rs
index c56bd0e..e6c5c54 100644
--- a/src/miller_columns.rs
+++ b/src/miller_columns.rs
@@ -155,7 +155,8 @@ where
}
}
- fn on_key(&mut self, key: Key) {
+ fn on_key(&mut self, key: Key) -> HResult<()> {
self.get_main_widget_mut().unwrap().on_key(key);
+ Ok(())
}
}
diff --git a/src/minibuffer.rs b/src/minibuffer.rs
index 8c45bd0..f48d84c 100644
--- a/src/minibuffer.rs
+++ b/src/minibuffer.rs
@@ -145,7 +145,7 @@ impl Widget for MiniBuffer {
self.input)
}
- fn on_key(&mut self, key: Key) {
+ fn on_key(&mut self, key: Key) -> HResult<()> {
match key {
Key::Esc | Key::Ctrl('c') => { self.input.clear(); self.done = true; },
Key::Char('\n') => {
@@ -205,7 +205,8 @@ impl Widget for MiniBuffer {
self.input.insert(self.position, key);
self.position += 1;
}
- _ => {}
+ _ => { }
}
+ Ok(())
}
}
diff --git a/src/preview.rs b/src/preview.rs
index 273c13a..fade5b2 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -185,12 +185,12 @@ impl<T: Widget + Send + 'static> Widget for WillBeWidget<T> {
let widget = widget.as_ref().unwrap();
widget.get_drawlist()
}
- fn on_key(&mut self, key: termion::event::Key) {
- if self.willbe.check().is_err() { return }
+ fn on_key(&mut self, key: termion::event::Key) -> HResult<()> {
+ if self.willbe.check().is_err() { return Ok(()) }
let widget = self.widget().unwrap();
let mut widget = widget.try_lock().unwrap();
let widget = widget.as_mut().unwrap();
- widget.on_key(key);
+ widget.on_key(key)
}
}
diff --git a/src/proclist.rs b/src/proclist.rs
new file mode 100644
index 0000000..c2d58ee
--- /dev/null
+++ b/src/proclist.rs
@@ -0,0 +1,250 @@
+use std::sync::{Arc, Mutex};
+use std::process::Child;
+use std::process::Stdio;
+use std::os::unix::io::FromRawFd;
+use std::io::{BufRead, BufReader};
+
+use termion::event::Key;
+use unicode_width::UnicodeWidthStr;
+
+use crate::coordinates::{Coordinates, Size, Position};
+use crate::listview::{Listable, ListView};
+use crate::textview::TextView;
+use crate::widget::Widget;
+use crate::window::{send_event, Events};
+use crate::fail::{HResult, HError};
+use crate::term;
+
+#[derive(Debug)]
+struct Process {
+ cmd: String,
+ handle: Arc<Mutex<Child>>,
+ output: Arc<Mutex<String>>,
+ status: Arc<Mutex<Option<i32>>>,
+ success: Arc<Mutex<Option<bool>>>
+}
+
+impl Process {
+ fn read_proc(&mut self) -> HResult<()> {
+ let handle = self.handle.clone();
+ let output = self.output.clone();
+ let status = self.status.clone();
+ let success = self.success.clone();
+
+ std::thread::spawn(move || {
+ let stdout = handle.lock().unwrap().stdout.take().unwrap();
+ let mut stdout = BufReader::new(stdout);
+ loop {
+ let mut line = String::new();
+ match stdout.read_line(&mut line) {
+ Ok(0) => break,
+ Ok(_) => {
+ output.lock().unwrap().push_str(&line);
+ send_event(Events::WidgetReady).unwrap();
+ }
+ Err(err) => {
+ dbg!(err);
+ break;
+ }
+ }
+ }
+ if let Ok(proc_status) = handle.lock().unwrap().wait() {
+ *success.lock().unwrap() = Some(proc_status.success());
+ *status.lock().unwrap() = proc_status.code();
+ }
+ });
+
+ Ok(())
+ }
+}
+
+impl Listable for ListView<Vec<Process>> {
+ fn len(&self) -> usize { self.content.len() }
+ fn render(&self) -> Vec<String> {
+ self.content.iter().map(|proc| {
+ self.render_proc(proc)
+ }).collect()
+ }
+}
+
+impl ListView<Vec<Process>> {
+ fn run_proc(&mut self, cmd: &str) -> HResult<()> {
+ let handle = std::process::Command::new("sh")
+ .arg("-c")
+ .arg(cmd)
+ .stdin(std::process::Stdio::null())
+ .stdout(std::process::Stdio::piped())
+ .stderr(unsafe { Stdio::from_raw_fd(2) })
+ .spawn()?;
+ let mut proc = Process {
+ cmd: cmd.to_string(),
+ handle: Arc::new(Mutex::new(handle)),
+ output: Arc::new(Mutex::new(String::new())),
+ status: Arc::new(Mutex::new(None)),
+ success: Arc::new(Mutex::new(None))
+ };
+ proc.read_proc()?;
+ self.content.push(proc);
+ Ok(())
+ }
+
+ fn kill_proc(&mut self) -> HResult<()> {
+ let proc = self.selected_proc()?;
+ proc.handle.lock()?.kill()?;
+ Ok(())
+ }
+
+ fn remove_proc(&mut self) -> HResult<()> {
+ self.kill_proc().ok();
+ let selection = self.get_selection();
+ self.content.remove(selection);
+ Ok(())
+ }
+
+ fn selected_proc(&mut self) -> Option<&mut Process> {
+ let selection = self.get_selection();
+ self.content.get_mut(selection)
+ }
+
+ pub fn render_proc(&self, proc: &Process) -> String {
+ let status = match *proc.status.lock().unwrap() {
+ Some(status) => format!("{}", status),
+ None => "<R>".to_string()
+ };
+
+ let xsize = self.get_coordinates().xsize();
+ let sized_string = term::sized_string(&proc.cmd, xsize);
+ let status_pos = xsize - status.len() as u16;
+ let padding = sized_string.len() - sized_string.width_cjk();
+ let padding = xsize - padding as u16;
+
+ let color_status = match *proc.success.lock().unwrap() {
+ Some(false) => { format!("{}{}", term::color_red(), status) }
+ _ => { status }
+ };
+
+ format!(
+ "{}{}{}{}{}{}",
+ termion::cursor::Save,
+ format!("{}{}{:padding$}{}",
+ term::normal_color(),
+ &sized_string,
+ " ",
+ term::normal_color(),
+ padding = padding as usize),
+ termion::cursor::Restore,
+ termion::cursor::Right(status_pos),
+ term::highlight_color(),
+ color_status
+ )
+ }
+}
+
+pub struct ProcView {
+ coordinates: Coordinates,
+ proc_list: ListView<Vec<Process>>,
+ textview: TextView,
+}
+
+impl ProcView {
+ pub fn new() -> ProcView {
+ ProcView {
+ coordinates: Coordinates::new(),
+ proc_list: ListView::new(vec![]),
+ textview: TextView::new_blank(),
+ }
+ }
+
+ pub fn run_proc(&mut self, cmd: &str) -> HResult<()> {
+ self.proc_list.run_proc(cmd)?;
+ Ok(())
+ }
+
+ pub fn remove_proc(&mut self) -> HResult<()> {
+ self.proc_list.remove_proc()?;
+ self.textview.set_text("");
+ Ok(())
+ }
+
+ fn show_output(&mut self) -> HResult<()> {
+ let output = self.proc_list.selected_proc()?.output.lock()?;
+ self.textview.set_text(&*output);
+ Ok(())
+ }
+
+ pub fn calculate_coordinates(&self) -> (Coordinates, Coordinates) {
+ let xsize = self.coordinates.xsize();
+ let ysize = self.coordinates.ysize();
+ let top = self.coordinates.top().y();
+ let ratio = (33, 66);
+
+ let left_xsize = xsize * ratio.0 / 100;
+ let left_size = Size((left_xsize, ysize));
+ let left_pos = self.coordinates.top();
+
+ let main_xsize = xsize * ratio.1 / 100;
+ let main_size = Size((main_xsize, ysize));
+ let main_pos = Position((left_xsize + 2, top));
+
+
+
+ let left_coords = Coordinates {
+ size: left_size,
+ position: left_pos,
+ };
+
+ let main_coords = Coordinates {
+ size: main_size,
+ position: main_pos,
+ };
+
+ (left_coords, main_coords)
+ }
+
+
+}
+
+impl Widget for ProcView {
+ fn get_coordinates(&self) -> &Coordinates {
+ &self.coordinates
+ }
+ fn set_coordinates(&mut self, coordinates: &Coordinates) {
+ self.coordinates = coordinates.clone();
+
+ let (lcoord, rcoord) = self.calculate_coordinates();
+ self.proc_list.set_coordinates(&lcoord);
+ self.textview.set_coordinates(&rcoord);
+
+ self.refresh();
+ }
+ fn render_header(&self) -> String {
+ "".to_string()
+ }
+ fn refresh(&mut self) {
+ self.show_output().ok();
+ self.proc_list.refresh();
+ self.textview.refresh();
+ }
+ fn get_drawlist(&self) -> String {
+ self.proc_list.get_drawlist() + &self.textview.get_drawlist()
+ }
+ fn on_key(&mut self, key: Key) -> HResult<()> {
+ match key {
+ Key::Char('w') => { return Err(HError::PopupFinnished) }
+ Key::Char('d') => { self.remove_proc()? }
+ Key::Char('k') => { self.proc_list.kill_proc()? }
+ Key::Up | Key::Char('p') => {
+ self.proc_list.move_up();
+ self.proc_list.refresh();
+ }
+ Key::Down | Key::Char('n') => {
+ self.proc_list.move_down();
+ self.proc_list.refresh();
+ }
+ _ => {}
+ }
+ self.refresh();
+ self.draw()?;
+ Ok(())
+ }
+}
diff --git a/src/tabview.rs b/src/tabview.rs
index 22ef78f..e4904a5 100644
--- a/src/tabview.rs
+++ b/src/tabview.rs
@@ -2,6 +2,7 @@ use termion::event::Key;
use crate::coordinates::{Coordinates};
use crate::widget::Widget;
+use crate::fail::HResult;
pub trait Tabbable {
fn new_tab(&mut self);
@@ -129,7 +130,8 @@ impl<T> Widget for TabView<T> where T: Widget, TabView<T>: Tabbable {
self.refresh();
}
- fn on_key(&mut self, key: Key) {
+ fn on_key(&mut self, key: Key) -> HResult<()> {
Tabbable::on_key(self, key);
+ Ok(())
}
}
diff --git a/src/textview.rs b/src/textview.rs
index a7a28c6..455e961 100644
--- a/src/textview.rs
+++ b/src/textview.rs
@@ -48,6 +48,12 @@ impl TextView {
coordinates: Coordinates::new(),
}
}
+
+ pub fn set_text(&mut self, text: &str) {
+ let lines = text.lines().map(|l| l.to_string()).collect();
+ self.lines = lines;
+ self.refresh();
+ }
}
impl Widget for TextView {
diff --git a/src/widget.rs b/src/widget.rs
index d41900f..353d198 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -1,9 +1,13 @@
+use std::sync::mpsc::channel;
+
use termion::event::{Event, Key, MouseEvent};
+use termion::input::TermRead;
use crate::coordinates::{Coordinates, Position, Size};
-use crate::fail::HResult;
+use crate::fail::{HResult, HError};
+use crate::window::{send_event, Events};
-use std::io::{BufWriter, Write};
+use std::io::{BufWriter, Write, stdin};
pub trait Widget {
@@ -18,7 +22,7 @@ pub trait Widget {
fn get_drawlist(&self) -> String;
- fn on_event(&mut self, event: Event) {
+ fn on_event(&mut self, event: Event) -> HResult<()> {
match event {
Event::Key(Key::Char('q')) => panic!("It's your fault!"),
Event::Key(key) => self.on_key(key),
@@ -27,22 +31,25 @@ pub trait Widget {
}
}
- fn on_key(&mut self, key: Key) {
+ fn on_key(&mut self, key: Key) -> HResult<()> {
match key {
_ => self.bad(Event::Key(key)),
}
+ Ok(())
}
- fn on_mouse(&mut self, event: MouseEvent) {
+ fn on_mouse(&mut self, event: MouseEvent) -> HResult<()> {
match event {
_ => self.bad(Event::Mouse(event)),
}
+ Ok(())
}
- fn on_wtf(&mut self, event: Vec<u8>) {
+ fn on_wtf(&mut self, event: Vec<u8>) -> HResult<()> {
match event {
_ => self.bad(Event::Unsupported(event)),
}
+ Ok(())
}
fn show_status(&self, status: &str) {
@@ -125,6 +132,49 @@ pub trait Widget {
Ok(())
}
+ fn popup(&mut self) -> HResult<()> {
+ self.run_widget();
+ send_event(Events::ExclusiveEvent(None));
+ Ok(())
+ }
+
+ fn run_widget(&mut self) -> HResult<()> {
+ let (tx_event, rx_event) = channel();
+ send_event(Events::ExclusiveEvent(Some(tx_event)))?;
+ dbg!("sent exclusive request");
+
+ self.clear()?;
+ self.refresh();
+ self.draw()?;
+
+ dbg!("entering loop");
+
+ for event in rx_event.iter() {
+ dbg!(&event);
+ match event {
+ Events::InputEvent(input) => {
+ if let Err(HError::PopupFinnished) = self.on_event(input) {
+ return Err(HError::PopupFinnished)
+ }
+ }
+ Events::WidgetReady => {
+ self.refresh();
+ }
+ _ => {}
+ }
+
+ self.draw()?;
+ }
+ Ok(())
+ }
+
+ fn clear(&self) -> HResult<()> {
+ let clearlist = self.get_clearlist();
+ write!(std::io::stdout(), "{}", clearlist)?;
+ std::io::stdout().flush()?;
+ Ok(())
+ }
+
fn animate_slide_up(&mut self) {
let coords = self.get_coordinates().clone();
let xpos = coords.position().x();
diff --git a/src/window.rs b/src/window.rs
index f974208..90c7812 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -20,11 +20,12 @@ lazy_static! {
= Arc::new(Mutex::new(MiniBuffer::new()));
}
-
+#[derive(Debug)]
pub enum Events {
InputEvent(Event),
WidgetReady,
ExclusiveInput(bool),
+ ExclusiveEvent(Option<Sender<Events>>),
}
pub struct Window<T>
@@ -87,32 +88,22 @@ where
pub fn handle_input(&mut self) {
- let (tx_event_internal, rx_event_internal) = channel();
let (tx_event, rx_event) = channel();
- *TX_EVENT.try_lock().unwrap() = Some(tx_event);
- let (tx_request_input, rx_request_input) = channel();
-
- let mut exclusive_mode = false;
+ let (tx_global_event, rx_global_event) = channel();
+ *TX_EVENT.try_lock().unwrap() = Some(tx_global_event);
+ let (tx_internal_event, rx_internal_event) = channel();
- event_thread(rx_event, tx_event_internal.clone());
- input_thread(tx_event_internal.clone(), rx_request_input);
- tx_request_input.send(()).unwrap();
+ input_thread(tx_event.clone());
+ global_event_thread(rx_global_event, tx_event.clone());
+ dispatch_events(rx_event, tx_internal_event);
- for event in rx_event_internal.iter() {
- //Self::clear_status();
- //let event = event.unwrap();
+ for event in rx_internal_event.iter() {
match event {
Events::InputEvent(event) => {
self.widget.on_event(event);
self.screen.cursor_hide();
self.draw();
- if !exclusive_mode {
- tx_request_input.send(()).unwrap();
- }
},
- Events::ExclusiveInput(setting) => {
- exclusive_mode = setting
- }
_ => {
self.widget.refresh();
self.draw();
@@ -122,23 +113,39 @@ where
}
}
-fn event_thread(rx: Receiver<Events>,
- tx: Sender<Events>) {
+fn dispatch_events(rx: Receiver<Events>, tx: Sender<Events>) {
std::thread::spawn(move || {
+ let mut tx_exclusive_event: Option<Sender<Events>> = None;
for event in rx.iter() {
+ match &event {
+ Events::ExclusiveEvent(tx_event) => {
+ tx_exclusive_event = tx_event.clone();
+ }
+ _ => {}
+ }
+ if let Some(tx_event) = &tx_exclusive_event {
+ tx_event.send(event).unwrap();
+ } else {
+ tx.send(event).unwrap();
+ }
+ }
+ });
+}
+
+fn global_event_thread(rx_global: Receiver<Events>,
+ tx: Sender<Events>) {
+ std::thread::spawn(move || {
+ for event in rx_global.iter() {
tx.send(event).unwrap();
}
});
}
-fn input_thread(tx: Sender<Events>, request_input: Receiver<()>) {
+fn input_thread(tx: Sender<Events>) {
std::thread::spawn(move || {
- for _ in request_input.iter() {
- for input in stdin().events() {
- let input = input.unwrap();
- tx.send(Events::InputEvent(input)).unwrap();
- break;
- }
+ for input in stdin().events() {
+ let input = input.unwrap();
+ tx.send(Events::InputEvent(input)).unwrap();
}
});
}