on master help sign in
Make dap_start non-blocking
43fbb6dBlaž Hrastnik
helix-dap/src/client.rs+4−8
@@ -288,16 +288,12 @@ impl Client {
288 self.request::<requests::Disconnect>(()).await
288 self.request::<requests::Disconnect>(()).await
289 }
289 }
290
290
291− pub async fn launch(&mut self, args: serde_json::Value) -> Result<Value> {
291+ pub fn launch(&self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
292− let response = self.request::<requests::Launch>(args).await?;
292+ self.call::<requests::Launch>(args)
293− log::error!("launch response {}", response);
294− Ok(response)
295 }
293 }
296
294
297− pub async fn attach(&mut self, args: serde_json::Value) -> Result<Value> {
295+ pub fn attach(&self, args: serde_json::Value) -> impl Future<Output = Result<Value>> {
298− let response = self.request::<requests::Attach>(args).await?;
296+ self.call::<requests::Attach>(args)
299− log::error!("attach response {}", response);
300− Ok(response)
301 }
297 }
302
298
303 pub async fn set_breakpoints(
299 pub async fn set_breakpoints(
helix-term/src/commands.rs+2−5
@@ -2571,8 +2571,7 @@ mod cmd {
2571 0 => None,
2571 0 => None,
2572 _ => Some(args.remove(0)),
2572 _ => Some(args.remove(0)),
2573 };
2573 };
2574− dap_start_impl(&mut cx.editor, name, None, Some(args));
2574+ dap_start_impl(cx, name, None, Some(args))
2575− Ok(())
2576 }
2575 }
2577
2576
2578 fn debug_remote(
2577 fn debug_remote(
@@ -2589,9 +2588,7 @@ mod cmd {
2589 0 => None,
2588 0 => None,
2590 _ => Some(args.remove(0)),
2589 _ => Some(args.remove(0)),
2591 };
2590 };
2592− dap_start_impl(&mut cx.editor, name, address, Some(args));
2591+ dap_start_impl(cx, name, address, Some(args))
2593−
2594− Ok(())
2595 }
2592 }
2596
2593
2597 fn tutor(
2594 fn tutor(
helix-term/src/commands/dap.rs+53−38
@@ -1,7 +1,7 @@
1use super::{align_view, Align, Context, Editor};
1use super::{align_view, Align, Context, Editor};
2use crate::{
2use crate::{
3− compositor::Compositor,
3+ compositor::{self, Compositor},
4− job::Callback,
4+ job::{Callback, Jobs},
5 ui::{self, FilePicker, Picker, Popup, Prompt, PromptEvent, Text},
5 ui::{self, FilePicker, Picker, Popup, Prompt, PromptEvent, Text},
6};
6};
7use helix_core::{
7use helix_core::{
@@ -16,8 +16,11 @@ use serde_json::{to_value, Value};
16use tokio_stream::wrappers::UnboundedReceiverStream;
16use tokio_stream::wrappers::UnboundedReceiverStream;
17
17
18use std::collections::HashMap;
18use std::collections::HashMap;
19+use std::future::Future;
19use std::path::PathBuf;
20use std::path::PathBuf;
20
21
22+use anyhow::bail;
23+
21// general utils:
24// general utils:
22pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Option<usize> {
25pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Option<usize> {
23 // 1-indexing to 0 indexing
26 // 1-indexing to 0 indexing
@@ -174,23 +177,39 @@ fn get_breakpoint_at_current_line(editor: &mut Editor) -> Option<(usize, Breakpo
174
177
175// -- DAP
178// -- DAP
176
179
180+fn dap_callback<T, F>(
181+ jobs: &mut Jobs,
182+ call: impl Future<Output = helix_dap::Result<serde_json::Value>> + 'static + Send,
183+ callback: F,
184+) where
185+ T: for<'de> serde::Deserialize<'de> + Send + 'static,
186+ F: FnOnce(&mut Editor, &mut Compositor, T) + Send + 'static,
187+{
188+ let callback = Box::pin(async move {
189+ let json = call.await?;
190+ let response = serde_json::from_value(json)?;
191+ let call: Callback = Box::new(move |editor: &mut Editor, compositor: &mut Compositor| {
192+ callback(editor, compositor, response)
193+ });
194+ Ok(call)
195+ });
196+ jobs.callback(callback);
197+}
198+
177pub fn dap_start_impl(
199pub fn dap_start_impl(
178− editor: &mut Editor,
200+ cx: &mut compositor::Context,
179 name: Option<&str>,
201 name: Option<&str>,
180 socket: Option<std::net::SocketAddr>,
202 socket: Option<std::net::SocketAddr>,
181 params: Option<Vec<&str>>,
203 params: Option<Vec<&str>>,
182−) {
204+) -> Result<(), anyhow::Error> {
183− let doc = doc!(editor);
205+ let doc = doc!(cx.editor);
184
206
185 let config = match doc
207 let config = match doc
186 .language_config()
208 .language_config()
187 .and_then(|config| config.debugger.as_ref())
209 .and_then(|config| config.debugger.as_ref())
188 {
210 {
189 Some(c) => c,
211 Some(c) => c,
190− None => {
191− editor.set_error("No debug adapter available for language".to_string());
212+ None => bail!("No debug adapter available for language"),
192− return;
193− }
194 };
213 };
195
214
196 let result = match socket {
215 let result = match socket {
@@ -206,16 +225,12 @@ pub fn dap_start_impl(
206
225
207 let (mut debugger, events) = match result {
226 let (mut debugger, events) = match result {
208 Ok(r) => r,
227 Ok(r) => r,
209− Err(e) => {
210− editor.set_error(format!("Failed to start debug session: {}", e));
228+ Err(e) => bail!("Failed to start debug session: {}", e),
211− return;
212− }
213 };
229 };
214
230
215 let request = debugger.initialize(config.name.clone());
231 let request = debugger.initialize(config.name.clone());
216 if let Err(e) = block_on(request) {
232 if let Err(e) = block_on(request) {
217− editor.set_error(format!("Failed to initialize debug adapter: {}", e));
233+ bail!("Failed to initialize debug adapter: {}", e);
218− return;
219 }
234 }
220
235
221 debugger.quirks = config.quirks.clone();
236 debugger.quirks = config.quirks.clone();
@@ -227,10 +242,7 @@ pub fn dap_start_impl(
227 };
242 };
228 let template = match template {
243 let template = match template {
229 Some(template) => template,
244 Some(template) => template,
230− None => {
231− editor.set_error("No debug config with given name".to_string());
245+ None => bail!("No debug config with given name"),
232− return;
233− }
234 };
246 };
235
247
236 let mut args: HashMap<&str, Value> = HashMap::new();
248 let mut args: HashMap<&str, Value> = HashMap::new();
@@ -282,28 +294,29 @@ pub fn dap_start_impl(
282
294
283 let args = to_value(args).unwrap();
295 let args = to_value(args).unwrap();
284
296
285− // problem: this blocks for too long while we get back the startInTerminal REQ
297+ let callback = |_editor: &mut Editor, _compositor: &mut Compositor, _response: Value| {
298+ // if let Err(e) = result {
299+ // editor.set_error(format!("Failed {} target: {}", template.request, e));
300+ // }
301+ };
286
302
287− log::error!("pre start");
288− let result = match &template.request[..] {
303+ match &template.request[..] {
304+ "launch" => {
289− "launch" => block_on(debugger.launch(args)),
305+ let call = debugger.launch(args);
306+ dap_callback(cx.jobs, call, callback);
307+ }
308+ "attach" => {
290− "attach" => block_on(debugger.attach(args)),
309+ let call = debugger.attach(args);
291− _ => {
310+ dap_callback(cx.jobs, call, callback);
292− editor.set_error("Unsupported request".to_string());
293− return;
294 }
311 }
312+ request => bail!("Unsupported request '{}'", request),
295 };
313 };
296− log::error!("post start");
297− if let Err(e) = result {
298− let msg = format!("Failed {} target: {}", template.request, e);
299− editor.set_error(msg);
300− return;
301− }
302
314
303 // TODO: either await "initialized" or buffer commands until event is received
315 // TODO: either await "initialized" or buffer commands until event is received
304− editor.debugger = Some(debugger);
316+ cx.editor.debugger = Some(debugger);
305 let stream = UnboundedReceiverStream::new(events);
317 let stream = UnboundedReceiverStream::new(events);
306− editor.debugger_events.push(stream);
318+ cx.editor.debugger_events.push(stream);
319+ Ok(())
307}
320}
308
321
309pub fn dap_launch(cx: &mut Context) {
322pub fn dap_launch(cx: &mut Context) {
@@ -404,12 +417,14 @@ fn debug_parameter_prompt(
404 });
417 });
405 cx.jobs.callback(callback);
418 cx.jobs.callback(callback);
406 } else {
419 } else {
407− dap_start_impl(
420+ if let Err(e) = dap_start_impl(
408− cx.editor,
421+ cx,
409 Some(&config_name),
422 Some(&config_name),
410 None,
423 None,
411 Some(params.iter().map(|x| x.as_str()).collect()),
424 Some(params.iter().map(|x| x.as_str()).collect()),
412− );
425+ ) {
426+ cx.editor.set_error(e.to_string());
427+ }
413 }
428 }
414 },
429 },
415 )
430 )