Support built-in Zed prompts for all platforms (#26201)
This pull request does two things: 1. Adds a setting to force Zed to use the built-in prompts, instead of the system provided ones. I've personally found the system prompts on macOS often fail to respond to keyboard input, are slow to render initially, and don't match Zed's style. 2. Makes the previously Linux-only Zed provided prompts available to everybody using the above setting. Release Notes: - Added support for a built-in prompting system, regardless of platform. Use the new `use_system_prompts` setting to control whether to use the system provided prompts or Zed's built-in system. Note that on Linux, this setting has no effect, as Linux doesn't have a system prompting mechanism.
This commit is contained in:
parent
382f9f6151
commit
0f5a3afe94
13 changed files with 99 additions and 21 deletions
|
@ -75,7 +75,6 @@ language_tools.workspace = true
|
|||
languages = { workspace = true, features = ["load-grammars"] }
|
||||
libc.workspace = true
|
||||
log.workspace = true
|
||||
markdown.workspace = true
|
||||
markdown_preview.workspace = true
|
||||
menu.workspace = true
|
||||
migrator.workspace = true
|
||||
|
@ -125,6 +124,7 @@ theme_selector.workspace = true
|
|||
time.workspace = true
|
||||
toolchain_selector.workspace = true
|
||||
ui.workspace = true
|
||||
ui_prompt.workspace = true
|
||||
url.workspace = true
|
||||
urlencoding.workspace = true
|
||||
util.workspace = true
|
||||
|
|
|
@ -487,9 +487,6 @@ fn main() {
|
|||
|
||||
load_embedded_fonts(cx);
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
crate::zed::linux_prompts::init(cx);
|
||||
|
||||
app_state.languages.set_theme(cx.theme().clone());
|
||||
editor::init(cx);
|
||||
image_viewer::init(cx);
|
||||
|
@ -498,6 +495,7 @@ fn main() {
|
|||
|
||||
audio::init(Assets, cx);
|
||||
workspace::init(app_state.clone(), cx);
|
||||
ui_prompt::init(cx);
|
||||
|
||||
go_to_line::init(cx);
|
||||
file_finder::init(cx);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
mod app_menus;
|
||||
pub mod inline_completion_registry;
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
pub(crate) mod linux_prompts;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) mod mac_only_instance;
|
||||
mod migrate;
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
use gpui::{
|
||||
div, App, AppContext as _, Context, Entity, EventEmitter, FocusHandle, Focusable, FontWeight,
|
||||
InteractiveElement, IntoElement, ParentElement, PromptHandle, PromptLevel, PromptResponse,
|
||||
Refineable, Render, RenderablePromptHandle, SharedString, Styled, TextStyleRefinement, Window,
|
||||
};
|
||||
use markdown::{Markdown, MarkdownStyle};
|
||||
use settings::Settings;
|
||||
use theme::ThemeSettings;
|
||||
use ui::{
|
||||
h_flex, v_flex, ActiveTheme, ButtonCommon, ButtonStyle, Clickable, ElevationIndex,
|
||||
FluentBuilder, LabelSize, TintColor,
|
||||
};
|
||||
use workspace::ui::StyledExt;
|
||||
|
||||
pub fn init(cx: &mut App) {
|
||||
cx.set_prompt_builder(fallback_prompt_renderer)
|
||||
}
|
||||
/// Use this function in conjunction with [App::set_prompt_builder] to force
|
||||
/// GPUI to always use the fallback prompt renderer.
|
||||
pub fn fallback_prompt_renderer(
|
||||
level: PromptLevel,
|
||||
message: &str,
|
||||
detail: Option<&str>,
|
||||
actions: &[&str],
|
||||
handle: PromptHandle,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> RenderablePromptHandle {
|
||||
let renderer = cx.new({
|
||||
|cx| FallbackPromptRenderer {
|
||||
_level: level,
|
||||
message: message.to_string(),
|
||||
actions: actions.iter().map(ToString::to_string).collect(),
|
||||
focus: cx.focus_handle(),
|
||||
active_action_id: 0,
|
||||
detail: detail.filter(|text| !text.is_empty()).map(|text| {
|
||||
cx.new(|cx| {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let mut base_text_style = window.text_style();
|
||||
base_text_style.refine(&TextStyleRefinement {
|
||||
font_family: Some(settings.ui_font.family.clone()),
|
||||
font_size: Some(settings.ui_font_size(cx).into()),
|
||||
color: Some(ui::Color::Muted.color(cx)),
|
||||
..Default::default()
|
||||
});
|
||||
let markdown_style = MarkdownStyle {
|
||||
base_text_style,
|
||||
selection_background_color: { cx.theme().players().local().selection },
|
||||
..Default::default()
|
||||
};
|
||||
Markdown::new(SharedString::new(text), markdown_style, None, None, cx)
|
||||
})
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
handle.with_view(renderer, window, cx)
|
||||
}
|
||||
|
||||
/// The default GPUI fallback for rendering prompts, when the platform doesn't support it.
|
||||
pub struct FallbackPromptRenderer {
|
||||
_level: PromptLevel,
|
||||
message: String,
|
||||
actions: Vec<String>,
|
||||
focus: FocusHandle,
|
||||
active_action_id: usize,
|
||||
detail: Option<Entity<Markdown>>,
|
||||
}
|
||||
|
||||
impl FallbackPromptRenderer {
|
||||
fn confirm(&mut self, _: &menu::Confirm, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
cx.emit(PromptResponse(self.active_action_id));
|
||||
}
|
||||
|
||||
fn cancel(&mut self, _: &menu::Cancel, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Some(ix) = self.actions.iter().position(|a| a == "Cancel") {
|
||||
cx.emit(PromptResponse(ix));
|
||||
}
|
||||
}
|
||||
|
||||
fn select_first(
|
||||
&mut self,
|
||||
_: &menu::SelectFirst,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.active_action_id = self.actions.len().saturating_sub(1);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn select_last(&mut self, _: &menu::SelectLast, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.active_action_id = 0;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn select_next(&mut self, _: &menu::SelectNext, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
if self.active_action_id > 0 {
|
||||
self.active_action_id -= 1;
|
||||
} else {
|
||||
self.active_action_id = self.actions.len().saturating_sub(1);
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn select_previous(
|
||||
&mut self,
|
||||
_: &menu::SelectPrevious,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.active_action_id = (self.active_action_id + 1) % self.actions.len();
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for FallbackPromptRenderer {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let font_family = settings.ui_font.family.clone();
|
||||
let prompt = v_flex()
|
||||
.key_context("Prompt")
|
||||
.cursor_default()
|
||||
.track_focus(&self.focus)
|
||||
.on_action(cx.listener(Self::confirm))
|
||||
.on_action(cx.listener(Self::cancel))
|
||||
.on_action(cx.listener(Self::select_next))
|
||||
.on_action(cx.listener(Self::select_previous))
|
||||
.on_action(cx.listener(Self::select_first))
|
||||
.on_action(cx.listener(Self::select_last))
|
||||
.elevation_3(cx)
|
||||
.w_72()
|
||||
.overflow_hidden()
|
||||
.p_4()
|
||||
.gap_4()
|
||||
.font_family(font_family)
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.font_weight(FontWeight::BOLD)
|
||||
.child(self.message.clone())
|
||||
.text_color(ui::Color::Default.color(cx)),
|
||||
)
|
||||
.children(
|
||||
self.detail
|
||||
.clone()
|
||||
.map(|detail| div().w_full().text_xs().child(detail)),
|
||||
)
|
||||
.child(h_flex().justify_end().gap_2().children(
|
||||
self.actions.iter().enumerate().rev().map(|(ix, action)| {
|
||||
ui::Button::new(ix, action.clone())
|
||||
.label_size(LabelSize::Large)
|
||||
.style(ButtonStyle::Filled)
|
||||
.when(ix == self.active_action_id, |el| {
|
||||
el.style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
})
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.on_click(cx.listener(move |_, _, _window, cx| {
|
||||
cx.emit(PromptResponse(ix));
|
||||
}))
|
||||
}),
|
||||
));
|
||||
|
||||
div().size_full().occlude().child(
|
||||
div()
|
||||
.size_full()
|
||||
.absolute()
|
||||
.top_0()
|
||||
.left_0()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.justify_around()
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.justify_around()
|
||||
.child(prompt),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PromptResponse> for FallbackPromptRenderer {}
|
||||
|
||||
impl Focusable for FallbackPromptRenderer {
|
||||
fn focus_handle(&self, _: &crate::App) -> FocusHandle {
|
||||
self.focus.clone()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue