edit predictions: Fix cursor popover edit preview panic (#24866)
Release Notes: - Fixed a panic when displaying a whitespace-only line in the edit prediction preview --------- Co-authored-by: Antonio <antonio@zed.dev>
This commit is contained in:
parent
a618830aea
commit
592e8fbffc
2 changed files with 42 additions and 36 deletions
|
@ -170,7 +170,7 @@ use ui::{
|
|||
h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,
|
||||
Tooltip,
|
||||
};
|
||||
use util::{defer, maybe, post_inc, RangeExt, ResultExt, TakeUntilExt, TryFutureExt};
|
||||
use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
|
||||
use workspace::item::{ItemHandle, PreviewTabsSettings};
|
||||
use workspace::notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt};
|
||||
use workspace::{
|
||||
|
@ -5994,52 +5994,23 @@ impl Editor {
|
|||
} => {
|
||||
let first_edit_row = edits.first()?.0.start.text_anchor.to_point(&snapshot).row;
|
||||
|
||||
let highlighted_edits = crate::inline_completion_edit_text(
|
||||
let (highlighted_edits, has_more_lines) = crate::inline_completion_edit_text(
|
||||
&snapshot,
|
||||
&edits,
|
||||
edit_preview.as_ref()?,
|
||||
true,
|
||||
cx,
|
||||
);
|
||||
)
|
||||
.first_line_preview();
|
||||
|
||||
let len_total = highlighted_edits.text.len();
|
||||
let first_line = &highlighted_edits.text
|
||||
[..highlighted_edits.text.find('\n').unwrap_or(len_total)];
|
||||
let first_line_len = first_line.len();
|
||||
|
||||
let first_highlight_start = highlighted_edits
|
||||
.highlights
|
||||
.first()
|
||||
.map_or(0, |(range, _)| range.start);
|
||||
let drop_prefix_len = first_line
|
||||
.char_indices()
|
||||
.find(|(_, c)| !c.is_whitespace())
|
||||
.map_or(first_highlight_start, |(ix, _)| {
|
||||
ix.min(first_highlight_start)
|
||||
});
|
||||
|
||||
let preview_text = &first_line[drop_prefix_len..];
|
||||
let preview_len = preview_text.len();
|
||||
let highlights = highlighted_edits
|
||||
.highlights
|
||||
.into_iter()
|
||||
.take_until(|(range, _)| range.start > first_line_len)
|
||||
.map(|(range, style)| {
|
||||
(
|
||||
range.start - drop_prefix_len
|
||||
..(range.end - drop_prefix_len).min(preview_len),
|
||||
style,
|
||||
)
|
||||
});
|
||||
|
||||
let styled_text = gpui::StyledText::new(SharedString::new(preview_text))
|
||||
.with_highlights(&style.text, highlights);
|
||||
let styled_text = gpui::StyledText::new(highlighted_edits.text)
|
||||
.with_highlights(&style.text, highlighted_edits.highlights);
|
||||
|
||||
let preview = h_flex()
|
||||
.gap_1()
|
||||
.min_w_16()
|
||||
.child(styled_text)
|
||||
.when(len_total > first_line_len, |parent| parent.child("…"));
|
||||
.when(has_more_lines, |parent| parent.child("…"));
|
||||
|
||||
let left = if first_edit_row != cursor_point.row {
|
||||
render_relative_row_jump("", cursor_point.row, first_edit_row)
|
||||
|
|
|
@ -622,6 +622,41 @@ impl HighlightedText {
|
|||
gpui::StyledText::new(self.text.clone())
|
||||
.with_highlights(default_style, self.highlights.iter().cloned())
|
||||
}
|
||||
|
||||
/// Returns the first line without leading whitespace unless highlighted
|
||||
/// and a boolean indicating if there are more lines after
|
||||
pub fn first_line_preview(self) -> (Self, bool) {
|
||||
let newline_ix = self.text.find('\n').unwrap_or(self.text.len());
|
||||
let first_line = &self.text[..newline_ix];
|
||||
|
||||
// Trim leading whitespace, unless an edit starts prior to it.
|
||||
let mut preview_start_ix = first_line.len() - first_line.trim_start().len();
|
||||
if let Some((first_highlight_range, _)) = self.highlights.first() {
|
||||
preview_start_ix = preview_start_ix.min(first_highlight_range.start);
|
||||
}
|
||||
|
||||
let preview_text = &first_line[preview_start_ix..];
|
||||
let preview_highlights = self
|
||||
.highlights
|
||||
.into_iter()
|
||||
.take_while(|(range, _)| range.start < newline_ix)
|
||||
.filter_map(|(mut range, highlight)| {
|
||||
range.start = range.start.saturating_sub(preview_start_ix);
|
||||
range.end = range.end.saturating_sub(preview_start_ix).min(newline_ix);
|
||||
if range.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some((range, highlight))
|
||||
}
|
||||
});
|
||||
|
||||
let preview = Self {
|
||||
text: SharedString::new(preview_text),
|
||||
highlights: preview_highlights.collect(),
|
||||
};
|
||||
|
||||
(preview, self.text.len() > newline_ix)
|
||||
}
|
||||
}
|
||||
|
||||
impl HighlightedTextBuilder {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue