From d1f155337f4ea0af8154970a9105f2a73409cfed Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 3 Aug 2022 11:04:59 +0200 Subject: [PATCH] Recompute layers above tab map entirely when tab size changes Previously, we wouldn't generate any `TabEdit` when the tab size changed, causing coordinate spaces in `WrapMap` and `BlockMap` to become outdated. This commit generates a synthetic edit that covers the entire `TabMap` to ensure layers above are synchronized. --- crates/editor/src/display_map.rs | 33 ++++++++++++++++++++++++ crates/editor/src/display_map/tab_map.rs | 12 +++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 9b12df60d9..ec32cdb399 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -1351,6 +1351,39 @@ pub mod tests { ) } + #[gpui::test] + fn test_changing_tab_size(cx: &mut gpui::MutableAppContext) { + cx.set_global({ + let mut settings = Settings::test(cx); + settings.editor_overrides.tab_size = Some(NonZeroU32::new(4).unwrap()); + settings + }); + let buffer = MultiBuffer::build_simple("\ta\n\tb\n\tc", cx); + let font_cache = cx.font_cache(); + let family_id = font_cache.load_family(&["Helvetica"]).unwrap(); + let font_id = font_cache + .select_font(family_id, &Default::default()) + .unwrap(); + let font_size = 14.0; + + let map = + cx.add_model(|cx| DisplayMap::new(buffer.clone(), font_id, font_size, None, 1, 1, cx)); + assert_eq!( + map.update(cx, |map, cx| map.snapshot(cx)).text(), + " a\n b\n c" + ); + + cx.set_global({ + let mut settings = Settings::test(cx); + settings.editor_overrides.tab_size = Some(NonZeroU32::new(2).unwrap()); + settings + }); + assert_eq!( + map.update(cx, |map, cx| map.snapshot(cx)).text(), + " a\n b\n c" + ); + } + fn syntax_chunks<'a>( rows: Range, map: &ModelHandle, diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 3ea3f63a57..839edd5c15 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -27,19 +27,27 @@ impl TabMap { tab_size: NonZeroU32, ) -> (TabSnapshot, Vec) { let mut old_snapshot = self.0.lock(); - let max_offset = old_snapshot.fold_snapshot.len(); let new_snapshot = TabSnapshot { fold_snapshot, tab_size, }; + if old_snapshot.tab_size != new_snapshot.tab_size { + let edits = vec![TabEdit { + old: TabPoint::zero()..old_snapshot.max_point(), + new: TabPoint::zero()..new_snapshot.max_point(), + }]; + return (new_snapshot, edits); + } + + let old_max_offset = old_snapshot.fold_snapshot.len(); let mut tab_edits = Vec::with_capacity(fold_edits.len()); for fold_edit in &mut fold_edits { let mut delta = 0; for chunk in old_snapshot .fold_snapshot - .chunks(fold_edit.old.end..max_offset, false, None) + .chunks(fold_edit.old.end..old_max_offset, false, None) { let patterns: &[_] = &['\t', '\n']; if let Some(ix) = chunk.text.find(patterns) {