Theme hints and suggestions differently

This commit is contained in:
Kirill Bulatov 2023-06-26 21:34:50 +03:00
parent 3312c9114b
commit 480d8c511b
9 changed files with 105 additions and 49 deletions

View file

@ -392,7 +392,13 @@ impl DisplaySnapshot {
/// Returns text chunks starting at the given display row until the end of the file /// Returns text chunks starting at the given display row until the end of the file
pub fn text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> { pub fn text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {
self.block_snapshot self.block_snapshot
.chunks(display_row..self.max_point().row() + 1, false, None, None) .chunks(
display_row..self.max_point().row() + 1,
false,
None,
None,
None,
)
.map(|h| h.text) .map(|h| h.text)
} }
@ -400,7 +406,7 @@ impl DisplaySnapshot {
pub fn reverse_text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> { pub fn reverse_text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {
(0..=display_row).into_iter().rev().flat_map(|row| { (0..=display_row).into_iter().rev().flat_map(|row| {
self.block_snapshot self.block_snapshot
.chunks(row..row + 1, false, None, None) .chunks(row..row + 1, false, None, None, None)
.map(|h| h.text) .map(|h| h.text)
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()
@ -412,13 +418,15 @@ impl DisplaySnapshot {
&self, &self,
display_rows: Range<u32>, display_rows: Range<u32>,
language_aware: bool, language_aware: bool,
inlay_highlights: Option<HighlightStyle>, hint_highlights: Option<HighlightStyle>,
suggestion_highlights: Option<HighlightStyle>,
) -> DisplayChunks<'_> { ) -> DisplayChunks<'_> {
self.block_snapshot.chunks( self.block_snapshot.chunks(
display_rows, display_rows,
language_aware, language_aware,
Some(&self.text_highlights), Some(&self.text_highlights),
inlay_highlights, hint_highlights,
suggestion_highlights,
) )
} }
@ -1711,7 +1719,7 @@ pub mod tests {
) -> Vec<(String, Option<Color>, Option<Color>)> { ) -> Vec<(String, Option<Color>, Option<Color>)> {
let snapshot = map.update(cx, |map, cx| map.snapshot(cx)); let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
let mut chunks: Vec<(String, Option<Color>, Option<Color>)> = Vec::new(); let mut chunks: Vec<(String, Option<Color>, Option<Color>)> = Vec::new();
for chunk in snapshot.chunks(rows, true, None) { for chunk in snapshot.chunks(rows, true, None, None) {
let syntax_color = chunk let syntax_color = chunk
.syntax_highlight_id .syntax_highlight_id
.and_then(|id| id.style(theme)?.color); .and_then(|id| id.style(theme)?.color);

View file

@ -573,9 +573,15 @@ impl<'a> BlockMapWriter<'a> {
impl BlockSnapshot { impl BlockSnapshot {
#[cfg(test)] #[cfg(test)]
pub fn text(&self) -> String { pub fn text(&self) -> String {
self.chunks(0..self.transforms.summary().output_rows, false, None, None) self.chunks(
.map(|chunk| chunk.text) 0..self.transforms.summary().output_rows,
.collect() false,
None,
None,
None,
)
.map(|chunk| chunk.text)
.collect()
} }
pub fn chunks<'a>( pub fn chunks<'a>(
@ -583,7 +589,8 @@ impl BlockSnapshot {
rows: Range<u32>, rows: Range<u32>,
language_aware: bool, language_aware: bool,
text_highlights: Option<&'a TextHighlights>, text_highlights: Option<&'a TextHighlights>,
inlay_highlights: Option<HighlightStyle>, hint_highlights: Option<HighlightStyle>,
suggestion_highlights: Option<HighlightStyle>,
) -> BlockChunks<'a> { ) -> BlockChunks<'a> {
let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows); let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(); let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
@ -616,7 +623,8 @@ impl BlockSnapshot {
input_start..input_end, input_start..input_end,
language_aware, language_aware,
text_highlights, text_highlights,
inlay_highlights, hint_highlights,
suggestion_highlights,
), ),
input_chunk: Default::default(), input_chunk: Default::default(),
transforms: cursor, transforms: cursor,
@ -1495,6 +1503,7 @@ mod tests {
false, false,
None, None,
None, None,
None,
) )
.map(|chunk| chunk.text) .map(|chunk| chunk.text)
.collect::<String>(); .collect::<String>();

View file

@ -475,7 +475,7 @@ pub struct FoldSnapshot {
impl FoldSnapshot { impl FoldSnapshot {
#[cfg(test)] #[cfg(test)]
pub fn text(&self) -> String { pub fn text(&self) -> String {
self.chunks(FoldOffset(0)..self.len(), false, None, None) self.chunks(FoldOffset(0)..self.len(), false, None, None, None)
.map(|c| c.text) .map(|c| c.text)
.collect() .collect()
} }
@ -652,7 +652,8 @@ impl FoldSnapshot {
range: Range<FoldOffset>, range: Range<FoldOffset>,
language_aware: bool, language_aware: bool,
text_highlights: Option<&'a TextHighlights>, text_highlights: Option<&'a TextHighlights>,
inlay_highlights: Option<HighlightStyle>, hint_highlights: Option<HighlightStyle>,
suggestion_highlights: Option<HighlightStyle>,
) -> FoldChunks<'a> { ) -> FoldChunks<'a> {
let mut transform_cursor = self.transforms.cursor::<(FoldOffset, InlayOffset)>(); let mut transform_cursor = self.transforms.cursor::<(FoldOffset, InlayOffset)>();
@ -674,7 +675,8 @@ impl FoldSnapshot {
inlay_start..inlay_end, inlay_start..inlay_end,
language_aware, language_aware,
text_highlights, text_highlights,
inlay_highlights, hint_highlights,
suggestion_highlights,
), ),
inlay_chunk: None, inlay_chunk: None,
inlay_offset: inlay_start, inlay_offset: inlay_start,
@ -685,7 +687,7 @@ impl FoldSnapshot {
} }
pub fn chars_at(&self, start: FoldPoint) -> impl '_ + Iterator<Item = char> { pub fn chars_at(&self, start: FoldPoint) -> impl '_ + Iterator<Item = char> {
self.chunks(start.to_offset(self)..self.len(), false, None, None) self.chunks(start.to_offset(self)..self.len(), false, None, None, None)
.flat_map(|chunk| chunk.text.chars()) .flat_map(|chunk| chunk.text.chars())
} }
@ -1514,7 +1516,7 @@ mod tests {
let text = &expected_text[start.0..end.0]; let text = &expected_text[start.0..end.0];
assert_eq!( assert_eq!(
snapshot snapshot
.chunks(start..end, false, Some(&highlights), None) .chunks(start..end, false, Some(&highlights), None, None)
.map(|c| c.text) .map(|c| c.text)
.collect::<String>(), .collect::<String>(),
text, text,

View file

@ -194,7 +194,8 @@ pub struct InlayChunks<'a> {
inlay_chunks: Option<text::Chunks<'a>>, inlay_chunks: Option<text::Chunks<'a>>,
output_offset: InlayOffset, output_offset: InlayOffset,
max_output_offset: InlayOffset, max_output_offset: InlayOffset,
highlight_style: Option<HighlightStyle>, hint_highlight_style: Option<HighlightStyle>,
suggestion_highlight_style: Option<HighlightStyle>,
highlight_endpoints: Peekable<vec::IntoIter<HighlightEndpoint>>, highlight_endpoints: Peekable<vec::IntoIter<HighlightEndpoint>>,
active_highlights: BTreeMap<Option<TypeId>, HighlightStyle>, active_highlights: BTreeMap<Option<TypeId>, HighlightStyle>,
snapshot: &'a InlaySnapshot, snapshot: &'a InlaySnapshot,
@ -281,9 +282,13 @@ impl<'a> Iterator for InlayChunks<'a> {
let chunk = inlay_chunks.next().unwrap(); let chunk = inlay_chunks.next().unwrap();
self.output_offset.0 += chunk.len(); self.output_offset.0 += chunk.len();
let highlight_style = match inlay.id {
InlayId::Suggestion(_) => self.suggestion_highlight_style,
InlayId::Hint(_) => self.hint_highlight_style,
};
Chunk { Chunk {
text: chunk, text: chunk,
highlight_style: self.highlight_style, highlight_style,
..Default::default() ..Default::default()
} }
} }
@ -576,7 +581,7 @@ impl InlayMap {
let mut to_remove = Vec::new(); let mut to_remove = Vec::new();
let mut to_insert = Vec::new(); let mut to_insert = Vec::new();
let snapshot = &mut self.snapshot; let snapshot = &mut self.snapshot;
for _ in 0..rng.gen_range(1..=5) { for i in 0..rng.gen_range(1..=5) {
if self.inlays.is_empty() || rng.gen() { if self.inlays.is_empty() || rng.gen() {
let position = snapshot.buffer.random_byte_range(0, rng).start; let position = snapshot.buffer.random_byte_range(0, rng).start;
let bias = if rng.gen() { Bias::Left } else { Bias::Right }; let bias = if rng.gen() { Bias::Left } else { Bias::Right };
@ -595,8 +600,14 @@ impl InlayMap {
bias, bias,
text text
); );
let inlay_id = if i % 2 == 0 {
InlayId::Hint(post_inc(next_inlay_id))
} else {
InlayId::Suggestion(post_inc(next_inlay_id))
};
to_insert.push(( to_insert.push((
InlayId(post_inc(next_inlay_id)), inlay_id,
InlayProperties { InlayProperties {
position: snapshot.buffer.anchor_at(position, bias), position: snapshot.buffer.anchor_at(position, bias),
text, text,
@ -927,7 +938,8 @@ impl InlaySnapshot {
range: Range<InlayOffset>, range: Range<InlayOffset>,
language_aware: bool, language_aware: bool,
text_highlights: Option<&'a TextHighlights>, text_highlights: Option<&'a TextHighlights>,
inlay_highlight_style: Option<HighlightStyle>, hint_highlights: Option<HighlightStyle>,
suggestion_highlights: Option<HighlightStyle>,
) -> InlayChunks<'a> { ) -> InlayChunks<'a> {
let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>(); let mut cursor = self.transforms.cursor::<(InlayOffset, usize)>();
cursor.seek(&range.start, Bias::Right, &()); cursor.seek(&range.start, Bias::Right, &());
@ -1002,7 +1014,8 @@ impl InlaySnapshot {
buffer_chunk: None, buffer_chunk: None,
output_offset: range.start, output_offset: range.start,
max_output_offset: range.end, max_output_offset: range.end,
highlight_style: inlay_highlight_style, hint_highlight_style: hint_highlights,
suggestion_highlight_style: suggestion_highlights,
highlight_endpoints: highlight_endpoints.into_iter().peekable(), highlight_endpoints: highlight_endpoints.into_iter().peekable(),
active_highlights: Default::default(), active_highlights: Default::default(),
snapshot: self, snapshot: self,
@ -1011,7 +1024,7 @@ impl InlaySnapshot {
#[cfg(test)] #[cfg(test)]
pub fn text(&self) -> String { pub fn text(&self) -> String {
self.chunks(Default::default()..self.len(), false, None, None) self.chunks(Default::default()..self.len(), false, None, None, None)
.map(|chunk| chunk.text) .map(|chunk| chunk.text)
.collect() .collect()
} }
@ -1078,7 +1091,7 @@ mod tests {
let (inlay_snapshot, _) = inlay_map.splice( let (inlay_snapshot, _) = inlay_map.splice(
Vec::new(), Vec::new(),
vec![( vec![(
InlayId(post_inc(&mut next_inlay_id)), InlayId::Hint(post_inc(&mut next_inlay_id)),
InlayProperties { InlayProperties {
position: buffer.read(cx).snapshot(cx).anchor_after(3), position: buffer.read(cx).snapshot(cx).anchor_after(3),
text: "|123|", text: "|123|",
@ -1157,14 +1170,14 @@ mod tests {
Vec::new(), Vec::new(),
vec![ vec![
( (
InlayId(post_inc(&mut next_inlay_id)), InlayId::Hint(post_inc(&mut next_inlay_id)),
InlayProperties { InlayProperties {
position: buffer.read(cx).snapshot(cx).anchor_before(3), position: buffer.read(cx).snapshot(cx).anchor_before(3),
text: "|123|", text: "|123|",
}, },
), ),
( (
InlayId(post_inc(&mut next_inlay_id)), InlayId::Suggestion(post_inc(&mut next_inlay_id)),
InlayProperties { InlayProperties {
position: buffer.read(cx).snapshot(cx).anchor_after(3), position: buffer.read(cx).snapshot(cx).anchor_after(3),
text: "|456|", text: "|456|",
@ -1370,21 +1383,21 @@ mod tests {
Vec::new(), Vec::new(),
vec![ vec![
( (
InlayId(post_inc(&mut next_inlay_id)), InlayId::Hint(post_inc(&mut next_inlay_id)),
InlayProperties { InlayProperties {
position: buffer.read(cx).snapshot(cx).anchor_before(0), position: buffer.read(cx).snapshot(cx).anchor_before(0),
text: "|123|\n", text: "|123|\n",
}, },
), ),
( (
InlayId(post_inc(&mut next_inlay_id)), InlayId::Hint(post_inc(&mut next_inlay_id)),
InlayProperties { InlayProperties {
position: buffer.read(cx).snapshot(cx).anchor_before(4), position: buffer.read(cx).snapshot(cx).anchor_before(4),
text: "|456|", text: "|456|",
}, },
), ),
( (
InlayId(post_inc(&mut next_inlay_id)), InlayId::Suggestion(post_inc(&mut next_inlay_id)),
InlayProperties { InlayProperties {
position: buffer.read(cx).snapshot(cx).anchor_before(7), position: buffer.read(cx).snapshot(cx).anchor_before(7),
text: "\n|567|\n", text: "\n|567|\n",
@ -1489,7 +1502,13 @@ mod tests {
start = expected_text.clip_offset(start, Bias::Right); start = expected_text.clip_offset(start, Bias::Right);
let actual_text = inlay_snapshot let actual_text = inlay_snapshot
.chunks(InlayOffset(start)..InlayOffset(end), false, None, None) .chunks(
InlayOffset(start)..InlayOffset(end),
false,
None,
None,
None,
)
.map(|chunk| chunk.text) .map(|chunk| chunk.text)
.collect::<String>(); .collect::<String>();
assert_eq!( assert_eq!(

View file

@ -70,6 +70,7 @@ impl TabMap {
false, false,
None, None,
None, None,
None,
) { ) {
for (ix, _) in chunk.text.match_indices('\t') { for (ix, _) in chunk.text.match_indices('\t') {
let offset_from_edit = offset_from_edit + (ix as u32); let offset_from_edit = offset_from_edit + (ix as u32);
@ -182,7 +183,7 @@ impl TabSnapshot {
self.max_point() self.max_point()
}; };
for c in self for c in self
.chunks(range.start..line_end, false, None, None) .chunks(range.start..line_end, false, None, None, None)
.flat_map(|chunk| chunk.text.chars()) .flat_map(|chunk| chunk.text.chars())
{ {
if c == '\n' { if c == '\n' {
@ -201,6 +202,7 @@ impl TabSnapshot {
false, false,
None, None,
None, None,
None,
) )
.flat_map(|chunk| chunk.text.chars()) .flat_map(|chunk| chunk.text.chars())
{ {
@ -222,7 +224,8 @@ impl TabSnapshot {
range: Range<TabPoint>, range: Range<TabPoint>,
language_aware: bool, language_aware: bool,
text_highlights: Option<&'a TextHighlights>, text_highlights: Option<&'a TextHighlights>,
inlay_highlights: Option<HighlightStyle>, hint_highlights: Option<HighlightStyle>,
suggestion_highlights: Option<HighlightStyle>,
) -> TabChunks<'a> { ) -> TabChunks<'a> {
let (input_start, expanded_char_column, to_next_stop) = let (input_start, expanded_char_column, to_next_stop) =
self.to_fold_point(range.start, Bias::Left); self.to_fold_point(range.start, Bias::Left);
@ -243,7 +246,8 @@ impl TabSnapshot {
input_start..input_end, input_start..input_end,
language_aware, language_aware,
text_highlights, text_highlights,
inlay_highlights, hint_highlights,
suggestion_highlights,
), ),
input_column, input_column,
column: expanded_char_column, column: expanded_char_column,
@ -266,7 +270,7 @@ impl TabSnapshot {
#[cfg(test)] #[cfg(test)]
pub fn text(&self) -> String { pub fn text(&self) -> String {
self.chunks(TabPoint::zero()..self.max_point(), false, None, None) self.chunks(TabPoint::zero()..self.max_point(), false, None, None, None)
.map(|chunk| chunk.text) .map(|chunk| chunk.text)
.collect() .collect()
} }
@ -595,6 +599,7 @@ mod tests {
false, false,
None, None,
None, None,
None,
) )
.map(|c| c.text) .map(|c| c.text)
.collect::<String>(), .collect::<String>(),
@ -669,7 +674,7 @@ mod tests {
let mut chunks = Vec::new(); let mut chunks = Vec::new();
let mut was_tab = false; let mut was_tab = false;
let mut text = String::new(); let mut text = String::new();
for chunk in snapshot.chunks(start..snapshot.max_point(), false, None, None) { for chunk in snapshot.chunks(start..snapshot.max_point(), false, None, None, None) {
if chunk.is_tab != was_tab { if chunk.is_tab != was_tab {
if !text.is_empty() { if !text.is_empty() {
chunks.push((mem::take(&mut text), was_tab)); chunks.push((mem::take(&mut text), was_tab));
@ -738,7 +743,7 @@ mod tests {
let expected_summary = TextSummary::from(expected_text.as_str()); let expected_summary = TextSummary::from(expected_text.as_str());
assert_eq!( assert_eq!(
tabs_snapshot tabs_snapshot
.chunks(start..end, false, None, None) .chunks(start..end, false, None, None, None)
.map(|c| c.text) .map(|c| c.text)
.collect::<String>(), .collect::<String>(),
expected_text, expected_text,

View file

@ -446,6 +446,7 @@ impl WrapSnapshot {
false, false,
None, None,
None, None,
None,
); );
let mut edit_transforms = Vec::<Transform>::new(); let mut edit_transforms = Vec::<Transform>::new();
for _ in edit.new_rows.start..edit.new_rows.end { for _ in edit.new_rows.start..edit.new_rows.end {
@ -575,7 +576,8 @@ impl WrapSnapshot {
rows: Range<u32>, rows: Range<u32>,
language_aware: bool, language_aware: bool,
text_highlights: Option<&'a TextHighlights>, text_highlights: Option<&'a TextHighlights>,
inlay_highlights: Option<HighlightStyle>, hint_highlights: Option<HighlightStyle>,
suggestion_highlights: Option<HighlightStyle>,
) -> WrapChunks<'a> { ) -> WrapChunks<'a> {
let output_start = WrapPoint::new(rows.start, 0); let output_start = WrapPoint::new(rows.start, 0);
let output_end = WrapPoint::new(rows.end, 0); let output_end = WrapPoint::new(rows.end, 0);
@ -593,7 +595,8 @@ impl WrapSnapshot {
input_start..input_end, input_start..input_end,
language_aware, language_aware,
text_highlights, text_highlights,
inlay_highlights, hint_highlights,
suggestion_highlights,
), ),
input_chunk: Default::default(), input_chunk: Default::default(),
output_position: output_start, output_position: output_start,
@ -1324,8 +1327,14 @@ mod tests {
} }
pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator<Item = &str> { pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator<Item = &str> {
self.chunks(wrap_row..self.max_point().row() + 1, false, None, None) self.chunks(
.map(|h| h.text) wrap_row..self.max_point().row() + 1,
false,
None,
None,
None,
)
.map(|h| h.text)
} }
fn verify_chunks(&mut self, rng: &mut impl Rng) { fn verify_chunks(&mut self, rng: &mut impl Rng) {
@ -1348,7 +1357,7 @@ mod tests {
} }
let actual_text = self let actual_text = self
.chunks(start_row..end_row, true, None, None) .chunks(start_row..end_row, true, None, None, None)
.map(|c| c.text) .map(|c| c.text)
.collect::<String>(); .collect::<String>();
assert_eq!( assert_eq!(

View file

@ -184,8 +184,11 @@ pub struct GutterHover {
pub hovered: bool, pub hovered: bool,
} }
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InlayId(usize); pub enum InlayId {
Suggestion(usize),
Hint(usize),
}
actions!( actions!(
editor, editor,
@ -3449,7 +3452,7 @@ impl Editor {
to_remove.push(suggestion.id); to_remove.push(suggestion.id);
} }
let suggestion_inlay_id = self.next_inlay_id(); let suggestion_inlay_id = InlayId::Suggestion(post_inc(&mut self.next_inlay_id));
let to_insert = vec![( let to_insert = vec![(
suggestion_inlay_id, suggestion_inlay_id,
InlayProperties { InlayProperties {
@ -7588,10 +7591,6 @@ impl Editor {
cx.write_to_clipboard(ClipboardItem::new(lines)); cx.write_to_clipboard(ClipboardItem::new(lines));
} }
pub fn next_inlay_id(&mut self) -> InlayId {
InlayId(post_inc(&mut self.next_inlay_id))
}
pub fn inlay_hint_cache(&self) -> &InlayHintCache { pub fn inlay_hint_cache(&self) -> &InlayHintCache {
&self.inlay_hint_cache &self.inlay_hint_cache
} }

View file

@ -1392,7 +1392,12 @@ impl EditorElement {
} else { } else {
let style = &self.style; let style = &self.style;
let chunks = snapshot let chunks = snapshot
.chunks(rows.clone(), true, Some(style.theme.hint)) .chunks(
rows.clone(),
true,
Some(style.theme.hint),
Some(style.theme.suggestion),
)
.map(|chunk| { .map(|chunk| {
let mut highlight_style = chunk let mut highlight_style = chunk
.syntax_highlight_id .syntax_highlight_id

View file

@ -616,7 +616,7 @@ async fn fetch_and_update_hints(
for new_hint in new_update.add_to_cache { for new_hint in new_update.add_to_cache {
let new_hint_position = multi_buffer_snapshot let new_hint_position = multi_buffer_snapshot
.anchor_in_excerpt(query.excerpt_id, new_hint.position); .anchor_in_excerpt(query.excerpt_id, new_hint.position);
let new_inlay_id = InlayId(post_inc(&mut editor.next_inlay_id)); let new_inlay_id = InlayId::Hint(post_inc(&mut editor.next_inlay_id));
if editor if editor
.inlay_hint_cache .inlay_hint_cache
.allowed_hint_kinds .allowed_hint_kinds