From 4f8607039cb59f3f0b87f66e91f9428490abd24a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 18 Apr 2023 10:56:43 -0700 Subject: [PATCH] Add is_tab field to chunks Co-authored-by: Antonio Scandurra --- crates/editor/src/display_map/block_map.rs | 5 +- crates/editor/src/display_map/fold_map.rs | 4 +- .../editor/src/display_map/suggestion_map.rs | 4 +- crates/editor/src/display_map/tab_map.rs | 52 +++++++++++++++++++ crates/language/src/buffer.rs | 3 +- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index c8be2379c26f14f928adbe126766b62a8bc2b929..93e43f876c47316e74f12a3e5ced4d6a3351b233 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -833,10 +833,7 @@ impl<'a> Iterator for BlockChunks<'a> { return Some(Chunk { text: unsafe { std::str::from_utf8_unchecked(&NEWLINES[..line_count as usize]) }, - syntax_highlight_id: None, - highlight_style: None, - diagnostic_severity: None, - is_unnecessary: false, + ..Default::default() }); } diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index b8802e3c90549175b8d63bc70a630d9fd132d58a..bd3cd1a620ada42b93fb5dd1a46151dbb0f8c37b 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -1065,13 +1065,11 @@ impl<'a> Iterator for FoldChunks<'a> { self.output_offset += output_text.len(); return Some(Chunk { text: output_text, - syntax_highlight_id: None, highlight_style: self.ellipses_color.map(|color| HighlightStyle { color: Some(color), ..Default::default() }), - diagnostic_severity: None, - is_unnecessary: false, + ..Default::default() }); } diff --git a/crates/editor/src/display_map/suggestion_map.rs b/crates/editor/src/display_map/suggestion_map.rs index 7be377a69b4f7a5ac88f12f3c64348e38c38e9b7..f48efc76f41bec4dc9a8847f9446f991227e9428 100644 --- a/crates/editor/src/display_map/suggestion_map.rs +++ b/crates/editor/src/display_map/suggestion_map.rs @@ -531,10 +531,8 @@ impl<'a> Iterator for SuggestionChunks<'a> { if let Some(chunk) = chunks.next() { return Some(Chunk { text: chunk, - syntax_highlight_id: None, highlight_style: self.highlight_style, - diagnostic_severity: None, - is_unnecessary: false, + ..Default::default() }); } else { self.suggestion_chunks = None; diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 2932994670ceaca5275215dad5b5335badb5ad38..d97ba4f40be2ebcf3e4d9e0aa5ad7c18d5772c37 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -268,6 +268,7 @@ impl TabSnapshot { tab_size: self.tab_size, chunk: Chunk { text: &SPACES[0..(to_next_stop as usize)], + is_tab: true, ..Default::default() }, inside_leading_tab: to_next_stop > 0, @@ -545,6 +546,7 @@ impl<'a> Iterator for TabChunks<'a> { self.output_position = next_output_position; return Some(Chunk { text: &SPACES[..len as usize], + is_tab: true, ..self.chunk }); } @@ -654,6 +656,56 @@ mod tests { assert_eq!(tab_snapshot.text(), input); } + #[gpui::test] + fn test_marking_tabs(cx: &mut gpui::AppContext) { + let input = "\t \thello"; + + let buffer = MultiBuffer::build_simple(&input, cx); + let buffer_snapshot = buffer.read(cx).snapshot(cx); + let (_, fold_snapshot) = FoldMap::new(buffer_snapshot.clone()); + let (_, suggestion_snapshot) = SuggestionMap::new(fold_snapshot); + let (_, tab_snapshot) = TabMap::new(suggestion_snapshot, 4.try_into().unwrap()); + + assert_eq!( + chunks(&tab_snapshot, TabPoint::zero()), + vec![ + (" ".to_string(), true), + (" ".to_string(), false), + (" ".to_string(), true), + ("hello".to_string(), false), + ] + ); + assert_eq!( + chunks(&tab_snapshot, TabPoint::new(0, 2)), + vec![ + (" ".to_string(), true), + (" ".to_string(), false), + (" ".to_string(), true), + ("hello".to_string(), false), + ] + ); + + fn chunks(snapshot: &TabSnapshot, start: TabPoint) -> Vec<(String, bool)> { + let mut chunks = Vec::new(); + let mut was_tab = false; + let mut text = String::new(); + for chunk in snapshot.chunks(start..snapshot.max_point(), false, None, None) { + if chunk.is_tab != was_tab { + if !text.is_empty() { + chunks.push((mem::take(&mut text), was_tab)); + } + was_tab = chunk.is_tab; + } + text.push_str(chunk.text); + } + + if !text.is_empty() { + chunks.push((text, was_tab)); + } + chunks + } + } + #[gpui::test(iterations = 100)] fn test_random_tabs(cx: &mut gpui::AppContext, mut rng: StdRng) { let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap(); diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 039012a95f22d506ef266273b4f4a27be24594b9..43766192eb871ade7c912bf098b525520a973d65 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -311,6 +311,7 @@ pub struct Chunk<'a> { pub highlight_style: Option, pub diagnostic_severity: Option, pub is_unnecessary: bool, + pub is_tab: bool, } pub struct Diff { @@ -2840,9 +2841,9 @@ impl<'a> Iterator for BufferChunks<'a> { Some(Chunk { text: slice, syntax_highlight_id: highlight_id, - highlight_style: None, diagnostic_severity: self.current_diagnostic_severity(), is_unnecessary: self.current_code_is_unnecessary(), + ..Default::default() }) } else { None