diff --git a/Cargo.lock b/Cargo.lock index d855eac..e383c7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1091,7 +1091,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "xplr" -version = "0.15.0" +version = "0.15.1" dependencies = [ "ansi-to-tui", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index d0d57d3..eefea52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "xplr" -version = "0.15.0" # Update lua.rs +version = "0.15.1" # Update lua.rs authors = ["Arijit Basu "] edition = "2018" description = "A hackable, minimal, fast TUI file explorer" diff --git a/docs/en/src/upgrade-guide.md b/docs/en/src/upgrade-guide.md index c281f07..cd556a0 100644 --- a/docs/en/src/upgrade-guide.md +++ b/docs/en/src/upgrade-guide.md @@ -45,7 +45,7 @@ compatibility. ### Instructions -#### [v0.14.7][3] -> [v0.15.0][43] +#### [v0.14.7][3] -> [v0.15.1][43] - Deprecated `config` field from `CallLua` argument. Use the globally available `xplr.config` instead. @@ -277,4 +277,4 @@ Else do the following: [40]: https://github.com/sayanarijit/xplr/releases/tag/v0.3.8 [41]: https://github.com/sayanarijit/xplr/releases/tag/v0.3.0 [42]: https://github.com/sayanarijit/xplr/releases/tag/v0.14.4 -[43]: https://github.com/sayanarijit/xplr/releases/tag/v0.15.0 +[43]: https://github.com/sayanarijit/xplr/releases/tag/v0.15.1 diff --git a/src/event_reader.rs b/src/event_reader.rs index 22073e8..4fc4756 100644 --- a/src/event_reader.rs +++ b/src/event_reader.rs @@ -1,77 +1,86 @@ use crate::app::Task; use crate::app::{ExternalMsg, InternalMsg, MsgIn}; use crate::input::Key; -use anyhow::Result; use crossterm::event::{self, Event, MouseEventKind}; +use std::sync::mpsc; use std::sync::mpsc::{Receiver, Sender}; use std::thread; -pub fn pause_reading(tx_event_reader: &Sender, rx_loop_waiter: &Receiver<()>) -> Result<()> { - tx_event_reader.send(true)?; - rx_loop_waiter.recv()?; - Ok(()) +pub(crate) struct EventReader { + task_sender: Sender, + stopper: Option<(Sender, Receiver<()>)>, } -pub fn resume_reading(tx_event_reader: &Sender, rx_loop_waiter: &Receiver<()>) -> Result<()> { - tx_event_reader.send(false)?; - rx_loop_waiter.recv()?; - Ok(()) -} +impl EventReader { + pub(crate) fn new(task_sender: Sender) -> Self { + Self { + task_sender, + stopper: None, + } + } -pub fn keep_reading( - tx_msg_in: Sender, - rx_event_reader: Receiver, - tx_loop_waiter: Sender<()>, -) { - thread::spawn(move || { - let mut is_paused = false; - loop { - if let Ok(paused) = rx_event_reader.try_recv() { - is_paused = paused; - tx_loop_waiter.send(()).unwrap(); - }; + pub(crate) fn start(&mut self) { + let sender = self.task_sender.clone(); + let (tx_stopper, rx_stopper) = mpsc::channel(); + let (tx_ack, rx_ack) = mpsc::channel(); + self.stopper = Some((tx_stopper, rx_ack)); - if is_paused { - thread::sleep(std::time::Duration::from_millis(200)); - } else if event::poll(std::time::Duration::from_millis(150)).unwrap_or_default() { - // NOTE: The poll timeout need to stay low, else spawning sub subshell - // and start typing immediately will cause panic. - // To reproduce, press `:`, then press and hold `!`. - match event::read() { - Ok(Event::Key(key)) => { - let key = Key::from_event(key); - let msg = MsgIn::Internal(InternalMsg::HandleKey(key)); - tx_msg_in.send(Task::new(msg, Some(key))).unwrap(); - } + thread::spawn(move || { + keep_reading(sender, rx_stopper, tx_ack); + }); + } - Ok(Event::Mouse(evt)) => match evt.kind { - MouseEventKind::ScrollUp => { - let msg = MsgIn::External(ExternalMsg::FocusPrevious); - tx_msg_in.send(Task::new(msg, None)).unwrap(); - } + pub(crate) fn stop(&self) { + if let Some((stopper, ack)) = &self.stopper { + stopper.send(true).unwrap(); + ack.recv().unwrap(); + } + } +} - MouseEventKind::ScrollDown => { - let msg = MsgIn::External(ExternalMsg::FocusNext); - tx_msg_in.send(Task::new(msg, None)).unwrap(); - } - _ => {} - }, +fn keep_reading(tx_msg_in: Sender, rx_stopper: Receiver, tx_ack: Sender<()>) { + loop { + if rx_stopper.try_recv().unwrap_or(false) { + tx_ack.send(()).unwrap(); + break; + } else if event::poll(std::time::Duration::from_millis(150)).unwrap_or_default() { + // NOTE: The poll timeout need to stay low, else spawning sub subshell + // and start typing immediately will cause panic. + // To reproduce, press `:`, then press and hold `!`. + match event::read() { + Ok(Event::Key(key)) => { + let key = Key::from_event(key); + let msg = MsgIn::Internal(InternalMsg::HandleKey(key)); + tx_msg_in.send(Task::new(msg, Some(key))).unwrap(); + } - Ok(Event::Resize(_, _)) => { - let msg = MsgIn::External(ExternalMsg::Refresh); + Ok(Event::Mouse(evt)) => match evt.kind { + MouseEventKind::ScrollUp => { + let msg = MsgIn::External(ExternalMsg::FocusPrevious); tx_msg_in.send(Task::new(msg, None)).unwrap(); } - Err(e) => { - tx_msg_in - .send(Task::new( - MsgIn::External(ExternalMsg::LogError(e.to_string())), - None, - )) - .unwrap(); + MouseEventKind::ScrollDown => { + let msg = MsgIn::External(ExternalMsg::FocusNext); + tx_msg_in.send(Task::new(msg, None)).unwrap(); } + _ => {} + }, + + Ok(Event::Resize(_, _)) => { + let msg = MsgIn::External(ExternalMsg::Refresh); + tx_msg_in.send(Task::new(msg, None)).unwrap(); + } + + Err(e) => { + tx_msg_in + .send(Task::new( + MsgIn::External(ExternalMsg::LogError(e.to_string())), + None, + )) + .unwrap(); } } } - }); + } } diff --git a/src/lua.rs b/src/lua.rs index 0f92e08..0444f5a 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -133,25 +133,25 @@ mod test { assert!(check_version(VERSION, "foo path").is_ok()); // Current release if OK - assert!(check_version("0.15.0", "foo path").is_ok()); + assert!(check_version("0.15.1", "foo path").is_ok()); // Prev major release is ERR // - Not yet // Prev minor release is ERR (Change when we get to v1) - assert!(check_version("0.14.0", "foo path").is_err()); + assert!(check_version("0.14.1", "foo path").is_err()); // Prev bugfix release is OK - // assert!(check_version("0.15.-1", "foo path").is_ok()); + assert!(check_version("0.15.0", "foo path").is_ok()); // Next major release is ERR - assert!(check_version("1.15.0", "foo path").is_err()); + assert!(check_version("1.15.1", "foo path").is_err()); // Next minor release is ERR - assert!(check_version("0.16.7", "foo path").is_err()); + assert!(check_version("0.16.1", "foo path").is_err()); // Next bugfix release is ERR (Change when we get to v1) - assert!(check_version("0.15.8", "foo path").is_err()); + assert!(check_version("0.15.2", "foo path").is_err()); } #[test] diff --git a/src/runner.rs b/src/runner.rs index 2d6a300..e0e6358 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -2,7 +2,7 @@ use crate::app; use crate::cli::Cli; -use crate::event_reader; +use crate::event_reader::EventReader; use crate::explorer; use crate::lua; use crate::pipe_reader; @@ -146,8 +146,6 @@ impl Runner { fs::create_dir_all(app.session_path())?; let (tx_msg_in, rx_msg_in) = mpsc::channel(); - let (tx_event_reader, rx_event_reader) = mpsc::channel(); - let (tx_loop_waiter, rx_loop_waiter) = mpsc::channel(); let (tx_pwd_watcher, rx_pwd_watcher) = mpsc::channel(); app = app.explore_pwd()?; @@ -208,8 +206,9 @@ impl Runner { terminal.hide_cursor()?; // Threads - event_reader::keep_reading(tx_msg_in.clone(), rx_event_reader, tx_loop_waiter); pwd_watcher::keep_watching(app.pwd(), tx_msg_in.clone(), rx_pwd_watcher)?; + let mut event_reader = EventReader::new(tx_msg_in.clone()); + event_reader.start(); // Enqueue on_load messages for msg in self.on_load { @@ -435,7 +434,7 @@ impl Runner { execute!(terminal.backend_mut(), event::DisableMouseCapture) .unwrap_or_default(); - event_reader::pause_reading(&tx_event_reader, &rx_loop_waiter)?; + event_reader.stop(); terminal.clear()?; terminal.set_cursor(0, 0)?; @@ -460,7 +459,7 @@ impl Runner { terminal.clear()?; term::enable_raw_mode()?; terminal.hide_cursor()?; - event_reader::resume_reading(&tx_event_reader, &rx_loop_waiter)?; + event_reader.start(); if mouse_enabled { match execute!( @@ -481,7 +480,7 @@ impl Runner { execute!(terminal.backend_mut(), event::DisableMouseCapture) .unwrap_or_default(); - event_reader::pause_reading(&tx_event_reader, &rx_loop_waiter)?; + event_reader.stop(); terminal.clear()?; terminal.set_cursor(0, 0)?; @@ -522,7 +521,7 @@ impl Runner { terminal.clear()?; term::enable_raw_mode()?; terminal.hide_cursor()?; - event_reader::resume_reading(&tx_event_reader, &rx_loop_waiter)?; + event_reader.start(); if mouse_enabled { match execute!(