Add command for editing breakpoint condition

This commit is contained in:
Dmitry Sharshakov 2021-09-04 22:57:58 +03:00
parent e36fc57fff
commit 1befbd076c
7 changed files with 88 additions and 11 deletions

View File

@ -317,6 +317,7 @@ pub fn doc(&self) -> &'static str {
dap_next, "Step to next",
dap_variables, "List variables",
dap_terminate, "End debug session",
dap_edit_condition, "Edit condition of the breakpoint on the current line",
dap_switch_thread, "Switch current thread",
dap_switch_stack_frame, "Switch stack frame",
shell_pipe, "Pipe selections through shell command",
@ -1979,10 +1980,10 @@ fn debug_eval(
Ok(())
}
fn get_breakpoint_at_current_line(
cx: &mut compositor::Context,
pub fn get_breakpoint_at_current_line(
editor: &mut Editor,
) -> Option<(usize, SourceBreakpoint)> {
let (view, doc) = current!(cx.editor);
let (view, doc) = current!(editor);
let text = doc.text().slice(..);
let pos = doc.selection(view.id).primary().cursor(text);
@ -1992,12 +1993,9 @@ fn get_breakpoint_at_current_line(
None => return None,
};
let vec = vec![];
let breakpoints = cx.editor.breakpoints.get(&path.clone()).unwrap_or(&vec);
let breakpoints = editor.breakpoints.get(&path).unwrap_or(&vec);
let i = breakpoints.iter().position(|b| b.line == line);
match i {
Some(i) => Some((i, breakpoints.get(i).unwrap().clone())),
None => None,
}
i.map(|i| (i, breakpoints.get(i).unwrap().clone()))
}
fn edit_breakpoint_impl(
@ -2015,7 +2013,7 @@ fn edit_breakpoint_impl(
}
};
if let Some((pos, mut bp)) = get_breakpoint_at_current_line(cx) {
if let Some((pos, mut bp)) = get_breakpoint_at_current_line(cx.editor) {
let breakpoints = cx.editor.breakpoints.entry(path.clone()).or_default();
breakpoints.remove(pos);
@ -2481,6 +2479,7 @@ fn command_mode(cx: &mut Context) {
.set_error(format!("no such command: '{}'", parts[0]));
};
},
None,
);
prompt.doc_fn = Box::new(|input: &str| {
let part = input.split(' ').next().unwrap_or_default();
@ -4584,6 +4583,7 @@ fn shell_keep_pipe(cx: &mut Context) {
let index = index.unwrap_or_else(|| ranges.len() - 1);
doc.set_selection(view.id, Selection::new(ranges, index));
},
None,
);
cx.push_layer(Box::new(prompt));
@ -4683,6 +4683,7 @@ fn shell(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBehavior) {
doc.append_changes_to_history(view.id);
}
},
None,
);
cx.push_layer(Box::new(prompt));

View File

@ -1,5 +1,8 @@
use super::{align_view, Align, Context, Editor};
use crate::ui::{FilePicker, Picker};
use crate::{
commands,
ui::{FilePicker, Picker, Prompt, PromptEvent},
};
use helix_core::Selection;
use helix_dap::{self as dap, Client};
use helix_lsp::block_on;
@ -474,6 +477,74 @@ pub fn dap_terminate(cx: &mut Context) {
cx.editor.debugger = None;
}
pub fn dap_edit_condition(cx: &mut Context) {
if let Some((pos, mut bp)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) {
let condition = bp.condition.clone();
let prompt = Prompt::new(
"condition: ".into(),
None,
|_input: &str| Vec::new(),
move |cx: &mut crate::compositor::Context, input: &str, event: PromptEvent| {
if event != PromptEvent::Validate {
return;
}
let (_, doc) = current!(cx.editor);
let path = match doc.path() {
Some(path) => path.to_path_buf(),
None => {
cx.editor
.set_status("Can't edit breakpoint: document has no path".to_owned());
return;
}
};
let breakpoints = cx.editor.breakpoints.entry(path.clone()).or_default();
breakpoints.remove(pos);
bp.condition = match input {
"" => None,
input => Some(input.to_owned()),
};
breakpoints.push(bp.clone());
if let Some(debugger) = &mut cx.editor.debugger {
// TODO: handle capabilities correctly again, by filterin breakpoints when emitting
// if breakpoint.condition.is_some()
// && !debugger
// .caps
// .as_ref()
// .unwrap()
// .supports_conditional_breakpoints
// .unwrap_or_default()
// {
// bail!(
// "Can't edit breakpoint: debugger does not support conditional breakpoints"
// )
// }
// if breakpoint.log_message.is_some()
// && !debugger
// .caps
// .as_ref()
// .unwrap()
// .supports_log_points
// .unwrap_or_default()
// {
// bail!("Can't edit breakpoint: debugger does not support logpoints")
// }
let request = debugger.set_breakpoints(path, breakpoints.clone());
if let Err(e) = block_on(request) {
cx.editor
.set_status(format!("Failed to set breakpoints: {:?}", e))
}
}
},
condition,
);
cx.push_layer(Box::new(prompt));
}
}
pub fn dap_switch_thread(cx: &mut Context) {
thread_picker(cx, |editor, thread| {
block_on(select_thread_id(editor, thread.id, true));

View File

@ -497,6 +497,7 @@ fn default() -> Keymaps {
"n" => dap_next,
"v" => dap_variables,
"t" => dap_terminate,
"C-c" => dap_edit_condition,
"s" => { "Switch"
"t" => dap_switch_thread,
"f" => dap_switch_stack_frame,

View File

@ -795,6 +795,7 @@ fn debug_parameter_prompt(
);
}
},
None,
)
}

View File

@ -70,6 +70,7 @@ pub fn regex_prompt(
}
}
},
None,
)
}

View File

@ -208,6 +208,7 @@ pub fn new(
|_editor: &mut Context, _pattern: &str, _event: PromptEvent| {
//
},
None,
);
let mut picker = Self {

View File

@ -59,10 +59,11 @@ pub fn new(
history_register: Option<char>,
mut completion_fn: impl FnMut(&str) -> Vec<Completion> + 'static,
callback_fn: impl FnMut(&mut Context, &str, PromptEvent) + 'static,
line: Option<String>,
) -> Self {
Self {
prompt,
line: String::new(),
line: line.unwrap_or_default(),
cursor: 0,
completion: completion_fn(""),
selection: None,