diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 77ec73d8bf8b3cb8d2e116b401155634efcdc62f..1491c790f60229e68ec86f1b967a157a51378b43 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -96,6 +96,22 @@ impl TabSnapshot { self.fold_snapshot.buffer_snapshot() } + pub fn line_len(&self, row: u32) -> u32 { + let max_point = self.max_point(); + if row < max_point.row() { + self.chunks( + TabPoint::new(row, 0)..TabPoint::new(row + 1, 0), + false, + None, + ) + .map(|chunk| chunk.text.len() as u32) + .sum::() + - 1 + } else { + max_point.column() + } + } + pub fn text_summary(&self) -> TextSummary { self.text_summary_for_range(TabPoint::zero()..self.max_point()) } @@ -517,8 +533,11 @@ mod tests { actual_summary.longest_row = expected_summary.longest_row; actual_summary.longest_row_chars = expected_summary.longest_row_chars; } + assert_eq!(actual_summary, expected_summary); + } - assert_eq!(actual_summary, expected_summary,); + for row in 0..=text.max_point().row { + assert_eq!(tabs_snapshot.line_len(row), text.line_len(row)); } } } diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index 00e9b63b1ad66625942c62daf21c4b04c372bb9f..0e88d87bd77b06ff3a4ab8bfb49c7f0c1aa2433e 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -559,11 +559,6 @@ impl WrapSnapshot { Patch::new(wrap_edits) } - pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator { - self.chunks(wrap_row..self.max_point().row() + 1, false, None) - .map(|h| h.text) - } - pub fn chunks<'a>( &'a self, rows: Range, @@ -599,16 +594,23 @@ impl WrapSnapshot { } pub fn line_len(&self, row: u32) -> u32 { - let mut len = 0; - for chunk in self.text_chunks(row) { - if let Some(newline_ix) = chunk.find('\n') { - len += newline_ix; - break; + let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(); + cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Left, &()); + if cursor + .item() + .map_or(false, |transform| transform.is_isomorphic()) + { + let overshoot = row - cursor.start().0.row(); + let tab_row = cursor.start().1.row() + overshoot; + let tab_line_len = self.tab_snapshot.line_len(tab_row); + if overshoot == 0 { + cursor.start().0.column() + (tab_line_len - cursor.start().1.column()) } else { - len += chunk.len(); + tab_line_len } + } else { + cursor.start().0.column() } - len as u32 } pub fn soft_wrap_indent(&self, row: u32) -> Option { @@ -741,6 +743,7 @@ impl WrapSnapshot { } } + let text = language::Rope::from(self.text().as_str()); let input_buffer_rows = self.buffer_snapshot().buffer_rows(0).collect::>(); let mut expected_buffer_rows = Vec::new(); let mut prev_tab_row = 0; @@ -754,6 +757,8 @@ impl WrapSnapshot { expected_buffer_rows.push(input_buffer_rows[buffer_point.row as usize]); prev_tab_row = tab_point.row(); } + + assert_eq!(self.line_len(display_row), text.line_len(display_row)); } for start_display_row in 0..expected_buffer_rows.len() { @@ -957,6 +962,10 @@ impl WrapPoint { &mut self.0.row } + pub fn column(self) -> u32 { + self.0.column + } + pub fn column_mut(&mut self) -> &mut u32 { &mut self.0.column } @@ -1272,6 +1281,11 @@ mod tests { self.text_chunks(0).collect() } + pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator { + self.chunks(wrap_row..self.max_point().row() + 1, false, None) + .map(|h| h.text) + } + fn verify_chunks(&mut self, rng: &mut impl Rng) { for _ in 0..5 { let mut end_row = rng.gen_range(0..=self.max_point().row());