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
14 changed files with 824 additions and 176 deletions
|
@ -47,6 +47,7 @@ semantic_index.workspace = true
|
|||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
similar.workspace = true
|
||||
smol.workspace = true
|
||||
strsim = "0.11"
|
||||
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>) {
|
||||
let request = self.to_completion_request(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,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::ops::Add;
|
||||
use std::{any::TypeId, borrow::Cow, fmt::Debug, num::NonZeroU32, ops::Range, sync::Arc};
|
||||
use std::{
|
||||
any::TypeId,
|
||||
borrow::Cow,
|
||||
fmt::Debug,
|
||||
num::NonZeroU32,
|
||||
ops::{Add, Range, Sub},
|
||||
sync::Arc,
|
||||
};
|
||||
use sum_tree::{Bias, TreeMap};
|
||||
use tab_map::{TabMap, TabSnapshot};
|
||||
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 {
|
||||
pub fn new(row: DisplayRow, column: u32) -> Self {
|
||||
Self(BlockPoint(Point::new(row.0, column)))
|
||||
|
|
|
@ -376,6 +376,7 @@ type CompletionId = usize;
|
|||
// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
|
||||
|
||||
type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
|
||||
type GutterHighlight = (fn(&AppContext) -> Hsla, Arc<[Range<Anchor>]>);
|
||||
|
||||
struct ScrollbarMarkerState {
|
||||
scrollbar_size: Size<Pixels>,
|
||||
|
@ -464,6 +465,7 @@ pub struct Editor {
|
|||
highlight_order: usize,
|
||||
highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
|
||||
background_highlights: TreeMap<TypeId, BackgroundHighlight>,
|
||||
gutter_highlights: TreeMap<TypeId, GutterHighlight>,
|
||||
scrollbar_marker_state: ScrollbarMarkerState,
|
||||
active_indent_guides_state: ActiveIndentGuidesState,
|
||||
nav_history: Option<ItemNavHistory>,
|
||||
|
@ -1752,6 +1754,7 @@ impl Editor {
|
|||
highlight_order: 0,
|
||||
highlighted_rows: HashMap::default(),
|
||||
background_highlights: Default::default(),
|
||||
gutter_highlights: TreeMap::default(),
|
||||
scrollbar_marker_state: ScrollbarMarkerState::default(),
|
||||
active_indent_guides_state: ActiveIndentGuidesState::default(),
|
||||
nav_history: None,
|
||||
|
@ -10263,6 +10266,25 @@ impl Editor {
|
|||
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")]
|
||||
pub fn all_text_background_highlights(
|
||||
&mut self,
|
||||
|
@ -10452,6 +10474,44 @@ impl Editor {
|
|||
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
|
||||
pub fn redacted_ranges(
|
||||
&self,
|
||||
|
|
|
@ -2837,6 +2837,8 @@ impl EditorElement {
|
|||
Self::paint_diff_hunks(layout.gutter_hitbox.bounds, layout, cx)
|
||||
}
|
||||
|
||||
self.paint_gutter_highlights(layout, cx);
|
||||
|
||||
if layout.blamed_display_rows.is_some() {
|
||||
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) {
|
||||
let Some(blamed_display_rows) = layout.blamed_display_rows.take() else {
|
||||
return;
|
||||
|
@ -4631,6 +4664,12 @@ impl Element for EditorElement {
|
|||
&snapshot.display_snapshot,
|
||||
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(
|
||||
start_anchor..end_anchor,
|
||||
|
@ -4991,6 +5030,7 @@ impl Element for EditorElement {
|
|||
active_rows,
|
||||
highlighted_rows,
|
||||
highlighted_ranges,
|
||||
highlighted_gutter_ranges,
|
||||
redacted_ranges,
|
||||
line_elements,
|
||||
line_numbers,
|
||||
|
@ -5121,6 +5161,7 @@ pub struct EditorLayout {
|
|||
inline_blame: Option<AnyElement>,
|
||||
blocks: Vec<BlockLayout>,
|
||||
highlighted_ranges: Vec<(Range<DisplayPoint>, Hsla)>,
|
||||
highlighted_gutter_ranges: Vec<(Range<DisplayPoint>, Hsla)>,
|
||||
redacted_ranges: Vec<Range<DisplayPoint>>,
|
||||
cursors: Vec<(DisplayPoint, Hsla)>,
|
||||
visible_cursors: Vec<CursorLayout>,
|
||||
|
|
|
@ -49,7 +49,7 @@ schemars.workspace = true
|
|||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
similar = "1.3"
|
||||
similar.workspace = true
|
||||
smallvec.workspace = true
|
||||
smol.workspace = true
|
||||
sum_tree.workspace = true
|
||||
|
|
|
@ -797,6 +797,10 @@ impl Buffer {
|
|||
.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].
|
||||
pub fn set_capability(&mut self, capability: Capability, cx: &mut ModelContext<Self>) {
|
||||
self.capability = capability;
|
||||
|
|
|
@ -106,6 +106,7 @@ pub enum IconName {
|
|||
Code,
|
||||
Collab,
|
||||
Command,
|
||||
Context,
|
||||
Control,
|
||||
Copilot,
|
||||
CopilotDisabled,
|
||||
|
@ -170,6 +171,7 @@ pub enum IconName {
|
|||
Rerun,
|
||||
Return,
|
||||
Reveal,
|
||||
RotateCw,
|
||||
Save,
|
||||
Screen,
|
||||
SelectAll,
|
||||
|
@ -186,6 +188,7 @@ pub enum IconName {
|
|||
Split,
|
||||
Star,
|
||||
StarFilled,
|
||||
Stop,
|
||||
Strikethrough,
|
||||
Supermaven,
|
||||
SupermavenDisabled,
|
||||
|
@ -233,6 +236,7 @@ impl IconName {
|
|||
IconName::Code => "icons/code.svg",
|
||||
IconName::Collab => "icons/user_group_16.svg",
|
||||
IconName::Command => "icons/command.svg",
|
||||
IconName::Context => "icons/context.svg",
|
||||
IconName::Control => "icons/control.svg",
|
||||
IconName::Copilot => "icons/copilot.svg",
|
||||
IconName::CopilotDisabled => "icons/copilot_disabled.svg",
|
||||
|
@ -297,6 +301,7 @@ impl IconName {
|
|||
IconName::ReplyArrowRight => "icons/reply_arrow_right.svg",
|
||||
IconName::Rerun => "icons/rerun.svg",
|
||||
IconName::Return => "icons/return.svg",
|
||||
IconName::RotateCw => "icons/rotate_cw.svg",
|
||||
IconName::Save => "icons/save.svg",
|
||||
IconName::Screen => "icons/desktop.svg",
|
||||
IconName::SelectAll => "icons/select_all.svg",
|
||||
|
@ -313,6 +318,7 @@ impl IconName {
|
|||
IconName::Split => "icons/split.svg",
|
||||
IconName::Star => "icons/star.svg",
|
||||
IconName::StarFilled => "icons/star_filled.svg",
|
||||
IconName::Stop => "icons/stop.svg",
|
||||
IconName::Strikethrough => "icons/strikethrough.svg",
|
||||
IconName::Supermaven => "icons/supermaven.svg",
|
||||
IconName::SupermavenDisabled => "icons/supermaven_disabled.svg",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue