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.
This commit is contained in:
Antonio Scandurra 2022-08-03 11:04:59 +02:00
parent 541c373d53
commit d1f155337f
2 changed files with 43 additions and 2 deletions

View File

@ -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<u32>,
map: &ModelHandle<DisplayMap>,

View File

@ -27,19 +27,27 @@ impl TabMap {
tab_size: NonZeroU32,
) -> (TabSnapshot, Vec<TabEdit>) {
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) {