Don't insert headers in MultiBuffer

This lays the groundwork to insert headers in the block map instead.
This commit is contained in:
Antonio Scandurra 2021-12-21 16:38:18 +01:00
parent 99317bbd62
commit 8534a9cc41
4 changed files with 165 additions and 385 deletions

View File

@ -348,11 +348,12 @@ impl DisplaySnapshot {
&'a self,
rows: Range<u32>,
) -> impl 'a + Iterator<Item = (Range<u32>, RenderHeaderFn)> {
todo!();
let start_row = DisplayPoint::new(rows.start, 0).to_point(self).row;
let end_row = DisplayPoint::new(rows.end, 0).to_point(self).row;
self.buffer_snapshot
.excerpt_headers_in_range(start_row..end_row)
.map(move |(rows, render)| {
.map(move |(row, header_height, render)| {
let start_row = Point::new(rows.start, 0).to_display_point(self).row();
let end_row = Point::new(rows.end, 0).to_display_point(self).row();
(start_row..end_row, render)

View File

@ -114,7 +114,6 @@ struct ExcerptSummary {
}
pub struct MultiBufferRows<'a> {
header_height: u32,
buffer_row_range: Range<u32>,
excerpts: Cursor<'a, Excerpt, Point>,
}
@ -134,13 +133,11 @@ pub struct MultiBufferBytes<'a> {
}
struct ExcerptChunks<'a> {
header_height: usize,
content_chunks: BufferChunks<'a>,
footer_height: usize,
}
struct ExcerptBytes<'a> {
header_height: usize,
content_bytes: language::rope::Bytes<'a>,
footer_height: usize,
}
@ -326,8 +323,7 @@ impl MultiBuffer {
cursor.prev(&());
}
let start_excerpt = cursor.item().expect("start offset out of bounds");
let start_overshoot =
(start - cursor.start()).saturating_sub(start_excerpt.header_height as usize);
let start_overshoot = start - cursor.start();
let buffer_start =
start_excerpt.range.start.to_offset(&start_excerpt.buffer) + start_overshoot;
@ -336,8 +332,7 @@ impl MultiBuffer {
cursor.prev(&());
}
let end_excerpt = cursor.item().expect("end offset out of bounds");
let end_overshoot =
(end - cursor.start()).saturating_sub(end_excerpt.header_height as usize);
let end_overshoot = end - cursor.start();
let buffer_end = end_excerpt.range.start.to_offset(&end_excerpt.buffer) + end_overshoot;
if start_excerpt.id == end_excerpt.id {
@ -749,10 +744,8 @@ impl MultiBuffer {
old_excerpt.range.clone(),
)
.map(|mut edit| {
let excerpt_old_start =
cursor.start().1 + old_excerpt.header_height as usize;
let excerpt_new_start = new_excerpts.summary().text.bytes
+ old_excerpt.header_height as usize;
let excerpt_old_start = cursor.start().1;
let excerpt_new_start = new_excerpts.summary().text.bytes;
edit.old.start += excerpt_old_start;
edit.old.end += excerpt_old_start;
edit.new.start += excerpt_new_start;
@ -831,14 +824,12 @@ impl MultiBufferSnapshot {
pub fn excerpt_headers_in_range<'a>(
&'a self,
range: Range<u32>,
) -> impl 'a + Iterator<Item = (Range<u32>, RenderHeaderFn)> {
) -> impl 'a + Iterator<Item = (u32, u8, RenderHeaderFn)> {
let mut cursor = self.excerpts.cursor::<Point>();
cursor.seek(&Point::new(range.start, 0), Bias::Right, &());
if let Some(excerpt) = cursor.item() {
if range.start >= cursor.start().row + excerpt.header_height as u32 {
cursor.next(&());
}
if cursor.item().is_some() && range.start > cursor.start().row {
cursor.next(&());
}
iter::from_fn(move || {
@ -849,9 +840,8 @@ impl MultiBufferSnapshot {
if let Some(render) = excerpt.render_header.clone() {
let start = cursor.start().row;
let end = start + excerpt.header_height as u32;
cursor.next(&());
return Some((start..end, render));
return Some((start, excerpt.header_height, render));
} else {
cursor.next(&());
}
@ -868,12 +858,9 @@ impl MultiBufferSnapshot {
let mut cursor = self.excerpts.cursor::<usize>();
cursor.seek(&offset, Bias::Left, &());
let mut excerpt_chunks = cursor.item().map(|excerpt| {
let start_after_header = cursor.start() + excerpt.header_height as usize;
let end_before_footer = cursor.start() + excerpt.text_summary.bytes;
let start = excerpt.range.start.to_offset(&excerpt.buffer);
let end =
start + (cmp::min(offset, end_before_footer).saturating_sub(start_after_header));
let end = start + (cmp::min(offset, end_before_footer) - cursor.start());
excerpt.buffer.reversed_chunks_in_range(start..end)
});
iter::from_fn(move || {
@ -888,11 +875,7 @@ impl MultiBufferSnapshot {
}
let excerpt = cursor.item().unwrap();
if offset <= cursor.start() + excerpt.header_height as usize {
let header_height = offset - cursor.start();
offset -= header_height;
Some(unsafe { str::from_utf8_unchecked(&NEWLINES[..header_height]) })
} else if offset == cursor.end(&()) && excerpt.has_trailing_newline {
if offset == cursor.end(&()) && excerpt.has_trailing_newline {
offset -= 1;
Some("\n")
} else {
@ -953,93 +936,48 @@ impl MultiBufferSnapshot {
pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
let mut cursor = self.excerpts.cursor::<usize>();
cursor.seek(&offset, Bias::Right, &());
if let Some(excerpt) = cursor.item() {
let header_end = *cursor.start() + excerpt.header_height as usize;
if offset < header_end {
if bias == Bias::Left {
cursor.prev(&());
if let Some(excerpt) = cursor.item() {
return *cursor.start() + excerpt.text_summary.bytes;
}
}
header_end
} else {
let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
let buffer_offset = excerpt
.buffer
.clip_offset(excerpt_start + (offset - header_end), bias);
let offset_in_excerpt = if buffer_offset > excerpt_start {
buffer_offset - excerpt_start
} else {
0
};
header_end + offset_in_excerpt
}
let overshoot = if let Some(excerpt) = cursor.item() {
let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
let buffer_offset = excerpt
.buffer
.clip_offset(excerpt_start + (offset - cursor.start()), bias);
buffer_offset.saturating_sub(excerpt_start)
} else {
self.excerpts.summary().text.bytes
}
0
};
cursor.start() + overshoot
}
pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
let mut cursor = self.excerpts.cursor::<Point>();
cursor.seek(&point, Bias::Right, &());
if let Some(excerpt) = cursor.item() {
let header_end = *cursor.start() + Point::new(excerpt.header_height as u32, 0);
if point < header_end {
if bias == Bias::Left {
cursor.prev(&());
if let Some(excerpt) = cursor.item() {
return *cursor.start() + excerpt.text_summary.lines;
}
}
header_end
} else {
let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
let buffer_point = excerpt
.buffer
.clip_point(excerpt_start + (point - header_end), bias);
let point_in_excerpt = if buffer_point > excerpt_start {
buffer_point - excerpt_start
} else {
Point::zero()
};
header_end + point_in_excerpt
}
let overshoot = if let Some(excerpt) = cursor.item() {
let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
let buffer_point = excerpt
.buffer
.clip_point(excerpt_start + (point - cursor.start()), bias);
buffer_point.saturating_sub(excerpt_start)
} else {
self.excerpts.summary().text.lines
}
Point::zero()
};
*cursor.start() + overshoot
}
pub fn clip_point_utf16(&self, point: PointUtf16, bias: Bias) -> PointUtf16 {
let mut cursor = self.excerpts.cursor::<PointUtf16>();
cursor.seek(&point, Bias::Right, &());
if let Some(excerpt) = cursor.item() {
let header_end = *cursor.start() + PointUtf16::new(excerpt.header_height as u32, 0);
if point < header_end {
if bias == Bias::Left {
cursor.prev(&());
if let Some(excerpt) = cursor.item() {
return *cursor.start() + excerpt.text_summary.lines_utf16;
}
}
header_end
} else {
let excerpt_start = excerpt
.buffer
.offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
let buffer_point = excerpt
.buffer
.clip_point_utf16(excerpt_start + (point - header_end), bias);
let point_in_excerpt = if buffer_point > excerpt_start {
buffer_point - excerpt_start
} else {
PointUtf16::new(0, 0)
};
header_end + point_in_excerpt
}
let overshoot = if let Some(excerpt) = cursor.item() {
let excerpt_start = excerpt
.buffer
.offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
let buffer_point = excerpt
.buffer
.clip_point_utf16(excerpt_start + (point - cursor.start()), bias);
buffer_point.saturating_sub(excerpt_start)
} else {
self.excerpts.summary().text.lines_utf16
}
PointUtf16::zero()
};
*cursor.start() + overshoot
}
pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> MultiBufferBytes<'a> {
@ -1067,7 +1005,6 @@ impl MultiBufferSnapshot {
pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
let mut result = MultiBufferRows {
header_height: 0,
buffer_row_range: 0..0,
excerpts: self.excerpts.cursor(),
};
@ -1097,19 +1034,12 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
let (start_offset, start_point) = cursor.start();
let overshoot = offset - start_offset;
let header_height = excerpt.header_height as usize;
if overshoot < header_height {
*start_point + Point::new(overshoot as u32, 0)
} else {
let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
let buffer_point = excerpt
.buffer
.offset_to_point(excerpt_start_offset + (overshoot - header_height));
*start_point
+ Point::new(header_height as u32, 0)
+ (buffer_point - excerpt_start_point)
}
let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
let buffer_point = excerpt
.buffer
.offset_to_point(excerpt_start_offset + overshoot);
*start_point + (buffer_point - excerpt_start_point)
} else {
self.excerpts.summary().text.lines
}
@ -1121,18 +1051,12 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
let (start_point, start_offset) = cursor.start();
let overshoot = point - start_point;
let header_height = Point::new(excerpt.header_height as u32, 0);
if overshoot < header_height {
start_offset + overshoot.row as usize
} else {
let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
let buffer_offset = excerpt
.buffer
.point_to_offset(excerpt_start_point + (overshoot - header_height));
*start_offset + excerpt.header_height as usize + buffer_offset
- excerpt_start_offset
}
let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
let excerpt_start_point = excerpt.range.start.to_point(&excerpt.buffer);
let buffer_offset = excerpt
.buffer
.point_to_offset(excerpt_start_point + overshoot);
*start_offset + buffer_offset - excerpt_start_offset
} else {
self.excerpts.summary().text.bytes
}
@ -1144,21 +1068,14 @@ impl MultiBufferSnapshot {
if let Some(excerpt) = cursor.item() {
let (start_point, start_offset) = cursor.start();
let overshoot = point - start_point;
let header_height = PointUtf16::new(excerpt.header_height as u32, 0);
if overshoot < header_height {
start_offset + overshoot.row as usize
} else {
let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
let excerpt_start_point = excerpt
.buffer
.offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
let buffer_offset = excerpt
.buffer
.point_utf16_to_offset(excerpt_start_point + (overshoot - header_height));
*start_offset
+ excerpt.header_height as usize
+ (buffer_offset - excerpt_start_offset)
}
let excerpt_start_offset = excerpt.range.start.to_offset(&excerpt.buffer);
let excerpt_start_point = excerpt
.buffer
.offset_to_point_utf16(excerpt.range.start.to_offset(&excerpt.buffer));
let buffer_offset = excerpt
.buffer
.point_utf16_to_offset(excerpt_start_point + overshoot);
*start_offset + (buffer_offset - excerpt_start_offset)
} else {
self.excerpts.summary().text.bytes
}
@ -1188,18 +1105,15 @@ impl MultiBufferSnapshot {
cursor.seek(&Point::new(row, 0), Bias::Right, &());
if let Some(excerpt) = cursor.item() {
let overshoot = row - cursor.start().row;
let header_height = excerpt.header_height as u32;
if overshoot >= header_height {
let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
let buffer_row = excerpt_start.row + overshoot - header_height;
let line_start = Point::new(buffer_row, 0);
let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
return Some((
&excerpt.buffer,
line_start.max(excerpt_start)..line_end.min(excerpt_end),
));
}
let excerpt_start = excerpt.range.start.to_point(&excerpt.buffer);
let excerpt_end = excerpt.range.end.to_point(&excerpt.buffer);
let buffer_row = excerpt_start.row + overshoot;
let line_start = Point::new(buffer_row, 0);
let line_end = Point::new(buffer_row, excerpt.buffer.line_len(buffer_row));
return Some((
&excerpt.buffer,
line_start.max(excerpt_start)..line_end.min(excerpt_end),
));
}
None
}
@ -1222,31 +1136,15 @@ impl MultiBufferSnapshot {
let mut cursor = self.excerpts.cursor::<usize>();
cursor.seek(&range.start, Bias::Right, &());
if let Some(excerpt) = cursor.item() {
let start_after_header = cursor.start() + excerpt.header_height as usize;
if range.start < start_after_header {
let header_len = cmp::min(range.end, start_after_header) - range.start;
summary.add_assign(&D::from_text_summary(&TextSummary {
bytes: header_len,
lines: Point::new(header_len as u32, 0),
lines_utf16: PointUtf16::new(header_len as u32, 0),
first_line_chars: 0,
last_line_chars: 0,
longest_row: 0,
longest_row_chars: 0,
}));
range.start = start_after_header;
range.end = cmp::max(range.start, range.end);
}
let mut end_before_newline = cursor.end(&());
if excerpt.has_trailing_newline {
end_before_newline -= 1;
}
let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
let start_in_excerpt = excerpt_start + (range.start - start_after_header);
let start_in_excerpt = excerpt_start + (range.start - cursor.start());
let end_in_excerpt =
excerpt_start + (cmp::min(end_before_newline, range.end) - start_after_header);
excerpt_start + (cmp::min(end_before_newline, range.end) - cursor.start());
summary.add_assign(
&excerpt
.buffer
@ -1275,28 +1173,15 @@ impl MultiBufferSnapshot {
&(),
)));
if let Some(excerpt) = cursor.item() {
let start_after_header = cursor.start() + excerpt.header_height as usize;
let header_len =
cmp::min(range.end - cursor.start(), excerpt.header_height as usize);
summary.add_assign(&D::from_text_summary(&TextSummary {
bytes: header_len,
lines: Point::new(header_len as u32, 0),
lines_utf16: PointUtf16::new(header_len as u32, 0),
first_line_chars: 0,
last_line_chars: 0,
longest_row: 0,
longest_row_chars: 0,
}));
range.end = cmp::max(start_after_header, range.end);
range.end = cmp::max(*cursor.start(), range.end);
let excerpt_start = excerpt.range.start.to_offset(&excerpt.buffer);
let end_in_excerpt = excerpt_start + (range.end - start_after_header);
let end_in_excerpt = excerpt_start + (range.end - cursor.start());
summary.add_assign(
&excerpt
.buffer
.text_summary_for_range(excerpt_start..end_in_excerpt),
);
cursor.next(&());
}
}
@ -1315,7 +1200,6 @@ impl MultiBufferSnapshot {
let mut position = D::from_text_summary(&cursor.start().text);
if let Some(excerpt) = cursor.item() {
position.add_summary(&excerpt.header_summary(), &());
if excerpt.id == anchor.excerpt_id {
let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
let buffer_position = anchor.text_anchor.summary::<D>(&excerpt.buffer);
@ -1351,9 +1235,8 @@ impl MultiBufferSnapshot {
cursor.next(&());
}
let mut position = D::from_text_summary(&cursor.start().text);
let position = D::from_text_summary(&cursor.start().text);
if let Some(excerpt) = cursor.item() {
position.add_summary(&excerpt.header_summary(), &());
if excerpt.id == *excerpt_id {
let excerpt_buffer_start = excerpt.range.start.summary::<D>(&excerpt.buffer);
summaries.extend(
@ -1395,8 +1278,7 @@ impl MultiBufferSnapshot {
cursor.prev(&());
}
if let Some(excerpt) = cursor.item() {
let start_after_header = cursor.start().0 + excerpt.header_height as usize;
let mut overshoot = offset.saturating_sub(start_after_header);
let mut overshoot = offset.saturating_sub(cursor.start().0);
if excerpt.has_trailing_newline && offset == cursor.end(&()).0 {
overshoot -= 1;
bias = Bias::Right;
@ -1458,14 +1340,12 @@ impl MultiBufferSnapshot {
let excerpt_buffer_start =
start_excerpt.range.start.to_offset(&start_excerpt.buffer);
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes
- start_excerpt.header_height as usize;
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
let start_after_header = cursor.start() + start_excerpt.header_height as usize;
let start_in_buffer =
excerpt_buffer_start + range.start.saturating_sub(start_after_header);
excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
let end_in_buffer =
excerpt_buffer_start + range.end.saturating_sub(start_after_header);
excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
let (mut start_bracket_range, mut end_bracket_range) = start_excerpt
.buffer
.enclosing_bracket_ranges(start_in_buffer..end_in_buffer)?;
@ -1474,13 +1354,13 @@ impl MultiBufferSnapshot {
&& end_bracket_range.end < excerpt_buffer_end
{
start_bracket_range.start =
start_after_header + (start_bracket_range.start - excerpt_buffer_start);
cursor.start() + (start_bracket_range.start - excerpt_buffer_start);
start_bracket_range.end =
start_after_header + (start_bracket_range.end - excerpt_buffer_start);
cursor.start() + (start_bracket_range.end - excerpt_buffer_start);
end_bracket_range.start =
start_after_header + (end_bracket_range.start - excerpt_buffer_start);
cursor.start() + (end_bracket_range.start - excerpt_buffer_start);
end_bracket_range.end =
start_after_header + (end_bracket_range.end - excerpt_buffer_start);
cursor.start() + (end_bracket_range.end - excerpt_buffer_start);
Some((start_bracket_range, end_bracket_range))
} else {
None
@ -1551,14 +1431,12 @@ impl MultiBufferSnapshot {
let excerpt_buffer_start =
start_excerpt.range.start.to_offset(&start_excerpt.buffer);
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes
- start_excerpt.header_height as usize;
let excerpt_buffer_end = excerpt_buffer_start + start_excerpt.text_summary.bytes;
let start_after_header = cursor.start() + start_excerpt.header_height as usize;
let start_in_buffer =
excerpt_buffer_start + range.start.saturating_sub(start_after_header);
excerpt_buffer_start + range.start.saturating_sub(*cursor.start());
let end_in_buffer =
excerpt_buffer_start + range.end.saturating_sub(start_after_header);
excerpt_buffer_start + range.end.saturating_sub(*cursor.start());
let mut ancestor_buffer_range = start_excerpt
.buffer
.range_for_syntax_ancestor(start_in_buffer..end_in_buffer)?;
@ -1566,9 +1444,8 @@ impl MultiBufferSnapshot {
cmp::max(ancestor_buffer_range.start, excerpt_buffer_start);
ancestor_buffer_range.end = cmp::min(ancestor_buffer_range.end, excerpt_buffer_end);
let start =
start_after_header + (ancestor_buffer_range.start - excerpt_buffer_start);
let end = start_after_header + (ancestor_buffer_range.end - excerpt_buffer_start);
let start = cursor.start() + (ancestor_buffer_range.start - excerpt_buffer_start);
let end = cursor.start() + (ancestor_buffer_range.end - excerpt_buffer_start);
Some(start..end)
})
}
@ -1737,54 +1614,26 @@ impl Excerpt {
render_header: Option<RenderHeaderFn>,
has_trailing_newline: bool,
) -> Self {
let mut text_summary =
buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer));
if header_height > 0 {
text_summary.first_line_chars = 0;
text_summary.lines.row += header_height as u32;
text_summary.lines_utf16.row += header_height as u32;
text_summary.bytes += header_height as usize;
text_summary.longest_row += header_height as u32;
}
Excerpt {
id,
text_summary: buffer.text_summary_for_range::<TextSummary, _>(range.to_offset(&buffer)),
buffer_id,
buffer,
range,
text_summary,
header_height,
render_header,
has_trailing_newline,
}
}
fn header_summary(&self) -> TextSummary {
TextSummary {
bytes: self.header_height as usize,
lines: Point::new(self.header_height as u32, 0),
lines_utf16: PointUtf16::new(self.header_height as u32, 0),
first_line_chars: 0,
last_line_chars: 0,
longest_row: 0,
longest_row_chars: 0,
}
}
fn chunks_in_range<'a>(
&'a self,
range: Range<usize>,
theme: Option<&'a SyntaxTheme>,
) -> ExcerptChunks<'a> {
let content_start = self.range.start.to_offset(&self.buffer);
let chunks_start = content_start + range.start.saturating_sub(self.header_height as usize);
let chunks_end = content_start
+ cmp::min(range.end, self.text_summary.bytes)
.saturating_sub(self.header_height as usize);
let header_height = cmp::min(
(self.header_height as usize).saturating_sub(range.start),
range.len(),
);
let chunks_start = content_start + range.start;
let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes);
let footer_height = if self.has_trailing_newline
&& range.start <= self.text_summary.bytes
@ -1798,7 +1647,6 @@ impl Excerpt {
let content_chunks = self.buffer.chunks(chunks_start..chunks_end, theme);
ExcerptChunks {
header_height,
content_chunks,
footer_height,
}
@ -1806,16 +1654,8 @@ impl Excerpt {
fn bytes_in_range(&self, range: Range<usize>) -> ExcerptBytes {
let content_start = self.range.start.to_offset(&self.buffer);
let bytes_start = content_start + range.start.saturating_sub(self.header_height as usize);
let bytes_end = content_start
+ cmp::min(range.end, self.text_summary.bytes)
.saturating_sub(self.header_height as usize);
let header_height = cmp::min(
(self.header_height as usize).saturating_sub(range.start),
range.len(),
);
let bytes_start = content_start + range.start;
let bytes_end = content_start + cmp::min(range.end, self.text_summary.bytes);
let footer_height = if self.has_trailing_newline
&& range.start <= self.text_summary.bytes
&& range.end > self.text_summary.bytes
@ -1824,11 +1664,9 @@ impl Excerpt {
} else {
0
};
let content_bytes = self.buffer.bytes_in_range(bytes_start..bytes_end);
ExcerptBytes {
header_height,
content_bytes,
footer_height,
}
@ -1860,7 +1698,6 @@ impl fmt::Debug for Excerpt {
.field("buffer_id", &self.buffer_id)
.field("range", &self.range)
.field("text_summary", &self.text_summary)
.field("header_height", &self.header_height)
.field("has_trailing_newline", &self.has_trailing_newline)
.finish()
}
@ -1935,7 +1772,6 @@ 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
@ -1952,13 +1788,8 @@ impl<'a> MultiBufferRows<'a> {
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;
self.buffer_row_range.start = excerpt_start + overshoot;
self.buffer_row_range.end = excerpt_start + excerpt.text_summary.lines.row + 1;
}
}
}
@ -1968,10 +1799,6 @@ impl<'a> Iterator for MultiBufferRows<'a> {
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.header_height > 0 {
self.header_height -= 1;
return Some(None);
}
if !self.buffer_row_range.is_empty() {
let row = Some(self.buffer_row_range.start);
self.buffer_row_range.start += 1;
@ -1980,11 +1807,9 @@ impl<'a> Iterator for MultiBufferRows<'a> {
self.excerpts.item()?;
self.excerpts.next(&());
let excerpt = self.excerpts.item()?;
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.end =
self.buffer_row_range.start + excerpt.text_summary.lines.row + 1
- self.header_height;
self.buffer_row_range.start + excerpt.text_summary.lines.row + 1;
}
}
}
@ -2078,12 +1903,6 @@ impl<'a> Iterator for ExcerptBytes<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
if self.header_height > 0 {
let result = &NEWLINES[..self.header_height];
self.header_height = 0;
return Some(result);
}
if let Some(chunk) = self.content_bytes.next() {
if !chunk.is_empty() {
return Some(chunk);
@ -2104,15 +1923,6 @@ impl<'a> Iterator for ExcerptChunks<'a> {
type Item = Chunk<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.header_height > 0 {
let text = unsafe { str::from_utf8_unchecked(&NEWLINES[..self.header_height]) };
self.header_height = 0;
return Some(Chunk {
text,
..Default::default()
});
}
if let Some(chunk) = self.content_chunks.next() {
return Some(chunk);
}
@ -2219,7 +2029,7 @@ mod tests {
subscription.consume().into_inner(),
[Edit {
old: 0..0,
new: 0..12
new: 0..10
}]
);
@ -2244,8 +2054,8 @@ mod tests {
assert_eq!(
subscription.consume().into_inner(),
[Edit {
old: 12..12,
new: 12..28
old: 10..10,
new: 10..22
}]
);
@ -2256,81 +2066,64 @@ mod tests {
assert_eq!(
snapshot.text(),
concat!(
"\n", // Preserve newlines
"\n", //
"bbbb\n", //
"bbbb\n", // Preserve newlines
"ccccc\n", //
"\n", //
"ddd\n", //
"eeee\n", //
"\n", //
"\n", //
"\n", //
"jj" //
)
);
assert_eq!(
snapshot.buffer_rows(0).collect::<Vec<_>>(),
&[
None,
None,
Some(1),
Some(2),
None,
Some(3),
Some(4),
None,
None,
None,
Some(3)
]
[Some(1), Some(2), Some(3), Some(4), Some(3)]
);
assert_eq!(
snapshot.buffer_rows(2).collect::<Vec<_>>(),
&[
Some(1),
Some(2),
None,
Some(3),
Some(4),
None,
None,
None,
Some(3)
]
[Some(3), Some(4), 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<_>>(), &[]);
assert_eq!(snapshot.buffer_rows(4).collect::<Vec<_>>(), [Some(3)]);
assert_eq!(snapshot.buffer_rows(5).collect::<Vec<_>>(), []);
{
let snapshot = multibuffer.read(cx).read(cx);
assert_eq!(
snapshot
.excerpt_headers_in_range(0..snapshot.max_point().row + 1)
.map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
.map(|(start_row, header_height, render)| (
start_row,
header_height,
render(cx).name().unwrap().to_string()
))
.collect::<Vec<_>>(),
&[
(0..2, "header 1".into()),
(4..5, "header 2".into()),
(7..10, "header 3".into())
(0, 2, "header 1".into()),
(2, 1, "header 2".into()),
(4, 3, "header 3".into())
]
);
assert_eq!(
snapshot
.excerpt_headers_in_range(1..5)
.map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
.excerpt_headers_in_range(1..4)
.map(|(start_row, header_height, render)| (
start_row,
header_height,
render(cx).name().unwrap().to_string()
))
.collect::<Vec<_>>(),
&[(0..2, "header 1".into()), (4..5, "header 2".into())]
&[(2, 1, "header 2".into())]
);
assert_eq!(
snapshot
.excerpt_headers_in_range(2..8)
.map(|(rows, render)| (rows, render(cx).name().unwrap().to_string()))
.excerpt_headers_in_range(2..5)
.map(|(start_row, header_height, render)| (
start_row,
header_height,
render(cx).name().unwrap().to_string()
))
.collect::<Vec<_>>(),
&[(4..5, "header 2".into()), (7..10, "header 3".into())]
&[(2, 1, "header 2".into()), (4, 3, "header 3".into())]
);
}
@ -2348,17 +2141,11 @@ mod tests {
assert_eq!(
multibuffer.read(cx).snapshot(cx).text(),
concat!(
"\n", // Preserve newlines
"\n", //
"bbbb\n", //
"bbbb\n", // Preserve newlines
"c\n", //
"cc\n", //
"\n", //
"ddd\n", //
"eeee\n", //
"\n", //
"\n", //
"\n", //
"jj" //
)
);
@ -2366,43 +2153,32 @@ mod tests {
assert_eq!(
subscription.consume().into_inner(),
[Edit {
old: 8..10,
new: 8..9
old: 6..8,
new: 6..7
}]
);
// bbbb\nc\ncc\nddd\neeee\njj
let multibuffer = multibuffer.read(cx).snapshot(cx);
assert_eq!(
multibuffer.clip_point(Point::new(0, 0), Bias::Left),
Point::new(2, 0)
multibuffer.clip_point(Point::new(0, 5), Bias::Left),
Point::new(0, 4)
);
assert_eq!(
multibuffer.clip_point(Point::new(0, 0), Bias::Right),
Point::new(2, 0)
multibuffer.clip_point(Point::new(0, 5), Bias::Right),
Point::new(0, 4)
);
assert_eq!(
multibuffer.clip_point(Point::new(1, 0), Bias::Left),
Point::new(2, 0)
multibuffer.clip_point(Point::new(5, 1), Bias::Right),
Point::new(5, 1)
);
assert_eq!(
multibuffer.clip_point(Point::new(1, 0), Bias::Right),
Point::new(2, 0)
multibuffer.clip_point(Point::new(5, 2), Bias::Right),
Point::new(5, 2)
);
assert_eq!(
multibuffer.clip_point(Point::new(8, 0), Bias::Left),
Point::new(7, 4)
);
assert_eq!(
multibuffer.clip_point(Point::new(8, 0), Bias::Right),
Point::new(11, 0)
);
assert_eq!(
multibuffer.clip_point(Point::new(9, 0), Bias::Left),
Point::new(7, 4)
);
assert_eq!(
multibuffer.clip_point(Point::new(9, 0), Bias::Right),
Point::new(11, 0)
multibuffer.clip_point(Point::new(5, 3), Bias::Right),
Point::new(5, 2)
);
}
@ -2464,12 +2240,12 @@ mod tests {
});
let old_snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 1);
assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 1);
assert_eq!(Anchor::min().to_offset(&old_snapshot), 1);
assert_eq!(Anchor::min().to_offset(&old_snapshot), 1);
assert_eq!(Anchor::max().to_offset(&old_snapshot), 12);
assert_eq!(Anchor::max().to_offset(&old_snapshot), 12);
assert_eq!(old_snapshot.anchor_before(0).to_offset(&old_snapshot), 0);
assert_eq!(old_snapshot.anchor_after(0).to_offset(&old_snapshot), 0);
assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
assert_eq!(Anchor::min().to_offset(&old_snapshot), 0);
assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
buffer_1.update(cx, |buffer, cx| {
buffer.edit([0..0], "W", cx);
@ -2481,19 +2257,19 @@ mod tests {
});
let new_snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(old_snapshot.text(), "\nabcd\n\nefghi");
assert_eq!(new_snapshot.text(), "\nWabcdX\n\nYefghiZ");
assert_eq!(old_snapshot.text(), "abcd\nefghi");
assert_eq!(new_snapshot.text(), "WabcdX\nYefghiZ");
assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 1);
assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 2);
assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 1);
assert_eq!(old_snapshot.anchor_before(0).to_offset(&new_snapshot), 0);
assert_eq!(old_snapshot.anchor_after(0).to_offset(&new_snapshot), 1);
assert_eq!(old_snapshot.anchor_before(1).to_offset(&new_snapshot), 2);
assert_eq!(old_snapshot.anchor_after(1).to_offset(&new_snapshot), 2);
assert_eq!(old_snapshot.anchor_before(2).to_offset(&new_snapshot), 3);
assert_eq!(old_snapshot.anchor_after(2).to_offset(&new_snapshot), 3);
assert_eq!(old_snapshot.anchor_before(7).to_offset(&new_snapshot), 9);
assert_eq!(old_snapshot.anchor_after(7).to_offset(&new_snapshot), 10);
assert_eq!(old_snapshot.anchor_before(12).to_offset(&new_snapshot), 15);
assert_eq!(old_snapshot.anchor_after(12).to_offset(&new_snapshot), 16);
assert_eq!(old_snapshot.anchor_before(5).to_offset(&new_snapshot), 7);
assert_eq!(old_snapshot.anchor_after(5).to_offset(&new_snapshot), 8);
assert_eq!(old_snapshot.anchor_before(10).to_offset(&new_snapshot), 13);
assert_eq!(old_snapshot.anchor_after(10).to_offset(&new_snapshot), 14);
}
#[gpui::test(iterations = 100)]
@ -2564,15 +2340,10 @@ mod tests {
let mut excerpt_starts = Vec::new();
let mut expected_text = String::new();
let mut expected_buffer_rows = Vec::new();
for (buffer, range, header_height) in &expected_excerpts {
for (buffer, range, _) in &expected_excerpts {
let buffer = buffer.read(cx);
let buffer_range = range.to_offset(buffer);
for _ in 0..*header_height {
expected_text.push('\n');
expected_buffer_rows.push(None);
}
excerpt_starts.push(TextSummary::from(expected_text.as_str()));
expected_text.extend(buffer.text_for_range(buffer_range.clone()));
expected_text.push('\n');

View File

@ -38,7 +38,7 @@ impl Point {
pub fn saturating_sub(self, other: Self) -> Self {
if self < other {
Point::zero()
Self::zero()
} else {
self - other
}

View File

@ -26,6 +26,14 @@ impl PointUtf16 {
pub fn is_zero(&self) -> bool {
self.row == 0 && self.column == 0
}
pub fn saturating_sub(self, other: Self) -> Self {
if self < other {
Self::zero()
} else {
self - other
}
}
}
impl<'a> Add<&'a Self> for PointUtf16 {