diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs index 9598e24e..651bf4d6 100644 --- a/helix-dap/src/client.rs +++ b/helix-dap/src/client.rs @@ -209,7 +209,7 @@ impl Client { } /// Execute a RPC request on the debugger. - fn call( + pub fn call( &self, arguments: R::Arguments, ) -> impl Future> @@ -248,7 +248,7 @@ impl Client { } } - async fn request(&self, params: R::Arguments) -> Result + pub async fn request(&self, params: R::Arguments) -> Result where R::Arguments: serde::Serialize, R::Result: core::fmt::Debug, // TODO: temporary @@ -384,9 +384,8 @@ impl Client { Ok((response.stack_frames, response.total_frames)) } - pub async fn threads(&self) -> Result> { - let response = self.request::(()).await?; - Ok(response.threads) + pub fn threads(&self) -> impl Future> { + self.call::(()) } pub async fn scopes(&self, frame_id: usize) -> Result> { diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index c2daaa6b..55e4bb03 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -340,8 +340,8 @@ impl Application { let all_threads_stopped = all_threads_stopped.unwrap_or_default(); if all_threads_stopped { - if let Ok(threads) = debugger.threads().await { - for thread in threads { + if let Ok(response) = debugger.request::(()).await { + for thread in response.threads { fetch_stack_trace(debugger, thread.id).await; } select_thread_id( diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs index d256e5c4..336ccf1a 100644 --- a/helix-term/src/commands/dap.rs +++ b/helix-term/src/commands/dap.rs @@ -19,7 +19,7 @@ use std::collections::HashMap; use std::future::Future; use std::path::PathBuf; -use anyhow::bail; +use anyhow::{anyhow, bail}; // general utils: pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Option { @@ -99,53 +99,61 @@ pub fn jump_to_stack_frame(editor: &mut Editor, frame: &helix_dap::StackFrame) { align_view(doc, view, Align::Center); } -fn thread_picker(cx: &mut Context, callback_fn: impl Fn(&mut Editor, &dap::Thread) + 'static) { +fn thread_picker( + cx: &mut Context, + callback_fn: impl Fn(&mut Editor, &dap::Thread) + Send + 'static, +) { let debugger = match &mut cx.editor.debugger { Some(debugger) => debugger, None => return, }; - let threads = match block_on(debugger.threads()) { - Ok(threads) => threads, - Err(e) => { - cx.editor - .set_error(format!("Failed to retrieve threads: {}", e)); - return; - } - }; - - if threads.len() == 1 { - callback_fn(cx.editor, &threads[0]); - return; - } + let future = debugger.threads(); + dap_callback( + cx.jobs, + future, + move |editor: &mut Editor, + compositor: &mut Compositor, + response: dap::requests::ThreadsResponse| { + let threads = response.threads; + if threads.len() == 1 { + callback_fn(editor, &threads[0]); + return; + } + let debugger = match &mut editor.debugger { + Some(debugger) => debugger, + None => return, + }; - let thread_states = debugger.thread_states.clone(); - let picker = FilePicker::new( - threads, - move |thread| { - format!( - "{} ({})", - thread.name, - thread_states - .get(&thread.id) - .map(|state| state.as_str()) - .unwrap_or("unknown") - ) - .into() - }, - move |cx, thread, _action| callback_fn(cx.editor, thread), - move |editor, thread| { - let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?; - let frame = frames.get(0)?; - let path = frame.source.as_ref()?.path.clone()?; - let pos = Some(( - frame.line.saturating_sub(1), - frame.end_line.unwrap_or(frame.line).saturating_sub(1), - )); - Some((path, pos)) + let thread_states = debugger.thread_states.clone(); + let picker = FilePicker::new( + threads, + move |thread| { + format!( + "{} ({})", + thread.name, + thread_states + .get(&thread.id) + .map(|state| state.as_str()) + .unwrap_or("unknown") + ) + .into() + }, + move |cx, thread, _action| callback_fn(cx.editor, thread), + move |editor, thread| { + let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?; + let frame = frames.get(0)?; + let path = frame.source.as_ref()?.path.clone()?; + let pos = Some(( + frame.line.saturating_sub(1), + frame.end_line.unwrap_or(frame.line).saturating_sub(1), + )); + Some((path, pos)) + }, + ); + compositor.push(Box::new(picker)); }, ); - cx.push_layer(Box::new(picker)) } fn get_breakpoint_at_current_line(editor: &mut Editor) -> Option<(usize, Breakpoint)> {