diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs index 487022cf..84704b96 100644 --- a/helix-dap/src/client.rs +++ b/helix-dap/src/client.rs @@ -33,6 +33,9 @@ pub struct Client { request_counter: AtomicU64, capabilities: Option, awaited_events: Arc>>>, + + // + pub breakpoints: HashMap>, } impl Client { @@ -51,6 +54,8 @@ impl Client { request_counter: AtomicU64::new(0), capabilities: None, awaited_events: Arc::new(Mutex::new(HashMap::default())), + // + breakpoints: HashMap::new(), }; tokio::spawn(Self::recv(Arc::clone(&client.awaited_events), server_rx)); diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 59072a09..42b9bcde 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -245,11 +245,7 @@ impl Application { } } - pub async fn handle_debugger_message( - &mut self, - call: (), - server_id: usize, - ) { + pub async fn handle_debugger_message(&mut self, call: ()) { // } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index bcab85c4..ddbf1cb5 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -302,6 +302,7 @@ impl Command { surround_delete, "Surround delete", select_textobject_around, "Select around object", select_textobject_inner, "Select inside object", + toggle_breakpoint, "Toggle breakpoint", suspend, "Suspend" ); } @@ -1913,25 +1914,21 @@ mod cmd { // look up config for filetype // if multiple available, open picker - log::error!("1"); - let client = Client::tcp_process("dlv", vec!["dap"], "-l 127.0.0.1:{}", 0); let mut client = block_on(client)?; - log::error!("2"); let request = client.initialize("go".to_owned()); let _ = block_on(request)?; - log::error!("3"); let mut args = HashMap::new(); args.insert("mode", "debug"); - args.insert("program", "main"); + args.insert("program", "main.go"); let request = client.launch(to_value(args)?); let _ = block_on(request)?; log::error!("4"); - doc.debugger = Some(client); + cx.editor.debugger = Some(client); Ok(()) } @@ -4282,3 +4279,36 @@ fn suspend(_cx: &mut Context) { #[cfg(not(windows))] signal_hook::low_level::raise(signal_hook::consts::signal::SIGTSTP).unwrap(); } + +// DAP +fn toggle_breakpoint(cx: &mut Context) { + let (view, doc) = current!(cx.editor); + let text = doc.text().slice(..); + let pos = doc.selection(view.id).primary().cursor(text); + + let breakpoint = helix_dap::SourceBreakpoint { + line: text.char_to_line(pos), + ..Default::default() + }; + + let path = match doc.path() { + Some(path) => path.to_path_buf(), + None => { + cx.editor + .set_error("Can't set breakpoint: document has no path".to_string()); + return; + } + }; + + // TODO: need to map breakpoints over edits and update them? + // we shouldn't really allow editing while debug is running though + + if let Some(debugger) = &mut cx.editor.debugger { + let breakpoints = debugger.breakpoints.entry(path).or_default(); + if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) { + breakpoints.remove(pos); + } else { + breakpoints.push(breakpoint); + } + } +} diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 57bcb321..05b75c5d 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -485,6 +485,9 @@ impl Default for Keymaps { "s" => symbol_picker, "a" => code_action, "'" => last_picker, + "d" => { "Debug" + "b" => toggle_breakpoint, + }, "w" => { "Window" "C-w" | "w" => rotate_view, "C-h" | "h" => hsplit, diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index b0e6de3e..074f322e 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -71,6 +71,7 @@ impl EditorView { is_focused: bool, loader: &syntax::Loader, config: &helix_view::editor::Config, + debugger: Option<&helix_dap::Client>, ) { let inner = view.inner_area(); let area = view.area; @@ -87,7 +88,9 @@ impl EditorView { }; Self::render_text_highlights(doc, view.offset, inner, surface, theme, highlights); - Self::render_gutter(doc, view, view.area, surface, theme, is_focused, config); + Self::render_gutter( + doc, view, view.area, surface, theme, is_focused, config, debugger, + ); if is_focused { Self::render_focused_view_elements(view, doc, inner, theme, surface); @@ -409,6 +412,7 @@ impl EditorView { theme: &Theme, is_focused: bool, config: &helix_view::editor::Config, + debugger: Option<&helix_dap::Client>, ) { let text = doc.text().slice(..); let last_line = view.last_line(doc); @@ -438,6 +442,10 @@ impl EditorView { .map(|range| range.cursor_line(text)) .collect(); + let breakpoints = doc + .path() + .and_then(|path| debugger.and_then(|debugger| debugger.breakpoints.get(path))); + for (i, line) in (view.offset.row..(last_line + 1)).enumerate() { use helix_core::diagnostic::Severity; if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) { @@ -457,6 +465,14 @@ impl EditorView { let selected = cursors.contains(&line); + if let Some(breakpoint) = breakpoints.and_then(|breakpoints| { + breakpoints + .iter() + .find(|breakpoint| breakpoint.line == line) + }) { + surface.set_stringn(viewport.x, viewport.y + i as u16, "▲", 1, warning); + } + let text = if line == last_line && !draw_last { " ~".into() } else { @@ -1007,6 +1023,7 @@ impl Component for EditorView { for (view, is_focused) in cx.editor.tree.views() { let doc = cx.editor.document(view.doc).unwrap(); let loader = &cx.editor.syn_loader; + let debugger = cx.editor.debugger.as_ref(); self.render_view( doc, view, @@ -1016,6 +1033,7 @@ impl Component for EditorView { is_focused, loader, &cx.editor.config, + debugger, ); } diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 3e8ed21c..ff0c8bf4 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -100,7 +100,6 @@ pub struct Document { diagnostics: Vec, language_server: Option>, - pub debugger: Option, } use std::fmt; @@ -426,7 +425,6 @@ impl Document { history: Cell::new(History::default()), last_saved_revision: 0, language_server: None, - debugger: None, line_ending: DEFAULT_LINE_ENDING, } } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 7b9f34fc..1fae59be 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -73,7 +73,10 @@ pub struct Editor { pub registers: Registers, pub theme: Theme, pub language_servers: helix_lsp::Registry, - pub debuggers: SelectAll>, + + pub debugger: Option, + pub debuggers: SelectAll>, + pub clipboard_provider: Box, pub syn_loader: Arc, @@ -111,6 +114,7 @@ impl Editor { selected_register: RegisterSelection::default(), theme: themes.default(), language_servers, + debugger: None, debuggers: SelectAll::new(), syn_loader: config_loader, theme_loader: themes,