diff --git a/crates/buffer/src/rope.rs b/crates/buffer/src/rope.rs index d5ac56be69..bb61b29b74 100644 --- a/crates/buffer/src/rope.rs +++ b/crates/buffer/src/rope.rs @@ -249,6 +249,11 @@ impl Rope { self.summary().lines_utf16 } } + + pub fn line_len(&self, row: u32) -> u32 { + self.clip_point(Point::new(row, u32::MAX), Bias::Left) + .column + } } impl<'a> From<&'a str> for Rope { diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index f17c79ab31..f5cdb4b157 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -14,8 +14,7 @@ use sum_tree::Bias; use tab_map::TabMap; use wrap_map::WrapMap; -pub use block_map::{BlockDisposition, BlockProperties, Chunks}; -pub use wrap_map::BufferRows; +pub use block_map::{BlockDisposition, BlockProperties, BufferRows, Chunks}; pub trait ToDisplayPoint { fn to_display_point(&self, map: &DisplayMapSnapshot) -> DisplayPoint; @@ -174,7 +173,7 @@ impl DisplayMapSnapshot { } pub fn buffer_rows(&self, start_row: u32) -> BufferRows { - self.wraps_snapshot.buffer_rows(start_row) + self.blocks_snapshot.buffer_rows(start_row) } pub fn buffer_row_count(&self) -> u32 { @@ -304,7 +303,11 @@ impl DisplayMapSnapshot { } pub fn soft_wrap_indent(&self, display_row: u32) -> Option { - self.wraps_snapshot.soft_wrap_indent(display_row) + let wrap_row = self + .blocks_snapshot + .to_wrap_point(BlockPoint::new(display_row, 0)) + .row(); + self.wraps_snapshot.soft_wrap_indent(wrap_row) } pub fn text(&self) -> String { @@ -339,7 +342,7 @@ impl DisplayMapSnapshot { } pub fn line_len(&self, row: u32) -> u32 { - self.wraps_snapshot.line_len(row) + self.blocks_snapshot.line_len(row) } pub fn longest_row(&self) -> u32 { diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 29be478406..13212290ad 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -336,7 +336,7 @@ fn push_isomorphic(tree: &mut SumTree, rows: u32) { } impl BlockPoint { - fn new(row: u32, column: u32) -> Self { + pub fn new(row: u32, column: u32) -> Self { Self(Point::new(row, column)) } } @@ -520,7 +520,24 @@ impl BlockSnapshot { } pub fn max_point(&self) -> BlockPoint { - self.to_block_point(self.wrap_snapshot.max_point()) + let row = self.transforms.summary().output_rows - 1; + BlockPoint::new(row, self.line_len(row)) + } + + pub fn line_len(&self, row: u32) -> u32 { + let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(); + cursor.seek(&BlockRow(row), Bias::Right, &()); + if let Some(transform) = cursor.item() { + let (output_start, input_start) = cursor.start(); + let overshoot = row - output_start.0; + if let Some(block) = &transform.block { + block.text.line_len(overshoot) + } else { + self.wrap_snapshot.line_len(input_start.0 + overshoot) + } + } else { + panic!("row out of range"); + } } pub fn clip_point(&self, point: BlockPoint, bias: Bias) -> BlockPoint { @@ -819,10 +836,6 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for BlockRow { } impl BlockDisposition { - fn is_above(&self) -> bool { - matches!(self, BlockDisposition::Above) - } - fn is_below(&self) -> bool { matches!(self, BlockDisposition::Below) } @@ -1275,6 +1288,15 @@ mod tests { ); } + for (row, line) in expected_lines.iter().enumerate() { + assert_eq!( + blocks_snapshot.line_len(row as u32), + line.len() as u32, + "invalid line len for row {}", + row + ); + } + for row in 0..=blocks_snapshot.wrap_snapshot.max_point().row() { let wrap_point = WrapPoint::new(row, 0); let block_point = blocks_snapshot.to_block_point(wrap_point); diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index e337dc7bbf..c0764190b1 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -902,10 +902,6 @@ impl WrapPoint { self.0.row } - pub fn column(self) -> u32 { - self.0.column - } - pub fn row_mut(&mut self) -> &mut u32 { &mut self.0.row }