diff options
Diffstat (limited to 'helix-term/src')
-rw-r--r-- | helix-term/src/application.rs | 50 | ||||
-rw-r--r-- | helix-term/src/commands/typed.rs | 11 | ||||
-rw-r--r-- | helix-term/src/ui/editor.rs | 2 |
3 files changed, 40 insertions, 23 deletions
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 99d3af18..dc12ba3c 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -274,16 +274,27 @@ impl Application { } #[cfg(feature = "integration")] - fn render(&mut self) {} + async fn render(&mut self) {} #[cfg(not(feature = "integration"))] - fn render(&mut self) { + async fn render(&mut self) { let mut cx = crate::compositor::Context { editor: &mut self.editor, jobs: &mut self.jobs, scroll: None, }; + // Acquire mutable access to the redraw_handle lock + // to ensure that there are no tasks running that want to block rendering + drop(cx.editor.redraw_handle.1.write().await); + cx.editor.needs_redraw = false; + { + // exhaust any leftover redraw notifications + let notify = cx.editor.redraw_handle.0.notified(); + tokio::pin!(notify); + notify.enable(); + } + let area = self .terminal .autoresize() @@ -304,7 +315,7 @@ impl Application { where S: Stream<Item = crossterm::Result<crossterm::event::Event>> + Unpin, { - self.render(); + self.render().await; self.last_render = Instant::now(); loop { @@ -329,18 +340,18 @@ impl Application { biased; Some(event) = input_stream.next() => { - self.handle_terminal_events(event); + self.handle_terminal_events(event).await; } Some(signal) = self.signals.next() => { self.handle_signals(signal).await; } Some(callback) = self.jobs.futures.next() => { self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback); - self.render(); + self.render().await; } Some(callback) = self.jobs.wait_futures.next() => { self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback); - self.render(); + self.render().await; } event = self.editor.wait_event() => { let _idle_handled = self.handle_editor_event(event).await; @@ -445,25 +456,25 @@ impl Application { self.compositor.resize(area); self.terminal.clear().expect("couldn't clear terminal"); - self.render(); + self.render().await; } signal::SIGUSR1 => { self.refresh_config(); - self.render(); + self.render().await; } _ => unreachable!(), } } - pub fn handle_idle_timeout(&mut self) { + pub async fn handle_idle_timeout(&mut self) { let mut cx = crate::compositor::Context { editor: &mut self.editor, jobs: &mut self.jobs, scroll: None, }; let should_render = self.compositor.handle_event(&Event::IdleTimeout, &mut cx); - if should_render { - self.render(); + if should_render || self.editor.needs_redraw { + self.render().await; } } @@ -536,11 +547,11 @@ impl Application { match event { EditorEvent::DocumentSaved(event) => { self.handle_document_write(event); - self.render(); + self.render().await; } EditorEvent::ConfigEvent(event) => { self.handle_config_events(event); - self.render(); + self.render().await; } EditorEvent::LanguageServerMessage((id, call)) => { self.handle_language_server_message(call, id).await; @@ -548,19 +559,19 @@ impl Application { let last = self.editor.language_servers.incoming.is_empty(); if last || self.last_render.elapsed() > LSP_DEADLINE { - self.render(); + self.render().await; self.last_render = Instant::now(); } } EditorEvent::DebuggerEvent(payload) => { let needs_render = self.editor.handle_debugger_message(payload).await; if needs_render { - self.render(); + self.render().await; } } EditorEvent::IdleTimer => { self.editor.clear_idle_timer(); - self.handle_idle_timeout(); + self.handle_idle_timeout().await; #[cfg(feature = "integration")] { @@ -572,7 +583,10 @@ impl Application { false } - pub fn handle_terminal_events(&mut self, event: Result<CrosstermEvent, crossterm::ErrorKind>) { + pub async fn handle_terminal_events( + &mut self, + event: Result<CrosstermEvent, crossterm::ErrorKind>, + ) { let mut cx = crate::compositor::Context { editor: &mut self.editor, jobs: &mut self.jobs, @@ -596,7 +610,7 @@ impl Application { }; if should_redraw && !self.editor.should_close() { - self.render(); + self.render().await; } } diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 2fa903a7..9f848efd 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1028,10 +1028,12 @@ fn reload( } let scrolloff = cx.editor.config().scrolloff; + let redraw_handle = cx.editor.redraw_handle.clone(); let (view, doc) = current!(cx.editor); - doc.reload(view).map(|_| { - view.ensure_cursor_in_view(doc, scrolloff); - }) + doc.reload(view, &cx.editor.diff_providers, redraw_handle) + .map(|_| { + view.ensure_cursor_in_view(doc, scrolloff); + }) } fn reload_all( @@ -1066,7 +1068,8 @@ fn reload_all( // Every doc is guaranteed to have at least 1 view at this point. let view = view_mut!(cx.editor, view_ids[0]); - doc.reload(view)?; + let redraw_handle = cx.editor.redraw_handle.clone(); + doc.reload(view, &cx.editor.diff_providers, redraw_handle)?; for view_id in view_ids { let view = view_mut!(cx.editor, view_id); diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 7bda74d2..32c8fe91 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -730,7 +730,7 @@ impl EditorView { let mut text = String::with_capacity(8); for gutter_type in view.gutters() { - let gutter = gutter_type.style(editor, doc, view, theme, is_focused); + let mut gutter = gutter_type.style(editor, doc, view, theme, is_focused); let width = gutter_type.width(view, doc); text.reserve(width); // ensure there's enough space for the gutter for (i, line) in (view.offset.row..(last_line + 1)).enumerate() { |