Revise "Hide/Show Inline Completions" menu (#23808)
> **Note:** https://github.com/zed-industries/zed/pull/23813 should be merged first! @nathansobo and I paired on revising this menu, including adding the "Predict Edits at Cursor" menu item (to make the keyboard shortcut more discoverable; clicking it makes the inline edits show up, as shown in the second screenshot) and switching from "Hide/Show" language to checkboxes. ## Before <img width="282" alt="Screenshot 2025-01-28 at 4 51 37 PM" src="https://github.com/user-attachments/assets/309c82c1-8fb5-44db-950e-1a8789a63993" /> ## After <img width="1138" alt="Screenshot 2025-01-28 at 4 50 05 PM" src="https://github.com/user-attachments/assets/302a126c-9389-42a4-bb7d-2896bce859e7" /> We also switched to use `SharedString` in more places, where it made more sense. @danilo-leal This isn't necessarily *exactly* what we want, but we were pairing and decided to get it in a state where we can actually try it out and tweak from here. Release Notes: - N/A --------- Co-authored-by: Nathan <nathan@zed.dev> Co-authored-by: Danilo Leal <daniloleal09@gmail.com> Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This commit is contained in:
parent
4cef772364
commit
ee0d2a8d94
2 changed files with 52 additions and 24 deletions
|
@ -1,14 +1,15 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use client::UserStore;
|
use client::UserStore;
|
||||||
use copilot::{Copilot, Status};
|
use copilot::{Copilot, Status};
|
||||||
use editor::{scroll::Autoscroll, Editor};
|
use editor::{actions::ShowInlineCompletion, scroll::Autoscroll, Editor};
|
||||||
use feature_flags::{
|
use feature_flags::{
|
||||||
FeatureFlagAppExt, PredictEditsFeatureFlag, PredictEditsRateCompletionsFeatureFlag,
|
FeatureFlagAppExt, PredictEditsFeatureFlag, PredictEditsRateCompletionsFeatureFlag,
|
||||||
};
|
};
|
||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, pulsating_between, Action, Animation, AnimationExt, App, AsyncWindowContext,
|
actions, div, pulsating_between, Action, Animation, AnimationExt, App, AsyncWindowContext,
|
||||||
Corner, Entity, IntoElement, ParentElement, Render, Subscription, WeakEntity,
|
Corner, Entity, FocusHandle, Focusable, IntoElement, ParentElement, Render, Subscription,
|
||||||
|
WeakEntity,
|
||||||
};
|
};
|
||||||
use language::{
|
use language::{
|
||||||
language_settings::{
|
language_settings::{
|
||||||
|
@ -43,6 +44,7 @@ struct CopilotErrorToast;
|
||||||
pub struct InlineCompletionButton {
|
pub struct InlineCompletionButton {
|
||||||
editor_subscription: Option<(Subscription, usize)>,
|
editor_subscription: Option<(Subscription, usize)>,
|
||||||
editor_enabled: Option<bool>,
|
editor_enabled: Option<bool>,
|
||||||
|
editor_focus_handle: Option<FocusHandle>,
|
||||||
language: Option<Arc<Language>>,
|
language: Option<Arc<Language>>,
|
||||||
file: Option<Arc<dyn File>>,
|
file: Option<Arc<dyn File>>,
|
||||||
inline_completion_provider: Option<Arc<dyn inline_completion::InlineCompletionProviderHandle>>,
|
inline_completion_provider: Option<Arc<dyn inline_completion::InlineCompletionProviderHandle>>,
|
||||||
|
@ -329,6 +331,7 @@ impl InlineCompletionButton {
|
||||||
Self {
|
Self {
|
||||||
editor_subscription: None,
|
editor_subscription: None,
|
||||||
editor_enabled: None,
|
editor_enabled: None,
|
||||||
|
editor_focus_handle: None,
|
||||||
language: None,
|
language: None,
|
||||||
file: None,
|
file: None,
|
||||||
inline_completion_provider: None,
|
inline_completion_provider: None,
|
||||||
|
@ -364,21 +367,26 @@ impl InlineCompletionButton {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Predict Edits at Cursor – alt-tab
|
||||||
|
// Automatically Predict:
|
||||||
|
// ✓ PATH
|
||||||
|
// ✓ Rust
|
||||||
|
// ✓ All Files
|
||||||
pub fn build_language_settings_menu(&self, mut menu: ContextMenu, cx: &mut App) -> ContextMenu {
|
pub fn build_language_settings_menu(&self, mut menu: ContextMenu, cx: &mut App) -> ContextMenu {
|
||||||
let fs = self.fs.clone();
|
let fs = self.fs.clone();
|
||||||
|
|
||||||
|
menu = menu.header("Predict Edits For:");
|
||||||
|
|
||||||
if let Some(language) = self.language.clone() {
|
if let Some(language) = self.language.clone() {
|
||||||
let fs = fs.clone();
|
let fs = fs.clone();
|
||||||
let language_enabled =
|
let language_enabled =
|
||||||
language_settings::language_settings(Some(language.name()), None, cx)
|
language_settings::language_settings(Some(language.name()), None, cx)
|
||||||
.show_inline_completions;
|
.show_inline_completions;
|
||||||
|
|
||||||
menu = menu.entry(
|
menu = menu.toggleable_entry(
|
||||||
format!(
|
language.name(),
|
||||||
"{} Inline Completions for {}",
|
language_enabled,
|
||||||
if language_enabled { "Hide" } else { "Show" },
|
IconPosition::Start,
|
||||||
language.name()
|
|
||||||
),
|
|
||||||
None,
|
None,
|
||||||
move |_, cx| {
|
move |_, cx| {
|
||||||
toggle_inline_completions_for_language(language.clone(), fs.clone(), cx)
|
toggle_inline_completions_for_language(language.clone(), fs.clone(), cx)
|
||||||
|
@ -387,16 +395,14 @@ impl InlineCompletionButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
let settings = AllLanguageSettings::get_global(cx);
|
let settings = AllLanguageSettings::get_global(cx);
|
||||||
|
|
||||||
if let Some(file) = &self.file {
|
if let Some(file) = &self.file {
|
||||||
let path = file.path().clone();
|
let path = file.path().clone();
|
||||||
let path_enabled = settings.inline_completions_enabled_for_path(&path);
|
let path_enabled = settings.inline_completions_enabled_for_path(&path);
|
||||||
|
|
||||||
menu = menu.entry(
|
menu = menu.toggleable_entry(
|
||||||
format!(
|
"This File",
|
||||||
"{} Inline Completions for This Path",
|
path_enabled,
|
||||||
if path_enabled { "Hide" } else { "Show" }
|
IconPosition::Start,
|
||||||
),
|
|
||||||
None,
|
None,
|
||||||
move |window, cx| {
|
move |window, cx| {
|
||||||
if let Some(workspace) = window.root().flatten() {
|
if let Some(workspace) = window.root().flatten() {
|
||||||
|
@ -416,15 +422,32 @@ impl InlineCompletionButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
let globally_enabled = settings.inline_completions_enabled(None, None, cx);
|
let globally_enabled = settings.inline_completions_enabled(None, None, cx);
|
||||||
menu.entry(
|
menu = menu.toggleable_entry(
|
||||||
if globally_enabled {
|
"All Files",
|
||||||
"Hide Inline Completions for All Files"
|
globally_enabled,
|
||||||
} else {
|
IconPosition::Start,
|
||||||
"Show Inline Completions for All Files"
|
|
||||||
},
|
|
||||||
None,
|
None,
|
||||||
move |_, cx| toggle_inline_completions_globally(fs.clone(), cx),
|
move |_, cx| toggle_inline_completions_globally(fs.clone(), cx),
|
||||||
)
|
);
|
||||||
|
|
||||||
|
if let Some(editor_focus_handle) = self.editor_focus_handle.clone() {
|
||||||
|
menu = menu
|
||||||
|
.separator()
|
||||||
|
.entry(
|
||||||
|
"Predict Edit at Cursor",
|
||||||
|
Some(Box::new(ShowInlineCompletion)),
|
||||||
|
{
|
||||||
|
let editor_focus_handle = editor_focus_handle.clone();
|
||||||
|
|
||||||
|
move |window, cx| {
|
||||||
|
editor_focus_handle.dispatch_action(&ShowInlineCompletion, window, cx);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.context(editor_focus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_copilot_context_menu(
|
fn build_copilot_context_menu(
|
||||||
|
@ -468,7 +491,7 @@ impl InlineCompletionButton {
|
||||||
self.build_language_settings_menu(menu, cx).when(
|
self.build_language_settings_menu(menu, cx).when(
|
||||||
cx.has_flag::<PredictEditsRateCompletionsFeatureFlag>(),
|
cx.has_flag::<PredictEditsRateCompletionsFeatureFlag>(),
|
||||||
|this| {
|
|this| {
|
||||||
this.separator().entry(
|
this.entry(
|
||||||
"Rate Completions",
|
"Rate Completions",
|
||||||
Some(RateCompletions.boxed_clone()),
|
Some(RateCompletions.boxed_clone()),
|
||||||
move |window, cx| {
|
move |window, cx| {
|
||||||
|
@ -504,6 +527,7 @@ impl InlineCompletionButton {
|
||||||
self.inline_completion_provider = editor.inline_completion_provider();
|
self.inline_completion_provider = editor.inline_completion_provider();
|
||||||
self.language = language.cloned();
|
self.language = language.cloned();
|
||||||
self.file = file;
|
self.file = file;
|
||||||
|
self.editor_focus_handle = Some(editor.focus_handle(cx));
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl RenderOnce for ListSubHeader {
|
||||||
.px(DynamicSpacing::Base02.rems(cx))
|
.px(DynamicSpacing::Base02.rems(cx))
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.h_6()
|
.h_5()
|
||||||
.when(self.inset, |this| this.px_2())
|
.when(self.inset, |this| this.px_2())
|
||||||
.when(self.selected, |this| {
|
.when(self.selected, |this| {
|
||||||
this.bg(cx.theme().colors().ghost_element_selected)
|
this.bg(cx.theme().colors().ghost_element_selected)
|
||||||
|
@ -70,7 +70,11 @@ impl RenderOnce for ListSubHeader {
|
||||||
Icon::new(i).color(Color::Muted).size(IconSize::Small)
|
Icon::new(i).color(Color::Muted).size(IconSize::Small)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.child(Label::new(self.label.clone()).color(Color::Muted)),
|
.child(
|
||||||
|
Label::new(self.label.clone())
|
||||||
|
.color(Color::Muted)
|
||||||
|
.size(LabelSize::Small),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue