From bffdc55d63449ca1a80e649df6f8b35f20937b91 Mon Sep 17 00:00:00 2001 From: tims <0xtimsb@gmail.com> Date: Fri, 6 Dec 2024 22:56:47 +0530 Subject: [PATCH] linux: Make prompt detail selectable (#21405) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #21305 As Linux doesn’t have native prompts, Zed uses a custom GPU-based prompt, like the "About Zed" prompt. Currently, the detail in the prompt isn’t selectable. This PR fixes that by using the editor's multi-line selectable functionality to make the detail selectable (and thus copyable). It achieves this by disabling editing and setting the cursor to transparent. The editor also does all the heavy lifting, like double-clicking to select a word or triple-clicking to select a line, like what user expects from selectable. Before/After: before after When detail is `None` or empty string: none Release Notes: - N/A --- Cargo.lock | 1 + crates/zed/Cargo.toml | 1 + crates/zed/src/zed/linux_prompts.rs | 43 ++++++++++++++++++++--------- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e421917d8f..b93ebce571 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16083,6 +16083,7 @@ dependencies = [ "languages", "libc", "log", + "markdown", "markdown_preview", "menu", "mimalloc", diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 6b26a01f27..9a672757a6 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -69,6 +69,7 @@ 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 mimalloc = { version = "0.1", optional = true } diff --git a/crates/zed/src/zed/linux_prompts.rs b/crates/zed/src/zed/linux_prompts.rs index 1961a5f9cd..aa262a11b9 100644 --- a/crates/zed/src/zed/linux_prompts.rs +++ b/crates/zed/src/zed/linux_prompts.rs @@ -1,13 +1,15 @@ use gpui::{ div, AppContext, EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement, - IntoElement, ParentElement, PromptHandle, PromptLevel, PromptResponse, Render, - RenderablePromptHandle, Styled, ViewContext, VisualContext, WindowContext, + IntoElement, ParentElement, PromptHandle, PromptLevel, PromptResponse, Refineable, Render, + RenderablePromptHandle, Styled, TextStyleRefinement, View, ViewContext, VisualContext, + WindowContext, }; +use markdown::{Markdown, MarkdownStyle}; use settings::Settings; use theme::ThemeSettings; use ui::{ - h_flex, v_flex, ButtonCommon, ButtonStyle, Clickable, ElevationIndex, FluentBuilder, LabelSize, - TintColor, + h_flex, v_flex, ActiveTheme, ButtonCommon, ButtonStyle, Clickable, ElevationIndex, + FluentBuilder, LabelSize, TintColor, }; use workspace::ui::StyledExt; @@ -28,10 +30,27 @@ pub fn fallback_prompt_renderer( |cx| FallbackPromptRenderer { _level: level, message: message.to_string(), - detail: detail.map(ToString::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_view(|cx| { + let settings = ThemeSettings::get_global(cx); + let mut base_text_style = cx.text_style(); + base_text_style.refine(&TextStyleRefinement { + font_family: Some(settings.ui_font.family.clone()), + font_size: Some(settings.ui_font_size.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(text.to_string(), markdown_style, None, None, cx) + }) + }), } }); @@ -42,10 +61,10 @@ pub fn fallback_prompt_renderer( pub struct FallbackPromptRenderer { _level: PromptLevel, message: String, - detail: Option, actions: Vec, focus: FocusHandle, active_action_id: usize, + detail: Option>, } impl FallbackPromptRenderer { @@ -111,13 +130,11 @@ impl Render for FallbackPromptRenderer { .child(self.message.clone()) .text_color(ui::Color::Default.color(cx)), ) - .children(self.detail.clone().map(|detail| { - div() - .w_full() - .text_xs() - .text_color(ui::Color::Muted.color(cx)) - .child(detail) - })) + .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())