mirror of https://github.com/helix-editor/helix
New way of starting debug sessions
parent
5e4da09be2
commit
8df6739759
|
@ -304,6 +304,7 @@ impl Command {
|
||||||
surround_delete, "Surround delete",
|
surround_delete, "Surround delete",
|
||||||
select_textobject_around, "Select around object",
|
select_textobject_around, "Select around object",
|
||||||
select_textobject_inner, "Select inside object",
|
select_textobject_inner, "Select inside object",
|
||||||
|
dap_launch, "Launch debug target",
|
||||||
dap_toggle_breakpoint, "Toggle breakpoint",
|
dap_toggle_breakpoint, "Toggle breakpoint",
|
||||||
dap_run, "Begin program execution",
|
dap_run, "Begin program execution",
|
||||||
dap_continue, "Continue program execution",
|
dap_continue, "Continue program execution",
|
||||||
|
@ -4491,7 +4492,7 @@ fn suspend(_cx: &mut Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DAP
|
// DAP
|
||||||
fn dap_start_impl(
|
pub fn dap_start_impl(
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
name: Option<&str>,
|
name: Option<&str>,
|
||||||
socket: Option<std::net::SocketAddr>,
|
socket: Option<std::net::SocketAddr>,
|
||||||
|
@ -4596,6 +4597,41 @@ fn dap_start_impl(
|
||||||
editor.debugger_events.push(stream);
|
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) {
|
fn dap_toggle_breakpoint(cx: &mut Context) {
|
||||||
use helix_lsp::block_on;
|
use helix_lsp::block_on;
|
||||||
|
|
||||||
|
|
|
@ -486,6 +486,7 @@ impl Default for Keymaps {
|
||||||
"a" => code_action,
|
"a" => code_action,
|
||||||
"'" => last_picker,
|
"'" => last_picker,
|
||||||
"d" => { "Debug"
|
"d" => { "Debug"
|
||||||
|
"s" => dap_launch,
|
||||||
"b" => dap_toggle_breakpoint,
|
"b" => dap_toggle_breakpoint,
|
||||||
"r" => dap_run,
|
"r" => dap_run,
|
||||||
"c" => dap_continue,
|
"c" => dap_continue,
|
||||||
|
|
|
@ -30,6 +30,8 @@ use std::borrow::Cow;
|
||||||
use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind};
|
use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind};
|
||||||
use tui::buffer::Buffer as Surface;
|
use tui::buffer::Buffer as Surface;
|
||||||
|
|
||||||
|
use super::{Prompt, PromptEvent};
|
||||||
|
|
||||||
pub struct EditorView {
|
pub struct EditorView {
|
||||||
keymaps: Keymaps,
|
keymaps: Keymaps,
|
||||||
on_next_key: Option<Box<dyn FnOnce(&mut commands::Context, KeyEvent)>>,
|
on_next_key: Option<Box<dyn FnOnce(&mut commands::Context, KeyEvent)>>,
|
||||||
|
@ -712,6 +714,45 @@ impl EditorView {
|
||||||
) -> Option<KeymapResult> {
|
) -> Option<KeymapResult> {
|
||||||
self.autoinfo = None;
|
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() {
|
if cxt.editor.variables.is_some() {
|
||||||
match event {
|
match event {
|
||||||
KeyEvent {
|
KeyEvent {
|
||||||
|
@ -735,6 +776,7 @@ impl EditorView {
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.keymaps.get_mut(&mode).unwrap().get(event) {
|
match self.keymaps.get_mut(&mode).unwrap().get(event) {
|
||||||
KeymapResult::Matched(command) => command.execute(cxt),
|
KeymapResult::Matched(command) => command.execute(cxt),
|
||||||
KeymapResult::Pending(node) => self.autoinfo = Some(node.into()),
|
KeymapResult::Pending(node) => self.autoinfo = Some(node.into()),
|
||||||
|
@ -1137,6 +1179,26 @@ impl Component for EditorView {
|
||||||
info.render(area, surface, cx);
|
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 {
|
if let Some(ref mut info) = self.autoinfo {
|
||||||
info.render(area, surface, cx);
|
info.render(area, surface, cx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ pub struct Editor {
|
||||||
|
|
||||||
pub debugger: Option<helix_dap::Client>,
|
pub debugger: Option<helix_dap::Client>,
|
||||||
pub debugger_events: SelectAll<UnboundedReceiverStream<helix_dap::Payload>>,
|
pub debugger_events: SelectAll<UnboundedReceiverStream<helix_dap::Payload>>,
|
||||||
|
pub debug_config_picker: Option<Vec<String>>,
|
||||||
pub variables: Option<Vec<String>>,
|
pub variables: Option<Vec<String>>,
|
||||||
pub variables_page: usize,
|
pub variables_page: usize,
|
||||||
|
|
||||||
|
@ -118,6 +119,7 @@ impl Editor {
|
||||||
language_servers,
|
language_servers,
|
||||||
debugger: None,
|
debugger: None,
|
||||||
debugger_events: SelectAll::new(),
|
debugger_events: SelectAll::new(),
|
||||||
|
debug_config_picker: None,
|
||||||
variables: None,
|
variables: None,
|
||||||
variables_page: 0,
|
variables_page: 0,
|
||||||
syn_loader: config_loader,
|
syn_loader: config_loader,
|
||||||
|
|
Loading…
Reference in New Issue