diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs index bf412c96..113bacd9 100644 --- a/helix-term/src/commands/dap.rs +++ b/helix-term/src/commands/dap.rs @@ -391,6 +391,7 @@ fn debug_parameter_prompt( } pub fn dap_toggle_breakpoint(cx: &mut Context) { + // TODO: accept line instead of current selection let (view, doc) = current!(cx.editor); let text = doc.text().slice(..); let pos = doc.selection(view.id).primary().cursor(text); @@ -413,6 +414,7 @@ pub fn dap_toggle_breakpoint(cx: &mut Context) { // we shouldn't really allow editing while debug is running though let breakpoints = cx.editor.breakpoints.entry(path.clone()).or_default(); + // TODO: always keep breakpoints sorted and use binary search if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) { breakpoints.remove(pos); } else { @@ -629,12 +631,14 @@ pub fn dap_disable_exceptions(cx: &mut Context) { } } +// TODO: both edit condition and edit log need to be stable: we might get new breakpoints from the debugger which can change offsets +// we also might be editing a breakpoint in a document that's no longer focused pub fn dap_edit_condition(cx: &mut Context) { - if let Some((pos, mut bp)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) { + if let Some((pos, breakpoint)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) { let callback = Box::pin(async move { let call: Callback = Box::new(move |_editor: &mut Editor, compositor: &mut Compositor| { - let condition = bp.condition.clone(); + let condition = breakpoint.condition; let prompt = Prompt::new( "condition: ".into(), None, @@ -657,14 +661,11 @@ pub fn dap_edit_condition(cx: &mut Context) { } }; - let breakpoints = - cx.editor.breakpoints.entry(path.clone()).or_default(); - breakpoints.remove(pos); - bp.condition = match input { + let breakpoints = &mut cx.editor.breakpoints.get_mut(path).unwrap(); + breakpoints[pos].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 @@ -709,11 +710,11 @@ pub fn dap_edit_condition(cx: &mut Context) { } pub fn dap_edit_log(cx: &mut Context) { - if let Some((pos, mut bp)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) { + if let Some((pos, breakpoint)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) { let callback = Box::pin(async move { let call: Callback = Box::new(move |_editor: &mut Editor, compositor: &mut Compositor| { - let log_message = bp.log_message.clone(); + let log_message = breakpoint.log_message; let prompt = Prompt::new( "log message: ".into(), None, @@ -736,14 +737,11 @@ pub fn dap_edit_log(cx: &mut Context) { } }; - let breakpoints = - cx.editor.breakpoints.entry(path.clone()).or_default(); - breakpoints.remove(pos); - bp.log_message = match input { + let breakpoints = &mut cx.editor.breakpoints.get_mut(path).unwrap(); + breakpoints[pos].log_message = 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 diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 01554c64..19f0243e 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -978,17 +978,17 @@ impl EditorView { let result = editor.tree.views().find_map(|(view, _focus)| { view.gutter_coords_at_screen_coords(row, column) - .map(|coords| (coords.0, coords.1, view.id)) + .map(|coords| (coords, view.id)) }); - if let Some((line, _, view_id)) = result { + if let Some((coords, view_id)) = result { editor.tree.focus = view_id; let doc = editor .documents .get_mut(&editor.tree.get(view_id).doc) .unwrap(); - if let Ok(pos) = doc.text().try_line_to_char(line) { + if let Ok(pos) = doc.text().try_line_to_char(coords.row) { doc.set_selection(view_id, Selection::point(pos)); commands::dap_toggle_breakpoint(cxt); @@ -1080,10 +1080,10 @@ impl EditorView { } => { let result = cxt.editor.tree.views().find_map(|(view, _focus)| { view.gutter_coords_at_screen_coords(row, column) - .map(|coords| (coords.0, coords.1, view.id)) + .map(|coords| (coords, view.id)) }); - if let Some((line, _, view_id)) = result { + if let Some((coords, view_id)) = result { cxt.editor.tree.focus = view_id; let doc = cxt @@ -1091,7 +1091,7 @@ impl EditorView { .documents .get_mut(&cxt.editor.tree.get(view_id).doc) .unwrap(); - if let Ok(pos) = doc.text().try_line_to_char(line) { + if let Ok(pos) = doc.text().try_line_to_char(coords.row) { doc.set_selection(view_id, Selection::point(pos)); if modifiers == crossterm::event::KeyModifiers::ALT { commands::Command::dap_edit_log.execute(cxt); diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index 02aa1327..3066801b 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -253,7 +253,7 @@ impl View { /// Translates screen coordinates into coordinates on the gutter of the view. /// Returns a tuple of usize typed line and column numbers starting with 0. /// Returns None if coordinates are not on the gutter. - pub fn gutter_coords_at_screen_coords(&self, row: u16, column: u16) -> Option<(usize, usize)> { + pub fn gutter_coords_at_screen_coords(&self, row: u16, column: u16) -> Option { // 1 for status if row < self.area.top() || row >= self.area.bottom() { return None; @@ -263,7 +263,7 @@ impl View { return None; } - Some(( + Some(Position::new( (row - self.area.top()) as usize, (column - self.area.left()) as usize, ))