text_view: Add to support custom code block style. (#1288)
And remove bg, padding for editor hover code blocks. <img width="589" height="214" alt="image" src="https://github.com/user-attachments/assets/55870f2f-e49e-4c2d-8899-9aa7edd17630" />
This commit is contained in:
parent
a6a14fd57b
commit
512f46aec8
5 changed files with 94 additions and 67 deletions
|
|
@ -11,13 +11,13 @@ pub(crate) use diagnostic_popover::*;
|
||||||
pub(crate) use hover_popover::*;
|
pub(crate) use hover_popover::*;
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, rems, App, Div, ElementId, Entity, InteractiveElement as _, IntoElement, SharedString,
|
div, px, rems, App, Div, ElementId, Entity, InteractiveElement as _, IntoElement, SharedString,
|
||||||
Stateful, Styled as _, Window,
|
Stateful, StyleRefinement, Styled as _, Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
text::{TextView, TextViewStyle},
|
text::{TextView, TextViewStyle},
|
||||||
StyledExt as _,
|
ActiveTheme, StyledExt as _,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) enum ContextMenu {
|
pub(crate) enum ContextMenu {
|
||||||
|
|
@ -58,7 +58,13 @@ pub(super) fn render_markdown(
|
||||||
1..=3 => rem_size * 1,
|
1..=3 => rem_size * 1,
|
||||||
4 => rem_size * 0.9,
|
4 => rem_size * 0.9,
|
||||||
_ => rem_size * 0.8,
|
_ => rem_size * 0.8,
|
||||||
}),
|
})
|
||||||
|
.code_block(
|
||||||
|
StyleRefinement::default()
|
||||||
|
.bg(cx.theme().transparent)
|
||||||
|
.p_0()
|
||||||
|
.text_size(px(11.)),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.selectable()
|
.selectable()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
mod format;
|
mod format;
|
||||||
mod inline;
|
mod inline;
|
||||||
mod node;
|
mod node;
|
||||||
|
mod style;
|
||||||
mod text_view;
|
mod text_view;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use gpui::App;
|
use gpui::App;
|
||||||
|
pub use style::*;
|
||||||
pub use text_view::*;
|
pub use text_view::*;
|
||||||
|
|
||||||
pub(crate) fn init(cx: &mut App) {
|
pub(crate) fn init(cx: &mut App) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::{collections::HashMap, ops::Range};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, img, prelude::FluentBuilder as _, px, relative, rems, AnyElement, App, DefiniteLength,
|
div, img, prelude::FluentBuilder as _, px, relative, rems, AnyElement, App, DefiniteLength,
|
||||||
Div, ElementId, FontStyle, FontWeight, Half, HighlightStyle, InteractiveElement as _,
|
Div, ElementId, FontStyle, FontWeight, Half, HighlightStyle, InteractiveElement as _,
|
||||||
IntoElement, Length, ObjectFit, ParentElement, Rems, SharedString, SharedUri,
|
IntoElement, Length, ObjectFit, ParentElement, SharedString, SharedUri,
|
||||||
StatefulInteractiveElement, Styled, StyledImage as _, Window,
|
StatefulInteractiveElement, Styled, StyledImage as _, Window,
|
||||||
};
|
};
|
||||||
use markdown::mdast;
|
use markdown::mdast;
|
||||||
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
highlighter::SyntaxHighlighter,
|
highlighter::SyntaxHighlighter,
|
||||||
text::inline::{Inline, InlineState},
|
text::inline::{Inline, InlineState},
|
||||||
tooltip::Tooltip,
|
tooltip::Tooltip,
|
||||||
v_flex, ActiveTheme as _, Icon, IconName,
|
v_flex, ActiveTheme as _, Icon, IconName, StyledExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{utils::list_item_prefix, TextViewStyle};
|
use super::{utils::list_item_prefix, TextViewStyle};
|
||||||
|
|
@ -318,16 +318,19 @@ impl CodeBlock {
|
||||||
text
|
text
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, mb: Rems, _: &mut Window, cx: &mut App) -> AnyElement {
|
fn render(&self, node_cx: &NodeContext, _: &mut Window, cx: &mut App) -> AnyElement {
|
||||||
|
let style = &node_cx.style;
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.id("codeblock")
|
.id("codeblock")
|
||||||
.mb(mb)
|
.mb(style.paragraph_gap)
|
||||||
.p_3()
|
.p_3()
|
||||||
.rounded(cx.theme().radius)
|
.rounded(cx.theme().radius)
|
||||||
.bg(cx.theme().accent)
|
.bg(cx.theme().accent)
|
||||||
.font_family("Menlo, Monaco, Consolas, monospace")
|
.font_family("Menlo, Monaco, Consolas, monospace")
|
||||||
.text_size(rems(0.875))
|
.text_size(rems(0.875))
|
||||||
.relative()
|
.relative()
|
||||||
|
.refine_style(&style.code_block)
|
||||||
.child(Inline::new(
|
.child(Inline::new(
|
||||||
"code",
|
"code",
|
||||||
self.state.clone(),
|
self.state.clone(),
|
||||||
|
|
@ -927,7 +930,7 @@ impl Node {
|
||||||
items
|
items
|
||||||
})
|
})
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
Node::CodeBlock(code_block) => code_block.render(mb, window, cx),
|
Node::CodeBlock(code_block) => code_block.render(node_cx, window, cx),
|
||||||
Node::Table { .. } => Self::render_table(&self, node_cx, window, cx).into_any_element(),
|
Node::Table { .. } => Self::render_table(&self, node_cx, window, cx).into_any_element(),
|
||||||
Node::Divider => div()
|
Node::Divider => div()
|
||||||
.id("divider")
|
.id("divider")
|
||||||
|
|
|
||||||
67
crates/ui/src/text/style.rs
Normal file
67
crates/ui/src/text/style.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
use std::{rc::Rc, sync::Arc};
|
||||||
|
|
||||||
|
use gpui::{px, rems, Pixels, Rems, StyleRefinement};
|
||||||
|
|
||||||
|
use crate::highlighter::HighlightTheme;
|
||||||
|
|
||||||
|
/// TextViewStyle used to customize the style for [`TextView`].
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TextViewStyle {
|
||||||
|
/// Gap of each paragraphs, default is 1 rem.
|
||||||
|
pub paragraph_gap: Rems,
|
||||||
|
/// Base font size for headings, default is 14px.
|
||||||
|
pub heading_base_font_size: Pixels,
|
||||||
|
/// Function to calculate heading font size based on heading level (1-6).
|
||||||
|
///
|
||||||
|
/// The first parameter is the heading level (1-6), the second parameter is the base font size.
|
||||||
|
/// The second parameter is the base font size.
|
||||||
|
pub heading_font_size: Option<Rc<dyn Fn(u8, Pixels) -> Pixels + 'static>>,
|
||||||
|
/// Highlight theme for code blocks. Default: [`HighlightTheme::default_light()`]
|
||||||
|
pub highlight_theme: Arc<HighlightTheme>,
|
||||||
|
/// The style refinement for code blocks.
|
||||||
|
pub code_block: StyleRefinement,
|
||||||
|
pub is_dark: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for TextViewStyle {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.paragraph_gap == other.paragraph_gap
|
||||||
|
&& self.heading_base_font_size == other.heading_base_font_size
|
||||||
|
&& self.highlight_theme == other.highlight_theme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TextViewStyle {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
paragraph_gap: rems(1.),
|
||||||
|
heading_base_font_size: px(14.),
|
||||||
|
heading_font_size: None,
|
||||||
|
highlight_theme: HighlightTheme::default_light().clone(),
|
||||||
|
code_block: StyleRefinement::default(),
|
||||||
|
is_dark: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextViewStyle {
|
||||||
|
/// Set paragraph gap, default is 1 rem.
|
||||||
|
pub fn paragraph_gap(mut self, gap: Rems) -> Self {
|
||||||
|
self.paragraph_gap = gap;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn heading_font_size<F>(mut self, f: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(u8, Pixels) -> Pixels + 'static,
|
||||||
|
{
|
||||||
|
self.heading_font_size = Some(Rc::new(f));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set style for code blocks.
|
||||||
|
pub fn code_block(mut self, style: StyleRefinement) -> Self {
|
||||||
|
self.code_block = style;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,20 @@
|
||||||
use std::{rc::Rc, sync::Arc, time::Instant};
|
use std::{rc::Rc, time::Instant};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, px, rems, AnyElement, App, Bounds, ClipboardItem, Element, ElementId, Entity, FocusHandle,
|
div, AnyElement, App, Bounds, ClipboardItem, Element, ElementId, Entity, FocusHandle,
|
||||||
GlobalElementId, InspectorElementId, InteractiveElement, IntoElement, KeyBinding, LayoutId,
|
GlobalElementId, InspectorElementId, InteractiveElement, IntoElement, KeyBinding, LayoutId,
|
||||||
MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Rems, RenderOnce,
|
MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, RenderOnce,
|
||||||
SharedString, Size, Window,
|
SharedString, Size, Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::format::{html::HtmlElement, markdown::MarkdownElement};
|
use super::format::{html::HtmlElement, markdown::MarkdownElement};
|
||||||
use crate::{
|
use crate::{
|
||||||
global_state::GlobalState,
|
global_state::GlobalState,
|
||||||
highlighter::HighlightTheme,
|
|
||||||
input::{self},
|
input::{self},
|
||||||
text::node::{self, NodeContext},
|
text::{
|
||||||
|
node::{self, NodeContext},
|
||||||
|
TextViewStyle,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const CONTEXT: &'static str = "TextView";
|
const CONTEXT: &'static str = "TextView";
|
||||||
|
|
@ -270,59 +272,6 @@ impl RenderOnce for Text {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TextViewStyle used to customize the style for [`TextView`].
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TextViewStyle {
|
|
||||||
/// Gap of each paragraphs, default is 1 rem.
|
|
||||||
pub paragraph_gap: Rems,
|
|
||||||
/// Base font size for headings, default is 14px.
|
|
||||||
pub heading_base_font_size: Pixels,
|
|
||||||
/// Function to calculate heading font size based on heading level (1-6).
|
|
||||||
///
|
|
||||||
/// The first parameter is the heading level (1-6), the second parameter is the base font size.
|
|
||||||
/// The second parameter is the base font size.
|
|
||||||
pub heading_font_size: Option<Rc<dyn Fn(u8, Pixels) -> Pixels + 'static>>,
|
|
||||||
/// Highlight theme for code blocks. Default: [`HighlightTheme::default_light()`]
|
|
||||||
pub highlight_theme: Arc<HighlightTheme>,
|
|
||||||
pub is_dark: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for TextViewStyle {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.paragraph_gap == other.paragraph_gap
|
|
||||||
&& self.heading_base_font_size == other.heading_base_font_size
|
|
||||||
&& self.highlight_theme == other.highlight_theme
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TextViewStyle {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
paragraph_gap: rems(1.),
|
|
||||||
heading_base_font_size: px(14.),
|
|
||||||
heading_font_size: None,
|
|
||||||
highlight_theme: HighlightTheme::default_light().clone(),
|
|
||||||
is_dark: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TextViewStyle {
|
|
||||||
/// Set paragraph gap, default is 1 rem.
|
|
||||||
pub fn paragraph_gap(mut self, gap: Rems) -> Self {
|
|
||||||
self.paragraph_gap = gap;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn heading_font_size<F>(mut self, f: F) -> Self
|
|
||||||
where
|
|
||||||
F: Fn(u8, Pixels) -> Pixels + 'static,
|
|
||||||
{
|
|
||||||
self.heading_font_size = Some(Rc::new(f));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TextView {
|
impl TextView {
|
||||||
/// Create a new markdown text view.
|
/// Create a new markdown text view.
|
||||||
pub fn markdown(
|
pub fn markdown(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue