Position blocks above/below buffer lines, even when the anchored line is soft-wrapped

Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Nathan Sobo 2021-11-15 16:45:51 -07:00
parent 2cb8b0fcd3
commit 862b988d56
4 changed files with 58 additions and 18 deletions

View file

@ -210,7 +210,7 @@ impl DisplayMapSnapshot {
fn point_to_display_point(&self, point: Point, bias: Bias) -> DisplayPoint {
DisplayPoint(
self.blocks_snapshot.to_block_point(
self.wraps_snapshot.to_wrap_point(
self.wraps_snapshot.from_tab_point(
self.tabs_snapshot
.to_tab_point(point.to_fold_point(&self.folds_snapshot, bias)),
),

View file

@ -179,9 +179,8 @@ impl BlockMap {
}
// Find the blocks within this edited region.
//
// TODO - convert these wrap map edits into buffer positions.
let start_anchor = buffer.anchor_before(Point::new(new_start.row(), 0));
let new_start = wrap_snapshot.to_point(new_start, Bias::Left);
let start_anchor = buffer.anchor_before(new_start);
let start_block_ix = match self.blocks[last_block_ix..].binary_search_by(|probe| {
probe
.position
@ -194,7 +193,8 @@ impl BlockMap {
let end_block_ix = if new_end.row() > wrap_snapshot.max_point().row() {
self.blocks.len()
} else {
let end_anchor = buffer.anchor_before(Point::new(new_end.row(), 0));
let new_end = wrap_snapshot.to_point(new_end, Bias::Left);
let end_anchor = buffer.anchor_before(new_end);
match self.blocks[start_block_ix..].binary_search_by(|probe| {
probe
.position
@ -210,7 +210,17 @@ impl BlockMap {
blocks_in_edit.extend(
self.blocks[start_block_ix..end_block_ix]
.iter()
.map(|block| (block.position.to_point(buffer).row, block)),
.map(|block| {
let mut position = block.position.to_point(buffer);
match block.disposition {
BlockDisposition::Above => position.column = 0,
BlockDisposition::Below => {
position.column = buffer.line_len(position.row)
}
}
let position = wrap_snapshot.from_point(position, Bias::Left);
(position.row(), block)
}),
);
blocks_in_edit.sort_unstable_by_key(|(row, block)| (*row, block.disposition, block.id));
@ -312,13 +322,24 @@ impl<'a> BlockMapWriter<'a> {
let buffer = self.0.buffer.read(cx);
let mut ids = Vec::new();
let mut edits = Vec::<Edit<u32>>::new();
let wrap_snapshot = &*self.0.wrap_snapshot.lock();
for block in blocks {
let id = BlockId(self.0.next_block_id.fetch_add(1, SeqCst));
ids.push(id);
let position = buffer.anchor_before(block.position);
let row = position.to_point(buffer).row;
let point = position.to_point(buffer);
let start_row = wrap_snapshot
.from_point(Point::new(point.row, 0), Bias::Left)
.row();
let end_row = if point.row == buffer.max_point().row {
wrap_snapshot.max_point().row() + 1
} else {
wrap_snapshot
.from_point(Point::new(point.row + 1, 0), Bias::Left)
.row()
};
let block_ix = match self
.0
@ -345,18 +366,18 @@ impl<'a> BlockMapWriter<'a> {
}),
);
if let Err(edit_ix) = edits.binary_search_by_key(&row, |edit| edit.old.start) {
if let Err(edit_ix) = edits.binary_search_by_key(&start_row, |edit| edit.old.start) {
edits.insert(
edit_ix,
Edit {
old: row..(row + 1),
new: row..(row + 1),
old: start_row..end_row,
new: start_row..end_row,
},
);
}
}
self.0.sync(&*self.0.wrap_snapshot.lock(), edits, cx);
self.0.sync(wrap_snapshot, edits, cx);
ids
}
@ -752,7 +773,7 @@ mod tests {
.select_font(family_id, &Default::default())
.unwrap();
let text = "\none two three\nfour five six\nseven eight";
let text = "one two three\nfour five six\nseven eight";
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
let (fold_map, folds_snapshot) = FoldMap::new(buffer.clone(), cx);
@ -764,13 +785,13 @@ mod tests {
writer.insert(
vec![
BlockProperties {
position: Point::new(1, 8),
position: Point::new(1, 12),
text: "BLOCK 1",
disposition: BlockDisposition::Above,
runs: vec![],
},
BlockProperties {
position: Point::new(2, 0),
position: Point::new(1, 1),
text: "BLOCK 2",
disposition: BlockDisposition::Below,
runs: vec![],
@ -784,7 +805,7 @@ mod tests {
let mut snapshot = block_map.read(wraps_snapshot, vec![], cx);
assert_eq!(
snapshot.text(),
"\nBLOCK 1\none two \nthree\nfour five \nsix\nBLOCK 2\nseven \neight"
"one two \nthree\nBLOCK 1\nfour five \nsix\nBLOCK 2\nseven \neight"
);
}

View file

@ -1,4 +1,5 @@
use super::fold_map::{self, FoldEdit, FoldPoint, Snapshot as FoldSnapshot};
use super::fold_map::{self, FoldEdit, FoldPoint, Snapshot as FoldSnapshot, ToFoldPoint};
use buffer::Point;
use language::{rope, HighlightedChunk};
use parking_lot::Mutex;
use std::{mem, ops::Range};
@ -207,6 +208,10 @@ impl Snapshot {
TabPoint::new(input.row(), expanded as u32)
}
pub fn from_point(&self, point: Point, bias: Bias) -> TabPoint {
self.to_tab_point(point.to_fold_point(&self.fold_snapshot, bias))
}
pub fn to_fold_point(&self, output: TabPoint, bias: Bias) -> (FoldPoint, usize, usize) {
let chars = self.fold_snapshot.chars_at(FoldPoint::new(output.row(), 0));
let expanded = output.column() as usize;
@ -219,6 +224,12 @@ impl Snapshot {
)
}
pub fn to_point(&self, point: TabPoint, bias: Bias) -> Point {
self.to_fold_point(point, bias)
.0
.to_buffer_point(&self.fold_snapshot)
}
fn expand_tabs(chars: impl Iterator<Item = char>, column: usize, tab_size: usize) -> usize {
let mut expanded_chars = 0;
let mut expanded_bytes = 0;

View file

@ -657,7 +657,15 @@ impl Snapshot {
TabPoint(tab_point)
}
pub fn to_wrap_point(&self, point: TabPoint) -> WrapPoint {
pub fn to_point(&self, point: WrapPoint, bias: Bias) -> Point {
self.tab_snapshot.to_point(self.to_tab_point(point), bias)
}
pub fn from_point(&self, point: Point, bias: Bias) -> WrapPoint {
self.from_tab_point(self.tab_snapshot.from_point(point, bias))
}
pub fn from_tab_point(&self, point: TabPoint) -> WrapPoint {
let mut cursor = self.transforms.cursor::<(TabPoint, WrapPoint)>();
cursor.seek(&point, Bias::Right, &());
WrapPoint(cursor.start().1 .0 + (point.0 - cursor.start().0 .0))
@ -673,7 +681,7 @@ impl Snapshot {
}
}
self.to_wrap_point(self.tab_snapshot.clip_point(self.to_tab_point(point), bias))
self.from_tab_point(self.tab_snapshot.clip_point(self.to_tab_point(point), bias))
}
fn check_invariants(&self) {