on master help sign in
use idle timer instead of fixed timeout
commit2386c81ebc118860107094591b76ef3864e120a8 authorSkyler Hawthorne <skyler@dead10ck.com> dateSat 23 Apr 2022, 21:49 (5 years ago) parent4012096
8 files changed+46−54
helix-term/src/application.rs+31−6 helix-term/tests/integration.rs−1 helix-term/tests/integration/auto_indent.rs−1 helix-term/tests/integration/auto_pairs.rs−2 helix-term/tests/integration/commands.rs−4 helix-term/tests/integration/helpers.rs+15−27 helix-term/tests/integration/movement.rs−8 helix-term/tests/integration/write.rs−5
helix-term/src/application.rs+31−6
@@ -40,6 +40,8 @@ use {
4040#[cfg(windows)]
4141type Signals = futures_util::stream::Empty<()>;
4242
43+const LSP_DEADLINE: Duration = Duration::from_millis(16);
44+
4345pub struct Application {
4446 compositor: Compositor,
4547 pub editor: Editor,
@@ -54,6 +56,7 @@ pub struct Application {
5456 signals: Signals,
5557 jobs: Jobs,
5658 lsp_progress: LspProgressMap,
59+ last_render: Instant,
5760}
5861
5962#[cfg(feature = "integration")]
@@ -203,6 +206,7 @@ impl Application {
203206 signals,
204207 jobs: Jobs::new(),
205208 lsp_progress: LspProgressMap::new(),
209+ last_render: Instant::now(),
206210 };
207211
208212 Ok(app)
@@ -230,58 +234,79 @@ impl Application {
230234 where
231235 S: Stream<Item = crossterm::Result<crossterm::event::Event>> + Unpin,
232236 {
233− let mut last_render = Instant::now();
234− let deadline = Duration::from_secs(1) / 60;
235−
236237 self.render();
238+ self.last_render = Instant::now();
237239
238240 loop {
239241 if self.editor.should_close() {
240242 break;
241243 }
242244
245+ self.event_loop_until_idle(input_stream).await;
246+ }
247+ }
248+
249+ pub async fn event_loop_until_idle<S>(&mut self, input_stream: &mut S) -> bool
250+ where
251+ S: Stream<Item = crossterm::Result<crossterm::event::Event>> + Unpin,
252+ {
253+ loop {
254+ if self.editor.should_close() {
255+ return false;
256+ }
257+
243258 use futures_util::StreamExt;
244259
245260 tokio::select! {
246261 biased;
247262
248263 Some(event) = input_stream.next() => {
249− self.handle_terminal_events(event)
264+ self.handle_terminal_events(event);
265+ self.editor.reset_idle_timer();
250266 }
251267 Some(signal) = self.signals.next() => {
252268 self.handle_signals(signal).await;
269+ self.editor.reset_idle_timer();
253270 }
254271 Some((id, call)) = self.editor.language_servers.incoming.next() => {
255272 self.handle_language_server_message(call, id).await;
256273 // limit render calls for fast language server messages
257274 let last = self.editor.language_servers.incoming.is_empty();
258− if last || last_render.elapsed() > deadline {
275+
276+ if last || self.last_render.elapsed() > LSP_DEADLINE {
259277 self.render();
260− last_render = Instant::now();
278+ self.last_render = Instant::now();
261279 }
280+
281+ self.editor.reset_idle_timer();
262282 }
263283 Some(payload) = self.editor.debugger_events.next() => {
264284 let needs_render = self.editor.handle_debugger_message(payload).await;
265285 if needs_render {
266286 self.render();
267287 }
288+ self.editor.reset_idle_timer();
268289 }
269290 Some(config_event) = self.editor.config_events.1.recv() => {
270291 self.handle_config_events(config_event);
271292 self.render();
293+ self.editor.reset_idle_timer();
272294 }
273295 Some(callback) = self.jobs.futures.next() => {
274296 self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
275297 self.render();
298+ self.editor.reset_idle_timer();
276299 }
277300 Some(callback) = self.jobs.wait_futures.next() => {
278301 self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
279302 self.render();
303+ self.editor.reset_idle_timer();
280304 }
281305 _ = &mut self.editor.idle_timer => {
282306 // idle timeout
283307 self.editor.clear_idle_timer();
284308 self.handle_idle_timeout();
309+ return true;
285310 }
286311 }
287312 }
helix-term/tests/integration.rs−1
@@ -17,7 +17,6 @@ mod integration {
1717 Args::default(),
1818 Config::default(),
1919 ("#[\n|]#", "ihello world<esc>", "hello world#[|\n]#"),
20− None,
2120 )
2221 .await?;
2322
helix-term/tests/integration/auto_indent.rs−1
@@ -18,7 +18,6 @@ async fn auto_indent_c() -> anyhow::Result<()> {
1818 }
1919 "},
2020 ),
21− None,
2221 )
2322 .await?;
2423
helix-term/tests/integration/auto_pairs.rs−2
@@ -6,7 +6,6 @@ async fn auto_pairs_basic() -> anyhow::Result<()> {
66 Args::default(),
77 Config::default(),
88 ("#[\n|]#", "i(<esc>", "(#[|)]#\n"),
9− None,
109 )
1110 .await?;
1211
@@ -20,7 +19,6 @@ async fn auto_pairs_basic() -> anyhow::Result<()> {
2019 ..Default::default()
2120 },
2221 ("#[\n|]#", "i(<esc>", "(#[|\n]#"),
23− None,
2422 )
2523 .await?;
2624
helix-term/tests/integration/commands.rs−4
@@ -1,7 +1,6 @@
11use std::{
22 io::{Read, Write},
33 ops::RangeInclusive,
4− time::Duration,
54};
65
76use helix_core::diagnostic::Severity;
@@ -23,7 +22,6 @@ async fn test_write_quit_fail() -> anyhow::Result<()> {
2322 Some(&|app| {
2423 assert_eq!(&Severity::Error, app.editor.get_status().unwrap().1);
2524 }),
26− None,
2725 )
2826 .await?;
2927
@@ -57,7 +55,6 @@ async fn test_buffer_close() -> anyhow::Result<()> {
5755 }),
5856 ),
5957 ],
60− None,
6158 )
6259 .await?;
6360
@@ -88,7 +85,6 @@ async fn test_buffer_close() -> anyhow::Result<()> {
8885 let doc = app.editor.document_by_path(file.path());
8986 assert!(doc.is_none(), "found doc: {:?}", doc);
9087 }),
91− Some(Duration::from_millis(5000)),
9288 )
9389 .await?;
9490
helix-term/tests/integration/helpers.rs+15−27
@@ -36,17 +36,15 @@ pub async fn test_key_sequence(
3636 app: &mut Application,
3737 in_keys: Option<&str>,
3838 test_fn: Option<&dyn Fn(&Application)>,
39− timeout: Option<Duration>,
4039) -> anyhow::Result<()> {
41− test_key_sequences(app, vec![(in_keys, test_fn)], timeout).await
40+ test_key_sequences(app, vec![(in_keys, test_fn)]).await
4241}
4342
4443pub async fn test_key_sequences(
4544 app: &mut Application,
4645 inputs: Vec<(Option<&str>, Option<&dyn Fn(&Application)>)>,
47− timeout: Option<Duration>,
4846) -> anyhow::Result<()> {
49− let timeout = timeout.unwrap_or(Duration::from_millis(500));
47+ const TIMEOUT: Duration = Duration::from_millis(500);
5048 let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
5149 let mut rx_stream = UnboundedReceiverStream::new(rx);
5250
@@ -57,10 +55,7 @@ pub async fn test_key_sequences(
5755 }
5856 }
5957
60− let event_loop = app.event_loop(&mut rx_stream);
61− let result = tokio::time::timeout(timeout, event_loop).await;
62−
63− if result.is_ok() {
58+ if !app.event_loop_until_idle(&mut rx_stream).await {
6459 bail!("application exited before test function could run");
6560 }
6661
@@ -74,7 +69,7 @@ pub async fn test_key_sequences(
7469 }
7570
7671 let event_loop = app.event_loop(&mut rx_stream);
77− tokio::time::timeout(timeout, event_loop).await?;
72+ tokio::time::timeout(TIMEOUT, event_loop).await?;
7873 app.close().await?;
7974
8075 Ok(())
@@ -84,7 +79,6 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>(
8479 app: Option<Application>,
8580 test_case: T,
8681 test_fn: &dyn Fn(&Application),
87− timeout: Option<Duration>,
8882) -> anyhow::Result<()> {
8983 let test_case = test_case.into();
9084 let mut app =
@@ -102,7 +96,7 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>(
10296 view.id,
10397 );
10498
105− test_key_sequence(&mut app, Some(&test_case.in_keys), Some(test_fn), timeout).await
99+ test_key_sequence(&mut app, Some(&test_case.in_keys), Some(test_fn)).await
106100}
107101
108102/// 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>>(
112106 args: Args,
113107 config: Config,
114108 test_case: T,
115− timeout: Option<Duration>,
116109) -> anyhow::Result<()> {
117110 let test_case = test_case.into();
118111 let app = Application::new(args, config).unwrap();
119112
120− test_key_sequence_with_input_text(
121− Some(app),
122− test_case.clone(),
123− &|app| {
124− let doc = doc!(app.editor);
125− assert_eq!(&test_case.out_text, doc.text());
126−
127− let mut selections: Vec<_> = doc.selections().values().cloned().collect();
128− assert_eq!(1, selections.len());
129−
130− let sel = selections.pop().unwrap();
131− assert_eq!(test_case.out_selection, sel);
132− },
133− timeout,
134− )
113+ test_key_sequence_with_input_text(Some(app), test_case.clone(), &|app| {
114+ let doc = doc!(app.editor);
115+ assert_eq!(&test_case.out_text, doc.text());
116+
117+ let mut selections: Vec<_> = doc.selections().values().cloned().collect();
118+ assert_eq!(1, selections.len());
119+
120+ let sel = selections.pop().unwrap();
121+ assert_eq!(test_case.out_selection, sel);
122+ })
135123 .await
136124}
137125
helix-term/tests/integration/movement.rs−8
@@ -14,7 +14,6 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> {
1414 out_text: String::new(),
1515 out_selection: Selection::single(0, 0),
1616 },
17− None,
1817 )
1918 .await?;
2019
@@ -22,7 +21,6 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> {
2221 Args::default(),
2322 Config::default(),
2423 ("#[\n|]#", "i", "#[|\n]#"),
25− None,
2624 )
2725 .await?;
2826
@@ -30,7 +28,6 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> {
3028 Args::default(),
3129 Config::default(),
3230 ("#[\n|]#", "i<esc>", "#[|\n]#"),
33− None,
3431 )
3532 .await?;
3633
@@ -38,7 +35,6 @@ async fn insert_mode_cursor_position() -> anyhow::Result<()> {
3835 Args::default(),
3936 Config::default(),
4037 ("#[\n|]#", "i<esc>i", "#[|\n]#"),
41− None,
4238 )
4339 .await?;
4440
@@ -52,7 +48,6 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
5248 Args::default(),
5349 Config::default(),
5450 ("#[f|]#oo\n", "vll<A-;><esc>", "#[|foo]#\n"),
55− None,
5651 )
5752 .await?;
5853
@@ -70,7 +65,6 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
7065 #(|bar)#"
7166 },
7267 ),
73− None,
7468 )
7569 .await?;
7670
@@ -88,7 +82,6 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
8882 #(ba|)#r"
8983 },
9084 ),
91− None,
9285 )
9386 .await?;
9487
@@ -106,7 +99,6 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
10699 #(b|)#ar"
107100 },
108101 ),
109− None,
110102 )
111103 .await?;
112104
helix-term/tests/integration/write.rs−5
@@ -1,7 +1,6 @@
11use std::{
22 io::{Read, Write},
33 ops::RangeInclusive,
4− time::Duration,
54};
65
76use helix_core::diagnostic::Severity;
@@ -24,7 +23,6 @@ async fn test_write() -> anyhow::Result<()> {
2423 )?,
2524 Some("ii can eat glass, it will not hurt me<ret><esc>:w<ret>"),
2625 None,
27− Some(Duration::from_millis(1000)),
2826 )
2927 .await?;
3028
@@ -59,7 +57,6 @@ async fn test_write_concurrent() -> anyhow::Result<()> {
5957 )?,
6058 Some(&command),
6159 None,
62− Some(Duration::from_millis(10000)),
6360 )
6461 .await?;
6562
@@ -108,7 +105,6 @@ async fn test_write_fail_mod_flag() -> anyhow::Result<()> {
108105 }),
109106 ),
110107 ],
111− None,
112108 )
113109 .await?;
114110
@@ -138,7 +134,6 @@ async fn test_write_fail_new_path() -> anyhow::Result<()> {
138134 }),
139135 ),
140136 ],
141− Some(Duration::from_millis(1000)),
142137 )
143138 .await?;
144139