Add MultiBufferSnapshot::range_contains_excerpt_boundary
Use this method to disable move_line_down across excerpt boundaries. Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
cbc162acf5
commit
accf90e843
2 changed files with 27 additions and 105 deletions
|
@ -1783,104 +1783,6 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
|
pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
|
||||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
|
||||||
|
|
||||||
let mut deletes = Vec::new();
|
|
||||||
let mut inserts = Vec::new();
|
|
||||||
// let mut new_selection_ranges = Vec::new();
|
|
||||||
let mut unfold_ranges = Vec::new();
|
|
||||||
let mut refold_ranges = Vec::new();
|
|
||||||
|
|
||||||
let selections = self.local_selections::<Point>(cx);
|
|
||||||
let mut selections = selections.iter().peekable();
|
|
||||||
let mut contiguous_row_selections = Vec::new();
|
|
||||||
let mut new_selections = Vec::new();
|
|
||||||
|
|
||||||
while let Some(selection) = selections.next() {
|
|
||||||
// Find all the selections that span a contiguous row range
|
|
||||||
contiguous_row_selections.push(selection.clone());
|
|
||||||
let start_row = selection.start.row;
|
|
||||||
let mut end_row = if selection.end.column > 0 || selection.is_empty() {
|
|
||||||
display_map
|
|
||||||
.next_row_boundary(selection.end.to_display_point(&display_map))
|
|
||||||
.1
|
|
||||||
.row
|
|
||||||
+ 1
|
|
||||||
} else {
|
|
||||||
selection.end.row
|
|
||||||
};
|
|
||||||
|
|
||||||
while let Some(next_selection) = selections.peek() {
|
|
||||||
if next_selection.start.row <= end_row {
|
|
||||||
end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
|
|
||||||
display_map
|
|
||||||
.next_row_boundary(next_selection.end.to_display_point(&display_map))
|
|
||||||
.1
|
|
||||||
.row
|
|
||||||
+ 1
|
|
||||||
} else {
|
|
||||||
next_selection.end.row
|
|
||||||
};
|
|
||||||
contiguous_row_selections.push(selections.next().unwrap().clone());
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the text spanned by the row range to be after the last line of the row range
|
|
||||||
if end_row <= buffer.max_point().row {
|
|
||||||
let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
|
|
||||||
let insertion_point = Point::new(end_row, buffer.line_len(end_row));
|
|
||||||
let insertion_row = insertion_point.row + 1;
|
|
||||||
let mut text = String::from("\n");
|
|
||||||
text.extend(buffer.text_for_range(range_to_move.clone()));
|
|
||||||
text.pop(); // Drop trailing newline
|
|
||||||
deletes.push(range_to_move.clone());
|
|
||||||
inserts.push((insertion_point, text));
|
|
||||||
|
|
||||||
// Make the selections relative to the insertion row
|
|
||||||
new_selections.extend(contiguous_row_selections.drain(..).map(|mut selection| {
|
|
||||||
selection.start.row = insertion_row + selection.start.row - start_row;
|
|
||||||
selection.end.row = insertion_row + selection.end.row - start_row;
|
|
||||||
selection
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Unfold all the folds spanned by these rows
|
|
||||||
unfold_ranges.push(range_to_move.clone());
|
|
||||||
|
|
||||||
// Refold ranges relative to the insertion row
|
|
||||||
for fold in display_map.folds_in_range(
|
|
||||||
buffer.anchor_before(range_to_move.start)
|
|
||||||
..buffer.anchor_after(range_to_move.end),
|
|
||||||
) {
|
|
||||||
let mut start = fold.start.to_point(&buffer);
|
|
||||||
let mut end = fold.end.to_point(&buffer);
|
|
||||||
start.row = insertion_row + start.row - start_row;
|
|
||||||
end.row = insertion_row + end.row - start_row;
|
|
||||||
refold_ranges.push(start..end);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
new_selections.extend(contiguous_row_selections.drain(..));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.start_transaction(cx);
|
|
||||||
self.unfold_ranges(unfold_ranges, cx);
|
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
|
||||||
for (point, text) in inserts.into_iter().rev() {
|
|
||||||
buffer.edit([point..point], text, cx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.fold_ranges(refold_ranges, cx);
|
|
||||||
self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
|
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
|
||||||
buffer.edit(deletes.into_iter().rev(), "", cx);
|
|
||||||
});
|
|
||||||
self.end_transaction(cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn move_line_down2(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
|
|
||||||
let selections = self.local_selections::<Point>(cx);
|
let selections = self.local_selections::<Point>(cx);
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||||
|
@ -1916,9 +1818,6 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("spanned buffer rows {:?}", buffer_rows);
|
|
||||||
println!("spanned display rows {:?}", display_rows);
|
|
||||||
|
|
||||||
// Cut the text from the selected rows and paste it at the end of the next line.
|
// Cut the text from the selected rows and paste it at the end of the next line.
|
||||||
if display_rows.end <= display_map.max_point().row() {
|
if display_rows.end <= display_map.max_point().row() {
|
||||||
let start = Point::new(buffer_rows.start, 0).to_offset(&buffer);
|
let start = Point::new(buffer_rows.start, 0).to_offset(&buffer);
|
||||||
|
@ -1930,8 +1829,10 @@ impl Editor {
|
||||||
let next_row_buffer_end = display_map.next_row_boundary(next_row_display_end).1;
|
let next_row_buffer_end = display_map.next_row_boundary(next_row_display_end).1;
|
||||||
let next_row_buffer_end_offset = next_row_buffer_end.to_offset(&buffer);
|
let next_row_buffer_end_offset = next_row_buffer_end.to_offset(&buffer);
|
||||||
|
|
||||||
dbg!(next_row_display_end);
|
if buffer.range_contains_excerpt_boundary(start..next_row_buffer_end_offset) {
|
||||||
dbg!(next_row_buffer_end);
|
new_selection_ranges.extend(contiguous_selections.drain(..));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
text.push('\n');
|
text.push('\n');
|
||||||
|
@ -1962,7 +1863,6 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.start_transaction(cx);
|
self.start_transaction(cx);
|
||||||
|
|
||||||
self.unfold_ranges(old_folds, cx);
|
self.unfold_ranges(old_folds, cx);
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
self.buffer.update(cx, |buffer, cx| {
|
||||||
for (range, text) in edits.into_iter().rev() {
|
for (range, text) in edits.into_iter().rev() {
|
||||||
|
@ -1971,7 +1871,6 @@ impl Editor {
|
||||||
});
|
});
|
||||||
self.fold_ranges(new_folds, cx);
|
self.fold_ranges(new_folds, cx);
|
||||||
self.select_ranges(new_selection_ranges, Some(Autoscroll::Fit), cx);
|
self.select_ranges(new_selection_ranges, Some(Autoscroll::Fit), cx);
|
||||||
|
|
||||||
self.end_transaction(cx);
|
self.end_transaction(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1395,6 +1395,23 @@ impl MultiBufferSnapshot {
|
||||||
panic!("excerpt not found");
|
panic!("excerpt not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn range_contains_excerpt_boundary<T: ToOffset>(&self, range: Range<T>) -> bool {
|
||||||
|
let start = range.start.to_offset(self);
|
||||||
|
let end = range.end.to_offset(self);
|
||||||
|
let mut cursor = self.excerpts.cursor::<(usize, Option<&ExcerptId>)>();
|
||||||
|
cursor.seek(&start, Bias::Right, &());
|
||||||
|
let start_id = cursor
|
||||||
|
.item()
|
||||||
|
.or_else(|| cursor.prev_item())
|
||||||
|
.map(|excerpt| &excerpt.id);
|
||||||
|
cursor.seek_forward(&end, Bias::Right, &());
|
||||||
|
let end_id = cursor
|
||||||
|
.item()
|
||||||
|
.or_else(|| cursor.prev_item())
|
||||||
|
.map(|excerpt| &excerpt.id);
|
||||||
|
start_id != end_id
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_count(&self) -> usize {
|
pub fn parse_count(&self) -> usize {
|
||||||
self.parse_count
|
self.parse_count
|
||||||
}
|
}
|
||||||
|
@ -2158,6 +2175,12 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
|
assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
|
||||||
assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
|
assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
|
||||||
|
assert!(!snapshot.range_contains_excerpt_boundary(Point::new(1, 0)..Point::new(1, 5)));
|
||||||
|
assert!(snapshot.range_contains_excerpt_boundary(Point::new(1, 0)..Point::new(2, 0)));
|
||||||
|
assert!(snapshot.range_contains_excerpt_boundary(Point::new(1, 0)..Point::new(4, 0)));
|
||||||
|
assert!(!snapshot.range_contains_excerpt_boundary(Point::new(2, 0)..Point::new(3, 0)));
|
||||||
|
assert!(!snapshot.range_contains_excerpt_boundary(Point::new(4, 0)..Point::new(4, 2)));
|
||||||
|
assert!(!snapshot.range_contains_excerpt_boundary(Point::new(4, 2)..Point::new(4, 2)));
|
||||||
|
|
||||||
buffer_1.update(cx, |buffer, cx| {
|
buffer_1.update(cx, |buffer, cx| {
|
||||||
buffer.edit(
|
buffer.edit(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue