diff options
-rw-r--r-- | helix-term/src/application.rs | 37 | ||||
-rw-r--r-- | helix-term/tests/integration.rs | 1 | ||||
-rw-r--r-- | helix-term/tests/integration/auto_indent.rs | 1 | ||||
-rw-r--r-- | helix-term/tests/integration/auto_pairs.rs | 2 | ||||
-rw-r--r-- | helix-term/tests/integration/commands.rs | 4 | ||||
-rw-r--r-- | helix-term/tests/integration/helpers.rs | 42 | ||||
-rw-r--r-- | helix-term/tests/integration/movement.rs | 8 | ||||
-rw-r--r-- | helix-term/tests/integration/write.rs | 5 |
8 files changed, 46 insertions, 54 deletions
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 15026bb6..3b96c45a 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -40,6 +40,8 @@ use { #[cfg(windows)] type Signals = futures_util::stream::Empty<()>; +const LSP_DEADLINE: Duration = Duration::from_millis(16); + pub struct Application { compositor: Compositor, pub editor: Editor, @@ -54,6 +56,7 @@ pub struct Application { signals: Signals, jobs: Jobs, lsp_progress: LspProgressMap, + last_render: Instant, } #[cfg(feature = "integration")] @@ -203,6 +206,7 @@ impl Application { signals, jobs: Jobs::new(), lsp_progress: LspProgressMap::new(), + last_render: Instant::now(), }; Ok(app) @@ -230,58 +234,79 @@ impl Application { where S: Stream<Item = crossterm::Result<crossterm::event::Event>> + Unpin, { - let mut last_render = Instant::now(); - let deadline = Duration::from_secs(1) / 60; - self.render(); + self.last_render = Instant::now(); loop { if self.editor.should_close() { break; } + self.event_loop_until_idle(input_stream).await; + } + } + + pub async fn event_loop_until_idle<S>(&mut self, input_stream: &mut S) -> bool + where + S: Stream<Item = crossterm::Result<crossterm::event::Event>> + Unpin, + { + loop { + if self.editor.should_close() { + return false; + } + use futures_util::StreamExt; tokio::select! { biased; Some(event) = input_stream.next() => { - self.handle_terminal_events(event) + self.handle_terminal_events(event); + self.editor.reset_idle_timer(); } Some(signal) = self.signals.next() => { self.handle_signals(signal).await; + self.editor.reset_idle_timer(); } Some((id, call)) = self.editor.language_servers.incoming.next() => { self.handle_language_server_message(call, id).await; // limit render calls for fast language server messages let last = self.editor.language_servers.incoming.is_empty(); - if last || last_render.elapsed() > deadline { + + if last || self.last_render.elapsed() > LSP_DEADLINE { self.render(); - last_render = Instant::now(); + self.last_render = Instant::now(); } + + self.editor.reset_idle_timer(); } Some(payload) = self.editor.debugger_events.next() => { let needs_render = self.editor.handle_debugger_message(payload).await; if needs_render { self.render(); } + self.editor.reset_idle_timer(); } Some(config_event) = self.editor.config_events.1.recv() => { self.handle_config_events(config_event); self.render(); + self.editor.reset_idle_timer(); } Some(callback) = self.jobs.futures.next() => { self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback); self.render(); + self.editor.reset_idle_timer(); } Some(callback) = self.jobs.wait_futures.next() => { self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback); self.render(); + self.editor.reset_idle_timer(); } _ = &mut self.editor.idle_timer => { // idle timeout self.editor.clear_idle_timer(); self.handle_idle_timeout(); + return true; } } } diff --git a/helix-term/tests/integration.rs b/helix-term/tests/integration.rs index 54364e12..061bd8ff 100644 --- a/helix-term/tests/integration.rs +++ b/helix-term/tests/integration.rs @@ -17,7 +17,6 @@ mod integration { Args::default(), Config::default(), ("#[\n|]#", "ihello world<esc>", "hello world#[|\n]#"), - None, ) .await?; diff --git a/helix-term/tests/integration/auto_indent.rs b/helix-term/tests/integration/auto_indent.rs index fdfc7dfb..74d1ac58 100644 --- a/helix-term/tests/integration/auto_indent.rs +++ b/helix-term/tests/integration/auto_indent.rs @@ -18,7 +18,6 @@ async fn auto_indent_c() -> anyhow::Result<()> { } "}, ), - None, ) .await?; diff --git a/helix-term/tests/integration/auto_pairs.rs b/helix-term/tests/integration/auto_pairs.rs index d34cd0fd..52fee55e 100644 --- a/helix-term/tests/integration/auto_pairs.rs +++ b/helix-term/tests/integration/auto_pairs.rs @@ -6,7 +6,6 @@ async fn auto_pairs_basic() -> anyhow::Result<()> { Args::default(), Config::default(), ("#[\n|]#", "i(<esc>", "(#[|)]#\n"), - None, ) .await?; @@ -20,7 +19,6 @@ async fn auto_pairs_basic() -> anyhow::Result<()> { ..Default::default() }, ("#[\n|]#", "i(<esc>", "(#[|\n]#"), - None, ) .await?; diff --git a/helix-term/tests/integration/commands.rs b/helix-term/tests/integration/commands.rs index 7da180b9..4ab87b9b 100644 --- a/helix-term/tests/integration/commands.rs +++ b/helix-term/tests/integration/commands.rs @@ -1,7 +1,6 @@ use std::{ io::{Read, Write}, ops::RangeInclusive, - time::Duration, }; use helix_core::diagnostic::Severity; @@ -23,7 +22,6 @@ async fn test_write_quit_fail() -> anyhow::Result<()> { Some(&|app| { assert_eq!(&Severity::Error, app.editor.get_status().unwrap().1); }), - None, ) .await?; @@ -57,7 +55,6 @@ async fn test_buffer_close() -> anyhow::Result<()> { }), ), ], - None, ) .await?; @@ -88,7 +85,6 @@ async fn test_buffer_close() -> anyhow::Result<()> { let doc = app.editor.document_by_path(file.path()); assert!(doc.is_none(), "found doc: {:?}", doc); }), - Some(Duration::from_millis(5000)), ) .await?; diff --git a/helix-term/tests/integration/helpers.rs b/helix-term/tests/integration/helpers.rs index 18a3517c..29cb8cd8 100644 --- a/helix-term/tests/integration/helpers.rs +++ b/helix-term/tests/integration/helpers.rs @@ -36,17 +36,15 @@ pub async fn test_key_sequence( app: &mut Application, in_keys: Option<&str>, test_fn: Option<&dyn Fn(&Application)>, - timeout: Option<Duration>, ) -> anyhow::Result<()> { - test_key_sequences(app, vec![(in_keys, test_fn)], timeout).await + test_key_sequences(app, vec![(in_keys, test_fn)]).await } pub async fn test_key_sequences( app: &mut Application, inputs: Vec<(Option<&str>, Option<&dyn Fn(&Application)>)>, - timeout: Option<Duration>, ) -> anyhow::Result<()> { - let timeout = timeout.unwrap_or(Duration::from_millis(500)); + const TIMEOUT: Duration = Duration::from_millis(500); let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); let mut rx_stream = UnboundedReceiverStream::new(rx); @@ -57,10 +55,7 @@ pub async fn test_key_sequences( } } - let event_loop = app.event_loop(&mut rx_stream); - let result = tokio::time::timeout(timeout, event_loop).await; - - if result.is_ok() { + if !app.event_loop_until_idle(&mut rx_stream).await { bail!("application exited before test function could run"); } @@ -74,7 +69,7 @@ pub async fn test_key_sequences( } let event_loop = app.event_loop(&mut rx_stream); - tokio::time::timeout(timeout, event_loop).await?; + tokio::time::timeout(TIMEOUT, event_loop).await?; app.close().await?; Ok(()) @@ -84,7 +79,6 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>( app: Option<Application>, test_case: T, test_fn: &dyn Fn(&Application), - timeout: Option<Duration>, ) -> anyhow::Result<()> { let test_case = test_case.into(); let mut app = @@ -102,7 +96,7 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>( view.id, ); - test_key_sequence(&mut app, Some(&test_case.in_keys), Some(test_fn), timeout).await + test_key_sequence(&mut app, Some(&test_case.in_keys), Some(test_fn)).await } /// Use this for very simple test cases where there is one input @@ -112,26 +106,20 @@ pub async fn test_key_sequence_text_result<T: Into<TestCase>>( args: Args, config: Config, test_case: T, - timeout: Option<Duration>, ) -> anyhow::Result<()> { let test_case = test_case.into(); let app = Application::new(args, config).unwrap(); - test_key_sequence_with_input_text( - Some(app), - test_case.clone(), - &|app| { - let doc = doc!(app.editor); - assert_eq!(&test_case.out_text, doc.text()); - - let mut selections: Vec<_> = doc.selections().values().cloned().collect(); - assert_eq!(1, selections.len()); - - let sel = selections.pop().unwrap(); - assert_eq!(test_case.out_selection, sel); - }, - timeout, - ) + test_key_sequence_with_input_text(Some(app), test_case.clone(), &|app| { + let doc = doc!(app.editor); + assert_eq!(&test_case.out_text, doc.text()); + + let mut selections: Vec<_> = doc.selections().values().cloned().collect(); + assert_eq!(1, selections.len()); + + let sel = selections.pop().unwrap(); + assert_eq!(test_case.out_selection, sel); + }) .await } diff --git a/helix-term/tests/integration/movement.rs b/helix-term/tests/integration/movement.rs index a1d294c6..cac10852 100644 --- a/helix-term/tests/integration/movement.rs +++ b/helix-term/tests/integration/movement.rs @@ -14,7 +14,6 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> { out_text: String::new(), out_selection: Selection::single(0, 0), }, - None, ) .await?; @@ -22,7 +21,6 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> { Args::default(), Config::default(), ("#[\n|]#", "i", "#[|\n]#"), - None, ) .await?; @@ -30,7 +28,6 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> { Args::default(), Config::default(), ("#[\n|]#", "i<esc>", "#[|\n]#"), - None, ) .await?; @@ -38,7 +35,6 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> { Args::default(), Config::default(), ("#[\n|]#", "i<esc>i", "#[|\n]#"), - None, ) .await?; @@ -52,7 +48,6 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> { Args::default(), Config::default(), ("#[f|]#oo\n", "vll<A-;><esc>", "#[|foo]#\n"), - None, ) .await?; @@ -70,7 +65,6 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> { #(|bar)#" }, ), - None, ) .await?; @@ -88,7 +82,6 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> { #(ba|)#r" }, ), - None, ) .await?; @@ -106,7 +99,6 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> { #(b|)#ar" }, ), - None, ) .await?; diff --git a/helix-term/tests/integration/write.rs b/helix-term/tests/integration/write.rs index 365e6b8d..0cc41dbc 100644 --- a/helix-term/tests/integration/write.rs +++ b/helix-term/tests/integration/write.rs @@ -1,7 +1,6 @@ use std::{ io::{Read, Write}, ops::RangeInclusive, - time::Duration, }; use helix_core::diagnostic::Severity; @@ -24,7 +23,6 @@ async fn test_write() -> anyhow::Result<()> { )?, Some("ii can eat glass, it will not hurt me<ret><esc>:w<ret>"), None, - Some(Duration::from_millis(1000)), ) .await?; @@ -59,7 +57,6 @@ async fn test_write_concurrent() -> anyhow::Result<()> { )?, Some(&command), None, - Some(Duration::from_millis(10000)), ) .await?; @@ -108,7 +105,6 @@ async fn test_write_fail_mod_flag() -> anyhow::Result<()> { }), ), ], - None, ) .await?; @@ -138,7 +134,6 @@ async fn test_write_fail_new_path() -> anyhow::Result<()> { }), ), ], - Some(Duration::from_millis(1000)), ) .await?; |