@@ -35,8 +35,8 @@ use crate::{
3535 ui::{self, Completion, Picker, Popup, Prompt, PromptEvent},
3636};
3737
38−use crate::application::{LspCallback, LspCallbackWrapper, LspCallbacks};
39−use futures_util::FutureExt;
38+use crate::job::{self, Job, JobFuture, Jobs};
39+use futures_util::{FutureExt, TryFutureExt};
4040use std::{fmt, future::Future, path::Display, str::FromStr};
4141
4242use std::{
@@ -54,7 +54,7 @@ pub struct Context<'a> {
5454
5555 pub callback: Option<crate::compositor::Callback>,
5656 pub on_next_key_callback: Option<Box<dyn FnOnce(&mut Context, KeyEvent)>>,
57− pub callbacks: &'a mut LspCallbacks,
57+ pub jobs: &'a mut Jobs,
5858}
5959
6060impl<'a> Context<'a> {
@@ -85,13 +85,13 @@ impl<'a> Context<'a> {
8585 let callback = Box::pin(async move {
8686 let json = call.await?;
8787 let response = serde_json::from_value(json)?;
88− let call: LspCallbackWrapper =
88+ let call: job::Callback =
8989 Box::new(move |editor: &mut Editor, compositor: &mut Compositor| {
9090 callback(editor, compositor, response)
9191 });
9292 Ok(call)
9393 });
94− self.callbacks.push(callback);
94+ self.jobs.callback(callback);
9595 }
9696
9797 /// Returns 1 if no explicit count was provided
@@ -1149,7 +1149,7 @@ mod cmd {
11491149 path: Option<P>,
11501150 ) -> Result<tokio::task::JoinHandle<Result<(), anyhow::Error>>, anyhow::Error> {
11511151 use anyhow::anyhow;
1152− let callbacks = &mut cx.callbacks;
1152+ let jobs = &mut cx.jobs;
11531153 let (view, doc) = current!(cx.editor);
11541154
11551155 if let Some(path) = path {
@@ -1168,7 +1168,7 @@ mod cmd {
11681168 doc.format().map(|fmt| {
11691169 let shared = fmt.shared();
11701170 let callback = make_format_callback(doc.id(), doc.version(), true, shared.clone());
1171− callbacks.push(callback);
1171+ jobs.callback(callback);
11721172 shared
11731173 })
11741174 } else {
@@ -1178,8 +1178,12 @@ mod cmd {
11781178 }
11791179
11801180 fn write(cx: &mut compositor::Context, args: &[&str], event: PromptEvent) {
1181− if let Err(e) = write_impl(cx, args.first()) {
1182− cx.editor.set_error(e.to_string());
1181+ match write_impl(cx, args.first()) {
1182+ Err(e) => cx.editor.set_error(e.to_string()),
1183+ Ok(handle) => {
1184+ cx.jobs
1185+ .add(Job::new(handle.unwrap_or_else(|e| Err(e.into()))).wait_before_exiting());
1186+ }
11831187 };
11841188 }
11851189
@@ -1192,7 +1196,7 @@ mod cmd {
11921196
11931197 if let Some(format) = doc.format() {
11941198 let callback = make_format_callback(doc.id(), doc.version(), false, format);
1195− cx.callbacks.push(callback);
1199+ cx.jobs.callback(callback);
11961200 }
11971201 }
11981202
@@ -1918,10 +1922,10 @@ fn make_format_callback(
19181922 doc_version: i32,
19191923 set_unmodified: bool,
19201924 format: impl Future<Output = helix_lsp::util::LspFormatting> + Send + 'static,
1921−) -> LspCallback {
1922− Box::pin(async move {
1925+) -> impl Future<Output = anyhow::Result<job::Callback>> {
1926+ async move {
19231927 let format = format.await;
1924− let call: LspCallbackWrapper =
1928+ let call: job::Callback =
19251929 Box::new(move |editor: &mut Editor, compositor: &mut Compositor| {
19261930 let view_id = view!(editor).id;
19271931 if let Some(doc) = editor.document_mut(doc_id) {
@@ -1937,7 +1941,7 @@ fn make_format_callback(
19371941 }
19381942 });
19391943 Ok(call)
1940− })
1944+ }
19411945}
19421946
19431947enum Open {