@@ -1,9 +1,12 @@
use super::{
Highlights,
fold_map::Chunk,
- wrap_map::{self, WrapEdit, WrapPoint, WrapSnapshot},
+ wrap_map::{self, WrapEdit, WrapPatch, WrapPoint, WrapSnapshot},
+};
+use crate::{
+ EditorStyle, GutterDimensions,
+ display_map::{dimensions::RowDelta, wrap_map::WrapRow},
};
-use crate::{EditorStyle, GutterDimensions};
use collections::{Bound, HashMap, HashSet};
use gpui::{AnyElement, App, EntityId, Pixels, Window};
use language::{Patch, Point};
@@ -75,10 +78,17 @@ impl From<CustomBlockId> for ElementId {
pub struct BlockPoint(pub Point);
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
-pub struct BlockRow(pub(super) u32);
+pub struct BlockRow(pub u32);
-#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
-struct WrapRow(u32);
+impl_for_row_types! {
+ BlockRow => RowDelta
+}
+
+impl BlockPoint {
+ pub fn row(&self) -> BlockRow {
+ BlockRow(self.0.row)
+ }
+}
pub type RenderBlock = Arc<dyn Send + Sync + Fn(&mut BlockContext) -> AnyElement>;
@@ -159,19 +169,19 @@ impl BlockPlacement<Anchor> {
BlockPlacement::Above(position) => {
let mut position = position.to_point(buffer_snapshot);
position.column = 0;
- let wrap_row = WrapRow(wrap_snapshot.make_wrap_point(position, Bias::Left).row());
+ let wrap_row = wrap_snapshot.make_wrap_point(position, Bias::Left).row();
Some(BlockPlacement::Above(wrap_row))
}
BlockPlacement::Near(position) => {
let mut position = position.to_point(buffer_snapshot);
position.column = buffer_snapshot.line_len(MultiBufferRow(position.row));
- let wrap_row = WrapRow(wrap_snapshot.make_wrap_point(position, Bias::Left).row());
+ let wrap_row = wrap_snapshot.make_wrap_point(position, Bias::Left).row();
Some(BlockPlacement::Near(wrap_row))
}
BlockPlacement::Below(position) => {
let mut position = position.to_point(buffer_snapshot);
position.column = buffer_snapshot.line_len(MultiBufferRow(position.row));
- let wrap_row = WrapRow(wrap_snapshot.make_wrap_point(position, Bias::Left).row());
+ let wrap_row = wrap_snapshot.make_wrap_point(position, Bias::Left).row();
Some(BlockPlacement::Below(wrap_row))
}
BlockPlacement::Replace(range) => {
@@ -181,11 +191,9 @@ impl BlockPlacement<Anchor> {
None
} else {
start.column = 0;
- let start_wrap_row =
- WrapRow(wrap_snapshot.make_wrap_point(start, Bias::Left).row());
+ let start_wrap_row = wrap_snapshot.make_wrap_point(start, Bias::Left).row();
end.column = buffer_snapshot.line_len(MultiBufferRow(end.row));
- let end_wrap_row =
- WrapRow(wrap_snapshot.make_wrap_point(end, Bias::Left).row());
+ let end_wrap_row = wrap_snapshot.make_wrap_point(end, Bias::Left).row();
Some(BlockPlacement::Replace(start_wrap_row..=end_wrap_row))
}
}
@@ -433,9 +441,9 @@ impl Debug for Block {
#[derive(Clone, Debug, Default)]
struct TransformSummary {
- input_rows: u32,
- output_rows: u32,
- longest_row: u32,
+ input_rows: WrapRow,
+ output_rows: BlockRow,
+ longest_row: BlockRow,
longest_row_chars: u32,
}
@@ -443,8 +451,8 @@ pub struct BlockChunks<'a> {
transforms: sum_tree::Cursor<'a, 'static, Transform, Dimensions<BlockRow, WrapRow>>,
input_chunks: wrap_map::WrapChunks<'a>,
input_chunk: Chunk<'a>,
- output_row: u32,
- max_output_row: u32,
+ output_row: BlockRow,
+ max_output_row: BlockRow,
masked: bool,
}
@@ -462,9 +470,9 @@ impl BlockMap {
buffer_header_height: u32,
excerpt_header_height: u32,
) -> Self {
- let row_count = wrap_snapshot.max_point().row() + 1;
+ let row_count = wrap_snapshot.max_point().row() + WrapRow(1);
let mut transforms = SumTree::default();
- push_isomorphic(&mut transforms, row_count, &wrap_snapshot);
+ push_isomorphic(&mut transforms, row_count - WrapRow(0), &wrap_snapshot);
let map = Self {
next_block_id: AtomicUsize::new(0),
custom_blocks: Vec::new(),
@@ -479,14 +487,14 @@ impl BlockMap {
map.sync(
&wrap_snapshot,
Patch::new(vec![Edit {
- old: 0..row_count,
- new: 0..row_count,
+ old: WrapRow(0)..row_count,
+ new: WrapRow(0)..row_count,
}]),
);
map
}
- pub fn read(&self, wrap_snapshot: WrapSnapshot, edits: Patch<u32>) -> BlockMapReader<'_> {
+ pub fn read(&self, wrap_snapshot: WrapSnapshot, edits: WrapPatch) -> BlockMapReader<'_> {
self.sync(&wrap_snapshot, edits);
*self.wrap_snapshot.borrow_mut() = wrap_snapshot.clone();
BlockMapReader {
@@ -501,13 +509,13 @@ impl BlockMap {
}
}
- pub fn write(&mut self, wrap_snapshot: WrapSnapshot, edits: Patch<u32>) -> BlockMapWriter<'_> {
+ pub fn write(&mut self, wrap_snapshot: WrapSnapshot, edits: WrapPatch) -> BlockMapWriter<'_> {
self.sync(&wrap_snapshot, edits);
*self.wrap_snapshot.borrow_mut() = wrap_snapshot;
BlockMapWriter(self)
}
- fn sync(&self, wrap_snapshot: &WrapSnapshot, mut edits: Patch<u32>) {
+ fn sync(&self, wrap_snapshot: &WrapSnapshot, mut edits: WrapPatch) {
let buffer = wrap_snapshot.buffer_snapshot();
// Handle changing the last excerpt if it is empty.
@@ -520,7 +528,7 @@ impl BlockMap {
{
let max_point = wrap_snapshot.max_point();
let edit_start = wrap_snapshot.prev_row_boundary(max_point);
- let edit_end = max_point.row() + 1;
+ let edit_end = max_point.row() + WrapRow(1);
edits = edits.compose([WrapEdit {
old: edit_start..edit_end,
new: edit_start..edit_end,
@@ -540,8 +548,8 @@ impl BlockMap {
let mut edits = edits.into_iter().peekable();
while let Some(edit) = edits.next() {
- let mut old_start = WrapRow(edit.old.start);
- let mut new_start = WrapRow(edit.new.start);
+ let mut old_start = edit.old.start;
+ let mut new_start = edit.new.start;
// Only preserve transforms that:
// * Strictly precedes this edit
@@ -550,7 +558,7 @@ impl BlockMap {
// However, if we hit a replace block that ends at the start of the edit we want to reconstruct it.
new_transforms.append(cursor.slice(&old_start, Bias::Left), ());
if let Some(transform) = cursor.item()
- && transform.summary.input_rows > 0
+ && transform.summary.input_rows > WrapRow(0)
&& cursor.end() == old_start
&& transform.block.as_ref().is_none_or(|b| !b.is_replacement())
{
@@ -573,8 +581,8 @@ impl BlockMap {
// If the edit starts within an isomorphic transform, preserve its prefix
// If the edit lands within a replacement block, expand the edit to include the start of the replaced input range
let transform = cursor.item().unwrap();
- let transform_rows_before_edit = old_start.0 - cursor.start().0;
- if transform_rows_before_edit > 0 {
+ let transform_rows_before_edit = old_start - *cursor.start();
+ if transform_rows_before_edit > RowDelta(0) {
if transform.block.is_none() {
// Preserve any portion of the old isomorphic transform that precedes this edit.
push_isomorphic(
@@ -586,32 +594,32 @@ impl BlockMap {
// We landed within a block that replaces some lines, so we
// extend the edit to start at the beginning of the
// replacement.
- debug_assert!(transform.summary.input_rows > 0);
- old_start.0 -= transform_rows_before_edit;
- new_start.0 -= transform_rows_before_edit;
+ debug_assert!(transform.summary.input_rows > WrapRow(0));
+ old_start -= transform_rows_before_edit;
+ new_start -= transform_rows_before_edit;
}
}
// Decide where the edit ends
// * It should end at a transform boundary
// * Coalesce edits that intersect the same transform
- let mut old_end = WrapRow(edit.old.end);
- let mut new_end = WrapRow(edit.new.end);
+ let mut old_end = edit.old.end;
+ let mut new_end = edit.new.end;
loop {
// Seek to the transform starting at or after the end of the edit
cursor.seek(&old_end, Bias::Left);
cursor.next();
// Extend edit to the end of the discarded transform so it is reconstructed in full
- let transform_rows_after_edit = cursor.start().0 - old_end.0;
- old_end.0 += transform_rows_after_edit;
- new_end.0 += transform_rows_after_edit;
+ let transform_rows_after_edit = *cursor.start() - old_end;
+ old_end += transform_rows_after_edit;
+ new_end += transform_rows_after_edit;
// Combine this edit with any subsequent edits that intersect the same transform.
while let Some(next_edit) = edits.peek() {
- if next_edit.old.start <= cursor.start().0 {
- old_end = WrapRow(next_edit.old.end);
- new_end = WrapRow(next_edit.new.end);
+ if next_edit.old.start <= *cursor.start() {
+ old_end = next_edit.old.end;
+ new_end = next_edit.new.end;
cursor.seek(&old_end, Bias::Left);
cursor.next();
edits.next();
@@ -635,8 +643,7 @@ impl BlockMap {
}
// Find the blocks within this edited region.
- let new_buffer_start =
- wrap_snapshot.to_point(WrapPoint::new(new_start.0, 0), Bias::Left);
+ let new_buffer_start = wrap_snapshot.to_point(WrapPoint::new(new_start, 0), Bias::Left);
let start_bound = Bound::Included(new_buffer_start);
let start_block_ix =
match self.custom_blocks[last_block_ix..].binary_search_by(|probe| {
@@ -651,12 +658,11 @@ impl BlockMap {
};
let end_bound;
- let end_block_ix = if new_end.0 > wrap_snapshot.max_point().row() {
+ let end_block_ix = if new_end > wrap_snapshot.max_point().row() {
end_bound = Bound::Unbounded;
self.custom_blocks.len()
} else {
- let new_buffer_end =
- wrap_snapshot.to_point(WrapPoint::new(new_end.0, 0), Bias::Left);
+ let new_buffer_end = wrap_snapshot.to_point(WrapPoint::new(new_end, 0), Bias::Left);
end_bound = Bound::Excluded(new_buffer_end);
match self.custom_blocks[start_block_ix..].binary_search_by(|probe| {
probe
@@ -699,30 +705,31 @@ impl BlockMap {
let mut just_processed_folded_buffer = false;
for (block_placement, block) in blocks_in_edit.drain(..) {
let mut summary = TransformSummary {
- input_rows: 0,
- output_rows: block.height(),
- longest_row: 0,
+ input_rows: WrapRow(0),
+ output_rows: BlockRow(block.height()),
+ longest_row: BlockRow(0),
longest_row_chars: 0,
};
let rows_before_block;
match block_placement {
BlockPlacement::Above(position) => {
- rows_before_block = position.0 - new_transforms.summary().input_rows;
+ rows_before_block = position - new_transforms.summary().input_rows;
just_processed_folded_buffer = false;
}
BlockPlacement::Near(position) | BlockPlacement::Below(position) => {
if just_processed_folded_buffer {
continue;
}
- if position.0 + 1 < new_transforms.summary().input_rows {
+ if position + RowDelta(1) < new_transforms.summary().input_rows {
continue;
}
- rows_before_block = (position.0 + 1) - new_transforms.summary().input_rows;
+ rows_before_block =
+ (position + RowDelta(1)) - new_transforms.summary().input_rows;
}
BlockPlacement::Replace(range) => {
- rows_before_block = range.start().0 - new_transforms.summary().input_rows;
- summary.input_rows = range.end().0 - range.start().0 + 1;
+ rows_before_block = *range.start() - new_transforms.summary().input_rows;
+ summary.input_rows = WrapRow(1) + (*range.end() - *range.start());
just_processed_folded_buffer = matches!(block, Block::FoldedBuffer { .. });
}
}
@@ -738,16 +745,15 @@ impl BlockMap {
}
// Insert an isomorphic transform after the final block.
- let rows_after_last_block = new_end
- .0
- .saturating_sub(new_transforms.summary().input_rows);
+ let rows_after_last_block =
+ RowDelta(new_end.0).saturating_sub(RowDelta(new_transforms.summary().input_rows.0));
push_isomorphic(&mut new_transforms, rows_after_last_block, wrap_snapshot);
}
new_transforms.append(cursor.suffix(), ());
debug_assert_eq!(
new_transforms.summary().input_rows,
- wrap_snapshot.max_point().row() + 1
+ wrap_snapshot.max_point().row() + WrapRow(1)
);
drop(cursor);
@@ -823,7 +829,7 @@ impl BlockMap {
.row();
return Some((
- BlockPlacement::Replace(WrapRow(wrap_row)..=WrapRow(wrap_end_row)),
+ BlockPlacement::Replace(wrap_row..=wrap_end_row),
Block::FoldedBuffer {
height: height + self.buffer_header_height,
first_excerpt,
@@ -849,7 +855,7 @@ impl BlockMap {
continue;
};
- return Some((BlockPlacement::Above(WrapRow(wrap_row)), block));
+ return Some((BlockPlacement::Above(wrap_row), block));
}
})
}
@@ -920,8 +926,8 @@ impl BlockMap {
}
}
-fn push_isomorphic(tree: &mut SumTree<Transform>, rows: u32, wrap_snapshot: &WrapSnapshot) {
- if rows == 0 {
+fn push_isomorphic(tree: &mut SumTree<Transform>, rows: RowDelta, wrap_snapshot: &WrapSnapshot) {
+ if rows == RowDelta(0) {
return;
}
@@ -929,9 +935,9 @@ fn push_isomorphic(tree: &mut SumTree<Transform>, rows: u32, wrap_snapshot: &Wra
let wrap_row_end = wrap_row_start + rows;
let wrap_summary = wrap_snapshot.text_summary_for_range(wrap_row_start..wrap_row_end);
let summary = TransformSummary {
- input_rows: rows,
- output_rows: rows,
- longest_row: wrap_summary.longest_row,
+ input_rows: WrapRow(rows.0),
+ output_rows: BlockRow(rows.0),
+ longest_row: BlockRow(wrap_summary.longest_row),
longest_row_chars: wrap_summary.longest_row_chars,
};
let mut merged = false;
@@ -956,8 +962,8 @@ fn push_isomorphic(tree: &mut SumTree<Transform>, rows: u32, wrap_snapshot: &Wra
}
impl BlockPoint {
- pub fn new(row: u32, column: u32) -> Self {
- Self(Point::new(row, column))
+ pub fn new(row: BlockRow, column: u32) -> Self {
+ Self(Point::new(row.0, column))
}
}
@@ -1000,15 +1006,13 @@ impl BlockMapReader<'_> {
.wrap_snapshot
.make_wrap_point(Point::new(buffer_row, 0), Bias::Left)
.row();
- let start_wrap_row = WrapRow(
- self.wrap_snapshot
- .prev_row_boundary(WrapPoint::new(wrap_row, 0)),
- );
- let end_wrap_row = WrapRow(
- self.wrap_snapshot
- .next_row_boundary(WrapPoint::new(wrap_row, 0))
- .unwrap_or(self.wrap_snapshot.max_point().row() + 1),
- );
+ let start_wrap_row = self
+ .wrap_snapshot
+ .prev_row_boundary(WrapPoint::new(wrap_row, 0));
+ let end_wrap_row = self
+ .wrap_snapshot
+ .next_row_boundary(WrapPoint::new(wrap_row, 0))
+ .unwrap_or(self.wrap_snapshot.max_point().row() + WrapRow(1));
let mut cursor = self.transforms.cursor::<Dimensions<WrapRow, BlockRow>>(());
cursor.seek(&start_wrap_row, Bias::Left);
@@ -1040,7 +1044,7 @@ impl BlockMapWriter<'_> {
let wrap_snapshot = &*self.0.wrap_snapshot.borrow();
let buffer = wrap_snapshot.buffer_snapshot();
- let mut previous_wrap_row_range: Option<Range<u32>> = None;
+ let mut previous_wrap_row_range: Option<Range<WrapRow>> = None;
for block in blocks {
if let BlockPlacement::Replace(_) = &block.placement {
debug_assert!(block.height.unwrap() > 0);
@@ -1063,7 +1067,7 @@ impl BlockMapWriter<'_> {
wrap_snapshot.prev_row_boundary(WrapPoint::new(start_wrap_row, 0));
let end_row = wrap_snapshot
.next_row_boundary(WrapPoint::new(end_wrap_row, 0))
- .unwrap_or(wrap_snapshot.max_point().row() + 1);
+ .unwrap_or(wrap_snapshot.max_point().row() + WrapRow(1));
start_row..end_row
});
(range.start, range.end)
@@ -1135,7 +1139,7 @@ impl BlockMapWriter<'_> {
wrap_snapshot.prev_row_boundary(WrapPoint::new(start_wrap_row, 0));
let end = wrap_snapshot
.next_row_boundary(WrapPoint::new(end_wrap_row, 0))
- .unwrap_or(wrap_snapshot.max_point().row() + 1);
+ .unwrap_or(wrap_snapshot.max_point().row() + WrapRow(1));
edits.push(Edit {
old: start..end,
new: start..end,
@@ -1153,7 +1157,7 @@ impl BlockMapWriter<'_> {
let buffer = wrap_snapshot.buffer_snapshot();
let mut edits = Patch::default();
let mut last_block_buffer_row = None;
- let mut previous_wrap_row_range: Option<Range<u32>> = None;
+ let mut previous_wrap_row_range: Option<Range<WrapRow>> = None;
self.0.custom_blocks.retain(|block| {
if block_ids.contains(&block.id) {
let start = block.placement.start().to_point(buffer);
@@ -1171,7 +1175,7 @@ impl BlockMapWriter<'_> {
wrap_snapshot.prev_row_boundary(WrapPoint::new(start_wrap_row, 0));
let end_row = wrap_snapshot
.next_row_boundary(WrapPoint::new(end_wrap_row, 0))
- .unwrap_or(wrap_snapshot.max_point().row() + 1);
+ .unwrap_or(wrap_snapshot.max_point().row() + WrapRow(1));
start_row..end_row
});
(range.start, range.end)
@@ -1255,9 +1259,9 @@ impl BlockMapWriter<'_> {
let wrap_snapshot = self.0.wrap_snapshot.borrow().clone();
for range in ranges {
let last_edit_row = cmp::min(
- wrap_snapshot.make_wrap_point(range.end, Bias::Right).row() + 1,
+ wrap_snapshot.make_wrap_point(range.end, Bias::Right).row() + WrapRow(1),
wrap_snapshot.max_point().row(),
- ) + 1;
+ ) + WrapRow(1);
let range = wrap_snapshot.make_wrap_point(range.start, Bias::Left).row()..last_edit_row;
edits.push(Edit {
old: range.clone(),
@@ -1304,7 +1308,7 @@ impl BlockSnapshot {
#[cfg(test)]
pub fn text(&self) -> String {
self.chunks(
- 0..self.transforms.summary().output_rows,
+ BlockRow(0)..self.transforms.summary().output_rows,
false,
false,
Highlights::default(),
@@ -1315,7 +1319,7 @@ impl BlockSnapshot {
pub(crate) fn chunks<'a>(
&'a self,
- rows: Range<u32>,
+ rows: Range<BlockRow>,
language_aware: bool,
masked: bool,
highlights: Highlights<'a>,
@@ -1323,9 +1327,9 @@ impl BlockSnapshot {
let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
- cursor.seek(&BlockRow(rows.start), Bias::Right);
- let transform_output_start = cursor.start().0.0;
- let transform_input_start = cursor.start().1.0;
+ cursor.seek(&rows.start, Bias::Right);
+ let transform_output_start = cursor.start().0;
+ let transform_input_start = cursor.start().1;
let mut input_start = transform_input_start;
let mut input_end = transform_input_start;
@@ -1335,7 +1339,7 @@ impl BlockSnapshot {
input_start += rows.start - transform_output_start;
input_end += cmp::min(
rows.end - transform_output_start,
- transform.summary.input_rows,
+ RowDelta(transform.summary.input_rows.0),
);
}
@@ -1361,11 +1365,11 @@ impl BlockSnapshot {
.item()
.is_some_and(|transform| transform.block.is_none())
{
- start_row.0 - output_start.0
+ start_row - *output_start
} else {
- 0
+ RowDelta(0)
};
- let input_start_row = input_start.0 + overshoot;
+ let input_start_row = *input_start + overshoot;
BlockRows {
transforms: cursor,
input_rows: self.wrap_snapshot.row_infos(input_start_row),
@@ -1374,16 +1378,19 @@ impl BlockSnapshot {
}
}
- pub fn blocks_in_range(&self, rows: Range<u32>) -> impl Iterator<Item = (u32, &Block)> {
+ pub fn blocks_in_range(
+ &self,
+ rows: Range<BlockRow>,
+ ) -> impl Iterator<Item = (BlockRow, &Block)> {
let mut cursor = self.transforms.cursor::<BlockRow>(());
- cursor.seek(&BlockRow(rows.start), Bias::Left);
- while cursor.start().0 < rows.start && cursor.end().0 <= rows.start {
+ cursor.seek(&rows.start, Bias::Left);
+ while *cursor.start() < rows.start && cursor.end() <= rows.start {
cursor.next();
}
std::iter::from_fn(move || {
while let Some(transform) = cursor.item() {
- let start_row = cursor.start().0;
+ let start_row = *cursor.start();
if start_row > rows.end
|| (start_row == rows.end
&& transform
@@ -1443,7 +1450,7 @@ impl BlockSnapshot {
.wrap_snapshot
.make_wrap_point(buffer.range_for_excerpt(excerpt_id)?.start, Bias::Left),
};
- let wrap_row = WrapRow(wrap_point.row());
+ let wrap_row = wrap_point.row();
let mut cursor = self.transforms.cursor::<WrapRow>(());
cursor.seek(&wrap_row, Bias::Left);
@@ -1464,11 +1471,15 @@ impl BlockSnapshot {
}
pub fn max_point(&self) -> BlockPoint {
- let row = self.transforms.summary().output_rows.saturating_sub(1);
- BlockPoint::new(row, self.line_len(BlockRow(row)))
+ let row = self
+ .transforms
+ .summary()
+ .output_rows
+ .saturating_sub(RowDelta(1));
+ BlockPoint::new(row, self.line_len(row))
}
- pub fn longest_row(&self) -> u32 {
+ pub fn longest_row(&self) -> BlockRow {
self.transforms.summary().longest_row
}
@@ -1480,12 +1491,12 @@ impl BlockSnapshot {
let mut longest_row_chars = 0;
if let Some(transform) = cursor.item() {
if transform.block.is_none() {
- let Dimensions(output_start, input_start, _) = cursor.start();
- let overshoot = range.start.0 - output_start.0;
- let wrap_start_row = input_start.0 + overshoot;
+ let &Dimensions(output_start, input_start, _) = cursor.start();
+ let overshoot = range.start - output_start;
+ let wrap_start_row = input_start + WrapRow(overshoot.0);
let wrap_end_row = cmp::min(
- input_start.0 + (range.end.0 - output_start.0),
- cursor.end().1.0,
+ input_start + WrapRow((range.end - output_start).0),
+ cursor.end().1,
);
let summary = self
.wrap_snapshot
@@ -1500,22 +1511,22 @@ impl BlockSnapshot {
if range.end > cursor_start_row {
let summary = cursor.summary::<_, TransformSummary>(&range.end, Bias::Right);
if summary.longest_row_chars > longest_row_chars {
- longest_row = BlockRow(cursor_start_row.0 + summary.longest_row);
+ longest_row = cursor_start_row + summary.longest_row;
longest_row_chars = summary.longest_row_chars;
}
if let Some(transform) = cursor.item()
&& transform.block.is_none()
{
- let Dimensions(output_start, input_start, _) = cursor.start();
- let overshoot = range.end.0 - output_start.0;
- let wrap_start_row = input_start.0;
- let wrap_end_row = input_start.0 + overshoot;
+ let &Dimensions(output_start, input_start, _) = cursor.start();
+ let overshoot = range.end - output_start;
+ let wrap_start_row = input_start;
+ let wrap_end_row = input_start + overshoot;
let summary = self
.wrap_snapshot
.text_summary_for_range(wrap_start_row..wrap_end_row);
if summary.longest_row_chars > longest_row_chars {
- longest_row = BlockRow(output_start.0 + summary.longest_row);
+ longest_row = output_start + RowDelta(summary.longest_row);
}
}
}
@@ -1529,13 +1540,13 @@ impl BlockSnapshot {
.find::<Dimensions<BlockRow, WrapRow>, _>((), &row, Bias::Right);
if let Some(transform) = item {
let Dimensions(output_start, input_start, _) = start;
- let overshoot = row.0 - output_start.0;
+ let overshoot = row - output_start;
if transform.block.is_some() {
0
} else {
- self.wrap_snapshot.line_len(input_start.0 + overshoot)
+ self.wrap_snapshot.line_len(input_start + overshoot)
}
- } else if row.0 == 0 {
+ } else if row == BlockRow(0) {
0
} else {
panic!("row out of range");
@@ -1559,9 +1570,9 @@ impl BlockSnapshot {
let wrap_point = self
.wrap_snapshot
.make_wrap_point(Point::new(row.0, 0), Bias::Left);
- let (_, _, item) =
- self.transforms
- .find::<WrapRow, _>((), &WrapRow(wrap_point.row()), Bias::Right);
+ let (_, _, item) = self
+ .transforms
+ .find::<WrapRow, _>((), &wrap_point.row(), Bias::Right);
item.is_some_and(|transform| {
transform
.block
@@ -1574,9 +1585,9 @@ impl BlockSnapshot {
let mut cursor = self.transforms.cursor::<Dimensions<BlockRow, WrapRow>>(());
cursor.seek(&BlockRow(point.row), Bias::Right);
- let max_input_row = WrapRow(self.transforms.summary().input_rows);
- let mut search_left =
- (bias == Bias::Left && cursor.start().1.0 > 0) || cursor.end().1 == max_input_row;
+ let max_input_row = self.transforms.summary().input_rows;
+ let mut search_left = (bias == Bias::Left && cursor.start().1 > WrapRow(0))
+ || cursor.end().1 == max_input_row;
let mut reversed = false;
loop {
@@ -1598,9 +1609,11 @@ impl BlockSnapshot {
}
None => {
let input_point = if point.row >= output_end_row.0 {
- let line_len = self.wrap_snapshot.line_len(input_end_row.0 - 1);
- self.wrap_snapshot
- .clip_point(WrapPoint::new(input_end_row.0 - 1, line_len), bias)
+ let line_len = self.wrap_snapshot.line_len(input_end_row - RowDelta(1));
+ self.wrap_snapshot.clip_point(
+ WrapPoint::new(input_end_row - RowDelta(1), line_len),
+ bias,
+ )
} else {
let output_overshoot = point.0.saturating_sub(output_start);
self.wrap_snapshot
@@ -1632,12 +1645,12 @@ impl BlockSnapshot {
pub fn to_block_point(&self, wrap_point: WrapPoint) -> BlockPoint {
let (start, _, item) = self.transforms.find::<Dimensions<WrapRow, BlockRow>, _>(
(),
- &WrapRow(wrap_point.row()),
+ &wrap_point.row(),
Bias::Right,
);
if let Some(transform) = item {
if transform.block.is_some() {
- BlockPoint::new(start.1.0, 0)
+ BlockPoint::new(start.1, 0)
} else {
let Dimensions(input_start_row, output_start_row, _) = start;
let input_start = Point::new(input_start_row.0, 0);
@@ -1660,20 +1673,20 @@ impl BlockSnapshot {
match transform.block.as_ref() {
Some(block) => {
if block.place_below() {
- let wrap_row = start.1.0 - 1;
+ let wrap_row = start.1 - RowDelta(1);
WrapPoint::new(wrap_row, self.wrap_snapshot.line_len(wrap_row))
} else if block.place_above() {
- WrapPoint::new(start.1.0, 0)
+ WrapPoint::new(start.1, 0)
} else if bias == Bias::Left {
- WrapPoint::new(start.1.0, 0)
+ WrapPoint::new(start.1, 0)
} else {
- let wrap_row = end.1.0 - 1;
+ let wrap_row = end.1 - RowDelta(1);
WrapPoint::new(wrap_row, self.wrap_snapshot.line_len(wrap_row))
}
}
None => {
- let overshoot = block_point.row - start.0.0;
- let wrap_row = start.1.0 + overshoot;
+ let overshoot = block_point.row() - start.0;
+ let wrap_row = start.1 + RowDelta(overshoot.0);
WrapPoint::new(wrap_row, block_point.column)
}
}
@@ -1705,11 +1718,11 @@ impl BlockChunks<'_> {
.item()
.is_some_and(|transform| transform.block.is_none())
{
- let start_input_row = self.transforms.start().1.0;
- let start_output_row = self.transforms.start().0.0;
+ let start_input_row = self.transforms.start().1;
+ let start_output_row = self.transforms.start().0;
if start_output_row < self.max_output_row {
let end_input_row = cmp::min(
- self.transforms.end().1.0,
+ self.transforms.end().1,
start_input_row + (self.max_output_row - start_output_row),
);
self.input_chunks.seek(start_input_row..end_input_row);
@@ -1732,22 +1745,22 @@ impl<'a> Iterator for BlockChunks<'a> {
let transform = self.transforms.item()?;
if transform.block.is_some() {
- let block_start = self.transforms.start().0.0;
- let mut block_end = self.transforms.end().0.0;
+ let block_start = self.transforms.start().0;
+ let mut block_end = self.transforms.end().0;
self.advance();
if self.transforms.item().is_none() {
- block_end -= 1;
+ block_end -= RowDelta(1);
}
let start_in_block = self.output_row - block_start;
let end_in_block = cmp::min(self.max_output_row, block_end) - block_start;
- // todo: We need to split the chunk here?
- let line_count = cmp::min(end_in_block - start_in_block, u128::BITS);
+ // todo: We need to split the chunk here instead of taking min
+ let line_count = cmp::min(end_in_block - start_in_block, RowDelta(u128::BITS));
self.output_row += line_count;
return Some(Chunk {
- text: unsafe { std::str::from_utf8_unchecked(&NEWLINES[..line_count as usize]) },
- chars: 1u128.unbounded_shl(line_count) - 1,
+ text: unsafe { std::str::from_utf8_unchecked(&NEWLINES[..line_count.0 as usize]) },
+ chars: 1u128.unbounded_shl(line_count.0) - 1,
..Default::default()
});
}
@@ -1757,7 +1770,7 @@ impl<'a> Iterator for BlockChunks<'a> {
self.input_chunk = input_chunk;
} else {
if self.output_row < self.max_output_row {
- self.output_row += 1;
+ self.output_row.0 += 1;
self.advance();
if self.transforms.item().is_some() {
return Some(Chunk {
@@ -1771,7 +1784,7 @@ impl<'a> Iterator for BlockChunks<'a> {
}
}
- let transform_end = self.transforms.end().0.0;
+ let transform_end = self.transforms.end().0;
let (prefix_rows, prefix_bytes) =
offset_for_row(self.input_chunk.text, transform_end - self.output_row);
self.output_row += prefix_rows;
@@ -1819,7 +1832,7 @@ impl Iterator for BlockRows<'_> {
self.started = true;
}
- if self.output_row.0 >= self.transforms.end().0.0 {
+ if self.output_row >= self.transforms.end().0 {
self.transforms.next();
while let Some(transform) = self.transforms.item() {
if transform
@@ -1839,7 +1852,7 @@ impl Iterator for BlockRows<'_> {
.as_ref()
.is_none_or(|block| block.is_replacement())
{
- self.input_rows.seek(self.transforms.start().1.0);
+ self.input_rows.seek(self.transforms.start().1);
}
}
@@ -1889,7 +1902,7 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for WrapRow {
}
fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
- self.0 += summary.input_rows;
+ *self += summary.input_rows;
}
}
@@ -1899,7 +1912,7 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for BlockRow {
}
fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
- self.0 += summary.output_rows;
+ *self += summary.output_rows;
}
}
@@ -1949,7 +1962,7 @@ impl Debug for CustomBlock {
// Count the number of bytes prior to a target point. If the string doesn't contain the target
// point, return its total extent. Otherwise return the target point itself.
-fn offset_for_row(s: &str, target: u32) -> (u32, usize) {
+fn offset_for_row(s: &str, target: RowDelta) -> (RowDelta, usize) {
let mut row = 0;
let mut offset = 0;
for (ix, line) in s.split('\n').enumerate() {
@@ -1957,12 +1970,12 @@ fn offset_for_row(s: &str, target: u32) -> (u32, usize) {
row += 1;
offset += 1;
}
- if row >= target {
+ if row >= target.0 {
break;
}
offset += line.len();
}
- (row, offset)
+ (RowDelta(row), offset)
}
#[cfg(test)]
@@ -1983,16 +1996,28 @@ mod tests {
#[gpui::test]
fn test_offset_for_row() {
- assert_eq!(offset_for_row("", 0), (0, 0));
- assert_eq!(offset_for_row("", 1), (0, 0));
- assert_eq!(offset_for_row("abcd", 0), (0, 0));
- assert_eq!(offset_for_row("abcd", 1), (0, 4));
- assert_eq!(offset_for_row("\n", 0), (0, 0));
- assert_eq!(offset_for_row("\n", 1), (1, 1));
- assert_eq!(offset_for_row("abc\ndef\nghi", 0), (0, 0));
- assert_eq!(offset_for_row("abc\ndef\nghi", 1), (1, 4));
- assert_eq!(offset_for_row("abc\ndef\nghi", 2), (2, 8));
- assert_eq!(offset_for_row("abc\ndef\nghi", 3), (2, 11));
+ assert_eq!(offset_for_row("", RowDelta(0)), (RowDelta(0), 0));
+ assert_eq!(offset_for_row("", RowDelta(1)), (RowDelta(0), 0));
+ assert_eq!(offset_for_row("abcd", RowDelta(0)), (RowDelta(0), 0));
+ assert_eq!(offset_for_row("abcd", RowDelta(1)), (RowDelta(0), 4));
+ assert_eq!(offset_for_row("\n", RowDelta(0)), (RowDelta(0), 0));
+ assert_eq!(offset_for_row("\n", RowDelta(1)), (RowDelta(1), 1));
+ assert_eq!(
+ offset_for_row("abc\ndef\nghi", RowDelta(0)),
+ (RowDelta(0), 0)
+ );
+ assert_eq!(
+ offset_for_row("abc\ndef\nghi", RowDelta(1)),
+ (RowDelta(1), 4)
+ );
+ assert_eq!(
+ offset_for_row("abc\ndef\nghi", RowDelta(2)),
+ (RowDelta(2), 8)
+ );
+ assert_eq!(
+ offset_for_row("abc\ndef\nghi", RowDelta(3)),
+ (RowDelta(2), 11)
+ );
}
#[gpui::test]
@@ -2040,10 +2065,10 @@ mod tests {
assert_eq!(snapshot.text(), "aaa\n\n\n\nbbb\nccc\nddd\n\n\n");
let blocks = snapshot
- .blocks_in_range(0..8)
+ .blocks_in_range(BlockRow(0)..BlockRow(8))
.map(|(start_row, block)| {
let block = block.as_custom().unwrap();
- (start_row..start_row + block.height.unwrap(), block.id)
+ (start_row.0..start_row.0 + block.height.unwrap(), block.id)
})
.collect::<Vec<_>>();
@@ -2058,74 +2083,74 @@ mod tests {
);
assert_eq!(
- snapshot.to_block_point(WrapPoint::new(0, 3)),
- BlockPoint::new(0, 3)
+ snapshot.to_block_point(WrapPoint::new(WrapRow(0), 3)),
+ BlockPoint::new(BlockRow(0), 3)
);
assert_eq!(
- snapshot.to_block_point(WrapPoint::new(1, 0)),
- BlockPoint::new(4, 0)
+ snapshot.to_block_point(WrapPoint::new(WrapRow(1), 0)),
+ BlockPoint::new(BlockRow(4), 0)
);
assert_eq!(
- snapshot.to_block_point(WrapPoint::new(3, 3)),
- BlockPoint::new(6, 3)
+ snapshot.to_block_point(WrapPoint::new(WrapRow(3), 3)),
+ BlockPoint::new(BlockRow(6), 3)
);
assert_eq!(
- snapshot.to_wrap_point(BlockPoint::new(0, 3), Bias::Left),
- WrapPoint::new(0, 3)
+ snapshot.to_wrap_point(BlockPoint::new(BlockRow(0), 3), Bias::Left),
+ WrapPoint::new(WrapRow(0), 3)
);
assert_eq!(
- snapshot.to_wrap_point(BlockPoint::new(1, 0), Bias::Left),
- WrapPoint::new(1, 0)
+ snapshot.to_wrap_point(BlockPoint::new(BlockRow(1), 0), Bias::Left),
+ WrapPoint::new(WrapRow(1), 0)
);
assert_eq!(
- snapshot.to_wrap_point(BlockPoint::new(3, 0), Bias::Left),
- WrapPoint::new(1, 0)
+ snapshot.to_wrap_point(BlockPoint::new(BlockRow(3), 0), Bias::Left),
+ WrapPoint::new(WrapRow(1), 0)
);
assert_eq!(
- snapshot.to_wrap_point(BlockPoint::new(7, 0), Bias::Left),
- WrapPoint::new(3, 3)
+ snapshot.to_wrap_point(BlockPoint::new(BlockRow(7), 0), Bias::Left),
+ WrapPoint::new(WrapRow(3), 3)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(1, 0), Bias::Left),
- BlockPoint::new(0, 3)
+ snapshot.clip_point(BlockPoint::new(BlockRow(1), 0), Bias::Left),
+ BlockPoint::new(BlockRow(0), 3)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(1, 0), Bias::Right),
- BlockPoint::new(4, 0)
+ snapshot.clip_point(BlockPoint::new(BlockRow(1), 0), Bias::Right),
+ BlockPoint::new(BlockRow(4), 0)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(1, 1), Bias::Left),
- BlockPoint::new(0, 3)
+ snapshot.clip_point(BlockPoint::new(BlockRow(1), 1), Bias::Left),
+ BlockPoint::new(BlockRow(0), 3)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(1, 1), Bias::Right),
- BlockPoint::new(4, 0)
+ snapshot.clip_point(BlockPoint::new(BlockRow(1), 1), Bias::Right),
+ BlockPoint::new(BlockRow(4), 0)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(4, 0), Bias::Left),
- BlockPoint::new(4, 0)
+ snapshot.clip_point(BlockPoint::new(BlockRow(4), 0), Bias::Left),
+ BlockPoint::new(BlockRow(4), 0)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(4, 0), Bias::Right),
- BlockPoint::new(4, 0)
+ snapshot.clip_point(BlockPoint::new(BlockRow(4), 0), Bias::Right),
+ BlockPoint::new(BlockRow(4), 0)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(6, 3), Bias::Left),
- BlockPoint::new(6, 3)
+ snapshot.clip_point(BlockPoint::new(BlockRow(6), 3), Bias::Left),
+ BlockPoint::new(BlockRow(6), 3)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(6, 3), Bias::Right),
- BlockPoint::new(6, 3)
+ snapshot.clip_point(BlockPoint::new(BlockRow(6), 3), Bias::Right),
+ BlockPoint::new(BlockRow(6), 3)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(7, 0), Bias::Left),
- BlockPoint::new(6, 3)
+ snapshot.clip_point(BlockPoint::new(BlockRow(7), 0), Bias::Left),
+ BlockPoint::new(BlockRow(6), 3)
);
assert_eq!(
- snapshot.clip_point(BlockPoint::new(7, 0), Bias::Right),
- BlockPoint::new(6, 3)
+ snapshot.clip_point(BlockPoint::new(BlockRow(7), 0), Bias::Right),
+ BlockPoint::new(BlockRow(6), 3)
);
assert_eq!(
@@ -2220,8 +2245,8 @@ mod tests {
assert_eq!(snapshot.text(), "\nBuff\ner 1\n\nBuff\ner 2\n\nBuff\ner 3");
let blocks: Vec<_> = snapshot
- .blocks_in_range(0..u32::MAX)
- .map(|(row, block)| (row..row + block.height(), block.id()))
+ .blocks_in_range(BlockRow(0)..BlockRow(u32::MAX))
+ .map(|(row, block)| (row.0..row.0 + block.height(), block.id()))
.collect();
assert_eq!(
blocks,
@@ -2675,7 +2700,7 @@ mod tests {
}]);
let blocks_snapshot = block_map.read(wrap_snapshot.clone(), Patch::default());
let blocks = blocks_snapshot
- .blocks_in_range(0..u32::MAX)
+ .blocks_in_range(BlockRow(0)..BlockRow(u32::MAX))
.collect::<Vec<_>>();
for (_, block) in &blocks {
if let BlockId::Custom(custom_block_id) = block.id() {
@@ -1,5 +1,6 @@
use super::{
Highlights,
+ dimensions::RowDelta,
fold_map::{Chunk, FoldRows},
tab_map::{self, TabEdit, TabPoint, TabSnapshot},
};
@@ -7,13 +8,20 @@ use gpui::{App, AppContext as _, Context, Entity, Font, LineWrapper, Pixels, Tas
use language::Point;
use multi_buffer::{MultiBufferSnapshot, RowInfo};
use smol::future::yield_now;
-use std::sync::LazyLock;
-use std::{cmp, collections::VecDeque, mem, ops::Range, time::Duration};
+use std::{cmp, collections::VecDeque, mem, ops::Range, sync::LazyLock, time::Duration};
use sum_tree::{Bias, Cursor, Dimensions, SumTree};
use text::Patch;
pub use super::tab_map::TextSummary;
-pub type WrapEdit = text::Edit<u32>;
+pub type WrapEdit = text::Edit<WrapRow>;
+pub type WrapPatch = text::Patch<WrapRow>;
+
+#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
+pub struct WrapRow(pub u32);
+
+impl_for_row_types! {
+ WrapRow => RowDelta
+}
/// Handles soft wrapping of text.
///
@@ -21,8 +29,8 @@ pub type WrapEdit = text::Edit<u32>;
pub struct WrapMap {
snapshot: WrapSnapshot,
pending_edits: VecDeque<(TabSnapshot, Vec<TabEdit>)>,
- interpolated_edits: Patch<u32>,
- edits_since_sync: Patch<u32>,
+ interpolated_edits: WrapPatch,
+ edits_since_sync: WrapPatch,
wrap_width: Option<Pixels>,
background_task: Option<Task<()>>,
font_with_size: (Font, Pixels),
@@ -54,7 +62,7 @@ pub struct WrapChunks<'a> {
input_chunks: tab_map::TabChunks<'a>,
input_chunk: Chunk<'a>,
output_position: WrapPoint,
- max_output_row: u32,
+ max_output_row: WrapRow,
transforms: Cursor<'a, 'static, Transform, Dimensions<WrapPoint, TabPoint>>,
snapshot: &'a WrapSnapshot,
}
@@ -63,19 +71,19 @@ pub struct WrapChunks<'a> {
pub struct WrapRows<'a> {
input_buffer_rows: FoldRows<'a>,
input_buffer_row: RowInfo,
- output_row: u32,
+ output_row: WrapRow,
soft_wrapped: bool,
- max_output_row: u32,
+ max_output_row: WrapRow,
transforms: Cursor<'a, 'static, Transform, Dimensions<WrapPoint, TabPoint>>,
}
impl WrapRows<'_> {
- pub(crate) fn seek(&mut self, start_row: u32) {
+ pub(crate) fn seek(&mut self, start_row: WrapRow) {
self.transforms
.seek(&WrapPoint::new(start_row, 0), Bias::Left);
let mut input_row = self.transforms.start().1.row();
if self.transforms.item().is_some_and(|t| t.is_isomorphic()) {
- input_row += start_row - self.transforms.start().0.row();
+ input_row += (start_row - self.transforms.start().0.row()).0;
}
self.soft_wrapped = self.transforms.item().is_some_and(|t| !t.is_isomorphic());
self.input_buffer_rows.seek(input_row);
@@ -120,7 +128,7 @@ impl WrapMap {
tab_snapshot: TabSnapshot,
edits: Vec<TabEdit>,
cx: &mut Context<Self>,
- ) -> (WrapSnapshot, Patch<u32>) {
+ ) -> (WrapSnapshot, WrapPatch) {
if self.wrap_width.is_some() {
self.pending_edits.push_back((tab_snapshot, edits));
self.flush_edits(cx);
@@ -226,8 +234,8 @@ impl WrapMap {
let new_rows = self.snapshot.transforms.summary().output.lines.row + 1;
self.snapshot.interpolated = false;
self.edits_since_sync = self.edits_since_sync.compose(Patch::new(vec![WrapEdit {
- old: 0..old_rows,
- new: 0..new_rows,
+ old: WrapRow(0)..WrapRow(old_rows),
+ new: WrapRow(0)..WrapRow(new_rows),
}]));
}
}
@@ -331,7 +339,7 @@ impl WrapSnapshot {
self.tab_snapshot.buffer_snapshot()
}
- fn interpolate(&mut self, new_tab_snapshot: TabSnapshot, tab_edits: &[TabEdit]) -> Patch<u32> {
+ fn interpolate(&mut self, new_tab_snapshot: TabSnapshot, tab_edits: &[TabEdit]) -> WrapPatch {
let mut new_transforms;
if tab_edits.is_empty() {
new_transforms = self.transforms.clone();
@@ -401,7 +409,7 @@ impl WrapSnapshot {
tab_edits: &[TabEdit],
wrap_width: Pixels,
line_wrapper: &mut LineWrapper,
- ) -> Patch<u32> {
+ ) -> WrapPatch {
#[derive(Debug)]
struct RowEdit {
old_rows: Range<u32>,
@@ -554,7 +562,7 @@ impl WrapSnapshot {
old_snapshot.compute_edits(tab_edits, self)
}
- fn compute_edits(&self, tab_edits: &[TabEdit], new_snapshot: &WrapSnapshot) -> Patch<u32> {
+ fn compute_edits(&self, tab_edits: &[TabEdit], new_snapshot: &WrapSnapshot) -> WrapPatch {
let mut wrap_edits = Vec::with_capacity(tab_edits.len());
let mut old_cursor = self.transforms.cursor::<TransformSummary>(());
let mut new_cursor = new_snapshot.transforms.cursor::<TransformSummary>(());
@@ -581,8 +589,8 @@ impl WrapSnapshot {
new_end += tab_edit.new.end.0 - new_cursor.start().input.lines;
wrap_edits.push(WrapEdit {
- old: old_start.row..old_end.row,
- new: new_start.row..new_end.row,
+ old: WrapRow(old_start.row)..WrapRow(old_end.row),
+ new: WrapRow(new_start.row)..WrapRow(new_end.row),
});
}
@@ -592,7 +600,7 @@ impl WrapSnapshot {
pub(crate) fn chunks<'a>(
&'a self,
- rows: Range<u32>,
+ rows: Range<WrapRow>,
language_aware: bool,
highlights: Highlights<'a>,
) -> WrapChunks<'a> {
@@ -627,17 +635,17 @@ impl WrapSnapshot {
WrapPoint(self.transforms.summary().output.lines)
}
- pub fn line_len(&self, row: u32) -> u32 {
+ pub fn line_len(&self, row: WrapRow) -> u32 {
let (start, _, item) = self.transforms.find::<Dimensions<WrapPoint, TabPoint>, _>(
(),
- &WrapPoint::new(row + 1, 0),
+ &WrapPoint::new(row + WrapRow(1), 0),
Bias::Left,
);
if item.is_some_and(|transform| transform.is_isomorphic()) {
let overshoot = row - start.0.row();
- let tab_row = start.1.row() + overshoot;
+ let tab_row = start.1.row() + overshoot.0;
let tab_line_len = self.tab_snapshot.line_len(tab_row);
- if overshoot == 0 {
+ if overshoot.0 == 0 {
start.0.column() + (tab_line_len - start.1.column())
} else {
tab_line_len
@@ -647,7 +655,7 @@ impl WrapSnapshot {
}
}
- pub fn text_summary_for_range(&self, rows: Range<u32>) -> TextSummary {
+ pub fn text_summary_for_range(&self, rows: Range<WrapRow>) -> TextSummary {
let mut summary = TextSummary::default();
let start = WrapPoint::new(rows.start, 0);
@@ -708,10 +716,12 @@ impl WrapSnapshot {
summary
}
- pub fn soft_wrap_indent(&self, row: u32) -> Option<u32> {
- let (.., item) =
- self.transforms
- .find::<WrapPoint, _>((), &WrapPoint::new(row + 1, 0), Bias::Right);
+ pub fn soft_wrap_indent(&self, row: WrapRow) -> Option<u32> {
+ let (.., item) = self.transforms.find::<WrapPoint, _>(
+ (),
+ &WrapPoint::new(row + WrapRow(1), 0),
+ Bias::Right,
+ );
item.and_then(|transform| {
if transform.is_isomorphic() {
None
@@ -725,14 +735,14 @@ impl WrapSnapshot {
self.transforms.summary().output.longest_row
}
- pub fn row_infos(&self, start_row: u32) -> WrapRows<'_> {
+ pub fn row_infos(&self, start_row: WrapRow) -> WrapRows<'_> {
let mut transforms = self
.transforms
.cursor::<Dimensions<WrapPoint, TabPoint>>(());
transforms.seek(&WrapPoint::new(start_row, 0), Bias::Left);
let mut input_row = transforms.start().1.row();
if transforms.item().is_some_and(|t| t.is_isomorphic()) {
- input_row += start_row - transforms.start().0.row();
+ input_row += (start_row - transforms.start().0.row()).0;
}
let soft_wrapped = transforms.item().is_some_and(|t| !t.is_isomorphic());
let mut input_buffer_rows = self.tab_snapshot.rows(input_row);
@@ -787,9 +797,9 @@ impl WrapSnapshot {
self.tab_point_to_wrap_point(self.tab_snapshot.clip_point(self.to_tab_point(point), bias))
}
- pub fn prev_row_boundary(&self, mut point: WrapPoint) -> u32 {
+ pub fn prev_row_boundary(&self, mut point: WrapPoint) -> WrapRow {
if self.transforms.is_empty() {
- return 0;
+ return WrapRow(0);
}
*point.column_mut() = 0;
@@ -813,7 +823,7 @@ impl WrapSnapshot {
unreachable!()
}
- pub fn next_row_boundary(&self, mut point: WrapPoint) -> Option<u32> {
+ pub fn next_row_boundary(&self, mut point: WrapPoint) -> Option<WrapRow> {
point.0 += Point::new(1, 0);
let mut cursor = self
@@ -833,13 +843,13 @@ impl WrapSnapshot {
#[cfg(test)]
pub fn text(&self) -> String {
- self.text_chunks(0).collect()
+ self.text_chunks(WrapRow(0)).collect()
}
#[cfg(test)]
- pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator<Item = &str> {
+ pub fn text_chunks(&self, wrap_row: WrapRow) -> impl Iterator<Item = &str> {
self.chunks(
- wrap_row..self.max_point().row() + 1,
+ wrap_row..self.max_point().row() + WrapRow(1),
false,
Highlights::default(),
)
@@ -867,21 +877,22 @@ impl WrapSnapshot {
let mut input_buffer_rows = self.tab_snapshot.rows(0);
let mut expected_buffer_rows = Vec::new();
let mut prev_tab_row = 0;
- for display_row in 0..=self.max_point().row() {
+ for display_row in 0..=self.max_point().row().0 {
+ let display_row = WrapRow(display_row);
let tab_point = self.to_tab_point(WrapPoint::new(display_row, 0));
- if tab_point.row() == prev_tab_row && display_row != 0 {
+ if tab_point.row() == prev_tab_row && display_row != WrapRow(0) {
expected_buffer_rows.push(None);
} else {
expected_buffer_rows.push(input_buffer_rows.next().unwrap().buffer_row);
}
prev_tab_row = tab_point.row();
- assert_eq!(self.line_len(display_row), text.line_len(display_row));
+ assert_eq!(self.line_len(display_row), text.line_len(display_row.0));
}
for start_display_row in 0..expected_buffer_rows.len() {
assert_eq!(
- self.row_infos(start_display_row as u32)
+ self.row_infos(WrapRow(start_display_row as u32))
.map(|row_info| row_info.buffer_row)
.collect::<Vec<_>>(),
&expected_buffer_rows[start_display_row..],
@@ -894,7 +905,7 @@ impl WrapSnapshot {
}
impl WrapChunks<'_> {
- pub(crate) fn seek(&mut self, rows: Range<u32>) {
+ pub(crate) fn seek(&mut self, rows: Range<WrapRow>) {
let output_start = WrapPoint::new(rows.start, 0);
let output_end = WrapPoint::new(rows.end, 0);
self.transforms.seek(&output_start, Bias::Right);
@@ -931,7 +942,7 @@ impl<'a> Iterator for WrapChunks<'a> {
// Exclude newline starting prior to the desired row.
start_ix = 1;
summary.row = 0;
- } else if self.output_position.row() + 1 >= self.max_output_row {
+ } else if self.output_position.row() + WrapRow(1) >= self.max_output_row {
// Exclude soft indentation ending after the desired row.
end_ix = 1;
summary.column = 0;
@@ -997,7 +1008,7 @@ impl Iterator for WrapRows<'_> {
let soft_wrapped = self.soft_wrapped;
let diff_status = self.input_buffer_row.diff_status;
- self.output_row += 1;
+ self.output_row += WrapRow(1);
self.transforms
.seek_forward(&WrapPoint::new(self.output_row, 0), Bias::Left);
if self.transforms.item().is_some_and(|t| t.is_isomorphic()) {
@@ -1107,12 +1118,12 @@ impl SumTreeExt for SumTree<Transform> {
}
impl WrapPoint {
- pub fn new(row: u32, column: u32) -> Self {
- Self(Point::new(row, column))
+ pub fn new(row: WrapRow, column: u32) -> Self {
+ Self(Point::new(row.0, column))
}
- pub fn row(self) -> u32 {
- self.0.row
+ pub fn row(self) -> WrapRow {
+ WrapRow(self.0.row)
}
pub fn row_mut(&mut self) -> &mut u32 {
@@ -1417,14 +1428,14 @@ mod tests {
for (snapshot, patch) in edits {
let snapshot_text = Rope::from(snapshot.text().as_str());
for edit in &patch {
- let old_start = initial_text.point_to_offset(Point::new(edit.new.start, 0));
+ let old_start = initial_text.point_to_offset(Point::new(edit.new.start.0, 0));
let old_end = initial_text.point_to_offset(cmp::min(
- Point::new(edit.new.start + edit.old.len() as u32, 0),
+ Point::new(edit.new.start.0 + (edit.old.end - edit.old.start).0, 0),
initial_text.max_point(),
));
- let new_start = snapshot_text.point_to_offset(Point::new(edit.new.start, 0));
+ let new_start = snapshot_text.point_to_offset(Point::new(edit.new.start.0, 0));
let new_end = snapshot_text.point_to_offset(cmp::min(
- Point::new(edit.new.end, 0),
+ Point::new(edit.new.end.0, 0),
snapshot_text.max_point(),
));
let new_text = snapshot_text
@@ -1484,11 +1495,11 @@ mod tests {
impl WrapSnapshot {
fn verify_chunks(&mut self, rng: &mut impl Rng) {
for _ in 0..5 {
- let mut end_row = rng.random_range(0..=self.max_point().row());
+ let mut end_row = rng.random_range(0..=self.max_point().row().0);
let start_row = rng.random_range(0..=end_row);
end_row += 1;
- let mut expected_text = self.text_chunks(start_row).collect::<String>();
+ let mut expected_text = self.text_chunks(WrapRow(start_row)).collect::<String>();
if expected_text.ends_with('\n') {
expected_text.push('\n');
}
@@ -1497,12 +1508,16 @@ mod tests {
.take((end_row - start_row) as usize)
.collect::<Vec<_>>()
.join("\n");
- if end_row <= self.max_point().row() {
+ if end_row <= self.max_point().row().0 {
expected_text.push('\n');
}
let actual_text = self
- .chunks(start_row..end_row, true, Highlights::default())
+ .chunks(
+ WrapRow(start_row)..WrapRow(end_row),
+ true,
+ Highlights::default(),
+ )
.map(|c| c.text)
.collect::<String>();
assert_eq!(