zeta: Various product fixes before Preview release (#23125)
Various fixes for Zeta and one fix that's visible to non-Zeta-using users of inline completions. Release Notes: - Changed inline completions (Copilot, Supermaven, ...) to not show up in empty buffers. --------- Co-authored-by: Antonio <antonio@zed.dev> Co-authored-by: Antonio Scandurra <me@as-cii.com> Co-authored-by: Bennet <bennet@zed.dev>
This commit is contained in:
parent
1b3b825c7f
commit
a67709629b
6 changed files with 247 additions and 121 deletions
161
crates/zeta/src/completion_diff_element.rs
Normal file
161
crates/zeta/src/completion_diff_element.rs
Normal file
|
@ -0,0 +1,161 @@
|
|||
use std::cmp;
|
||||
|
||||
use crate::InlineCompletion;
|
||||
use gpui::{
|
||||
point, prelude::*, quad, size, AnyElement, AppContext, Bounds, Corners, Edges, HighlightStyle,
|
||||
Hsla, StyledText, TextLayout, TextStyle,
|
||||
};
|
||||
use language::OffsetRangeExt;
|
||||
use settings::Settings;
|
||||
use theme::ThemeSettings;
|
||||
use ui::prelude::*;
|
||||
|
||||
pub struct CompletionDiffElement {
|
||||
element: AnyElement,
|
||||
text_layout: TextLayout,
|
||||
cursor_offset: usize,
|
||||
}
|
||||
|
||||
impl CompletionDiffElement {
|
||||
pub fn new(completion: &InlineCompletion, cx: &AppContext) -> Self {
|
||||
let mut diff = completion
|
||||
.snapshot
|
||||
.text_for_range(completion.excerpt_range.clone())
|
||||
.collect::<String>();
|
||||
|
||||
let mut cursor_offset_in_diff = None;
|
||||
let mut delta = 0;
|
||||
let mut diff_highlights = Vec::new();
|
||||
for (old_range, new_text) in completion.edits.iter() {
|
||||
let old_range = old_range.to_offset(&completion.snapshot);
|
||||
|
||||
if cursor_offset_in_diff.is_none() && completion.cursor_offset <= old_range.end {
|
||||
cursor_offset_in_diff =
|
||||
Some(completion.cursor_offset - completion.excerpt_range.start + delta);
|
||||
}
|
||||
|
||||
let old_start_in_diff = old_range.start - completion.excerpt_range.start + delta;
|
||||
let old_end_in_diff = old_range.end - completion.excerpt_range.start + delta;
|
||||
if old_start_in_diff < old_end_in_diff {
|
||||
diff_highlights.push((
|
||||
old_start_in_diff..old_end_in_diff,
|
||||
HighlightStyle {
|
||||
background_color: Some(cx.theme().status().deleted_background),
|
||||
strikethrough: Some(gpui::StrikethroughStyle {
|
||||
thickness: px(1.),
|
||||
color: Some(cx.theme().colors().text_muted),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
if !new_text.is_empty() {
|
||||
diff.insert_str(old_end_in_diff, new_text);
|
||||
diff_highlights.push((
|
||||
old_end_in_diff..old_end_in_diff + new_text.len(),
|
||||
HighlightStyle {
|
||||
background_color: Some(cx.theme().status().created_background),
|
||||
..Default::default()
|
||||
},
|
||||
));
|
||||
delta += new_text.len();
|
||||
}
|
||||
}
|
||||
|
||||
let cursor_offset_in_diff = cursor_offset_in_diff
|
||||
.unwrap_or_else(|| completion.cursor_offset - completion.excerpt_range.start + delta);
|
||||
|
||||
let settings = ThemeSettings::get_global(cx).clone();
|
||||
let text_style = TextStyle {
|
||||
color: cx.theme().colors().editor_foreground,
|
||||
font_size: settings.buffer_font_size(cx).into(),
|
||||
font_family: settings.buffer_font.family,
|
||||
font_features: settings.buffer_font.features,
|
||||
font_fallbacks: settings.buffer_font.fallbacks,
|
||||
line_height: relative(settings.buffer_line_height.value()),
|
||||
font_weight: settings.buffer_font.weight,
|
||||
font_style: settings.buffer_font.style,
|
||||
..Default::default()
|
||||
};
|
||||
let element = StyledText::new(diff).with_highlights(&text_style, diff_highlights);
|
||||
let text_layout = element.layout().clone();
|
||||
|
||||
CompletionDiffElement {
|
||||
element: element.into_any_element(),
|
||||
text_layout,
|
||||
cursor_offset: cursor_offset_in_diff,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoElement for CompletionDiffElement {
|
||||
type Element = Self;
|
||||
|
||||
fn into_element(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for CompletionDiffElement {
|
||||
type RequestLayoutState = ();
|
||||
type PrepaintState = ();
|
||||
|
||||
fn id(&self) -> Option<ElementId> {
|
||||
None
|
||||
}
|
||||
|
||||
fn request_layout(
|
||||
&mut self,
|
||||
_id: Option<&gpui::GlobalElementId>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (gpui::LayoutId, Self::RequestLayoutState) {
|
||||
(self.element.request_layout(cx), ())
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
_id: Option<&gpui::GlobalElementId>,
|
||||
_bounds: gpui::Bounds<Pixels>,
|
||||
_request_layout: &mut Self::RequestLayoutState,
|
||||
cx: &mut WindowContext,
|
||||
) -> Self::PrepaintState {
|
||||
self.element.prepaint(cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
_id: Option<&gpui::GlobalElementId>,
|
||||
_bounds: gpui::Bounds<Pixels>,
|
||||
_request_layout: &mut Self::RequestLayoutState,
|
||||
_prepaint: &mut Self::PrepaintState,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
if let Some(position) = self.text_layout.position_for_index(self.cursor_offset) {
|
||||
let bounds = self.text_layout.bounds();
|
||||
let line_height = self.text_layout.line_height();
|
||||
let line_width = self
|
||||
.text_layout
|
||||
.line_layout_for_index(self.cursor_offset)
|
||||
.map_or(bounds.size.width, |layout| layout.width());
|
||||
cx.paint_quad(quad(
|
||||
Bounds::new(
|
||||
point(bounds.origin.x, position.y),
|
||||
size(cmp::max(bounds.size.width, line_width), line_height),
|
||||
),
|
||||
Corners::default(),
|
||||
cx.theme().colors().editor_active_line_background,
|
||||
Edges::default(),
|
||||
Hsla::transparent_black(),
|
||||
));
|
||||
self.element.paint(cx);
|
||||
cx.paint_quad(quad(
|
||||
Bounds::new(position, size(px(2.), line_height)),
|
||||
Corners::default(),
|
||||
cx.theme().players().local().cursor,
|
||||
Edges::default(),
|
||||
Hsla::transparent_black(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue