Implement MultiBuffer::reversed_chars_at
This commit is contained in:
parent
9cbb680fb2
commit
e23965e7c9
2 changed files with 56 additions and 4 deletions
|
@ -14,6 +14,7 @@ use std::{
|
||||||
cmp, io,
|
cmp, io,
|
||||||
iter::{self, FromIterator, Peekable},
|
iter::{self, FromIterator, Peekable},
|
||||||
ops::{Range, Sub},
|
ops::{Range, Sub},
|
||||||
|
str,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::{Duration, Instant, SystemTime},
|
time::{Duration, Instant, SystemTime},
|
||||||
};
|
};
|
||||||
|
@ -754,9 +755,47 @@ impl MultiBufferSnapshot {
|
||||||
&'a self,
|
&'a self,
|
||||||
position: T,
|
position: T,
|
||||||
) -> impl Iterator<Item = char> + 'a {
|
) -> impl Iterator<Item = char> + 'a {
|
||||||
// TODO
|
let mut offset = position.to_offset(self);
|
||||||
let offset = position.to_offset(self);
|
let mut cursor = self.excerpts.cursor::<usize>();
|
||||||
self.as_singleton().unwrap().reversed_chars_at(offset)
|
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 mut end_before_footer = cursor.start() + excerpt.text_summary.bytes;
|
||||||
|
if excerpt.has_trailing_newline {
|
||||||
|
end_before_footer -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = excerpt.range.start.to_offset(&excerpt.buffer);
|
||||||
|
let end =
|
||||||
|
start + (cmp::min(offset, end_before_footer).saturating_sub(start_after_header));
|
||||||
|
excerpt.buffer.reversed_chunks_in_range(start..end)
|
||||||
|
});
|
||||||
|
iter::from_fn(move || {
|
||||||
|
if offset == *cursor.start() {
|
||||||
|
cursor.prev(&());
|
||||||
|
let excerpt = cursor.item()?;
|
||||||
|
excerpt_chunks = Some(
|
||||||
|
excerpt
|
||||||
|
.buffer
|
||||||
|
.reversed_chunks_in_range(excerpt.range.clone()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
offset -= 1;
|
||||||
|
Some("\n")
|
||||||
|
} else {
|
||||||
|
let chunk = excerpt_chunks.as_mut().unwrap().next().unwrap();
|
||||||
|
offset -= chunk.len();
|
||||||
|
Some(chunk)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.flat_map(|c| c.chars().rev())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
|
pub fn chars_at<'a, T: ToOffset>(&'a self, position: T) -> impl Iterator<Item = char> + 'a {
|
||||||
|
@ -1593,7 +1632,7 @@ impl<'a> Iterator for MultiBufferChunks<'a> {
|
||||||
if self.header_height > 0 {
|
if self.header_height > 0 {
|
||||||
let chunk = Chunk {
|
let chunk = Chunk {
|
||||||
text: unsafe {
|
text: unsafe {
|
||||||
std::str::from_utf8_unchecked(&NEWLINES[..self.header_height as usize])
|
str::from_utf8_unchecked(&NEWLINES[..self.header_height as usize])
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -2152,6 +2191,14 @@ mod tests {
|
||||||
start_ix..end_ix
|
start_ix..end_ix
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _ in 0..10 {
|
||||||
|
let end_ix = snapshot.clip_offset(rng.gen_range(0..=snapshot.len()), Bias::Right);
|
||||||
|
assert_eq!(
|
||||||
|
expected_text[..end_ix].chars().rev().collect::<String>(),
|
||||||
|
snapshot.reversed_chars_at(end_ix).collect::<String>()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let snapshot = list.read(cx).snapshot(cx);
|
let snapshot = list.read(cx).snapshot(cx);
|
||||||
|
|
|
@ -1332,6 +1332,11 @@ impl BufferSnapshot {
|
||||||
self.visible_text.reversed_chars_at(offset)
|
self.visible_text.reversed_chars_at(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reversed_chunks_in_range<T: ToOffset>(&self, range: Range<T>) -> rope::Chunks {
|
||||||
|
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||||
|
self.visible_text.reversed_chunks_in_range(range)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> rope::Bytes<'a> {
|
pub fn bytes_in_range<'a, T: ToOffset>(&'a self, range: Range<T>) -> rope::Bytes<'a> {
|
||||||
let start = range.start.to_offset(self);
|
let start = range.start.to_offset(self);
|
||||||
let end = range.end.to_offset(self);
|
let end = range.end.to_offset(self);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue