on master help sign in
New way of starting debug sessions
commit8df6739759396b45d06356dd78c39117590b062b authorDmitry Sharshakov <d3dx12.xx@gmail.com> dateSat 28 Aug 2021, 14:23 (5 years ago) parent5e4da09
4 files changed+102−1
helix-term/src/commands.rs+37−1 helix-term/src/keymap.rs+1 helix-term/src/ui/editor.rs+62 helix-view/src/editor.rs+2
helix-term/src/commands.rs+37−1
@@ -304,6 +304,7 @@ impl Command {
304304 surround_delete, "Surround delete",
305305 select_textobject_around, "Select around object",
306306 select_textobject_inner, "Select inside object",
307+ dap_launch, "Launch debug target",
307308 dap_toggle_breakpoint, "Toggle breakpoint",
308309 dap_run, "Begin program execution",
309310 dap_continue, "Continue program execution",
@@ -4491,7 +4492,7 @@ fn suspend(_cx: &mut Context) {
44914492}
44924493
44934494// DAP
4494−fn dap_start_impl(
4495+pub fn dap_start_impl(
44954496 editor: &mut Editor,
44964497 name: Option<&str>,
44974498 socket: Option<std::net::SocketAddr>,
@@ -4596,6 +4597,41 @@ fn dap_start_impl(
45964597 editor.debugger_events.push(stream);
45974598}
45984599
4600+fn dap_launch(cx: &mut Context) {
4601+ if cx.editor.debugger.is_some() {
4602+ cx.editor
4603+ .set_error("Can't start debug: debugger is running".to_string());
4604+ return;
4605+ }
4606+
4607+ let (_, doc) = current!(cx.editor);
4608+ let path = match doc.path() {
4609+ Some(path) => path.to_path_buf(),
4610+ None => {
4611+ cx.editor
4612+ .set_error("Can't start debug: document has no path".to_string());
4613+ return;
4614+ }
4615+ };
4616+
4617+ let config = cx
4618+ .editor
4619+ .syn_loader
4620+ .language_config_for_file_name(&path)
4621+ .and_then(|x| x.debugger.clone());
4622+ let config = match config {
4623+ Some(c) => c,
4624+ None => {
4625+ cx.editor.set_error(
4626+ "Can't start debug: no debug adapter available for language".to_string(),
4627+ );
4628+ return;
4629+ }
4630+ };
4631+
4632+ cx.editor.debug_config_picker = Some(config.templates.iter().map(|t| t.name.clone()).collect());
4633+}
4634+
45994635fn dap_toggle_breakpoint(cx: &mut Context) {
46004636 use helix_lsp::block_on;
46014637
helix-term/src/keymap.rs+1
@@ -486,6 +486,7 @@ impl Default for Keymaps {
486486 "a" => code_action,
487487 "'" => last_picker,
488488 "d" => { "Debug"
489+ "s" => dap_launch,
489490 "b" => dap_toggle_breakpoint,
490491 "r" => dap_run,
491492 "c" => dap_continue,
helix-term/src/ui/editor.rs+62
@@ -30,6 +30,8 @@ use std::borrow::Cow;
3030use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind};
3131use tui::buffer::Buffer as Surface;
3232
33+use super::{Prompt, PromptEvent};
34+
3335pub struct EditorView {
3436 keymaps: Keymaps,
3537 on_next_key: Option<Box<dyn FnOnce(&mut commands::Context, KeyEvent)>>,
@@ -712,6 +714,45 @@ impl EditorView {
712714 ) -> Option<KeymapResult> {
713715 self.autoinfo = None;
714716
717+ if let Some(picker) = cxt.editor.debug_config_picker.clone() {
718+ match event {
719+ KeyEvent {
720+ code: KeyCode::Esc, ..
721+ } => {}
722+ KeyEvent {
723+ code: KeyCode::Char(char),
724+ ..
725+ } => {
726+ let name = match picker.iter().find(|t| t.starts_with(char)) {
727+ Some(n) => n.clone(),
728+ None => return None,
729+ };
730+ let prompt = Prompt::new(
731+ "arg:".to_owned(),
732+ None,
733+ |_input: &str| Vec::new(), // this is fine because Vec::new() doesn't allocate
734+ move |cx: &mut crate::compositor::Context,
735+ input: &str,
736+ event: PromptEvent| {
737+ if event != PromptEvent::Validate {
738+ return;
739+ }
740+ commands::dap_start_impl(
741+ cx.editor,
742+ Some(&name),
743+ None,
744+ Some(vec![input]),
745+ );
746+ },
747+ );
748+ cxt.push_layer(Box::new(prompt));
749+ }
750+ _ => return None,
751+ }
752+ cxt.editor.debug_config_picker = None;
753+ return None;
754+ }
755+
715756 if cxt.editor.variables.is_some() {
716757 match event {
717758 KeyEvent {
@@ -735,6 +776,7 @@ impl EditorView {
735776 }
736777 return None;
737778 }
779+
738780 match self.keymaps.get_mut(&mode).unwrap().get(event) {
739781 KeymapResult::Matched(command) => command.execute(cxt),
740782 KeymapResult::Pending(node) => self.autoinfo = Some(node.into()),
@@ -1137,6 +1179,26 @@ impl Component for EditorView {
11371179 info.render(area, surface, cx);
11381180 }
11391181
1182+ if let Some(ref configs) = cx.editor.debug_config_picker {
1183+ let mut text = String::new();
1184+ let mut height = 0;
1185+ let mut max_len = 20;
1186+
1187+ for line in configs {
1188+ max_len = max_len.max(line.len() as u16 + 2);
1189+ height += 1;
1190+ text.push_str(&format!("{} {}\n", line.chars().next().unwrap(), line));
1191+ }
1192+
1193+ let mut info = Info {
1194+ height: 20.min(height + 1),
1195+ width: 70.min(max_len),
1196+ title: "Debug targets".to_owned(),
1197+ text: text + "Exit Esc",
1198+ };
1199+ info.render(area, surface, cx);
1200+ }
1201+
11401202 if let Some(ref mut info) = self.autoinfo {
11411203 info.render(area, surface, cx);
11421204 }
helix-view/src/editor.rs+2
@@ -76,6 +76,7 @@ pub struct Editor {
7676
7777 pub debugger: Option<helix_dap::Client>,
7878 pub debugger_events: SelectAll<UnboundedReceiverStream<helix_dap::Payload>>,
79+ pub debug_config_picker: Option<Vec<String>>,
7980 pub variables: Option<Vec<String>>,
8081 pub variables_page: usize,
8182
@@ -118,6 +119,7 @@ impl Editor {
118119 language_servers,
119120 debugger: None,
120121 debugger_events: SelectAll::new(),
122+ debug_config_picker: None,
121123 variables: None,
122124 variables_page: 0,
123125 syn_loader: config_loader,