Merge branch 'master' into new-file

This commit is contained in:
Max Brunsfeld
2021-05-07 10:10:20 -07:00
12 changed files with 1024 additions and 592 deletions
+174 -120
View File
@@ -393,39 +393,48 @@ impl Buffer {
insertion_splits.insert(
base_insertion.id,
SumTree::from_item(InsertionSplit {
fragment_id: FragmentId::min_value().clone(),
extent: 0,
}),
SumTree::from_item(
InsertionSplit {
fragment_id: FragmentId::min_value().clone(),
extent: 0,
},
&(),
),
);
fragments.push(
Fragment {
id: FragmentId::min_value().clone(),
insertion: base_insertion.clone(),
text: base_insertion.text.slice(0..0),
deletions: Default::default(),
max_undos: Default::default(),
visible: true,
},
&(),
);
fragments.push(Fragment {
id: FragmentId::min_value().clone(),
insertion: base_insertion.clone(),
text: base_insertion.text.slice(0..0),
deletions: Default::default(),
max_undos: Default::default(),
visible: true,
});
if base_insertion.text.len() > 0 {
let base_fragment_id =
FragmentId::between(&FragmentId::min_value(), &FragmentId::max_value());
insertion_splits
.get_mut(&base_insertion.id)
.unwrap()
.push(InsertionSplit {
insertion_splits.get_mut(&base_insertion.id).unwrap().push(
InsertionSplit {
fragment_id: base_fragment_id.clone(),
extent: base_insertion.text.len(),
});
fragments.push(Fragment {
id: base_fragment_id,
text: base_insertion.text.clone(),
insertion: base_insertion,
deletions: Default::default(),
max_undos: Default::default(),
visible: true,
});
},
&(),
);
fragments.push(
Fragment {
id: base_fragment_id,
text: base_insertion.text.clone(),
insertion: base_insertion,
deletions: Default::default(),
max_undos: Default::default(),
visible: true,
},
&(),
);
}
Self {
@@ -507,22 +516,22 @@ impl Buffer {
let mut summary = TextSummary::default();
let mut cursor = self.fragments.cursor::<usize, usize>();
cursor.seek(&range.start, SeekBias::Right);
cursor.seek(&range.start, SeekBias::Right, &());
if let Some(fragment) = cursor.item() {
let summary_start = cmp::max(*cursor.start(), range.start) - cursor.start();
let summary_end = cmp::min(range.end - cursor.start(), fragment.len());
summary += &fragment.text.slice(summary_start..summary_end).summary();
summary += fragment.text.slice(summary_start..summary_end).summary();
cursor.next();
}
if range.end > *cursor.start() {
summary += &cursor.summary::<TextSummary>(&range.end, SeekBias::Right);
summary += cursor.summary::<TextSummary>(&range.end, SeekBias::Right, &());
if let Some(fragment) = cursor.item() {
let summary_start = cmp::max(*cursor.start(), range.start) - cursor.start();
let summary_end = cmp::min(range.end - cursor.start(), fragment.len());
summary += &fragment.text.slice(summary_start..summary_end).summary();
summary += fragment.text.slice(summary_start..summary_end).summary();
}
}
@@ -552,22 +561,22 @@ impl Buffer {
let mut summary = TextSummary::default();
let mut cursor = self.fragments.cursor::<usize, usize>();
cursor.seek(&range.start, SeekBias::Right);
cursor.seek(&range.start, SeekBias::Right, &());
if let Some(fragment) = cursor.item() {
let summary_start = cmp::max(*cursor.start(), range.start) - cursor.start();
let summary_end = cmp::min(range.end - cursor.start(), fragment.len());
summary += &fragment.text.slice(summary_start..summary_end).summary();
summary += fragment.text.slice(summary_start..summary_end).summary();
cursor.next();
}
if range.end > *cursor.start() {
summary += &cursor.summary::<TextSummary>(&range.end, SeekBias::Right);
summary += cursor.summary::<TextSummary>(&range.end, SeekBias::Right, &());
if let Some(fragment) = cursor.item() {
let summary_start = cmp::max(*cursor.start(), range.start) - cursor.start();
let summary_end = cmp::min(range.end - cursor.start(), fragment.len());
summary += &fragment.text.slice(summary_start..summary_end).summary();
summary += fragment.text.slice(summary_start..summary_end).summary();
}
}
@@ -970,10 +979,10 @@ impl Buffer {
let mut cursor = old_fragments.cursor::<FragmentIdRef, ()>();
let mut new_fragments =
cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left);
cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left, &());
if start_offset == cursor.item().unwrap().end_offset() {
new_fragments.push(cursor.item().unwrap().clone());
new_fragments.push(cursor.item().unwrap().clone(), &());
cursor.next();
}
@@ -1012,30 +1021,33 @@ impl Buffer {
None
};
if let Some(fragment) = before_range {
new_fragments.push(fragment);
new_fragments.push(fragment, &());
}
if let Some(fragment) = insertion {
new_fragments.push(fragment);
new_fragments.push(fragment, &());
}
if let Some(mut fragment) = within_range {
if fragment.was_visible(&version_in_range, &self.undo_map) {
fragment.deletions.insert(local_timestamp);
fragment.visible = false;
}
new_fragments.push(fragment);
new_fragments.push(fragment, &());
}
if let Some(fragment) = after_range {
new_fragments.push(fragment);
new_fragments.push(fragment, &());
}
} else {
if new_text.is_some() && lamport_timestamp > fragment.insertion.lamport_timestamp {
new_fragments.push(self.build_fragment_to_insert(
cursor.prev_item().as_ref().unwrap(),
Some(&fragment),
new_text.take().unwrap(),
local_timestamp,
lamport_timestamp,
));
new_fragments.push(
self.build_fragment_to_insert(
cursor.prev_item().as_ref().unwrap(),
Some(&fragment),
new_text.take().unwrap(),
local_timestamp,
lamport_timestamp,
),
&(),
);
}
if fragment.id < end_fragment_id
@@ -1044,23 +1056,26 @@ impl Buffer {
fragment.deletions.insert(local_timestamp);
fragment.visible = false;
}
new_fragments.push(fragment);
new_fragments.push(fragment, &());
}
cursor.next();
}
if let Some(new_text) = new_text {
new_fragments.push(self.build_fragment_to_insert(
cursor.prev_item().as_ref().unwrap(),
None,
new_text,
local_timestamp,
lamport_timestamp,
));
new_fragments.push(
self.build_fragment_to_insert(
cursor.prev_item().as_ref().unwrap(),
None,
new_text,
local_timestamp,
lamport_timestamp,
),
&(),
);
}
new_fragments.push_tree(cursor.slice(&last_id_ref, SeekBias::Right));
new_fragments.push_tree(cursor.slice(&last_id_ref, SeekBias::Right, &()), &());
self.fragments = new_fragments;
self.local_clock.observe(local_timestamp);
self.lamport_clock.observe(lamport_timestamp);
@@ -1148,23 +1163,26 @@ impl Buffer {
let mut insertion_splits = splits.cursor::<(), ()>().map(|s| &s.fragment_id).peekable();
let first_split_id = insertion_splits.next().unwrap();
new_fragments = cursor.slice(&FragmentIdRef::new(first_split_id), SeekBias::Left);
new_fragments = cursor.slice(&FragmentIdRef::new(first_split_id), SeekBias::Left, &());
loop {
let mut fragment = cursor.item().unwrap().clone();
fragment.visible = fragment.is_visible(&self.undo_map);
fragment.max_undos.observe(undo.id);
new_fragments.push(fragment);
new_fragments.push(fragment, &());
cursor.next();
if let Some(split_id) = insertion_splits.next() {
new_fragments
.push_tree(cursor.slice(&FragmentIdRef::new(split_id), SeekBias::Left));
new_fragments.push_tree(
cursor.slice(&FragmentIdRef::new(split_id), SeekBias::Left, &()),
&(),
);
} else {
break;
}
}
} else {
new_fragments = cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left);
new_fragments =
cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left, &());
while let Some(fragment) = cursor.item() {
if fragment.id > end_fragment_id {
break;
@@ -1176,13 +1194,13 @@ impl Buffer {
fragment.visible = fragment.is_visible(&self.undo_map);
fragment.max_undos.observe(undo.id);
}
new_fragments.push(fragment);
new_fragments.push(fragment, &());
cursor.next();
}
}
}
new_fragments.push_tree(cursor.suffix());
new_fragments.push_tree(cursor.suffix(&()), &());
drop(cursor);
self.fragments = new_fragments;
@@ -1246,7 +1264,7 @@ impl Buffer {
.get(&edit_id)
.ok_or_else(|| anyhow!("invalid operation"))?;
let mut cursor = split_tree.cursor::<usize, ()>();
cursor.seek(&offset, SeekBias::Left);
cursor.seek(&offset, SeekBias::Left, &());
Ok(cursor
.item()
.ok_or_else(|| anyhow!("invalid operation"))?
@@ -1268,7 +1286,10 @@ impl Buffer {
let old_fragments = self.fragments.clone();
let mut cursor = old_fragments.cursor::<usize, usize>();
let mut new_fragments = SumTree::new();
new_fragments.push_tree(cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right));
new_fragments.push_tree(
cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right, &()),
&(),
);
let mut start_id = None;
let mut start_offset = None;
@@ -1290,7 +1311,8 @@ impl Buffer {
.remove(&fragment.insertion.id)
.unwrap();
let mut splits_cursor = old_split_tree.cursor::<usize, ()>();
let mut new_split_tree = splits_cursor.slice(&fragment.start_offset(), SeekBias::Right);
let mut new_split_tree =
splits_cursor.slice(&fragment.start_offset(), SeekBias::Right, &());
// Find all splices that start or end within the current fragment. Then, split the
// fragment and reassemble it in both trees accounting for the deleted and the newly
@@ -1303,11 +1325,14 @@ impl Buffer {
prefix.id =
FragmentId::between(&new_fragments.last().unwrap().id, &fragment.id);
fragment.set_start_offset(prefix.end_offset());
new_fragments.push(prefix.clone());
new_split_tree.push(InsertionSplit {
extent: prefix.end_offset() - prefix.start_offset(),
fragment_id: prefix.id,
});
new_fragments.push(prefix.clone(), &());
new_split_tree.push(
InsertionSplit {
extent: prefix.end_offset() - prefix.start_offset(),
fragment_id: prefix.id,
},
&(),
);
fragment_start = range.start;
}
@@ -1331,7 +1356,7 @@ impl Buffer {
local_timestamp,
lamport_timestamp,
);
new_fragments.push(new_fragment);
new_fragments.push(new_fragment, &());
}
}
@@ -1347,11 +1372,14 @@ impl Buffer {
prefix.visible = false;
}
fragment.set_start_offset(prefix.end_offset());
new_fragments.push(prefix.clone());
new_split_tree.push(InsertionSplit {
extent: prefix.end_offset() - prefix.start_offset(),
fragment_id: prefix.id,
});
new_fragments.push(prefix.clone(), &());
new_split_tree.push(
InsertionSplit {
extent: prefix.end_offset() - prefix.start_offset(),
fragment_id: prefix.id,
},
&(),
);
fragment_start = range.end;
end_id = Some(fragment.insertion.id);
end_offset = Some(fragment.start_offset());
@@ -1395,16 +1423,21 @@ impl Buffer {
break;
}
}
new_split_tree.push(InsertionSplit {
extent: fragment.end_offset() - fragment.start_offset(),
fragment_id: fragment.id.clone(),
});
new_split_tree.push(
InsertionSplit {
extent: fragment.end_offset() - fragment.start_offset(),
fragment_id: fragment.id.clone(),
},
&(),
);
splits_cursor.next();
new_split_tree
.push_tree(splits_cursor.slice(&old_split_tree.extent::<usize>(), SeekBias::Right));
new_split_tree.push_tree(
splits_cursor.slice(&old_split_tree.extent::<usize>(), SeekBias::Right, &()),
&(),
);
self.insertion_splits
.insert(fragment.insertion.id, new_split_tree);
new_fragments.push(fragment);
new_fragments.push(fragment, &());
// Scan forward until we find a fragment that is not fully contained by the current splice.
cursor.next();
@@ -1420,7 +1453,7 @@ impl Buffer {
new_fragment.deletions.insert(local_timestamp);
new_fragment.visible = false;
}
new_fragments.push(new_fragment);
new_fragments.push(new_fragment, &());
cursor.next();
if range.end == fragment_end {
@@ -1462,7 +1495,8 @@ impl Buffer {
// and push all the fragments in between into the new tree.
if cur_range.as_ref().map_or(false, |r| r.start > fragment_end) {
new_fragments.push_tree(
cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right),
cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right, &()),
&(),
);
}
}
@@ -1494,11 +1528,13 @@ impl Buffer {
local_timestamp,
lamport_timestamp,
);
new_fragments.push(new_fragment);
new_fragments.push(new_fragment, &());
}
} else {
new_fragments
.push_tree(cursor.slice(&old_fragments.extent::<usize>(), SeekBias::Right));
new_fragments.push_tree(
cursor.slice(&old_fragments.extent::<usize>(), SeekBias::Right, &()),
&(),
);
}
self.fragments = new_fragments;
@@ -1556,32 +1592,43 @@ impl Buffer {
.remove(&fragment.insertion.id)
.unwrap();
let mut cursor = old_split_tree.cursor::<usize, ()>();
let mut new_split_tree = cursor.slice(&fragment.start_offset(), SeekBias::Right);
let mut new_split_tree = cursor.slice(&fragment.start_offset(), SeekBias::Right, &());
if let Some(ref fragment) = before_range {
new_split_tree.push(InsertionSplit {
extent: range.start - fragment.start_offset(),
fragment_id: fragment.id.clone(),
});
new_split_tree.push(
InsertionSplit {
extent: range.start - fragment.start_offset(),
fragment_id: fragment.id.clone(),
},
&(),
);
}
if let Some(ref fragment) = within_range {
new_split_tree.push(InsertionSplit {
extent: range.end - range.start,
fragment_id: fragment.id.clone(),
});
new_split_tree.push(
InsertionSplit {
extent: range.end - range.start,
fragment_id: fragment.id.clone(),
},
&(),
);
}
if let Some(ref fragment) = after_range {
new_split_tree.push(InsertionSplit {
extent: fragment.end_offset() - range.end,
fragment_id: fragment.id.clone(),
});
new_split_tree.push(
InsertionSplit {
extent: fragment.end_offset() - range.end,
fragment_id: fragment.id.clone(),
},
&(),
);
}
cursor.next();
new_split_tree
.push_tree(cursor.slice(&old_split_tree.extent::<usize>(), SeekBias::Right));
new_split_tree.push_tree(
cursor.slice(&old_split_tree.extent::<usize>(), SeekBias::Right, &()),
&(),
);
self.insertion_splits
.insert(fragment.insertion.id, new_split_tree);
@@ -1606,10 +1653,13 @@ impl Buffer {
);
let mut split_tree = SumTree::new();
split_tree.push(InsertionSplit {
extent: text.len(),
fragment_id: new_fragment_id.clone(),
});
split_tree.push(
InsertionSplit {
extent: text.len(),
fragment_id: new_fragment_id.clone(),
},
&(),
);
self.insertion_splits.insert(local_timestamp, split_tree);
Fragment::new(
@@ -1658,7 +1708,7 @@ impl Buffer {
};
let mut cursor = self.fragments.cursor::<usize, usize>();
cursor.seek(&offset, seek_bias);
cursor.seek(&offset, seek_bias, &());
let fragment = cursor.item().unwrap();
let offset_in_fragment = offset - cursor.start();
let offset_in_insertion = fragment.start_offset() + offset_in_fragment;
@@ -1690,7 +1740,7 @@ impl Buffer {
.get(&insertion_id)
.ok_or_else(|| anyhow!("split does not exist for insertion id"))?;
let mut splits_cursor = splits.cursor::<usize, ()>();
splits_cursor.seek(offset, seek_bias);
splits_cursor.seek(offset, seek_bias, &());
splits_cursor
.item()
.ok_or_else(|| anyhow!("split offset is out of range"))
@@ -1718,13 +1768,13 @@ impl Buffer {
.get(&insertion_id)
.ok_or_else(|| anyhow!("split does not exist for insertion id"))?;
let mut splits_cursor = splits.cursor::<usize, ()>();
splits_cursor.seek(offset, seek_bias);
splits_cursor.seek(offset, seek_bias, &());
let split = splits_cursor
.item()
.ok_or_else(|| anyhow!("split offset is out of range"))?;
let mut fragments_cursor = self.fragments.cursor::<FragmentIdRef, TextSummary>();
fragments_cursor.seek(&FragmentIdRef::new(&split.fragment_id), SeekBias::Left);
fragments_cursor.seek(&FragmentIdRef::new(&split.fragment_id), SeekBias::Left, &());
let fragment = fragments_cursor
.item()
.ok_or_else(|| anyhow!("fragment id does not exist"))?;
@@ -1744,7 +1794,7 @@ impl Buffer {
#[allow(dead_code)]
pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
let mut fragments_cursor = self.fragments.cursor::<usize, TextSummary>();
fragments_cursor.seek(&offset, SeekBias::Left);
fragments_cursor.seek(&offset, SeekBias::Left, &());
fragments_cursor
.item()
.ok_or_else(|| anyhow!("offset is out of range"))
@@ -1810,7 +1860,7 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for Point {
impl<'a> CharIter<'a> {
fn new(fragments: &'a SumTree<Fragment>, offset: usize) -> Self {
let mut fragments_cursor = fragments.cursor::<usize, usize>();
fragments_cursor.seek(&offset, SeekBias::Right);
fragments_cursor.seek(&offset, SeekBias::Right, &());
let fragment_chars = fragments_cursor.item().map_or("".chars(), |fragment| {
let offset_in_fragment = offset - fragments_cursor.start();
fragment.text[offset_in_fragment..].chars()
@@ -1847,7 +1897,7 @@ impl<'a> Iterator for CharIter<'a> {
impl<'a> FragmentIter<'a> {
fn new(fragments: &'a SumTree<Fragment>) -> Self {
let mut cursor = fragments.cursor::<usize, usize>();
cursor.seek(&0, SeekBias::Right);
cursor.seek(&0, SeekBias::Right, &());
Self {
cursor,
started: false,
@@ -2140,8 +2190,10 @@ impl sum_tree::Item for Fragment {
}
}
impl<'a> AddAssign<&'a FragmentSummary> for FragmentSummary {
fn add_assign(&mut self, other: &Self) {
impl sum_tree::Summary for FragmentSummary {
type Context = ();
fn add_summary(&mut self, other: &Self, _: &()) {
self.text_summary += &other.text_summary;
debug_assert!(self.max_fragment_id <= other.max_fragment_id);
self.max_fragment_id = other.max_fragment_id.clone();
@@ -2204,8 +2256,10 @@ impl sum_tree::Item for InsertionSplit {
}
}
impl<'a> AddAssign<&'a InsertionSplitSummary> for InsertionSplitSummary {
fn add_assign(&mut self, other: &Self) {
impl sum_tree::Summary for InsertionSplitSummary {
type Context = ();
fn add_summary(&mut self, other: &Self, _: &()) {
self.extent += other.extent;
}
}
@@ -2262,7 +2316,7 @@ pub trait ToOffset {
impl ToOffset for Point {
fn to_offset(&self, buffer: &Buffer) -> Result<usize> {
let mut fragments_cursor = buffer.fragments.cursor::<Point, TextSummary>();
fragments_cursor.seek(self, SeekBias::Left);
fragments_cursor.seek(self, SeekBias::Left, &());
fragments_cursor
.item()
.ok_or_else(|| anyhow!("point is out of range"))
@@ -2306,7 +2360,7 @@ impl ToPoint for Anchor {
impl ToPoint for usize {
fn to_point(&self, buffer: &Buffer) -> Result<Point> {
let mut fragments_cursor = buffer.fragments.cursor::<usize, TextSummary>();
fragments_cursor.seek(&self, SeekBias::Left);
fragments_cursor.seek(&self, SeekBias::Left, &());
fragments_cursor
.item()
.ok_or_else(|| anyhow!("offset is out of range"))
+3 -1
View File
@@ -75,6 +75,7 @@ impl Selection {
pub fn buffer_rows_for_display_rows(
&self,
include_end_if_at_line_start: bool,
map: &DisplayMap,
ctx: &AppContext,
) -> (Range<u32>, Range<u32>) {
@@ -84,7 +85,8 @@ impl Selection {
.unwrap();
let mut display_end = self.end.to_display_point(map, ctx).unwrap();
if display_end.row() != map.max_point(ctx).row()
if !include_end_if_at_line_start
&& display_end.row() != map.max_point(ctx).row()
&& display_start.row() != display_end.row()
&& display_end.column() == 0
{
+21 -11
View File
@@ -58,6 +58,14 @@ pub struct TextSummary {
pub rightmost_point: Point,
}
impl sum_tree::Summary for TextSummary {
type Context = ();
fn add_summary(&mut self, other: &Self, _: &()) {
*self += other;
}
}
impl<'a> std::ops::AddAssign<&'a Self> for TextSummary {
fn add_assign(&mut self, other: &'a Self) {
let joined_line_len = self.lines.column + other.first_line_len;
@@ -85,8 +93,8 @@ impl std::ops::AddAssign<Self> for TextSummary {
}
impl<'a> sum_tree::Dimension<'a, TextSummary> for TextSummary {
fn add_summary(&mut self, summary: &TextSummary) {
*self += summary;
fn add_summary(&mut self, other: &TextSummary) {
*self += other;
}
}
@@ -157,7 +165,7 @@ impl From<Arc<str>> for Text {
}
let mut tree = SumTree::new();
tree.extend(runs);
tree.extend(runs, &());
Text {
text,
runs: tree,
@@ -231,13 +239,14 @@ impl Text {
pub fn line_len(&self, row: u32) -> u32 {
let mut cursor = self.runs.cursor::<usize, Point>();
cursor.seek(&self.range.start, SeekBias::Right);
cursor.seek(&self.range.start, SeekBias::Right, &());
let absolute_row = cursor.start().row + row;
let mut cursor = self.runs.cursor::<Point, usize>();
cursor.seek(&Point::new(absolute_row, 0), SeekBias::Right);
cursor.seek(&Point::new(absolute_row, 0), SeekBias::Right, &());
let prefix_len = self.range.start.saturating_sub(*cursor.start());
let line_len = cursor.summary::<usize>(&Point::new(absolute_row + 1, 0), SeekBias::Left);
let line_len =
cursor.summary::<usize>(&Point::new(absolute_row + 1, 0), SeekBias::Left, &());
let suffix_len = cursor.start().saturating_sub(self.range.end);
line_len
@@ -262,14 +271,15 @@ impl Text {
candidates.push(Point::new(0, self.line_len(0)));
if lines.row > 1 {
let mut cursor = self.runs.cursor::<usize, Point>();
cursor.seek(&self.range.start, SeekBias::Right);
cursor.seek(&self.range.start, SeekBias::Right, &());
let absolute_start_row = cursor.start().row;
let mut cursor = self.runs.cursor::<Point, usize>();
cursor.seek(&Point::new(absolute_start_row + 1, 0), SeekBias::Right);
cursor.seek(&Point::new(absolute_start_row + 1, 0), SeekBias::Right, &());
let summary = cursor.summary::<TextSummary>(
&Point::new(absolute_start_row + lines.row, 0),
SeekBias::Left,
&(),
);
candidates.push(Point::new(1, 0) + &summary.rightmost_point);
@@ -287,7 +297,7 @@ impl Text {
pub fn offset_for_point(&self, point: Point) -> usize {
let mut cursor = self.runs.cursor::<Point, TextSummary>();
let abs_point = self.abs_point_for_offset(self.range.start) + &point;
cursor.seek(&abs_point, SeekBias::Right);
cursor.seek(&abs_point, SeekBias::Right, &());
let overshoot = abs_point - &cursor.start().lines;
let abs_offset = cursor.start().chars + overshoot.column as usize;
abs_offset - self.range.start
@@ -307,14 +317,14 @@ impl Text {
fn abs_point_for_offset(&self, offset: usize) -> Point {
let mut cursor = self.runs.cursor::<usize, TextSummary>();
cursor.seek(&offset, SeekBias::Right);
cursor.seek(&offset, SeekBias::Right, &());
let overshoot = (offset - cursor.start().chars) as u32;
cursor.start().lines + &Point::new(0, overshoot)
}
fn abs_byte_offset_for_offset(&self, offset: usize) -> usize {
let mut cursor = self.runs.cursor::<usize, TextSummary>();
cursor.seek(&offset, SeekBias::Right);
cursor.seek(&offset, SeekBias::Right, &());
let overshoot = offset - cursor.start().chars;
cursor.start().bytes + overshoot * cursor.item().map_or(0, |run| run.char_size()) as usize
}