Skip to content

Commit

Permalink
fix(command): write-quit: do not quit if write fails
Browse files Browse the repository at this point in the history
During write-quit, if the file fails to be written for any reason, helix
will still quit without saving the changes. This fixes this behavior by
introducing fallibility to the asynchronous job queues. This will also
benefit all contexts which may depend on these job queues.

Fixes #1575
  • Loading branch information
dead10ck committed Jun 19, 2022
1 parent fac36bc commit 41bf1d5
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 6 deletions.
2 changes: 1 addition & 1 deletion helix-term/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ impl Application {
}

pub async fn close(&mut self) -> anyhow::Result<()> {
self.jobs.finish().await;
self.jobs.finish().await?;

if self.editor.close_language_servers(None).await.is_err() {
log::error!("Timed out waiting for language servers to shutdown");
Expand Down
2 changes: 2 additions & 0 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ fn write_impl(
doc.detect_language(cx.editor.syn_loader.clone());
let _ = cx.editor.refresh_language_server(id);
}

Ok(())
}

Expand Down Expand Up @@ -422,6 +423,7 @@ fn write_quit(
event: PromptEvent,
) -> anyhow::Result<()> {
write_impl(cx, args.first(), false)?;
helix_lsp::block_on(cx.jobs.finish())?;
quit(cx, &[], event)
}

Expand Down
20 changes: 16 additions & 4 deletions helix-term/src/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use helix_view::Editor;

use crate::compositor::Compositor;

use futures_util::future::{self, BoxFuture, Future, FutureExt};
use futures_util::future::{BoxFuture, Future, FutureExt};
use futures_util::stream::{FuturesUnordered, StreamExt};

pub type Callback = Box<dyn FnOnce(&mut Editor, &mut Compositor) + Send>;
Expand Down Expand Up @@ -93,9 +93,21 @@ impl Jobs {
}

/// Blocks until all the jobs that need to be waited on are done.
pub async fn finish(&mut self) {
let wait_futures = std::mem::take(&mut self.wait_futures);
pub async fn finish(&mut self) -> anyhow::Result<()> {
log::debug!("waiting on jobs...");
wait_futures.for_each(|_| future::ready(())).await
let mut wait_futures = std::mem::take(&mut self.wait_futures);
while let (Some(job), tail) = wait_futures.into_future().await {
match job {
Ok(_) => {
wait_futures = tail;
}
Err(e) => {
self.wait_futures = tail;
return Err(e);
}
}
}

Ok(())
}
}
1 change: 0 additions & 1 deletion helix-term/tests/test/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use helix_term::application::Application;
use super::*;

#[tokio::test]
#[ignore]
async fn test_write_quit_fail() -> anyhow::Result<()> {
let file = helpers::new_readonly_tempfile()?;

Expand Down

0 comments on commit 41bf1d5

Please sign in to comment.