diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 62200d76..5eb51965 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -304,6 +304,7 @@ impl Command { surround_delete, "Surround delete", select_textobject_around, "Select around object", select_textobject_inner, "Select inside object", + dap_launch, "Launch debug target", dap_toggle_breakpoint, "Toggle breakpoint", dap_run, "Begin program execution", dap_continue, "Continue program execution", @@ -4491,7 +4492,7 @@ fn suspend(_cx: &mut Context) { } // DAP -fn dap_start_impl( +pub fn dap_start_impl( editor: &mut Editor, name: Option<&str>, socket: Option, @@ -4596,6 +4597,41 @@ fn dap_start_impl( editor.debugger_events.push(stream); } +fn dap_launch(cx: &mut Context) { + if cx.editor.debugger.is_some() { + cx.editor + .set_error("Can't start debug: debugger is running".to_string()); + return; + } + + let (_, doc) = current!(cx.editor); + let path = match doc.path() { + Some(path) => path.to_path_buf(), + None => { + cx.editor + .set_error("Can't start debug: document has no path".to_string()); + return; + } + }; + + let config = cx + .editor + .syn_loader + .language_config_for_file_name(&path) + .and_then(|x| x.debugger.clone()); + let config = match config { + Some(c) => c, + None => { + cx.editor.set_error( + "Can't start debug: no debug adapter available for language".to_string(), + ); + return; + } + }; + + cx.editor.debug_config_picker = Some(config.templates.iter().map(|t| t.name.clone()).collect()); +} + fn dap_toggle_breakpoint(cx: &mut Context) { use helix_lsp::block_on; diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 02b5f25c..d16c9a3a 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -486,6 +486,7 @@ impl Default for Keymaps { "a" => code_action, "'" => last_picker, "d" => { "Debug" + "s" => dap_launch, "b" => dap_toggle_breakpoint, "r" => dap_run, "c" => dap_continue, diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 04cee3db..1f4fc1c5 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -30,6 +30,8 @@ use std::borrow::Cow; use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind}; use tui::buffer::Buffer as Surface; +use super::{Prompt, PromptEvent}; + pub struct EditorView { keymaps: Keymaps, on_next_key: Option>, @@ -712,6 +714,45 @@ impl EditorView { ) -> Option { self.autoinfo = None; + if let Some(picker) = cxt.editor.debug_config_picker.clone() { + match event { + KeyEvent { + code: KeyCode::Esc, .. + } => {} + KeyEvent { + code: KeyCode::Char(char), + .. + } => { + let name = match picker.iter().find(|t| t.starts_with(char)) { + Some(n) => n.clone(), + None => return None, + }; + let prompt = Prompt::new( + "arg:".to_owned(), + None, + |_input: &str| Vec::new(), // this is fine because Vec::new() doesn't allocate + move |cx: &mut crate::compositor::Context, + input: &str, + event: PromptEvent| { + if event != PromptEvent::Validate { + return; + } + commands::dap_start_impl( + cx.editor, + Some(&name), + None, + Some(vec![input]), + ); + }, + ); + cxt.push_layer(Box::new(prompt)); + } + _ => return None, + } + cxt.editor.debug_config_picker = None; + return None; + } + if cxt.editor.variables.is_some() { match event { KeyEvent { @@ -735,6 +776,7 @@ impl EditorView { } return None; } + match self.keymaps.get_mut(&mode).unwrap().get(event) { KeymapResult::Matched(command) => command.execute(cxt), KeymapResult::Pending(node) => self.autoinfo = Some(node.into()), @@ -1137,6 +1179,26 @@ impl Component for EditorView { info.render(area, surface, cx); } + if let Some(ref configs) = cx.editor.debug_config_picker { + let mut text = String::new(); + let mut height = 0; + let mut max_len = 20; + + for line in configs { + max_len = max_len.max(line.len() as u16 + 2); + height += 1; + text.push_str(&format!("{} {}\n", line.chars().next().unwrap(), line)); + } + + let mut info = Info { + height: 20.min(height + 1), + width: 70.min(max_len), + title: "Debug targets".to_owned(), + text: text + "Exit Esc", + }; + info.render(area, surface, cx); + } + if let Some(ref mut info) = self.autoinfo { info.render(area, surface, cx); } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index faaa5c3a..c1b9cf1a 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -76,6 +76,7 @@ pub struct Editor { pub debugger: Option, pub debugger_events: SelectAll>, + pub debug_config_picker: Option>, pub variables: Option>, pub variables_page: usize, @@ -118,6 +119,7 @@ impl Editor { language_servers, debugger: None, debugger_events: SelectAll::new(), + debug_config_picker: None, variables: None, variables_page: 0, syn_loader: config_loader,