debugger: Add support for setting multiple breakpoints via actions (#28437)
Allow setting multiple breakpoints with multi cursors Release Notes: - N/A --------- Co-authored-by: Anthony Eid <hello@anthonyeid.me> Co-authored-by: Remco Smits <djsmits12@gmail.com> Co-authored-by: Anthony <anthony@zed.dev>
This commit is contained in:
parent
5757e352b0
commit
c35238bd72
2 changed files with 93 additions and 64 deletions
|
@ -8854,15 +8854,6 @@ impl Editor {
|
|||
});
|
||||
}
|
||||
|
||||
fn breakpoint_at_cursor_head(
|
||||
&self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<(Anchor, Breakpoint)> {
|
||||
let cursor_position: Point = self.selections.newest(cx).head();
|
||||
self.breakpoint_at_row(cursor_position.row, window, cx)
|
||||
}
|
||||
|
||||
pub(crate) fn breakpoint_at_row(
|
||||
&self,
|
||||
row: u32,
|
||||
|
@ -8872,6 +8863,15 @@ impl Editor {
|
|||
let snapshot = self.snapshot(window, cx);
|
||||
let breakpoint_position = snapshot.buffer_snapshot.anchor_before(Point::new(row, 0));
|
||||
|
||||
self.breakpoint_at_anchor(breakpoint_position, &snapshot, cx)
|
||||
}
|
||||
|
||||
pub(crate) fn breakpoint_at_anchor(
|
||||
&self,
|
||||
breakpoint_position: Anchor,
|
||||
snapshot: &EditorSnapshot,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<(Anchor, Breakpoint)> {
|
||||
let project = self.project.clone()?;
|
||||
|
||||
let buffer_id = breakpoint_position.buffer_id.or_else(|| {
|
||||
|
@ -8929,29 +8929,51 @@ impl Editor {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let (anchor, bp) = self
|
||||
.breakpoint_at_cursor_head(window, cx)
|
||||
.unwrap_or_else(|| {
|
||||
let cursor_position: Point = self.selections.newest(cx).head();
|
||||
for (anchor, breakpoint) in self.breakpoints_at_cursors(window, cx) {
|
||||
let breakpoint = breakpoint.unwrap_or_else(|| Breakpoint {
|
||||
message: None,
|
||||
state: BreakpointState::Enabled,
|
||||
condition: None,
|
||||
hit_condition: None,
|
||||
});
|
||||
|
||||
let breakpoint_position = self
|
||||
.snapshot(window, cx)
|
||||
self.add_edit_breakpoint_block(
|
||||
anchor,
|
||||
&breakpoint,
|
||||
BreakpointPromptEditAction::Log,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn breakpoints_at_cursors(
|
||||
&self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Vec<(Anchor, Option<Breakpoint>)> {
|
||||
let snapshot = self.snapshot(window, cx);
|
||||
let cursors = self
|
||||
.selections
|
||||
.disjoint_anchors()
|
||||
.into_iter()
|
||||
.map(|selection| {
|
||||
let cursor_position: Point = selection.head().to_point(&snapshot.buffer_snapshot);
|
||||
|
||||
let breakpoint_position = snapshot
|
||||
.display_snapshot
|
||||
.buffer_snapshot
|
||||
.anchor_after(Point::new(cursor_position.row, 0));
|
||||
let breakpoint = self
|
||||
.breakpoint_at_anchor(breakpoint_position, &snapshot, cx)
|
||||
.map(|(anchor, breakpoint)| (anchor, Some(breakpoint)));
|
||||
|
||||
(
|
||||
breakpoint_position,
|
||||
Breakpoint {
|
||||
message: None,
|
||||
state: BreakpointState::Enabled,
|
||||
condition: None,
|
||||
hit_condition: None,
|
||||
},
|
||||
)
|
||||
});
|
||||
breakpoint.unwrap_or_else(|| (breakpoint_position, None))
|
||||
})
|
||||
// There might be multiple cursors on the same line; all of them should have the same anchors though as their breakpoints positions, which makes it possible to sort and dedup the list.
|
||||
.collect::<HashMap<Anchor, _>>();
|
||||
|
||||
self.add_edit_breakpoint_block(anchor, &bp, BreakpointPromptEditAction::Log, window, cx);
|
||||
cursors.into_iter().collect()
|
||||
}
|
||||
|
||||
pub fn enable_breakpoint(
|
||||
|
@ -8960,15 +8982,16 @@ impl Editor {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if let Some((anchor, breakpoint)) = self.breakpoint_at_cursor_head(window, cx) {
|
||||
if breakpoint.is_disabled() {
|
||||
self.edit_breakpoint_at_anchor(
|
||||
anchor,
|
||||
breakpoint,
|
||||
BreakpointEditAction::InvertState,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
for (anchor, breakpoint) in self.breakpoints_at_cursors(window, cx) {
|
||||
let Some(breakpoint) = breakpoint.filter(|breakpoint| breakpoint.is_disabled()) else {
|
||||
continue;
|
||||
};
|
||||
self.edit_breakpoint_at_anchor(
|
||||
anchor,
|
||||
breakpoint,
|
||||
BreakpointEditAction::InvertState,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8978,15 +9001,16 @@ impl Editor {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if let Some((anchor, breakpoint)) = self.breakpoint_at_cursor_head(window, cx) {
|
||||
if breakpoint.is_enabled() {
|
||||
self.edit_breakpoint_at_anchor(
|
||||
anchor,
|
||||
breakpoint,
|
||||
BreakpointEditAction::InvertState,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
for (anchor, breakpoint) in self.breakpoints_at_cursors(window, cx) {
|
||||
let Some(breakpoint) = breakpoint.filter(|breakpoint| breakpoint.is_enabled()) else {
|
||||
continue;
|
||||
};
|
||||
self.edit_breakpoint_at_anchor(
|
||||
anchor,
|
||||
breakpoint,
|
||||
BreakpointEditAction::InvertState,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8996,25 +9020,22 @@ impl Editor {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let edit_action = BreakpointEditAction::Toggle;
|
||||
|
||||
if let Some((anchor, breakpoint)) = self.breakpoint_at_cursor_head(window, cx) {
|
||||
self.edit_breakpoint_at_anchor(anchor, breakpoint, edit_action, cx);
|
||||
} else {
|
||||
let cursor_position: Point = self.selections.newest(cx).head();
|
||||
|
||||
let breakpoint_position = self
|
||||
.snapshot(window, cx)
|
||||
.display_snapshot
|
||||
.buffer_snapshot
|
||||
.anchor_after(Point::new(cursor_position.row, 0));
|
||||
|
||||
self.edit_breakpoint_at_anchor(
|
||||
breakpoint_position,
|
||||
Breakpoint::new_standard(),
|
||||
edit_action,
|
||||
cx,
|
||||
);
|
||||
for (anchor, breakpoint) in self.breakpoints_at_cursors(window, cx) {
|
||||
if let Some(breakpoint) = breakpoint {
|
||||
self.edit_breakpoint_at_anchor(
|
||||
anchor,
|
||||
breakpoint,
|
||||
BreakpointEditAction::Toggle,
|
||||
cx,
|
||||
);
|
||||
} else {
|
||||
self.edit_breakpoint_at_anchor(
|
||||
anchor,
|
||||
Breakpoint::new_standard(),
|
||||
BreakpointEditAction::Toggle,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17999,7 +17999,15 @@ fn add_log_breakpoint_at_cursor(
|
|||
cx: &mut Context<Editor>,
|
||||
) {
|
||||
let (anchor, bp) = editor
|
||||
.breakpoint_at_cursor_head(window, cx)
|
||||
.breakpoints_at_cursors(window, cx)
|
||||
.first()
|
||||
.and_then(|(anchor, bp)| {
|
||||
if let Some(bp) = bp {
|
||||
Some((*anchor, bp.clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let cursor_position: Point = editor.selections.newest(cx).head();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue