summaryrefslogtreecommitdiff
path: root/helix-term/src
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src')
-rw-r--r--helix-term/src/application.rs50
-rw-r--r--helix-term/src/commands/typed.rs11
-rw-r--r--helix-term/src/ui/editor.rs2
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() {