@@ -19,7 +19,7 @@ use std::collections::HashMap;
19use std::future::Future;
19use std::future::Future;
20use std::path::PathBuf;
20use std::path::PathBuf;
22−use anyhow::bail;
22+use anyhow::{anyhow, bail};
24// general utils:
24// general utils:
25pub 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> {
@@ -99,53 +99,61 @@ pub fn jump_to_stack_frame(editor: &mut Editor, frame: &helix_dap::StackFrame) {
99 align_view(doc, view, Align::Center);
99 align_view(doc, view, Align::Center);
102−fn thread_picker(cx: &mut Context, callback_fn: impl Fn(&mut Editor, &dap::Thread) + 'static) {
104+ callback_fn: impl Fn(&mut Editor, &dap::Thread) + Send + 'static,
103 let debugger = match &mut cx.editor.debugger {
106 let debugger = match &mut cx.editor.debugger {
104 Some(debugger) => debugger,
107 Some(debugger) => debugger,
105 None => return,
108 None => return,
108− let threads = match block_on(debugger.threads()) {
111+ let future = debugger.threads();
109− Ok(threads) => threads,
112+ dap_callback(
110− Err(e) => {
113+ cx.jobs,
111− cx.editor
114+ future,
112− .set_error(format!("Failed to retrieve threads: {}", e));
115+ move |editor: &mut Editor,
113− return;
116+ compositor: &mut Compositor,
114− }
117+ response: dap::requests::ThreadsResponse| {
115− };
118+ let threads = response.threads;
117− if threads.len() == 1 {
119+ if threads.len() == 1 {
118− callback_fn(cx.editor, &threads[0]);
120+ callback_fn(editor, &threads[0]);
123+ let debugger = match &mut editor.debugger {
124+ Some(debugger) => debugger,
122− let thread_states = debugger.thread_states.clone();
128+ let thread_states = debugger.thread_states.clone();
123− let picker = FilePicker::new(
129+ let picker = FilePicker::new(
124− threads,
130+ threads,
125− move |thread| {
131+ move |thread| {
126− format!(
132+ format!(
127− "{} ({})",
133+ "{} ({})",
128− thread.name,
134+ thread.name,
129− thread_states
135+ thread_states
130− .get(&thread.id)
136+ .get(&thread.id)
131− .map(|state| state.as_str())
137+ .map(|state| state.as_str())
132− .unwrap_or("unknown")
138+ .unwrap_or("unknown")
136− move |cx, thread, _action| callback_fn(cx.editor, thread),
142+ move |cx, thread, _action| callback_fn(cx.editor, thread),
137− move |editor, thread| {
143+ move |editor, thread| {
138− let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?;
144+ let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?;
139− let frame = frames.get(0)?;
145+ let frame = frames.get(0)?;
140− let path = frame.source.as_ref()?.path.clone()?;
146+ let path = frame.source.as_ref()?.path.clone()?;
141− let pos = Some((
147+ let pos = Some((
142− frame.line.saturating_sub(1),
148+ frame.line.saturating_sub(1),
143− frame.end_line.unwrap_or(frame.line).saturating_sub(1),
149+ frame.end_line.unwrap_or(frame.line).saturating_sub(1),
145− Some((path, pos))
151+ Some((path, pos))
154+ compositor.push(Box::new(picker));
148− cx.push_layer(Box::new(picker))
151fn get_breakpoint_at_current_line(editor: &mut Editor) -> Option<(usize, Breakpoint)> {
159fn get_breakpoint_at_current_line(editor: &mut Editor) -> Option<(usize, Breakpoint)> {