mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
Overhaul inline assistant (#12846)
This pull request introduces a new diff mechanism that helps users understand exactly which lines were changed by the LLM. Release Notes: - N/A
This commit is contained in:
parent
3722275cfa
commit
98659eabf1
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -373,6 +373,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"settings",
|
"settings",
|
||||||
|
"similar",
|
||||||
"smol",
|
"smol",
|
||||||
"strsim 0.11.1",
|
"strsim 0.11.1",
|
||||||
"strum",
|
"strum",
|
||||||
|
@ -340,6 +340,7 @@ serde_repr = "0.1"
|
|||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
shellexpand = "2.1.0"
|
shellexpand = "2.1.0"
|
||||||
shlex = "1.3.0"
|
shlex = "1.3.0"
|
||||||
|
similar = "1.3"
|
||||||
smallvec = { version = "1.6", features = ["union"] }
|
smallvec = { version = "1.6", features = ["union"] }
|
||||||
smol = "1.2"
|
smol = "1.2"
|
||||||
strum = { version = "0.25.0", features = ["derive"] }
|
strum = { version = "0.25.0", features = ["derive"] }
|
||||||
|
6
assets/icons/context.svg
Normal file
6
assets/icons/context.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12.6667 2H3.33333C2.59695 2 2 2.59695 2 3.33333V12.6667C2 13.403 2.59695 14 3.33333 14H12.6667C13.403 14 14 13.403 14 12.6667V3.33333C14 2.59695 13.403 2 12.6667 2Z" stroke="#888888" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M9 5H5" stroke="#888888" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M10.5 8H5" stroke="#888888" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M9 10.9502H5" stroke="#888888" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 683 B |
1
assets/icons/rotate_cw.svg
Normal file
1
assets/icons/rotate_cw.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rotate-cw"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>
|
After Width: | Height: | Size: 303 B |
3
assets/icons/stop.svg
Normal file
3
assets/icons/stop.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M9.88889 1H2.11111C1.49746 1 1 1.49746 1 2.11111V9.88889C1 10.5025 1.49746 11 2.11111 11H9.88889C10.5025 11 11 10.5025 11 9.88889V2.11111C11 1.49746 10.5025 1 9.88889 1Z" stroke="#C56757" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 369 B |
@ -47,6 +47,7 @@ semantic_index.workspace = true
|
|||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
|
similar.workspace = true
|
||||||
smol.workspace = true
|
smol.workspace = true
|
||||||
strsim = "0.11"
|
strsim = "0.11"
|
||||||
strum.workspace = true
|
strum.workspace = true
|
||||||
|
@ -1222,6 +1222,10 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn token_count(&self) -> Option<usize> {
|
||||||
|
self.token_count
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn count_remaining_tokens(&mut self, cx: &mut ModelContext<Self>) {
|
pub(crate) fn count_remaining_tokens(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
let request = self.to_completion_request(cx);
|
let request = self.to_completion_request(cx);
|
||||||
self.pending_token_count = cx.spawn(|this, mut cx| {
|
self.pending_token_count = cx.spawn(|this, mut cx| {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -52,8 +52,14 @@ use multi_buffer::{
|
|||||||
ToOffset, ToPoint,
|
ToOffset, ToPoint,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::ops::Add;
|
use std::{
|
||||||
use std::{any::TypeId, borrow::Cow, fmt::Debug, num::NonZeroU32, ops::Range, sync::Arc};
|
any::TypeId,
|
||||||
|
borrow::Cow,
|
||||||
|
fmt::Debug,
|
||||||
|
num::NonZeroU32,
|
||||||
|
ops::{Add, Range, Sub},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
use sum_tree::{Bias, TreeMap};
|
use sum_tree::{Bias, TreeMap};
|
||||||
use tab_map::{TabMap, TabSnapshot};
|
use tab_map::{TabMap, TabSnapshot};
|
||||||
use text::LineIndent;
|
use text::LineIndent;
|
||||||
@ -1027,6 +1033,14 @@ impl Add for DisplayRow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sub for DisplayRow {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, other: Self) -> Self::Output {
|
||||||
|
DisplayRow(self.0 - other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DisplayPoint {
|
impl DisplayPoint {
|
||||||
pub fn new(row: DisplayRow, column: u32) -> Self {
|
pub fn new(row: DisplayRow, column: u32) -> Self {
|
||||||
Self(BlockPoint(Point::new(row.0, column)))
|
Self(BlockPoint(Point::new(row.0, column)))
|
||||||
|
@ -376,6 +376,7 @@ type CompletionId = usize;
|
|||||||
// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
|
// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
|
||||||
|
|
||||||
type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
|
type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
|
||||||
|
type GutterHighlight = (fn(&AppContext) -> Hsla, Arc<[Range<Anchor>]>);
|
||||||
|
|
||||||
struct ScrollbarMarkerState {
|
struct ScrollbarMarkerState {
|
||||||
scrollbar_size: Size<Pixels>,
|
scrollbar_size: Size<Pixels>,
|
||||||
@ -464,6 +465,7 @@ pub struct Editor {
|
|||||||
highlight_order: usize,
|
highlight_order: usize,
|
||||||
highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
|
highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
|
||||||
background_highlights: TreeMap<TypeId, BackgroundHighlight>,
|
background_highlights: TreeMap<TypeId, BackgroundHighlight>,
|
||||||
|
gutter_highlights: TreeMap<TypeId, GutterHighlight>,
|
||||||
scrollbar_marker_state: ScrollbarMarkerState,
|
scrollbar_marker_state: ScrollbarMarkerState,
|
||||||
active_indent_guides_state: ActiveIndentGuidesState,
|
active_indent_guides_state: ActiveIndentGuidesState,
|
||||||
nav_history: Option<ItemNavHistory>,
|
nav_history: Option<ItemNavHistory>,
|
||||||
@ -1752,6 +1754,7 @@ impl Editor {
|
|||||||
highlight_order: 0,
|
highlight_order: 0,
|
||||||
highlighted_rows: HashMap::default(),
|
highlighted_rows: HashMap::default(),
|
||||||
background_highlights: Default::default(),
|
background_highlights: Default::default(),
|
||||||
|
gutter_highlights: TreeMap::default(),
|
||||||
scrollbar_marker_state: ScrollbarMarkerState::default(),
|
scrollbar_marker_state: ScrollbarMarkerState::default(),
|
||||||
active_indent_guides_state: ActiveIndentGuidesState::default(),
|
active_indent_guides_state: ActiveIndentGuidesState::default(),
|
||||||
nav_history: None,
|
nav_history: None,
|
||||||
@ -10263,6 +10266,25 @@ impl Editor {
|
|||||||
Some(text_highlights)
|
Some(text_highlights)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn highlight_gutter<T: 'static>(
|
||||||
|
&mut self,
|
||||||
|
ranges: &[Range<Anchor>],
|
||||||
|
color_fetcher: fn(&AppContext) -> Hsla,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
self.gutter_highlights
|
||||||
|
.insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_gutter_highlights<T: 'static>(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Option<GutterHighlight> {
|
||||||
|
cx.notify();
|
||||||
|
self.gutter_highlights.remove(&TypeId::of::<T>())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "test-support")]
|
#[cfg(feature = "test-support")]
|
||||||
pub fn all_text_background_highlights(
|
pub fn all_text_background_highlights(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -10452,6 +10474,44 @@ impl Editor {
|
|||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn gutter_highlights_in_range(
|
||||||
|
&self,
|
||||||
|
search_range: Range<Anchor>,
|
||||||
|
display_snapshot: &DisplaySnapshot,
|
||||||
|
cx: &AppContext,
|
||||||
|
) -> Vec<(Range<DisplayPoint>, Hsla)> {
|
||||||
|
let mut results = Vec::new();
|
||||||
|
for (color_fetcher, ranges) in self.gutter_highlights.values() {
|
||||||
|
let color = color_fetcher(cx);
|
||||||
|
let start_ix = match ranges.binary_search_by(|probe| {
|
||||||
|
let cmp = probe
|
||||||
|
.end
|
||||||
|
.cmp(&search_range.start, &display_snapshot.buffer_snapshot);
|
||||||
|
if cmp.is_gt() {
|
||||||
|
Ordering::Greater
|
||||||
|
} else {
|
||||||
|
Ordering::Less
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Ok(i) | Err(i) => i,
|
||||||
|
};
|
||||||
|
for range in &ranges[start_ix..] {
|
||||||
|
if range
|
||||||
|
.start
|
||||||
|
.cmp(&search_range.end, &display_snapshot.buffer_snapshot)
|
||||||
|
.is_ge()
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = range.start.to_display_point(&display_snapshot);
|
||||||
|
let end = range.end.to_display_point(&display_snapshot);
|
||||||
|
results.push((start..end, color))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the text ranges corresponding to the redaction query
|
/// Get the text ranges corresponding to the redaction query
|
||||||
pub fn redacted_ranges(
|
pub fn redacted_ranges(
|
||||||
&self,
|
&self,
|
||||||
|
@ -2837,6 +2837,8 @@ impl EditorElement {
|
|||||||
Self::paint_diff_hunks(layout.gutter_hitbox.bounds, layout, cx)
|
Self::paint_diff_hunks(layout.gutter_hitbox.bounds, layout, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.paint_gutter_highlights(layout, cx);
|
||||||
|
|
||||||
if layout.blamed_display_rows.is_some() {
|
if layout.blamed_display_rows.is_some() {
|
||||||
self.paint_blamed_display_rows(layout, cx);
|
self.paint_blamed_display_rows(layout, cx);
|
||||||
}
|
}
|
||||||
@ -3006,6 +3008,37 @@ impl EditorElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn paint_gutter_highlights(&self, layout: &EditorLayout, cx: &mut WindowContext) {
|
||||||
|
let highlight_width = 0.275 * layout.position_map.line_height;
|
||||||
|
let highlight_corner_radii = Corners::all(0.05 * layout.position_map.line_height);
|
||||||
|
cx.paint_layer(layout.gutter_hitbox.bounds, |cx| {
|
||||||
|
for (range, color) in &layout.highlighted_gutter_ranges {
|
||||||
|
let start_row = if range.start.row() < layout.visible_display_row_range.start {
|
||||||
|
layout.visible_display_row_range.start - DisplayRow(1)
|
||||||
|
} else {
|
||||||
|
range.start.row()
|
||||||
|
};
|
||||||
|
let end_row = if range.end.row() > layout.visible_display_row_range.end {
|
||||||
|
layout.visible_display_row_range.end + DisplayRow(1)
|
||||||
|
} else {
|
||||||
|
range.end.row()
|
||||||
|
};
|
||||||
|
|
||||||
|
let start_y = layout.gutter_hitbox.top()
|
||||||
|
+ start_row.0 as f32 * layout.position_map.line_height
|
||||||
|
- layout.position_map.scroll_pixel_position.y;
|
||||||
|
let end_y = layout.gutter_hitbox.top()
|
||||||
|
+ (end_row.0 + 1) as f32 * layout.position_map.line_height
|
||||||
|
- layout.position_map.scroll_pixel_position.y;
|
||||||
|
let bounds = Bounds::from_corners(
|
||||||
|
point(layout.gutter_hitbox.left(), start_y),
|
||||||
|
point(layout.gutter_hitbox.left() + highlight_width, end_y),
|
||||||
|
);
|
||||||
|
cx.paint_quad(fill(bounds, *color).corner_radii(highlight_corner_radii));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn paint_blamed_display_rows(&self, layout: &mut EditorLayout, cx: &mut WindowContext) {
|
fn paint_blamed_display_rows(&self, layout: &mut EditorLayout, cx: &mut WindowContext) {
|
||||||
let Some(blamed_display_rows) = layout.blamed_display_rows.take() else {
|
let Some(blamed_display_rows) = layout.blamed_display_rows.take() else {
|
||||||
return;
|
return;
|
||||||
@ -4631,6 +4664,12 @@ impl Element for EditorElement {
|
|||||||
&snapshot.display_snapshot,
|
&snapshot.display_snapshot,
|
||||||
cx.theme().colors(),
|
cx.theme().colors(),
|
||||||
);
|
);
|
||||||
|
let highlighted_gutter_ranges =
|
||||||
|
self.editor.read(cx).gutter_highlights_in_range(
|
||||||
|
start_anchor..end_anchor,
|
||||||
|
&snapshot.display_snapshot,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
let redacted_ranges = self.editor.read(cx).redacted_ranges(
|
let redacted_ranges = self.editor.read(cx).redacted_ranges(
|
||||||
start_anchor..end_anchor,
|
start_anchor..end_anchor,
|
||||||
@ -4991,6 +5030,7 @@ impl Element for EditorElement {
|
|||||||
active_rows,
|
active_rows,
|
||||||
highlighted_rows,
|
highlighted_rows,
|
||||||
highlighted_ranges,
|
highlighted_ranges,
|
||||||
|
highlighted_gutter_ranges,
|
||||||
redacted_ranges,
|
redacted_ranges,
|
||||||
line_elements,
|
line_elements,
|
||||||
line_numbers,
|
line_numbers,
|
||||||
@ -5121,6 +5161,7 @@ pub struct EditorLayout {
|
|||||||
inline_blame: Option<AnyElement>,
|
inline_blame: Option<AnyElement>,
|
||||||
blocks: Vec<BlockLayout>,
|
blocks: Vec<BlockLayout>,
|
||||||
highlighted_ranges: Vec<(Range<DisplayPoint>, Hsla)>,
|
highlighted_ranges: Vec<(Range<DisplayPoint>, Hsla)>,
|
||||||
|
highlighted_gutter_ranges: Vec<(Range<DisplayPoint>, Hsla)>,
|
||||||
redacted_ranges: Vec<Range<DisplayPoint>>,
|
redacted_ranges: Vec<Range<DisplayPoint>>,
|
||||||
cursors: Vec<(DisplayPoint, Hsla)>,
|
cursors: Vec<(DisplayPoint, Hsla)>,
|
||||||
visible_cursors: Vec<CursorLayout>,
|
visible_cursors: Vec<CursorLayout>,
|
||||||
|
@ -49,7 +49,7 @@ schemars.workspace = true
|
|||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
similar = "1.3"
|
similar.workspace = true
|
||||||
smallvec.workspace = true
|
smallvec.workspace = true
|
||||||
smol.workspace = true
|
smol.workspace = true
|
||||||
sum_tree.workspace = true
|
sum_tree.workspace = true
|
||||||
|
@ -797,6 +797,10 @@ impl Buffer {
|
|||||||
.set_language_registry(language_registry);
|
.set_language_registry(language_registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn language_registry(&self) -> Option<Arc<LanguageRegistry>> {
|
||||||
|
self.syntax_map.lock().language_registry()
|
||||||
|
}
|
||||||
|
|
||||||
/// Assign the buffer a new [Capability].
|
/// Assign the buffer a new [Capability].
|
||||||
pub fn set_capability(&mut self, capability: Capability, cx: &mut ModelContext<Self>) {
|
pub fn set_capability(&mut self, capability: Capability, cx: &mut ModelContext<Self>) {
|
||||||
self.capability = capability;
|
self.capability = capability;
|
||||||
|
@ -106,6 +106,7 @@ pub enum IconName {
|
|||||||
Code,
|
Code,
|
||||||
Collab,
|
Collab,
|
||||||
Command,
|
Command,
|
||||||
|
Context,
|
||||||
Control,
|
Control,
|
||||||
Copilot,
|
Copilot,
|
||||||
CopilotDisabled,
|
CopilotDisabled,
|
||||||
@ -170,6 +171,7 @@ pub enum IconName {
|
|||||||
Rerun,
|
Rerun,
|
||||||
Return,
|
Return,
|
||||||
Reveal,
|
Reveal,
|
||||||
|
RotateCw,
|
||||||
Save,
|
Save,
|
||||||
Screen,
|
Screen,
|
||||||
SelectAll,
|
SelectAll,
|
||||||
@ -186,6 +188,7 @@ pub enum IconName {
|
|||||||
Split,
|
Split,
|
||||||
Star,
|
Star,
|
||||||
StarFilled,
|
StarFilled,
|
||||||
|
Stop,
|
||||||
Strikethrough,
|
Strikethrough,
|
||||||
Supermaven,
|
Supermaven,
|
||||||
SupermavenDisabled,
|
SupermavenDisabled,
|
||||||
@ -233,6 +236,7 @@ impl IconName {
|
|||||||
IconName::Code => "icons/code.svg",
|
IconName::Code => "icons/code.svg",
|
||||||
IconName::Collab => "icons/user_group_16.svg",
|
IconName::Collab => "icons/user_group_16.svg",
|
||||||
IconName::Command => "icons/command.svg",
|
IconName::Command => "icons/command.svg",
|
||||||
|
IconName::Context => "icons/context.svg",
|
||||||
IconName::Control => "icons/control.svg",
|
IconName::Control => "icons/control.svg",
|
||||||
IconName::Copilot => "icons/copilot.svg",
|
IconName::Copilot => "icons/copilot.svg",
|
||||||
IconName::CopilotDisabled => "icons/copilot_disabled.svg",
|
IconName::CopilotDisabled => "icons/copilot_disabled.svg",
|
||||||
@ -297,6 +301,7 @@ impl IconName {
|
|||||||
IconName::ReplyArrowRight => "icons/reply_arrow_right.svg",
|
IconName::ReplyArrowRight => "icons/reply_arrow_right.svg",
|
||||||
IconName::Rerun => "icons/rerun.svg",
|
IconName::Rerun => "icons/rerun.svg",
|
||||||
IconName::Return => "icons/return.svg",
|
IconName::Return => "icons/return.svg",
|
||||||
|
IconName::RotateCw => "icons/rotate_cw.svg",
|
||||||
IconName::Save => "icons/save.svg",
|
IconName::Save => "icons/save.svg",
|
||||||
IconName::Screen => "icons/desktop.svg",
|
IconName::Screen => "icons/desktop.svg",
|
||||||
IconName::SelectAll => "icons/select_all.svg",
|
IconName::SelectAll => "icons/select_all.svg",
|
||||||
@ -313,6 +318,7 @@ impl IconName {
|
|||||||
IconName::Split => "icons/split.svg",
|
IconName::Split => "icons/split.svg",
|
||||||
IconName::Star => "icons/star.svg",
|
IconName::Star => "icons/star.svg",
|
||||||
IconName::StarFilled => "icons/star_filled.svg",
|
IconName::StarFilled => "icons/star_filled.svg",
|
||||||
|
IconName::Stop => "icons/stop.svg",
|
||||||
IconName::Strikethrough => "icons/strikethrough.svg",
|
IconName::Strikethrough => "icons/strikethrough.svg",
|
||||||
IconName::Supermaven => "icons/supermaven.svg",
|
IconName::Supermaven => "icons/supermaven.svg",
|
||||||
IconName::SupermavenDisabled => "icons/supermaven_disabled.svg",
|
IconName::SupermavenDisabled => "icons/supermaven_disabled.svg",
|
||||||
|
Loading…
Reference in New Issue
Block a user