This commit is contained in:
Antonio Scandurra 2024-11-01 19:01:52 +01:00
parent 896ee3c374
commit 3906b16cd6
4 changed files with 87 additions and 70 deletions

View file

@ -255,7 +255,7 @@ impl DisplayMap {
pub fn insert_creases(
&mut self,
creases: impl IntoIterator<Item = Crease>,
creases: impl IntoIterator<Item = Crease<Anchor>>,
cx: &mut ModelContext<Self>,
) -> Vec<CreaseId> {
let snapshot = self.buffer.read(cx).snapshot(cx);
@ -1054,19 +1054,27 @@ impl DisplaySnapshot {
.unwrap_or(false)
}
pub fn foldable_range(
&self,
buffer_row: MultiBufferRow,
) -> Option<(Range<Point>, FoldPlaceholder)> {
pub fn crease_for_buffer_row(&self, buffer_row: MultiBufferRow) -> Option<Crease<Point>> {
let start = MultiBufferPoint::new(buffer_row.0, self.buffer_snapshot.line_len(buffer_row));
if let Some(crease) = self
.crease_snapshot
.query_row(buffer_row, &self.buffer_snapshot)
{
Some((
crease.range().to_point(&self.buffer_snapshot),
crease.placeholder.clone(),
))
match crease {
Crease::Inline {
range,
placeholder,
render_toggle,
render_trailer,
metadata,
} => Some(Crease::Inline {
range: range.to_point(&self.buffer_snapshot),
placeholder: placeholder.clone(),
render_toggle: render_toggle.clone(),
render_trailer: render_trailer.clone(),
metadata: metadata.clone(),
}),
}
} else if self.starts_indent(MultiBufferRow(start.row))
&& !self.is_line_folded(MultiBufferRow(start.row))
{
@ -1103,7 +1111,13 @@ impl DisplaySnapshot {
.line_len(MultiBufferRow(row_before_line_breaks.row)),
);
Some((start..row_before_line_breaks, self.fold_placeholder.clone()))
Some(Crease::Inline {
range: start..row_before_line_breaks,
placeholder: self.fold_placeholder,
render_toggle: None,
render_trailer: None,
metadata: None,
})
} else {
None
}

View file

@ -2,7 +2,7 @@ use collections::HashMap;
use gpui::{AnyElement, IntoElement};
use multi_buffer::{Anchor, AnchorRangeExt, MultiBufferRow, MultiBufferSnapshot, ToPoint};
use serde::{Deserialize, Serialize};
use std::{cmp::Ordering, ops::Range, sync::Arc};
use std::{cmp::Ordering, fmt::Debug, ops::Range, sync::Arc};
use sum_tree::{Bias, SeekTarget, SumTree};
use text::Point;
use ui::{IconName, SharedString, WindowContext};
@ -45,7 +45,7 @@ impl CreaseSnapshot {
&'a self,
row: MultiBufferRow,
snapshot: &'a MultiBufferSnapshot,
) -> Option<&'a Crease> {
) -> Option<&'a Crease<Anchor>> {
let start = snapshot.anchor_before(Point::new(row.0, 0));
let mut cursor = self.creases.cursor::<ItemSummary>(snapshot);
cursor.seek(&start, Bias::Left, snapshot);
@ -69,7 +69,7 @@ impl CreaseSnapshot {
&'a self,
range: Range<MultiBufferRow>,
snapshot: &'a MultiBufferSnapshot,
) -> impl 'a + Iterator<Item = &'a Crease> {
) -> impl 'a + Iterator<Item = &'a Crease<Anchor>> {
let start = snapshot.anchor_before(Point::new(range.start.0, 0));
let mut cursor = self.creases.cursor::<ItemSummary>(snapshot);
cursor.seek(&start, Bias::Left, snapshot);
@ -125,9 +125,9 @@ type RenderTrailerFn =
Arc<dyn Send + Sync + Fn(MultiBufferRow, bool, &mut WindowContext) -> AnyElement>;
#[derive(Clone)]
pub enum Crease {
pub enum Crease<T> {
Inline {
range: Range<Anchor>,
range: Range<T>,
placeholder: FoldPlaceholder,
render_toggle: RenderToggleFn,
render_trailer: RenderTrailerFn,
@ -142,9 +142,9 @@ pub struct CreaseMetadata {
pub label: SharedString,
}
impl Crease {
impl<T> Crease<T> {
pub fn inline<RenderToggle, ToggleElement, RenderTrailer, TrailerElement>(
range: Range<Anchor>,
range: Range<T>,
placeholder: FoldPlaceholder,
render_toggle: RenderToggle,
render_trailer: RenderTrailer,
@ -199,20 +199,26 @@ impl Crease {
}
}
pub fn range(&self) -> &Range<Anchor> {
pub fn range(&self) -> &Range<T> {
match self {
Crease::Inline { range, .. } => range,
}
}
}
impl std::fmt::Debug for Crease {
impl<T> std::fmt::Debug for Crease<T>
where
T: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Crease::Inline { range, .. } => f
.debug_struct("Crease::Fold")
Crease::Inline {
range, metadata, ..
} => f
.debug_struct("Crease::Inline")
.field("range", range)
.finish(),
.field("metadata", metadata)
.finish_non_exhaustive(),
}
}
}
@ -220,7 +226,7 @@ impl std::fmt::Debug for Crease {
#[derive(Clone, Debug)]
struct CreaseItem {
id: CreaseId,
crease: Crease,
crease: Crease<Anchor>,
}
impl CreaseMap {
@ -230,7 +236,7 @@ impl CreaseMap {
pub fn insert(
&mut self,
creases: impl IntoIterator<Item = Crease>,
creases: impl IntoIterator<Item = Crease<Anchor>>,
snapshot: &MultiBufferSnapshot,
) -> Vec<CreaseId> {
let mut new_ids = Vec::new();

View file

@ -6706,7 +6706,7 @@ impl Editor {
buffer.edit([(range, text)], None, cx);
}
});
this.fold_ranges(refold_ranges, true, cx);
this.fold_creases(refold_ranges, true, cx);
this.change_selections(Some(Autoscroll::fit()), cx, |s| {
s.select(new_selections);
})
@ -6800,7 +6800,7 @@ impl Editor {
buffer.edit([(range, text)], None, cx);
}
});
this.fold_ranges(refold_ranges, true, cx);
this.fold_creases(refold_ranges, true, cx);
this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
});
}
@ -10703,7 +10703,7 @@ impl Editor {
}
pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
let mut fold_ranges = Vec::new();
let mut to_fold = Vec::new();
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let selections = self.selections.all_adjusted(cx);
@ -10715,12 +10715,10 @@ impl Editor {
let mut found = false;
let mut row = range.start.row;
while row <= range.end.row {
if let Some((foldable_range, fold_text)) =
{ display_map.foldable_range(MultiBufferRow(row)) }
{
if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
found = true;
row = foldable_range.end.row + 1;
fold_ranges.push((foldable_range, fold_text));
row = crease.range().end.row + 1;
to_fold.push(crease);
} else {
row += 1
}
@ -10731,11 +10729,9 @@ impl Editor {
}
for row in (0..=range.start.row).rev() {
if let Some((foldable_range, fold_text)) =
display_map.foldable_range(MultiBufferRow(row))
{
if foldable_range.end.row >= buffer_start_row {
fold_ranges.push((foldable_range, fold_text));
if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
if crease.range().end.row >= buffer_start_row {
to_fold.push(crease);
if row <= range.start.row {
break;
}
@ -10744,26 +10740,29 @@ impl Editor {
}
}
self.fold_ranges(fold_ranges, true, cx);
self.fold_creases(to_fold, true, cx);
}
fn fold_at_level(&mut self, fold_at: &FoldAtLevel, cx: &mut ViewContext<Self>) {
let fold_at_level = fold_at.level;
let snapshot = self.buffer.read(cx).snapshot(cx);
let mut fold_ranges = Vec::new();
let mut to_fold = Vec::new();
let mut stack = vec![(0, snapshot.max_buffer_row().0, 1)];
while let Some((mut start_row, end_row, current_level)) = stack.pop() {
while start_row < end_row {
match self.snapshot(cx).foldable_range(MultiBufferRow(start_row)) {
Some(foldable_range) => {
let nested_start_row = foldable_range.0.start.row + 1;
let nested_end_row = foldable_range.0.end.row;
match self
.snapshot(cx)
.crease_for_buffer_row(MultiBufferRow(start_row))
{
Some(crease) => {
let nested_start_row = crease.range().start.row + 1;
let nested_end_row = crease.range().end.row;
if current_level < fold_at_level {
stack.push((nested_start_row, nested_end_row, current_level + 1));
} else if current_level == fold_at_level {
fold_ranges.push(foldable_range);
to_fold.push(crease);
}
start_row = nested_end_row + 1;
@ -10773,7 +10772,7 @@ impl Editor {
}
}
self.fold_ranges(fold_ranges, true, cx);
self.fold_creases(to_fold, true, cx);
}
pub fn fold_all(&mut self, _: &actions::FoldAll, cx: &mut ViewContext<Self>) {
@ -10781,16 +10780,18 @@ impl Editor {
let snapshot = self.buffer.read(cx).snapshot(cx);
for row in 0..snapshot.max_buffer_row().0 {
if let Some(foldable_range) = self.snapshot(cx).foldable_range(MultiBufferRow(row)) {
if let Some(foldable_range) =
self.snapshot(cx).crease_for_buffer_row(MultiBufferRow(row))
{
fold_ranges.push(foldable_range);
}
}
self.fold_ranges(fold_ranges, true, cx);
self.fold_creases(fold_ranges, true, cx);
}
pub fn fold_recursive(&mut self, _: &actions::FoldRecursive, cx: &mut ViewContext<Self>) {
let mut fold_ranges = Vec::new();
let mut to_fold = Vec::new();
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let selections = self.selections.all_adjusted(cx);
@ -10801,11 +10802,9 @@ impl Editor {
if range.start.row != range.end.row {
let mut found = false;
for row in range.start.row..=range.end.row {
if let Some((foldable_range, fold_text)) =
{ display_map.foldable_range(MultiBufferRow(row)) }
{
if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
found = true;
fold_ranges.push((foldable_range, fold_text));
to_fold.push(crease);
}
}
if found {
@ -10814,11 +10813,9 @@ impl Editor {
}
for row in (0..=range.start.row).rev() {
if let Some((foldable_range, fold_text)) =
display_map.foldable_range(MultiBufferRow(row))
{
if foldable_range.end.row >= buffer_start_row {
fold_ranges.push((foldable_range, fold_text));
if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
if crease.range().end.row >= buffer_start_row {
to_fold.push(crease);
} else {
break;
}
@ -10826,21 +10823,21 @@ impl Editor {
}
}
self.fold_ranges(fold_ranges, true, cx);
self.fold_creases(to_fold, true, cx);
}
pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
let buffer_row = fold_at.buffer_row;
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
if let Some((fold_range, placeholder)) = display_map.foldable_range(buffer_row) {
if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
let autoscroll = self
.selections
.all::<Point>(cx)
.iter()
.any(|selection| fold_range.overlaps(&selection.range()));
.any(|selection| crease.range().overlaps(&selection.range()));
self.fold_ranges([(fold_range, placeholder)], autoscroll, cx);
self.fold_creases([crease], autoscroll, cx);
}
}
@ -10927,12 +10924,12 @@ impl Editor {
(s.start..s.end, display_map.fold_placeholder.clone())
}
});
self.fold_ranges(ranges, true, cx);
self.fold_creases(ranges, true, cx);
}
pub fn fold_ranges<T: ToOffset + Clone>(
pub fn fold_creases<T: ToOffset + Clone>(
&mut self,
ranges: impl IntoIterator<Item = (Range<T>, FoldPlaceholder)>,
ranges: impl IntoIterator<Item = Crease<T>>,
auto_scroll: bool,
cx: &mut ViewContext<Self>,
) {
@ -11102,7 +11099,7 @@ impl Editor {
pub fn insert_creases(
&mut self,
creases: impl IntoIterator<Item = Crease>,
creases: impl IntoIterator<Item = Crease<Anchor>>,
cx: &mut ViewContext<Self>,
) -> Vec<CreaseId> {
self.display_map

View file

@ -592,7 +592,7 @@ fn test_clone(cx: &mut TestAppContext) {
_ = editor.update(cx, |editor, cx| {
editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
editor.fold_ranges(
editor.fold_creases(
[
(Point::new(1, 0)..Point::new(2, 0), FoldPlaceholder::test()),
(Point::new(3, 0)..Point::new(4, 0), FoldPlaceholder::test()),
@ -1279,7 +1279,7 @@ fn test_move_cursor_multibyte(cx: &mut TestAppContext) {
assert_eq!('α'.len_utf8(), 2);
_ = view.update(cx, |view, cx| {
view.fold_ranges(
view.fold_creases(
vec![
(Point::new(0, 6)..Point::new(0, 12), FoldPlaceholder::test()),
(Point::new(1, 2)..Point::new(1, 4), FoldPlaceholder::test()),
@ -3871,7 +3871,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) {
build_editor(buffer, cx)
});
_ = view.update(cx, |view, cx| {
view.fold_ranges(
view.fold_creases(
vec![
(Point::new(0, 2)..Point::new(1, 2), FoldPlaceholder::test()),
(Point::new(2, 3)..Point::new(4, 1), FoldPlaceholder::test()),
@ -4770,7 +4770,7 @@ fn test_split_selection_into_lines(cx: &mut TestAppContext) {
build_editor(buffer, cx)
});
_ = view.update(cx, |view, cx| {
view.fold_ranges(
view.fold_creases(
vec![
(Point::new(0, 2)..Point::new(1, 2), FoldPlaceholder::test()),
(Point::new(2, 3)..Point::new(4, 1), FoldPlaceholder::test()),
@ -5451,7 +5451,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
// Ensure that we keep expanding the selection if the larger selection starts or ends within
// a fold.
editor.update(cx, |view, cx| {
view.fold_ranges(
view.fold_creases(
vec![
(
Point::new(0, 21)..Point::new(0, 24),