on master help sign in
dap: Remap keys, match current thread behavior from dap-mode, switch-thread
986828eBlaž Hrastnik
helix-dap/src/client.rs+2−2
@@ -31,7 +31,7 @@ pub struct Client {
31 pub breakpoints: HashMap<PathBuf, Vec<SourceBreakpoint>>,
31 pub breakpoints: HashMap<PathBuf, Vec<SourceBreakpoint>>,
32 // TODO: multiple threads support
32 // TODO: multiple threads support
33 pub stack_pointer: Option<StackFrame>,
33 pub stack_pointer: Option<StackFrame>,
34− pub stopped_thread: Option<usize>,
34+ pub thread_id: Option<usize>,
35 pub is_running: bool,
35 pub is_running: bool,
36}
36}
37
37
@@ -77,7 +77,7 @@ impl Client {
77 //
77 //
78 breakpoints: HashMap::new(),
78 breakpoints: HashMap::new(),
79 stack_pointer: None,
79 stack_pointer: None,
80− stopped_thread: None,
80+ thread_id: None,
81 is_running: false,
81 is_running: false,
82 };
82 };
83
83
helix-term/src/application.rs+6−13
@@ -1,4 +1,4 @@
1−use helix_core::{merge_toml_values, syntax, Range, Selection};
1+use helix_core::{merge_toml_values, syntax, Selection};
2use helix_dap::Payload;
2use helix_dap::Payload;
3use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap};
3use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap};
4use helix_view::{theme, Editor};
4use helix_view::{theme, Editor};
@@ -280,19 +280,13 @@ impl Application {
280 ..
280 ..
281 }) => {
281 }) => {
282 debugger.is_running = false;
282 debugger.is_running = false;
283− let main = debugger.threads().await.ok().and_then(|threads| {
284− // Workaround for debugging Go tests. Main thread has * in beginning of its name
285− let mut main = threads.iter().find(|t| t.name.starts_with('*')).cloned();
286− if main.is_none() {
287− main = threads.get(0).cloned();
288− }
289− main
290− });
291
283
284+ // whichever thread stops is made "current".
285+ debugger.thread_id = thread_id;
286+
292− if let Some(main) = main {
287+ if let Some(thread_id) = thread_id {
293− let (bt, _) = debugger.stack_trace(main.id).await.unwrap();
288+ let (bt, _) = debugger.stack_trace(thread_id).await.unwrap();
294 debugger.stack_pointer = bt.get(0).cloned();
289 debugger.stack_pointer = bt.get(0).cloned();
295− debugger.stopped_thread = Some(main.id);
296 }
290 }
297
291
298 let scope = match thread_id {
292 let scope = match thread_id {
@@ -379,7 +373,6 @@ impl Application {
379 .set_status("Debugged application started".to_owned());
373 .set_status("Debugged application started".to_owned());
380 }
374 }
381 Event::Continued(_) => {
375 Event::Continued(_) => {
382− debugger.stopped_thread = None;
383 debugger.stack_pointer = None;
376 debugger.stack_pointer = None;
384 debugger.is_running = true;
377 debugger.is_running = true;
385 }
378 }
helix-term/src/commands.rs+1
@@ -316,6 +316,7 @@ impl Command {
316 dap_next, "Step to next",
316 dap_next, "Step to next",
317 dap_variables, "List variables",
317 dap_variables, "List variables",
318 dap_terminate, "End debug session",
318 dap_terminate, "End debug session",
319+ dap_switch_thread, "Switch current thread",
319 suspend, "Suspend"
320 suspend, "Suspend"
320 );
321 );
321}
322}
helix-term/src/commands/dap.rs+32−4
@@ -1,4 +1,5 @@
1use super::{Context, Editor};
1use super::{Context, Editor};
2+use crate::ui::Picker;
2use helix_dap::Client;
3use helix_dap::Client;
3use helix_lsp::block_on;
4use helix_lsp::block_on;
4
5
@@ -221,7 +222,7 @@ pub fn dap_continue(cx: &mut Context) {
221 return;
222 return;
222 }
223 }
223
224
224− let request = debugger.continue_thread(debugger.stopped_thread.unwrap());
225+ let request = debugger.continue_thread(debugger.thread_id.unwrap());
225 if let Err(e) = block_on(request) {
226 if let Err(e) = block_on(request) {
226 cx.editor.set_error(format!("Failed to continue: {:?}", e));
227 cx.editor.set_error(format!("Failed to continue: {:?}", e));
227 return;
228 return;
@@ -254,7 +255,7 @@ pub fn dap_step_in(cx: &mut Context) {
254 return;
255 return;
255 }
256 }
256
257
257− let request = debugger.step_in(debugger.stopped_thread.unwrap());
258+ let request = debugger.step_in(debugger.thread_id.unwrap());
258 if let Err(e) = block_on(request) {
259 if let Err(e) = block_on(request) {
259 cx.editor.set_error(format!("Failed to step: {:?}", e));
260 cx.editor.set_error(format!("Failed to step: {:?}", e));
260 }
261 }
@@ -269,7 +270,7 @@ pub fn dap_step_out(cx: &mut Context) {
269 return;
270 return;
270 }
271 }
271
272
272− let request = debugger.step_out(debugger.stopped_thread.unwrap());
273+ let request = debugger.step_out(debugger.thread_id.unwrap());
273 if let Err(e) = block_on(request) {
274 if let Err(e) = block_on(request) {
274 cx.editor.set_error(format!("Failed to step: {:?}", e));
275 cx.editor.set_error(format!("Failed to step: {:?}", e));
275 }
276 }
@@ -284,7 +285,7 @@ pub fn dap_next(cx: &mut Context) {
284 return;
285 return;
285 }
286 }
286
287
287− let request = debugger.next(debugger.stopped_thread.unwrap());
288+ let request = debugger.next(debugger.thread_id.unwrap());
288 if let Err(e) = block_on(request) {
289 if let Err(e) = block_on(request) {
289 cx.editor.set_error(format!("Failed to step: {:?}", e));
290 cx.editor.set_error(format!("Failed to step: {:?}", e));
290 }
291 }
@@ -347,3 +348,30 @@ pub fn dap_terminate(cx: &mut Context) {
347 cx.editor.debugger = None;
348 cx.editor.debugger = None;
348 }
349 }
349}
350}
351+
352+pub fn dap_switch_thread(cx: &mut Context) {
353+ if let Some(debugger) = &mut cx.editor.debugger {
354+ let request = debugger.threads();
355+ let threads = match block_on(request) {
356+ Ok(threads) => threads,
357+ Err(e) => {
358+ cx.editor
359+ .set_error(format!("Failed to retrieve threads: {:?}", e));
360+ return;
361+ }
362+ };
363+
364+ let picker = Picker::new(
365+ true,
366+ threads,
367+ |thread| thread.name.clone().into(),
368+ |editor, thread, _action| {
369+ if let Some(debugger) = &mut editor.debugger {
370+ debugger.thread_id = Some(thread.id);
371+ // TODO: probably need to refetch stack frames?
372+ }
373+ },
374+ );
375+ cx.push_layer(Box::new(picker))
376+ }
377+}
helix-term/src/keymap.rs+9−4
@@ -486,16 +486,21 @@ impl Default for Keymaps {
486 "a" => code_action,
486 "a" => code_action,
487 "'" => last_picker,
487 "'" => last_picker,
488 "d" => { "Debug"
488 "d" => { "Debug"
489− "s" => dap_launch,
489+ "l" => dap_launch,
490 "b" => dap_toggle_breakpoint,
490 "b" => dap_toggle_breakpoint,
491 "r" => dap_run,
491 "r" => dap_run,
492 "c" => dap_continue,
492 "c" => dap_continue,
493 "h" => dap_pause,
493 "h" => dap_pause,
494− "j" => dap_step_in,
494+ "i" => dap_step_in,
495− "k" => dap_step_out,
495+ "o" => dap_step_out,
496− "l" => dap_next,
496+ "n" => dap_next,
497 "v" => dap_variables,
497 "v" => dap_variables,
498 "t" => dap_terminate,
498 "t" => dap_terminate,
499+ "s" => { "Switch"
500+ "t" => dap_switch_thread,
501+ // f = stack frame
502+ // sl, sb
503+ },
499 },
504 },
500 "w" => { "Window"
505 "w" => { "Window"
501 "C-w" | "w" => rotate_view,
506 "C-w" | "w" => rotate_view,