diff options
Diffstat (limited to 'helix-term/src/commands')
-rw-r--r-- | helix-term/src/commands/dap.rs | 102 |
1 files changed, 85 insertions, 17 deletions
diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs index 66127360..a1558dde 100644 --- a/helix-term/src/commands/dap.rs +++ b/helix-term/src/commands/dap.rs @@ -1,5 +1,6 @@ -use super::{Context, Editor}; +use super::{align_view, Align, Context, Editor}; use crate::ui::Picker; +use helix_core::Selection; use helix_dap::Client; use helix_lsp::block_on; @@ -8,6 +9,68 @@ use tokio_stream::wrappers::UnboundedReceiverStream; use std::collections::HashMap; +// general utils: +pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Option<usize> { + // 1-indexing to 0 indexing + let line = doc.try_line_to_char(line - 1).ok()?; + let pos = line + column; + // TODO: this is probably utf-16 offsets + Some(pos) +} + +pub async fn select_thread_id(editor: &mut Editor, thread_id: usize, force: bool) { + let debugger = match &mut editor.debugger { + Some(debugger) => debugger, + None => return, + }; + + if !force && debugger.thread_id.is_some() { + return; + } + + debugger.thread_id = Some(thread_id); + + // fetch stack trace + // TODO: handle requesting more total frames + let (frames, _) = debugger.stack_trace(thread_id).await.unwrap(); + debugger.stack_frames.insert(thread_id, frames); + debugger.active_frame = Some(0); // TODO: check how to determine this + + let frame = debugger.stack_frames[&thread_id].get(0).cloned(); + if let Some(frame) = &frame { + jump_to_stack_frame(editor, frame); + } +} + +pub fn jump_to_stack_frame(editor: &mut Editor, frame: &helix_dap::StackFrame) { + let path = if let Some(helix_dap::Source { + path: Some(ref path), + .. + }) = frame.source + { + path.clone() + } else { + return; + }; + + editor + .open(path, helix_view::editor::Action::Replace) + .unwrap(); // TODO: there should be no unwrapping! + + let (view, doc) = current!(editor); + + let text_end = doc.text().len_chars().saturating_sub(1); + let start = dap_pos_to_pos(doc.text(), frame.line, frame.column).unwrap_or(0); + let end = frame + .end_line + .and_then(|end_line| dap_pos_to_pos(doc.text(), end_line, frame.end_column.unwrap_or(0))) + .unwrap_or(start); + + let selection = Selection::single(start.min(text_end), end.min(text_end)); + doc.set_selection(view.id, selection); + align_view(doc, view, Align::Center); +} + // DAP pub fn dap_start_impl( editor: &mut Editor, @@ -222,13 +285,18 @@ pub fn dap_continue(cx: &mut Context) { return; } - let request = debugger.continue_thread(debugger.thread_id.unwrap()); - if let Err(e) = block_on(request) { - cx.editor.set_error(format!("Failed to continue: {:?}", e)); - return; + if let Some(thread_id) = debugger.thread_id { + let request = debugger.continue_thread(debugger.thread_id.unwrap()); + if let Err(e) = block_on(request) { + cx.editor.set_error(format!("Failed to continue: {:?}", e)); + return; + } + debugger.is_running = true; + debugger.stack_frames.remove(&thread_id); + } else { + cx.editor + .set_error("Currently active thread is not stopped. Switch the thread.".into()); } - debugger.is_running = true; - debugger.stack_pointer = None; } } @@ -299,13 +367,16 @@ pub fn dap_variables(cx: &mut Context) { .set_status("Cannot access variables while target is running".to_owned()); return; } - if debugger.stack_pointer.is_none() { - cx.editor - .set_status("Cannot find current stack pointer to access variables".to_owned()); - return; - } + let (frame, thread_id) = match (debugger.active_frame, debugger.thread_id) { + (Some(frame), Some(thread_id)) => (frame, thread_id), + _ => { + cx.editor + .set_status("Cannot find current stack frame to access variables".to_owned()); + return; + } + }; - let frame_id = debugger.stack_pointer.clone().unwrap().id; + let frame_id = debugger.stack_frames[&thread_id][frame].id; let scopes = match block_on(debugger.scopes(frame_id)) { Ok(s) => s, Err(e) => { @@ -366,10 +437,7 @@ pub fn dap_switch_thread(cx: &mut Context) { threads, |thread| thread.name.clone().into(), |editor, thread, _action| { - if let Some(debugger) = &mut editor.debugger { - debugger.thread_id = Some(thread.id); - // TODO: probably need to refetch stack frames? - } + block_on(select_thread_id(editor, thread.id, true)); }, ); cx.push_layer(Box::new(picker)) |