diff --git a/crates/assistant_tools/Cargo.toml b/crates/assistant_tools/Cargo.toml index 83e47f6ca5..6bc0b076cb 100644 --- a/crates/assistant_tools/Cargo.toml +++ b/crates/assistant_tools/Cargo.toml @@ -50,13 +50,13 @@ strsim.workspace = true task.workspace = true terminal.workspace = true terminal_view.workspace = true +theme.workspace = true ui.workspace = true util.workspace = true web_search.workspace = true workspace-hack.workspace = true workspace.workspace = true zed_llm_client.workspace = true -theme.workspace = true [dev-dependencies] client = { workspace = true, features = ["test-support"] } diff --git a/crates/assistant_tools/src/edit_file_tool.rs b/crates/assistant_tools/src/edit_file_tool.rs index 57816b6f88..ef37b77f49 100644 --- a/crates/assistant_tools/src/edit_file_tool.rs +++ b/crates/assistant_tools/src/edit_file_tool.rs @@ -5,10 +5,10 @@ use crate::{ use anyhow::{Context as _, Result, anyhow}; use assistant_tool::{ActionLog, AnyToolCard, Tool, ToolCard, ToolResult, ToolUseStatus}; use buffer_diff::{BufferDiff, BufferDiffSnapshot}; -use editor::{Editor, EditorMode, MultiBuffer, PathKey}; +use editor::{Editor, EditorElement, EditorMode, EditorStyle, MultiBuffer, PathKey}; use gpui::{ Animation, AnimationExt, AnyWindowHandle, App, AppContext, AsyncApp, Context, Entity, EntityId, - Task, TextStyleRefinement, WeakEntity, pulsating_between, + Task, TextStyle, TextStyleRefinement, WeakEntity, pulsating_between, }; use language::{ Anchor, Buffer, Capability, LanguageRegistry, LineEnding, OffsetRangeExt, Rope, TextBuffer, @@ -382,14 +382,13 @@ impl EditFileToolCard { .map(|diff_hunk| diff_hunk.buffer_range.to_point(&snapshot)) .collect::>(); multibuffer.clear(cx); - let (_, is_newly_added) = multibuffer.set_excerpts_for_path( + multibuffer.set_excerpts_for_path( PathKey::for_buffer(&buffer, cx), buffer, diff_hunk_ranges, editor::DEFAULT_MULTIBUFFER_CONTEXT, cx, ); - debug_assert!(is_newly_added); multibuffer.add_diff(buffer_diff, cx); let end = multibuffer.len(cx); Some(multibuffer.snapshot(cx).offset_to_point(end).row + 1) @@ -554,7 +553,30 @@ impl ToolCard for EditFileToolCard { .map(|style| style.text.line_height_in_pixels(window.rem_size())) .unwrap_or_default(); - let element = editor.render(window, cx); + let settings = ThemeSettings::get_global(cx); + let element = EditorElement::new( + &cx.entity(), + EditorStyle { + background: cx.theme().colors().editor_background, + horizontal_padding: rems(0.25).to_pixels(window.rem_size()), + local_player: cx.theme().players().local(), + text: TextStyle { + color: cx.theme().colors().editor_foreground, + font_family: settings.buffer_font.family.clone(), + font_features: settings.buffer_font.features.clone(), + font_fallbacks: settings.buffer_font.fallbacks.clone(), + font_size: settings.buffer_font_size(cx).into(), + font_weight: settings.buffer_font.weight, + line_height: relative(settings.buffer_line_height.value()), + ..Default::default() + }, + scrollbar_width: EditorElement::SCROLLBAR_WIDTH, + syntax: cx.theme().syntax().clone(), + status: cx.theme().status().clone(), + ..Default::default() + }, + ); + (element.into_any_element(), line_height) }); @@ -775,9 +797,16 @@ async fn build_buffer_diff( })? .await; + let secondary_diff = cx.new(|cx| { + let mut diff = BufferDiff::new(&buffer, cx); + diff.set_snapshot(diff_snapshot.clone(), &buffer, cx); + diff + })?; + cx.new(|cx| { let mut diff = BufferDiff::new(&buffer.text, cx); - diff.set_snapshot(diff_snapshot, &buffer.text, cx); + diff.set_snapshot(diff_snapshot, &buffer, cx); + diff.set_secondary_diff(secondary_diff); diff }) } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index c49da98be4..7cb0ed1875 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -517,6 +517,7 @@ pub enum SoftWrap { #[derive(Clone)] pub struct EditorStyle { pub background: Hsla, + pub horizontal_padding: Pixels, pub local_player: PlayerColor, pub text: TextStyle, pub scrollbar_width: Pixels, @@ -531,6 +532,7 @@ impl Default for EditorStyle { fn default() -> Self { Self { background: Hsla::default(), + horizontal_padding: Pixels::default(), local_player: PlayerColor::default(), text: TextStyle::default(), scrollbar_width: Pixels::default(), @@ -20352,6 +20354,7 @@ impl Render for Editor { &cx.entity(), EditorStyle { background, + horizontal_padding: Pixels::default(), local_player: cx.theme().players().local(), text: text_style, scrollbar_width: EditorElement::SCROLLBAR_WIDTH, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index b77023ffce..93b58dbd01 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -170,7 +170,7 @@ pub struct EditorElement { type DisplayRowDelta = u32; impl EditorElement { - pub(crate) const SCROLLBAR_WIDTH: Pixels = px(15.); + pub const SCROLLBAR_WIDTH: Pixels = px(15.); pub fn new(editor: &Entity, style: EditorStyle) -> Self { Self { @@ -6810,10 +6810,27 @@ impl Element for EditorElement { cx, ) .unwrap_or_default(); - let text_width = bounds.size.width - gutter_dimensions.width; + let hitbox = window.insert_hitbox(bounds, false); + let gutter_hitbox = + window.insert_hitbox(gutter_bounds(bounds, gutter_dimensions), false); + let text_hitbox = window.insert_hitbox( + Bounds { + origin: gutter_hitbox.top_right() + + point(style.horizontal_padding, Pixels::default()), + size: size( + bounds.size.width + - gutter_dimensions.width + - 2. * style.horizontal_padding, + bounds.size.height, + ), + }, + false, + ); - let editor_width = - text_width - gutter_dimensions.margin - em_width - style.scrollbar_width; + let editor_width = text_hitbox.size.width + - gutter_dimensions.margin + - em_width + - style.scrollbar_width; snapshot = self.editor.update(cx, |editor, cx| { editor.last_bounds = Some(bounds); @@ -6849,24 +6866,13 @@ impl Element for EditorElement { .map(|(guide, active)| (self.column_pixels(*guide, window, cx), *active)) .collect::>(); - let hitbox = window.insert_hitbox(bounds, false); - let gutter_hitbox = - window.insert_hitbox(gutter_bounds(bounds, gutter_dimensions), false); - let text_hitbox = window.insert_hitbox( - Bounds { - origin: gutter_hitbox.top_right(), - size: size(text_width, bounds.size.height), - }, - false, - ); - // Offset the content_bounds from the text_bounds by the gutter margin (which // is roughly half a character wide) to make hit testing work more like how we want. let content_offset = point(gutter_dimensions.margin, Pixels::ZERO); let content_origin = text_hitbox.origin + content_offset; let editor_text_bounds = - Bounds::from_corners(content_origin, bounds.bottom_right()); + Bounds::from_corners(content_origin, text_hitbox.bounds.bottom_right()); let height_in_lines = editor_text_bounds.size.height / line_height;