Implement MultiBuffer::buffer_rows
This commit is contained in:
parent
a293e9c0c5
commit
db33e4935a
1 changed files with 117 additions and 6 deletions
|
@ -111,6 +111,12 @@ struct ExcerptSummary {
|
|||
text: TextSummary,
|
||||
}
|
||||
|
||||
pub struct MultiBufferRows<'a> {
|
||||
header_height: u32,
|
||||
buffer_row_range: Range<u32>,
|
||||
excerpts: Cursor<'a, Excerpt, Point>,
|
||||
}
|
||||
|
||||
pub struct MultiBufferChunks<'a> {
|
||||
range: Range<usize>,
|
||||
excerpts: Cursor<'a, Excerpt, usize>,
|
||||
|
@ -1052,6 +1058,32 @@ impl MultiBufferSnapshot {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn buffer_rows<'a>(&'a self, start_row: u32) -> MultiBufferRows<'a> {
|
||||
let mut excerpts = self.excerpts.cursor::<Point>();
|
||||
excerpts.seek(&Point::new(start_row, 0), Bias::Right, &());
|
||||
if excerpts.item().is_none() {
|
||||
excerpts.prev(&());
|
||||
}
|
||||
|
||||
let mut header_height = 0;
|
||||
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>(
|
||||
&'a self,
|
||||
range: Range<T>,
|
||||
|
@ -1821,6 +1853,34 @@ impl<'a> sum_tree::Dimension<'a, ExcerptSummary> for Option<&'a ExcerptId> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for MultiBufferRows<'a> {
|
||||
type Item = Option<u32>;
|
||||
|
||||
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;
|
||||
return Some(row);
|
||||
}
|
||||
self.excerpts.next(&());
|
||||
if let Some(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;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MultiBufferChunks<'a> {
|
||||
pub fn offset(&self) -> usize {
|
||||
self.range.start
|
||||
|
@ -2009,15 +2069,26 @@ mod tests {
|
|||
fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
|
||||
let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
|
||||
|
||||
let snapshot = multibuffer.read(cx).snapshot(cx);
|
||||
assert_eq!(snapshot.text(), buffer.read(cx).text());
|
||||
|
||||
assert_eq!(
|
||||
multibuffer.read(cx).snapshot(cx).text(),
|
||||
buffer.read(cx).text()
|
||||
snapshot.buffer_rows(0).collect::<Vec<_>>(),
|
||||
(0..buffer.read(cx).row_count())
|
||||
.map(Some)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX", cx));
|
||||
buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX\n", cx));
|
||||
let snapshot = multibuffer.read(cx).snapshot(cx);
|
||||
|
||||
assert_eq!(snapshot.text(), buffer.read(cx).text());
|
||||
assert_eq!(
|
||||
multibuffer.read(cx).snapshot(cx).text(),
|
||||
buffer.read(cx).text()
|
||||
snapshot.buffer_rows(0).collect::<Vec<_>>(),
|
||||
(0..buffer.read(cx).row_count())
|
||||
.map(Some)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2075,8 +2146,9 @@ mod tests {
|
|||
subscription
|
||||
});
|
||||
|
||||
let snapshot = multibuffer.read(cx).snapshot(cx);
|
||||
assert_eq!(
|
||||
multibuffer.read(cx).snapshot(cx).text(),
|
||||
snapshot.text(),
|
||||
concat!(
|
||||
"\n", // Preserve newlines
|
||||
"\n", //
|
||||
|
@ -2091,6 +2163,22 @@ mod tests {
|
|||
"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)
|
||||
]
|
||||
);
|
||||
|
||||
{
|
||||
let snapshot = multibuffer.read(cx).read(cx);
|
||||
|
@ -2342,17 +2430,25 @@ 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 {
|
||||
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');
|
||||
|
||||
let buffer_row_range = buffer.offset_to_point(buffer_range.start).row
|
||||
..=buffer.offset_to_point(buffer_range.end).row;
|
||||
for row in buffer_row_range {
|
||||
expected_buffer_rows.push(Some(row));
|
||||
}
|
||||
}
|
||||
// Remove final trailing newline.
|
||||
if !expected_excerpts.is_empty() {
|
||||
|
@ -2362,6 +2458,21 @@ mod tests {
|
|||
assert_eq!(snapshot.text(), expected_text);
|
||||
log::info!("MultiBuffer text: {:?}", expected_text);
|
||||
|
||||
assert_eq!(
|
||||
snapshot.buffer_rows(0).collect::<Vec<_>>(),
|
||||
expected_buffer_rows,
|
||||
);
|
||||
|
||||
for _ in 0..5 {
|
||||
let start_row = rng.gen_range(0..=expected_buffer_rows.len());
|
||||
assert_eq!(
|
||||
snapshot.buffer_rows(start_row as u32).collect::<Vec<_>>(),
|
||||
&expected_buffer_rows[start_row..],
|
||||
"buffer_rows({})",
|
||||
start_row
|
||||
);
|
||||
}
|
||||
|
||||
let mut excerpt_starts = excerpt_starts.into_iter();
|
||||
for (buffer, range, _) in &expected_excerpts {
|
||||
let buffer_id = buffer.id();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue