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:
When detail is `None` or empty string:
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())