diff --git a/crates/assistant/src/assistant_settings.rs b/crates/assistant/src/assistant_settings.rs index 98188305fbac11d9fdbf9284ada43a125810ad46..5bfd406658251259579d9139d1e34d2e2af8c172 100644 --- a/crates/assistant/src/assistant_settings.rs +++ b/crates/assistant/src/assistant_settings.rs @@ -60,7 +60,6 @@ pub struct AssistantSettings { pub inline_alternatives: Vec, pub using_outdated_settings_version: bool, pub enable_experimental_live_diffs: bool, - pub show_hints: bool, } impl AssistantSettings { @@ -203,7 +202,6 @@ impl AssistantSettingsContent { AssistantSettingsContent::Versioned(settings) => match settings { VersionedAssistantSettingsContent::V1(settings) => AssistantSettingsContentV2 { enabled: settings.enabled, - show_hints: None, button: settings.button, dock: settings.dock, default_width: settings.default_width, @@ -244,7 +242,6 @@ impl AssistantSettingsContent { }, AssistantSettingsContent::Legacy(settings) => AssistantSettingsContentV2 { enabled: None, - show_hints: None, button: settings.button, dock: settings.dock, default_width: settings.default_width, @@ -357,7 +354,6 @@ impl Default for VersionedAssistantSettingsContent { fn default() -> Self { Self::V2(AssistantSettingsContentV2 { enabled: None, - show_hints: None, button: None, dock: None, default_width: None, @@ -375,11 +371,6 @@ pub struct AssistantSettingsContentV2 { /// /// Default: true enabled: Option, - /// Whether to show inline hints that show keybindings for inline assistant - /// and assistant panel. - /// - /// Default: true - show_hints: Option, /// Whether to show the assistant panel button in the status bar. /// /// Default: true @@ -514,7 +505,6 @@ impl Settings for AssistantSettings { let value = value.upgrade(); merge(&mut settings.enabled, value.enabled); - merge(&mut settings.show_hints, value.show_hints); merge(&mut settings.button, value.button); merge(&mut settings.dock, value.dock); merge( @@ -585,7 +575,6 @@ mod tests { }), inline_alternatives: None, enabled: None, - show_hints: None, button: None, dock: None, default_width: None, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 160ea1d90d65134b18ac3eedf68a4b122ec54c07..eb310fa75706ab3512a82400badf5d6910b3b89b 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -540,15 +540,6 @@ pub enum IsVimMode { No, } -pub trait ActiveLineTrailerProvider { - fn render_active_line_trailer( - &mut self, - style: &EditorStyle, - focus_handle: &FocusHandle, - cx: &mut WindowContext, - ) -> Option; -} - /// Zed's primary text input `View`, allowing users to edit a [`MultiBuffer`] /// /// See the [module level documentation](self) for more information. @@ -676,7 +667,6 @@ pub struct Editor { next_scroll_position: NextScrollCursorCenterTopBottom, addons: HashMap>, _scroll_cursor_center_top_bottom_task: Task<()>, - active_line_trailer_provider: Option>, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] @@ -2215,7 +2205,6 @@ impl Editor { addons: HashMap::default(), _scroll_cursor_center_top_bottom_task: Task::ready(()), text_style_refinement: None, - active_line_trailer_provider: None, }; this.tasks_update_task = Some(this.refresh_runnables(cx)); this._subscriptions.extend(project_subscriptions); @@ -2504,16 +2493,6 @@ impl Editor { self.refresh_inline_completion(false, false, cx); } - pub fn set_active_line_trailer_provider( - &mut self, - provider: Option, - _cx: &mut ViewContext, - ) where - T: ActiveLineTrailerProvider + 'static, - { - self.active_line_trailer_provider = provider.map(|provider| Box::new(provider) as Box<_>); - } - pub fn placeholder_text(&self, _cx: &WindowContext) -> Option<&str> { self.placeholder_text.as_deref() } @@ -11870,29 +11849,6 @@ impl Editor { && self.has_blame_entries(cx) } - pub fn render_active_line_trailer( - &mut self, - style: &EditorStyle, - cx: &mut WindowContext, - ) -> Option { - let selection = self.selections.newest::(cx); - if !selection.is_empty() { - return None; - }; - - let snapshot = self.buffer.read(cx).snapshot(cx); - let buffer_row = MultiBufferRow(selection.head().row); - - if snapshot.line_len(buffer_row) != 0 || self.has_active_inline_completion(cx) { - return None; - } - - let focus_handle = self.focus_handle.clone(); - self.active_line_trailer_provider - .as_mut()? - .render_active_line_trailer(style, &focus_handle, cx) - } - fn has_blame_entries(&self, cx: &mut WindowContext) -> bool { self.blame() .map_or(false, |blame| blame.read(cx).has_generated_entries()) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 6e4538ae6dc407262948d48f08f4df6e3b0b1e16..7702134409f70106dde8c9f7b9a28b79eb62e64b 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1412,7 +1412,7 @@ impl EditorElement { } #[allow(clippy::too_many_arguments)] - fn layout_active_line_trailer( + fn layout_inline_blame( &self, display_row: DisplayRow, display_snapshot: &DisplaySnapshot, @@ -1424,71 +1424,61 @@ impl EditorElement { line_height: Pixels, cx: &mut WindowContext, ) -> Option { - let render_inline_blame = self + if !self .editor - .update(cx, |editor, cx| editor.render_git_blame_inline(cx)); - if render_inline_blame { - let workspace = self - .editor - .read(cx) - .workspace - .as_ref() - .map(|(w, _)| w.clone()); - - let display_point = DisplayPoint::new(display_row, 0); - let buffer_row = MultiBufferRow(display_point.to_point(display_snapshot).row); + .update(cx, |editor, cx| editor.render_git_blame_inline(cx)) + { + return None; + } - let blame = self.editor.read(cx).blame.clone()?; - let blame_entry = blame - .update(cx, |blame, cx| { - blame.blame_for_rows([Some(buffer_row)], cx).next() - }) - .flatten()?; + let workspace = self + .editor + .read(cx) + .workspace + .as_ref() + .map(|(w, _)| w.clone()); - let mut element = - render_inline_blame_entry(&blame, blame_entry, &self.style, workspace, cx); + let display_point = DisplayPoint::new(display_row, 0); + let buffer_row = MultiBufferRow(display_point.to_point(display_snapshot).row); - let start_y = content_origin.y - + line_height * (display_row.as_f32() - scroll_pixel_position.y / line_height); + let blame = self.editor.read(cx).blame.clone()?; + let blame_entry = blame + .update(cx, |blame, cx| { + blame.blame_for_rows([Some(buffer_row)], cx).next() + }) + .flatten()?; - let start_x = { - const INLINE_BLAME_PADDING_EM_WIDTHS: f32 = 6.; + let mut element = + render_inline_blame_entry(&blame, blame_entry, &self.style, workspace, cx); - let line_end = if let Some(crease_trailer) = crease_trailer { - crease_trailer.bounds.right() - } else { - content_origin.x - scroll_pixel_position.x + line_layout.width - }; - let padded_line_end = line_end + em_width * INLINE_BLAME_PADDING_EM_WIDTHS; + let start_y = content_origin.y + + line_height * (display_row.as_f32() - scroll_pixel_position.y / line_height); - let min_column_in_pixels = ProjectSettings::get_global(cx) - .git - .inline_blame - .and_then(|settings| settings.min_column) - .map(|col| self.column_pixels(col as usize, cx)) - .unwrap_or(px(0.)); - let min_start = content_origin.x - scroll_pixel_position.x + min_column_in_pixels; + let start_x = { + const INLINE_BLAME_PADDING_EM_WIDTHS: f32 = 6.; - cmp::max(padded_line_end, min_start) + let line_end = if let Some(crease_trailer) = crease_trailer { + crease_trailer.bounds.right() + } else { + content_origin.x - scroll_pixel_position.x + line_layout.width }; + let padded_line_end = line_end + em_width * INLINE_BLAME_PADDING_EM_WIDTHS; + + let min_column_in_pixels = ProjectSettings::get_global(cx) + .git + .inline_blame + .and_then(|settings| settings.min_column) + .map(|col| self.column_pixels(col as usize, cx)) + .unwrap_or(px(0.)); + let min_start = content_origin.x - scroll_pixel_position.x + min_column_in_pixels; - let absolute_offset = point(start_x, start_y); - element.prepaint_as_root(absolute_offset, AvailableSpace::min_size(), cx); + cmp::max(padded_line_end, min_start) + }; - Some(element) - } else if let Some(mut element) = self.editor.update(cx, |editor, cx| { - editor.render_active_line_trailer(&self.style, cx) - }) { - let start_y = content_origin.y - + line_height * (display_row.as_f32() - scroll_pixel_position.y / line_height); - let start_x = content_origin.x - scroll_pixel_position.x + em_width; - let absolute_offset = point(start_x, start_y); - element.prepaint_as_root(absolute_offset, AvailableSpace::min_size(), cx); + let absolute_offset = point(start_x, start_y); + element.prepaint_as_root(absolute_offset, AvailableSpace::min_size(), cx); - Some(element) - } else { - None - } + Some(element) } #[allow(clippy::too_many_arguments)] @@ -3464,7 +3454,7 @@ impl EditorElement { self.paint_lines(&invisible_display_ranges, layout, cx); self.paint_redactions(layout, cx); self.paint_cursors(layout, cx); - self.paint_active_line_trailer(layout, cx); + self.paint_inline_blame(layout, cx); cx.with_element_namespace("crease_trailers", |cx| { for trailer in layout.crease_trailers.iter_mut().flatten() { trailer.element.paint(cx); @@ -3946,10 +3936,10 @@ impl EditorElement { } } - fn paint_active_line_trailer(&mut self, layout: &mut EditorLayout, cx: &mut WindowContext) { - if let Some(mut element) = layout.active_line_trailer.take() { + fn paint_inline_blame(&mut self, layout: &mut EditorLayout, cx: &mut WindowContext) { + if let Some(mut inline_blame) = layout.inline_blame.take() { cx.paint_layer(layout.text_hitbox.bounds, |cx| { - element.paint(cx); + inline_blame.paint(cx); }) } } @@ -5341,14 +5331,14 @@ impl Element for EditorElement { ) }); - let mut active_line_trailer = None; + let mut inline_blame = None; if let Some(newest_selection_head) = newest_selection_head { let display_row = newest_selection_head.row(); if (start_row..end_row).contains(&display_row) { let line_ix = display_row.minus(start_row) as usize; let line_layout = &line_layouts[line_ix]; let crease_trailer_layout = crease_trailers[line_ix].as_ref(); - active_line_trailer = self.layout_active_line_trailer( + inline_blame = self.layout_inline_blame( display_row, &snapshot.display_snapshot, line_layout, @@ -5667,7 +5657,7 @@ impl Element for EditorElement { line_elements, line_numbers, blamed_display_rows, - active_line_trailer, + inline_blame, blocks, cursors, visible_cursors, @@ -5804,7 +5794,7 @@ pub struct EditorLayout { line_numbers: Vec>, display_hunks: Vec<(DisplayDiffHunk, Option)>, blamed_display_rows: Option>, - active_line_trailer: Option, + inline_blame: Option, blocks: Vec, highlighted_ranges: Vec<(Range, Hsla)>, highlighted_gutter_ranges: Vec<(Range, Hsla)>, diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index e4fa74f981ed5ff102b3a97d6f575fbf9d23c3e3..674606231e9c1ad2934cb6be3b222ebf6bf168cd 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -3050,7 +3050,7 @@ impl<'a> WindowContext<'a> { } /// Represent this action as a key binding string, to display in the UI. - pub fn keystroke_text_for_action(&self, action: &dyn Action) -> String { + pub fn keystroke_text_for(&self, action: &dyn Action) -> String { self.bindings_for_action(action) .into_iter() .next() @@ -3065,26 +3065,6 @@ impl<'a> WindowContext<'a> { .unwrap_or_else(|| action.name().to_string()) } - /// Represent this action as a key binding string, to display in the UI. - pub fn keystroke_text_for_action_in( - &self, - action: &dyn Action, - focus_handle: &FocusHandle, - ) -> String { - self.bindings_for_action_in(action, focus_handle) - .into_iter() - .next() - .map(|binding| { - binding - .keystrokes() - .iter() - .map(ToString::to_string) - .collect::>() - .join(" ") - }) - .unwrap_or_else(|| action.name().to_string()) - } - /// Dispatch a mouse or keyboard event on the window. #[profiling::function] pub fn dispatch_event(&mut self, event: PlatformInput) -> DispatchEventResult { diff --git a/crates/outline_panel/src/outline_panel.rs b/crates/outline_panel/src/outline_panel.rs index f378348782e9a4e7155df9a9b16ac5e34e511d3c..f878b582d942e16c703b4856c36368265933eaf7 100644 --- a/crates/outline_panel/src/outline_panel.rs +++ b/crates/outline_panel/src/outline_panel.rs @@ -3875,13 +3875,13 @@ impl OutlinePanel { .child({ let keystroke = match self.position(cx) { DockPosition::Left => { - cx.keystroke_text_for_action(&workspace::ToggleLeftDock) + cx.keystroke_text_for(&workspace::ToggleLeftDock) } DockPosition::Bottom => { - cx.keystroke_text_for_action(&workspace::ToggleBottomDock) + cx.keystroke_text_for(&workspace::ToggleBottomDock) } DockPosition::Right => { - cx.keystroke_text_for_action(&workspace::ToggleRightDock) + cx.keystroke_text_for(&workspace::ToggleRightDock) } }; Label::new(format!("Toggle this panel with {keystroke}")) diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index e01309cacdd09401ae072b8af4ce11d11efd0098..072e8ba6959f619f09d065556cb1e59fe525acbe 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -185,13 +185,13 @@ impl PickerDelegate for RecentProjectsDelegate { fn placeholder_text(&self, cx: &mut WindowContext) -> Arc { let (create_window, reuse_window) = if self.create_new_window { ( - cx.keystroke_text_for_action(&menu::Confirm), - cx.keystroke_text_for_action(&menu::SecondaryConfirm), + cx.keystroke_text_for(&menu::Confirm), + cx.keystroke_text_for(&menu::SecondaryConfirm), ) } else { ( - cx.keystroke_text_for_action(&menu::SecondaryConfirm), - cx.keystroke_text_for_action(&menu::Confirm), + cx.keystroke_text_for(&menu::SecondaryConfirm), + cx.keystroke_text_for(&menu::Confirm), ) }; Arc::from(format!( diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index c632843baa4ac1d837f421852e4567475c757933..a5fc52e93372b787462c0aa3406ca9fea0a1ba67 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -66,7 +66,7 @@ use zed::{ OpenRequest, }; -use crate::zed::{assistant_hints, inline_completion_registry}; +use crate::zed::inline_completion_registry; #[cfg(feature = "mimalloc")] #[global_allocator] @@ -401,7 +401,6 @@ fn main() { stdout_is_a_pty(), cx, ); - assistant_hints::init(cx); repl::init( app_state.fs.clone(), app_state.client.telemetry().clone(), diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 867ffa91e686fe19b3c95812d04ecdd36fc20ff6..07260735022fd607a2ea3f6e99396761b60fd592 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,5 +1,4 @@ mod app_menus; -pub mod assistant_hints; pub mod inline_completion_registry; #[cfg(any(target_os = "linux", target_os = "freebsd"))] pub(crate) mod linux_prompts; diff --git a/crates/zed/src/zed/assistant_hints.rs b/crates/zed/src/zed/assistant_hints.rs deleted file mode 100644 index 244b7fab26588d9b741b6e151ef3851f303c4710..0000000000000000000000000000000000000000 --- a/crates/zed/src/zed/assistant_hints.rs +++ /dev/null @@ -1,115 +0,0 @@ -use assistant::assistant_settings::AssistantSettings; -use collections::HashMap; -use editor::{ActiveLineTrailerProvider, Editor, EditorMode}; -use gpui::{AnyWindowHandle, AppContext, ViewContext, WeakView, WindowContext}; -use settings::{Settings, SettingsStore}; -use std::{cell::RefCell, rc::Rc}; -use theme::ActiveTheme; -use ui::prelude::*; -use workspace::Workspace; - -pub fn init(cx: &mut AppContext) { - let editors: Rc, AnyWindowHandle>>> = Rc::default(); - - cx.observe_new_views({ - let editors = editors.clone(); - move |_: &mut Workspace, cx: &mut ViewContext| { - let workspace_handle = cx.view().clone(); - cx.subscribe(&workspace_handle, { - let editors = editors.clone(); - move |_, _, event, cx| match event { - workspace::Event::ItemAdded { item } => { - if let Some(editor) = item.act_as::(cx) { - if editor.read(cx).mode() != EditorMode::Full { - return; - } - - cx.on_release({ - let editor_handle = editor.downgrade(); - let editors = editors.clone(); - move |_, _, _| { - editors.borrow_mut().remove(&editor_handle); - } - }) - .detach(); - editors - .borrow_mut() - .insert(editor.downgrade(), cx.window_handle()); - - let show_hints = should_show_hints(cx); - editor.update(cx, |editor, cx| { - assign_active_line_trailer_provider(editor, show_hints, cx) - }) - } - } - _ => {} - } - }) - .detach(); - } - }) - .detach(); - - let mut show_hints = AssistantSettings::get_global(cx).show_hints; - cx.observe_global::(move |cx| { - let new_show_hints = should_show_hints(cx); - if new_show_hints != show_hints { - show_hints = new_show_hints; - for (editor, window) in editors.borrow().iter() { - _ = window.update(cx, |_window, cx| { - _ = editor.update(cx, |editor, cx| { - assign_active_line_trailer_provider(editor, show_hints, cx); - }) - }); - } - } - }) - .detach(); -} - -struct AssistantHintsProvider; - -impl ActiveLineTrailerProvider for AssistantHintsProvider { - fn render_active_line_trailer( - &mut self, - style: &editor::EditorStyle, - focus_handle: &gpui::FocusHandle, - cx: &mut WindowContext, - ) -> Option { - if !focus_handle.is_focused(cx) { - return None; - } - - let chat_keybinding = - cx.keystroke_text_for_action_in(&assistant::ToggleFocus, focus_handle); - let generate_keybinding = - cx.keystroke_text_for_action_in(&zed_actions::InlineAssist::default(), focus_handle); - - Some( - h_flex() - .id("inline-assistant-instructions") - .w_full() - .font_family(style.text.font().family) - .text_color(cx.theme().status().hint) - .line_height(style.text.line_height) - .child(format!( - "{chat_keybinding} to chat, {generate_keybinding} to generate" - )) - .into_any(), - ) - } -} - -fn assign_active_line_trailer_provider( - editor: &mut Editor, - show_hints: bool, - cx: &mut ViewContext, -) { - let provider = show_hints.then_some(AssistantHintsProvider); - editor.set_active_line_trailer_provider(provider, cx); -} - -fn should_show_hints(cx: &AppContext) -> bool { - let assistant_settings = AssistantSettings::get_global(cx); - assistant_settings.enabled && assistant_settings.show_hints -} diff --git a/docs/src/assistant/configuration.md b/docs/src/assistant/configuration.md index 1be96491f4ae7879a62c43c7803f4f232e366663..2145bd95045c43177b4218c95d16dd3316c6020c 100644 --- a/docs/src/assistant/configuration.md +++ b/docs/src/assistant/configuration.md @@ -200,28 +200,18 @@ You must provide the model's Context Window in the `max_tokens` parameter, this { "assistant": { "enabled": true, - "show_hints": true, - "button": true, - "dock": "right" - "default_width": 480, "default_model": { "provider": "zed.dev", "model": "claude-3-5-sonnet" }, "version": "2", + "button": true, + "default_width": 480, + "dock": "right" } } ``` -| key | type | default | description | -| -------------- | ------- | ------- | ------------------------------------------------------------------------------------- | -| enabled | boolean | true | Setting this to `false` will completely disable the assistant | -| show_hints | boolean | true | Whether to to show hints in the editor explaining how to use assistant | -| button | boolean | true | Show the assistant icon in the status bar | -| dock | string | "right" | The default dock position for the assistant panel. Can be ["left", "right", "bottom"] | -| default_height | string | null | The pixel height of the assistant panel when docked to the bottom | -| default_width | string | null | The pixel width of the assistant panel when docked to the left or right | - #### Custom endpoints {#custom-endpoint} You can use a custom API endpoint for different providers, as long as it's compatible with the providers API structure. @@ -281,3 +271,13 @@ will generate two outputs for every assist. One with Claude 3.5 Sonnet, and one } } ``` + +#### Common Panel Settings + +| key | type | default | description | +| -------------- | ------- | ------- | ------------------------------------------------------------------------------------- | +| enabled | boolean | true | Setting this to `false` will completely disable the assistant | +| button | boolean | true | Show the assistant icon in the status bar | +| dock | string | "right" | The default dock position for the assistant panel. Can be ["left", "right", "bottom"] | +| default_height | string | null | The pixel height of the assistant panel when docked to the bottom | +| default_width | string | null | The pixel width of the assistant panel when docked to the left or right | diff --git a/docs/src/configuring-zed.md b/docs/src/configuring-zed.md index b4da7901a19bdac197c16d894ae532bffc5470ed..ce8068fa3bb9ca7045cfa3123ddeaac4e222ad12 100644 --- a/docs/src/configuring-zed.md +++ b/docs/src/configuring-zed.md @@ -2327,18 +2327,15 @@ Run the `theme selector: toggle` action in the command palette to see a current - Default: ```json -{ - "assistant": { - "enabled": true, - "button": true, - "dock": "right", - "default_width": 640, - "default_height": 320, - "provider": "openai", - "version": "1", - "show_hints": true - } -} +"assistant": { + "enabled": true, + "button": true, + "dock": "right", + "default_width": 640, + "default_height": 320, + "provider": "openai", + "version": "1", +}, ``` ## Outline Panel