on master help sign in
dap: Modify breakpoints in place with no cloning
5f329a2Blaž Hrastnik
helix-term/src/commands/dap.rs+12−14
@@ -391,6 +391,7 @@ fn debug_parameter_prompt(
391}
391}
392
392
393pub fn dap_toggle_breakpoint(cx: &mut Context) {
393pub fn dap_toggle_breakpoint(cx: &mut Context) {
394+ // TODO: accept line instead of current selection
394 let (view, doc) = current!(cx.editor);
395 let (view, doc) = current!(cx.editor);
395 let text = doc.text().slice(..);
396 let text = doc.text().slice(..);
396 let pos = doc.selection(view.id).primary().cursor(text);
397 let pos = doc.selection(view.id).primary().cursor(text);
@@ -413,6 +414,7 @@ pub fn dap_toggle_breakpoint(cx: &mut Context) {
413 // we shouldn't really allow editing while debug is running though
414 // we shouldn't really allow editing while debug is running though
414
415
415 let breakpoints = cx.editor.breakpoints.entry(path.clone()).or_default();
416 let breakpoints = cx.editor.breakpoints.entry(path.clone()).or_default();
417+ // TODO: always keep breakpoints sorted and use binary search
416 if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
418 if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
417 breakpoints.remove(pos);
419 breakpoints.remove(pos);
418 } else {
420 } else {
@@ -629,12 +631,14 @@ pub fn dap_disable_exceptions(cx: &mut Context) {
629 }
631 }
630}
632}
631
633
634+// TODO: both edit condition and edit log need to be stable: we might get new breakpoints from the debugger which can change offsets
635+// we also might be editing a breakpoint in a document that's no longer focused
632pub fn dap_edit_condition(cx: &mut Context) {
636pub fn dap_edit_condition(cx: &mut Context) {
633− if let Some((pos, mut bp)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) {
637+ if let Some((pos, breakpoint)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) {
634 let callback = Box::pin(async move {
638 let callback = Box::pin(async move {
635 let call: Callback =
639 let call: Callback =
636 Box::new(move |_editor: &mut Editor, compositor: &mut Compositor| {
640 Box::new(move |_editor: &mut Editor, compositor: &mut Compositor| {
637− let condition = bp.condition.clone();
641+ let condition = breakpoint.condition;
638 let prompt = Prompt::new(
642 let prompt = Prompt::new(
639 "condition: ".into(),
643 "condition: ".into(),
640 None,
644 None,
@@ -657,14 +661,11 @@ pub fn dap_edit_condition(cx: &mut Context) {
657 }
661 }
658 };
662 };
659
663
660− let breakpoints =
661− cx.editor.breakpoints.entry(path.clone()).or_default();
664+ let breakpoints = &mut cx.editor.breakpoints.get_mut(path).unwrap();
662− breakpoints.remove(pos);
663− bp.condition = match input {
665+ breakpoints[pos].condition = match input {
664 "" => None,
666 "" => None,
665 input => Some(input.to_owned()),
667 input => Some(input.to_owned()),
666 };
668 };
667− breakpoints.push(bp.clone());
668
669
669 if let Some(debugger) = &mut cx.editor.debugger {
670 if let Some(debugger) = &mut cx.editor.debugger {
670 // TODO: handle capabilities correctly again, by filterin breakpoints when emitting
671 // TODO: handle capabilities correctly again, by filterin breakpoints when emitting
@@ -709,11 +710,11 @@ pub fn dap_edit_condition(cx: &mut Context) {
709}
710}
710
711
711pub fn dap_edit_log(cx: &mut Context) {
712pub fn dap_edit_log(cx: &mut Context) {
712− if let Some((pos, mut bp)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) {
713+ if let Some((pos, breakpoint)) = commands::cmd::get_breakpoint_at_current_line(cx.editor) {
713 let callback = Box::pin(async move {
714 let callback = Box::pin(async move {
714 let call: Callback =
715 let call: Callback =
715 Box::new(move |_editor: &mut Editor, compositor: &mut Compositor| {
716 Box::new(move |_editor: &mut Editor, compositor: &mut Compositor| {
716− let log_message = bp.log_message.clone();
717+ let log_message = breakpoint.log_message;
717 let prompt = Prompt::new(
718 let prompt = Prompt::new(
718 "log message: ".into(),
719 "log message: ".into(),
719 None,
720 None,
@@ -736,14 +737,11 @@ pub fn dap_edit_log(cx: &mut Context) {
736 }
737 }
737 };
738 };
738
739
739− let breakpoints =
740− cx.editor.breakpoints.entry(path.clone()).or_default();
740+ let breakpoints = &mut cx.editor.breakpoints.get_mut(path).unwrap();
741− breakpoints.remove(pos);
742− bp.log_message = match input {
741+ breakpoints[pos].log_message = match input {
743 "" => None,
742 "" => None,
744 input => Some(input.to_owned()),
743 input => Some(input.to_owned()),
745 };
744 };
746− breakpoints.push(bp.clone());
747
745
748 if let Some(debugger) = &mut cx.editor.debugger {
746 if let Some(debugger) = &mut cx.editor.debugger {
749 // TODO: handle capabilities correctly again, by filterin breakpoints when emitting
747 // TODO: handle capabilities correctly again, by filterin breakpoints when emitting
helix-term/src/ui/editor.rs+6−6
@@ -978,17 +978,17 @@ impl EditorView {
978
978
979 let result = editor.tree.views().find_map(|(view, _focus)| {
979 let result = editor.tree.views().find_map(|(view, _focus)| {
980 view.gutter_coords_at_screen_coords(row, column)
980 view.gutter_coords_at_screen_coords(row, column)
981− .map(|coords| (coords.0, coords.1, view.id))
981+ .map(|coords| (coords, view.id))
982 });
982 });
983
983
984− if let Some((line, _, view_id)) = result {
984+ if let Some((coords, view_id)) = result {
985 editor.tree.focus = view_id;
985 editor.tree.focus = view_id;
986
986
987 let doc = editor
987 let doc = editor
988 .documents
988 .documents
989 .get_mut(&editor.tree.get(view_id).doc)
989 .get_mut(&editor.tree.get(view_id).doc)
990 .unwrap();
990 .unwrap();
991− if let Ok(pos) = doc.text().try_line_to_char(line) {
991+ if let Ok(pos) = doc.text().try_line_to_char(coords.row) {
992 doc.set_selection(view_id, Selection::point(pos));
992 doc.set_selection(view_id, Selection::point(pos));
993 commands::dap_toggle_breakpoint(cxt);
993 commands::dap_toggle_breakpoint(cxt);
994
994
@@ -1080,10 +1080,10 @@ impl EditorView {
1080 } => {
1080 } => {
1081 let result = cxt.editor.tree.views().find_map(|(view, _focus)| {
1081 let result = cxt.editor.tree.views().find_map(|(view, _focus)| {
1082 view.gutter_coords_at_screen_coords(row, column)
1082 view.gutter_coords_at_screen_coords(row, column)
1083− .map(|coords| (coords.0, coords.1, view.id))
1083+ .map(|coords| (coords, view.id))
1084 });
1084 });
1085
1085
1086− if let Some((line, _, view_id)) = result {
1086+ if let Some((coords, view_id)) = result {
1087 cxt.editor.tree.focus = view_id;
1087 cxt.editor.tree.focus = view_id;
1088
1088
1089 let doc = cxt
1089 let doc = cxt
@@ -1091,7 +1091,7 @@ impl EditorView {
1091 .documents
1091 .documents
1092 .get_mut(&cxt.editor.tree.get(view_id).doc)
1092 .get_mut(&cxt.editor.tree.get(view_id).doc)
1093 .unwrap();
1093 .unwrap();
1094− if let Ok(pos) = doc.text().try_line_to_char(line) {
1094+ if let Ok(pos) = doc.text().try_line_to_char(coords.row) {
1095 doc.set_selection(view_id, Selection::point(pos));
1095 doc.set_selection(view_id, Selection::point(pos));
1096 if modifiers == crossterm::event::KeyModifiers::ALT {
1096 if modifiers == crossterm::event::KeyModifiers::ALT {
1097 commands::Command::dap_edit_log.execute(cxt);
1097 commands::Command::dap_edit_log.execute(cxt);
helix-view/src/view.rs+2−2
@@ -253,7 +253,7 @@ impl View {
253 /// Translates screen coordinates into coordinates on the gutter of the view.
253 /// Translates screen coordinates into coordinates on the gutter of the view.
254 /// Returns a tuple of usize typed line and column numbers starting with 0.
254 /// Returns a tuple of usize typed line and column numbers starting with 0.
255 /// Returns None if coordinates are not on the gutter.
255 /// Returns None if coordinates are not on the gutter.
256− pub fn gutter_coords_at_screen_coords(&self, row: u16, column: u16) -> Option<(usize, usize)> {
256+ pub fn gutter_coords_at_screen_coords(&self, row: u16, column: u16) -> Option<Position> {
257 // 1 for status
257 // 1 for status
258 if row < self.area.top() || row >= self.area.bottom() {
258 if row < self.area.top() || row >= self.area.bottom() {
259 return None;
259 return None;
@@ -263,7 +263,7 @@ impl View {
263 return None;
263 return None;
264 }
264 }
265
265
266− Some((
266+ Some(Position::new(
267 (row - self.area.top()) as usize,
267 (row - self.area.top()) as usize,
268 (column - self.area.left()) as usize,
268 (column - self.area.left()) as usize,
269 ))
269 ))