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,
|
text: TextSummary,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct MultiBufferRows<'a> {
|
||||||
|
header_height: u32,
|
||||||
|
buffer_row_range: Range<u32>,
|
||||||
|
excerpts: Cursor<'a, Excerpt, Point>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MultiBufferChunks<'a> {
|
pub struct MultiBufferChunks<'a> {
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
excerpts: Cursor<'a, Excerpt, 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>(
|
pub fn chunks<'a, T: ToOffset>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<T>,
|
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> {
|
impl<'a> MultiBufferChunks<'a> {
|
||||||
pub fn offset(&self) -> usize {
|
pub fn offset(&self) -> usize {
|
||||||
self.range.start
|
self.range.start
|
||||||
|
@ -2009,15 +2069,26 @@ mod tests {
|
||||||
fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
|
fn test_singleton_multibuffer(cx: &mut MutableAppContext) {
|
||||||
let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(6, 6, 'a'), cx));
|
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 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!(
|
assert_eq!(
|
||||||
multibuffer.read(cx).snapshot(cx).text(),
|
snapshot.buffer_rows(0).collect::<Vec<_>>(),
|
||||||
buffer.read(cx).text()
|
(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!(
|
assert_eq!(
|
||||||
multibuffer.read(cx).snapshot(cx).text(),
|
snapshot.buffer_rows(0).collect::<Vec<_>>(),
|
||||||
buffer.read(cx).text()
|
(0..buffer.read(cx).row_count())
|
||||||
|
.map(Some)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2075,8 +2146,9 @@ mod tests {
|
||||||
subscription
|
subscription
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let snapshot = multibuffer.read(cx).snapshot(cx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
multibuffer.read(cx).snapshot(cx).text(),
|
snapshot.text(),
|
||||||
concat!(
|
concat!(
|
||||||
"\n", // Preserve newlines
|
"\n", // Preserve newlines
|
||||||
"\n", //
|
"\n", //
|
||||||
|
@ -2091,6 +2163,22 @@ mod tests {
|
||||||
"jj" //
|
"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);
|
let snapshot = multibuffer.read(cx).read(cx);
|
||||||
|
@ -2342,17 +2430,25 @@ mod tests {
|
||||||
|
|
||||||
let mut excerpt_starts = Vec::new();
|
let mut excerpt_starts = Vec::new();
|
||||||
let mut expected_text = String::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, header_height) in &expected_excerpts {
|
||||||
let buffer = buffer.read(cx);
|
let buffer = buffer.read(cx);
|
||||||
let buffer_range = range.to_offset(buffer);
|
let buffer_range = range.to_offset(buffer);
|
||||||
|
|
||||||
for _ in 0..*header_height {
|
for _ in 0..*header_height {
|
||||||
expected_text.push('\n');
|
expected_text.push('\n');
|
||||||
|
expected_buffer_rows.push(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
excerpt_starts.push(TextSummary::from(expected_text.as_str()));
|
excerpt_starts.push(TextSummary::from(expected_text.as_str()));
|
||||||
expected_text.extend(buffer.text_for_range(buffer_range.clone()));
|
expected_text.extend(buffer.text_for_range(buffer_range.clone()));
|
||||||
expected_text.push('\n');
|
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.
|
// Remove final trailing newline.
|
||||||
if !expected_excerpts.is_empty() {
|
if !expected_excerpts.is_empty() {
|
||||||
|
@ -2362,6 +2458,21 @@ mod tests {
|
||||||
assert_eq!(snapshot.text(), expected_text);
|
assert_eq!(snapshot.text(), expected_text);
|
||||||
log::info!("MultiBuffer 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();
|
let mut excerpt_starts = excerpt_starts.into_iter();
|
||||||
for (buffer, range, _) in &expected_excerpts {
|
for (buffer, range, _) in &expected_excerpts {
|
||||||
let buffer_id = buffer.id();
|
let buffer_id = buffer.id();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue