Integrate MultiBuffer::buffer_rows into the display map
This commit is contained in:
parent
db33e4935a
commit
6444fcd442
4 changed files with 146 additions and 67 deletions
|
@ -1263,6 +1263,7 @@ mod tests {
|
||||||
.sort_unstable_by_key(|(id, block)| (block.position.row, block.disposition, *id));
|
.sort_unstable_by_key(|(id, block)| (block.position.row, block.disposition, *id));
|
||||||
let mut sorted_blocks = sorted_blocks.into_iter().peekable();
|
let mut sorted_blocks = sorted_blocks.into_iter().peekable();
|
||||||
|
|
||||||
|
let input_buffer_rows = buffer_snapshot.buffer_rows(0).collect::<Vec<_>>();
|
||||||
let mut expected_buffer_rows = Vec::new();
|
let mut expected_buffer_rows = Vec::new();
|
||||||
let mut expected_text = String::new();
|
let mut expected_text = String::new();
|
||||||
let input_text = wraps_snapshot.text();
|
let input_text = wraps_snapshot.text();
|
||||||
|
@ -1272,9 +1273,9 @@ mod tests {
|
||||||
expected_text.push('\n');
|
expected_text.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
let buffer_row = wraps_snapshot
|
let buffer_row = input_buffer_rows[wraps_snapshot
|
||||||
.to_point(WrapPoint::new(row, 0), Bias::Left)
|
.to_point(WrapPoint::new(row, 0), Bias::Left)
|
||||||
.row;
|
.row as usize];
|
||||||
|
|
||||||
while let Some((_, block)) = sorted_blocks.peek() {
|
while let Some((_, block)) = sorted_blocks.peek() {
|
||||||
if block.position.row == row && block.disposition == BlockDisposition::Above {
|
if block.position.row == row && block.disposition == BlockDisposition::Above {
|
||||||
|
@ -1290,7 +1291,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let soft_wrapped = wraps_snapshot.to_tab_point(WrapPoint::new(row, 0)).column() > 0;
|
let soft_wrapped = wraps_snapshot.to_tab_point(WrapPoint::new(row, 0)).column() > 0;
|
||||||
expected_buffer_rows.push(if soft_wrapped { None } else { Some(buffer_row) });
|
expected_buffer_rows.push(if soft_wrapped { None } else { buffer_row });
|
||||||
expected_text.push_str(input_line);
|
expected_text.push_str(input_line);
|
||||||
|
|
||||||
while let Some((_, block)) = sorted_blocks.peek() {
|
while let Some((_, block)) = sorted_blocks.peek() {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use crate::{Anchor, AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot, ToOffset};
|
use crate::{
|
||||||
|
multi_buffer::MultiBufferRows, Anchor, AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot,
|
||||||
|
ToOffset,
|
||||||
|
};
|
||||||
use language::{Chunk, Edit, Point, PointUtf16, TextSummary};
|
use language::{Chunk, Edit, Point, PointUtf16, TextSummary};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -563,9 +566,18 @@ impl FoldSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
let fold_point = FoldPoint::new(start_row, 0);
|
let fold_point = FoldPoint::new(start_row, 0);
|
||||||
let mut cursor = self.transforms.cursor();
|
let mut cursor = self.transforms.cursor::<(FoldPoint, Point)>();
|
||||||
cursor.seek(&fold_point, Bias::Left, &());
|
cursor.seek(&fold_point, Bias::Left, &());
|
||||||
FoldBufferRows { fold_point, cursor }
|
|
||||||
|
let overshoot = fold_point.0 - cursor.start().0 .0;
|
||||||
|
let buffer_point = cursor.start().1 + overshoot;
|
||||||
|
let input_buffer_rows = self.buffer_snapshot.buffer_rows(buffer_point.row);
|
||||||
|
|
||||||
|
FoldBufferRows {
|
||||||
|
fold_point,
|
||||||
|
input_buffer_rows,
|
||||||
|
cursor,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_point(&self) -> FoldPoint {
|
pub fn max_point(&self) -> FoldPoint {
|
||||||
|
@ -897,26 +909,30 @@ impl<'a> sum_tree::Dimension<'a, FoldSummary> for usize {
|
||||||
|
|
||||||
pub struct FoldBufferRows<'a> {
|
pub struct FoldBufferRows<'a> {
|
||||||
cursor: Cursor<'a, Transform, (FoldPoint, Point)>,
|
cursor: Cursor<'a, Transform, (FoldPoint, Point)>,
|
||||||
|
input_buffer_rows: MultiBufferRows<'a>,
|
||||||
fold_point: FoldPoint,
|
fold_point: FoldPoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for FoldBufferRows<'a> {
|
impl<'a> Iterator for FoldBufferRows<'a> {
|
||||||
type Item = u32;
|
type Item = Option<u32>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut traversed_fold = false;
|
||||||
while self.fold_point > self.cursor.end(&()).0 {
|
while self.fold_point > self.cursor.end(&()).0 {
|
||||||
self.cursor.next(&());
|
self.cursor.next(&());
|
||||||
|
traversed_fold = true;
|
||||||
if self.cursor.item().is_none() {
|
if self.cursor.item().is_none() {
|
||||||
// TODO: Return a bool from next?
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.cursor.item().is_some() {
|
if self.cursor.item().is_some() {
|
||||||
let overshoot = self.fold_point.0 - self.cursor.start().0 .0;
|
if traversed_fold {
|
||||||
let buffer_point = self.cursor.start().1 + overshoot;
|
self.input_buffer_rows.seek(self.cursor.start().1.row);
|
||||||
|
self.input_buffer_rows.next();
|
||||||
|
}
|
||||||
*self.fold_point.row_mut() += 1;
|
*self.fold_point.row_mut() += 1;
|
||||||
Some(buffer_point.row)
|
self.input_buffer_rows.next()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1282,20 +1298,38 @@ mod tests {
|
||||||
snapshot_edits.push((snapshot.clone(), edits));
|
snapshot_edits.push((snapshot.clone(), edits));
|
||||||
|
|
||||||
let mut expected_text: String = buffer_snapshot.text().to_string();
|
let mut expected_text: String = buffer_snapshot.text().to_string();
|
||||||
let mut expected_buffer_rows = Vec::new();
|
|
||||||
let mut next_row = buffer_snapshot.max_point().row;
|
|
||||||
for fold_range in map.merged_fold_ranges().into_iter().rev() {
|
for fold_range in map.merged_fold_ranges().into_iter().rev() {
|
||||||
let fold_start = buffer_snapshot.offset_to_point(fold_range.start);
|
|
||||||
let fold_end = buffer_snapshot.offset_to_point(fold_range.end);
|
|
||||||
expected_buffer_rows.extend((fold_end.row + 1..=next_row).rev());
|
|
||||||
next_row = fold_start.row;
|
|
||||||
|
|
||||||
expected_text.replace_range(fold_range.start..fold_range.end, "…");
|
expected_text.replace_range(fold_range.start..fold_range.end, "…");
|
||||||
}
|
}
|
||||||
expected_buffer_rows.extend((0..=next_row).rev());
|
|
||||||
expected_buffer_rows.reverse();
|
|
||||||
|
|
||||||
assert_eq!(snapshot.text(), expected_text);
|
assert_eq!(snapshot.text(), expected_text);
|
||||||
|
log::info!(
|
||||||
|
"fold text {:?} ({} lines)",
|
||||||
|
expected_text,
|
||||||
|
expected_text.matches('\n').count() + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut prev_row = 0;
|
||||||
|
let mut expected_buffer_rows = Vec::new();
|
||||||
|
for fold_range in map.merged_fold_ranges().into_iter() {
|
||||||
|
let fold_start = buffer_snapshot.offset_to_point(fold_range.start).row;
|
||||||
|
let fold_end = buffer_snapshot.offset_to_point(fold_range.end).row;
|
||||||
|
expected_buffer_rows.extend(
|
||||||
|
buffer_snapshot
|
||||||
|
.buffer_rows(prev_row)
|
||||||
|
.take((1 + fold_start - prev_row) as usize),
|
||||||
|
);
|
||||||
|
prev_row = 1 + fold_end;
|
||||||
|
}
|
||||||
|
expected_buffer_rows.extend(buffer_snapshot.buffer_rows(prev_row));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
expected_buffer_rows.len(),
|
||||||
|
expected_text.matches('\n').count() + 1,
|
||||||
|
"wrong expected buffer rows {:?}. text: {:?}",
|
||||||
|
expected_buffer_rows,
|
||||||
|
expected_text
|
||||||
|
);
|
||||||
|
|
||||||
for (output_row, line) in expected_text.lines().enumerate() {
|
for (output_row, line) in expected_text.lines().enumerate() {
|
||||||
let line_len = snapshot.line_len(output_row as u32);
|
let line_len = snapshot.line_len(output_row as u32);
|
||||||
|
@ -1373,14 +1407,19 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (idx, buffer_row) in expected_buffer_rows.iter().enumerate() {
|
let mut fold_row = 0;
|
||||||
let fold_row = Point::new(*buffer_row, 0)
|
while fold_row < expected_buffer_rows.len() as u32 {
|
||||||
.to_fold_point(&snapshot, Right)
|
fold_row = snapshot
|
||||||
|
.clip_point(FoldPoint::new(fold_row, 0), Bias::Right)
|
||||||
.row();
|
.row();
|
||||||
|
eprintln!("fold_row: {} of {}", fold_row, expected_buffer_rows.len());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
snapshot.buffer_rows(fold_row).collect::<Vec<_>>(),
|
snapshot.buffer_rows(fold_row).collect::<Vec<_>>(),
|
||||||
expected_buffer_rows[idx..],
|
expected_buffer_rows[(fold_row as usize)..],
|
||||||
|
"wrong buffer rows starting at fold row {}",
|
||||||
|
fold_row,
|
||||||
);
|
);
|
||||||
|
fold_row += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for fold_range in map.merged_fold_ranges() {
|
for fold_range in map.merged_fold_ranges() {
|
||||||
|
@ -1470,8 +1509,11 @@ mod tests {
|
||||||
|
|
||||||
let (snapshot, _) = map.read(buffer_snapshot.clone(), vec![]);
|
let (snapshot, _) = map.read(buffer_snapshot.clone(), vec![]);
|
||||||
assert_eq!(snapshot.text(), "aa…cccc\nd…eeeee\nffffff\n");
|
assert_eq!(snapshot.text(), "aa…cccc\nd…eeeee\nffffff\n");
|
||||||
assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), [0, 3, 5, 6]);
|
assert_eq!(
|
||||||
assert_eq!(snapshot.buffer_rows(3).collect::<Vec<_>>(), [6]);
|
snapshot.buffer_rows(0).collect::<Vec<_>>(),
|
||||||
|
[Some(0), Some(3), Some(5), Some(6)]
|
||||||
|
);
|
||||||
|
assert_eq!(snapshot.buffer_rows(3).collect::<Vec<_>>(), [Some(6)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FoldMap {
|
impl FoldMap {
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub struct WrapChunks<'a> {
|
||||||
|
|
||||||
pub struct WrapBufferRows<'a> {
|
pub struct WrapBufferRows<'a> {
|
||||||
input_buffer_rows: fold_map::FoldBufferRows<'a>,
|
input_buffer_rows: fold_map::FoldBufferRows<'a>,
|
||||||
input_buffer_row: u32,
|
input_buffer_row: Option<u32>,
|
||||||
output_row: u32,
|
output_row: u32,
|
||||||
soft_wrapped: bool,
|
soft_wrapped: bool,
|
||||||
max_output_row: u32,
|
max_output_row: u32,
|
||||||
|
@ -751,22 +751,19 @@ impl WrapSnapshot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let input_buffer_rows = self.buffer_snapshot().buffer_rows(0).collect::<Vec<_>>();
|
||||||
let mut expected_buffer_rows = Vec::new();
|
let mut expected_buffer_rows = Vec::new();
|
||||||
let mut buffer_row = 0;
|
|
||||||
let mut prev_tab_row = 0;
|
let mut prev_tab_row = 0;
|
||||||
for display_row in 0..=self.max_point().row() {
|
for display_row in 0..=self.max_point().row() {
|
||||||
let tab_point = self.to_tab_point(WrapPoint::new(display_row, 0));
|
let tab_point = self.to_tab_point(WrapPoint::new(display_row, 0));
|
||||||
let soft_wrapped;
|
if tab_point.row() == prev_tab_row && display_row != 0 {
|
||||||
if tab_point.row() == prev_tab_row {
|
expected_buffer_rows.push(None);
|
||||||
soft_wrapped = display_row != 0;
|
|
||||||
} else {
|
} else {
|
||||||
let fold_point = self.tab_snapshot.to_fold_point(tab_point, Bias::Left).0;
|
let fold_point = self.tab_snapshot.to_fold_point(tab_point, Bias::Left).0;
|
||||||
let buffer_point = fold_point.to_buffer_point(&self.tab_snapshot.fold_snapshot);
|
let buffer_point = fold_point.to_buffer_point(&self.tab_snapshot.fold_snapshot);
|
||||||
buffer_row = buffer_point.row;
|
expected_buffer_rows.push(input_buffer_rows[buffer_point.row as usize]);
|
||||||
prev_tab_row = tab_point.row();
|
prev_tab_row = tab_point.row();
|
||||||
soft_wrapped = false;
|
|
||||||
}
|
}
|
||||||
expected_buffer_rows.push(if soft_wrapped { None } else { Some(buffer_row) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for start_display_row in 0..expected_buffer_rows.len() {
|
for start_display_row in 0..expected_buffer_rows.len() {
|
||||||
|
@ -866,7 +863,7 @@ impl<'a> Iterator for WrapBufferRows<'a> {
|
||||||
self.soft_wrapped = true;
|
self.soft_wrapped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(if soft_wrapped { None } else { Some(buffer_row) })
|
Some(if soft_wrapped { None } else { buffer_row })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1059,29 +1059,13 @@ impl MultiBufferSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
|
pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
|
||||||
let mut excerpts = self.excerpts.cursor::<Point>();
|
let mut result = MultiBufferRows {
|
||||||
excerpts.seek(&Point::new(start_row, 0), Bias::Right, &());
|
header_height: 0,
|
||||||
if excerpts.item().is_none() {
|
buffer_row_range: 0..0,
|
||||||
excerpts.prev(&());
|
excerpts: self.excerpts.cursor(),
|
||||||
}
|
};
|
||||||
|
result.seek(start_row);
|
||||||
let mut header_height = 0;
|
result
|
||||||
let mut buffer_row_range = 0..0;
|
|
||||||
if let Some(excerpt) = excerpts.item() {
|
|
||||||
let overshoot = start_row - excerpts.start().row;
|
|
||||||
let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
|
|
||||||
let excerpt_header_height = excerpt.header_height as u32;
|
|
||||||
header_height = excerpt_header_height.saturating_sub(overshoot);
|
|
||||||
buffer_row_range.start =
|
|
||||||
excerpt_start + overshoot.saturating_sub(excerpt_header_height);
|
|
||||||
buffer_row_range.end =
|
|
||||||
excerpt_start + excerpt.text_summary.lines.row + 1 - excerpt_header_height;
|
|
||||||
}
|
|
||||||
MultiBufferRows {
|
|
||||||
header_height,
|
|
||||||
buffer_row_range,
|
|
||||||
excerpts,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chunks<'a, T: ToOffset>(
|
pub fn chunks<'a, T: ToOffset>(
|
||||||
|
@ -1853,6 +1837,36 @@ impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> MultiBufferRows<'a> {
|
||||||
|
pub fn seek(&mut self, row: u32) {
|
||||||
|
self.header_height = 0;
|
||||||
|
self.buffer_row_range = 0..0;
|
||||||
|
|
||||||
|
self.excerpts
|
||||||
|
.seek_forward(&Point::new(row, 0), Bias::Right, &());
|
||||||
|
if self.excerpts.item().is_none() {
|
||||||
|
self.excerpts.prev(&());
|
||||||
|
|
||||||
|
if self.excerpts.item().is_none() && row == 0 {
|
||||||
|
self.buffer_row_range = 0..1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(excerpt) = self.excerpts.item() {
|
||||||
|
let overshoot = row - self.excerpts.start().row;
|
||||||
|
let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer).row;
|
||||||
|
let excerpt_header_height = excerpt.header_height as u32;
|
||||||
|
|
||||||
|
self.header_height = excerpt_header_height.saturating_sub(overshoot);
|
||||||
|
self.buffer_row_range.start =
|
||||||
|
excerpt_start + overshoot.saturating_sub(excerpt_header_height);
|
||||||
|
self.buffer_row_range.end =
|
||||||
|
excerpt_start + excerpt.text_summary.lines.row + 1 - excerpt_header_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for MultiBufferRows<'a> {
|
impl<'a> Iterator for MultiBufferRows<'a> {
|
||||||
type Item = Option<u32>;
|
type Item = Option<u32>;
|
||||||
|
|
||||||
|
@ -1867,16 +1881,14 @@ impl<'a> Iterator for MultiBufferRows<'a> {
|
||||||
self.buffer_row_range.start += 1;
|
self.buffer_row_range.start += 1;
|
||||||
return Some(row);
|
return Some(row);
|
||||||
}
|
}
|
||||||
|
self.excerpts.item()?;
|
||||||
self.excerpts.next(&());
|
self.excerpts.next(&());
|
||||||
if let Some(excerpt) = self.excerpts.item() {
|
let excerpt = self.excerpts.item()?;
|
||||||
self.header_height = excerpt.header_height as u32;
|
self.header_height = excerpt.header_height as u32;
|
||||||
self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
|
self.buffer_row_range.start = excerpt.range.start.to_point(&excerpt.buffer).row;
|
||||||
self.buffer_row_range.end =
|
self.buffer_row_range.end =
|
||||||
self.buffer_row_range.start + excerpt.text_summary.lines.row + 1
|
self.buffer_row_range.start + excerpt.text_summary.lines.row + 1
|
||||||
- self.header_height;
|
- self.header_height;
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2179,6 +2191,23 @@ mod tests {
|
||||||
Some(3)
|
Some(3)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
snapshot.buffer_rows(2).collect::<Vec<_>>(),
|
||||||
|
&[
|
||||||
|
Some(1),
|
||||||
|
Some(2),
|
||||||
|
None,
|
||||||
|
Some(3),
|
||||||
|
Some(4),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(3)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert_eq!(snapshot.buffer_rows(10).collect::<Vec<_>>(), &[Some(3)]);
|
||||||
|
assert_eq!(snapshot.buffer_rows(11).collect::<Vec<_>>(), &[]);
|
||||||
|
assert_eq!(snapshot.buffer_rows(12).collect::<Vec<_>>(), &[]);
|
||||||
|
|
||||||
{
|
{
|
||||||
let snapshot = multibuffer.read(cx).read(cx);
|
let snapshot = multibuffer.read(cx).read(cx);
|
||||||
|
@ -2283,6 +2312,16 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_empty_excerpt_buffer(cx: &mut MutableAppContext) {
|
||||||
|
let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
|
||||||
|
|
||||||
|
let snapshot = multibuffer.read(cx).snapshot(cx);
|
||||||
|
assert_eq!(snapshot.text(), "");
|
||||||
|
assert_eq!(snapshot.buffer_rows(0).collect::<Vec<_>>(), &[Some(0)]);
|
||||||
|
assert_eq!(snapshot.buffer_rows(1).collect::<Vec<_>>(), &[]);
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
|
fn test_singleton_multibuffer_anchors(cx: &mut MutableAppContext) {
|
||||||
let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
|
let buffer = cx.add_model(|cx| Buffer::new(0, "abcd", cx));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue