mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-26 10:40:54 +00:00
Provide editor styling information separately from editor settings
* Since regular editors' font sizes and families are controlled by the settings and not the theme, don't store a dummy text style in the theme. Instead, only store a font color, and synthesize the text style for regular editors using both the theme and the settings. * Style single-line and auto-height editors (now called "field editors") using a single function that takes the entire theme and selects a relevant sub-object. Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
39ebaebd83
commit
47b654063e
18 changed files with 377 additions and 556 deletions
|
@ -2,7 +2,7 @@ use client::{
|
|||
channel::{Channel, ChannelEvent, ChannelList, ChannelMessage},
|
||||
Client,
|
||||
};
|
||||
use editor::{Editor, EditorSettings};
|
||||
use editor::Editor;
|
||||
use gpui::{
|
||||
action,
|
||||
elements::*,
|
||||
|
@ -16,7 +16,7 @@ use postage::{prelude::Stream, watch};
|
|||
use std::sync::Arc;
|
||||
use time::{OffsetDateTime, UtcOffset};
|
||||
use util::{ResultExt, TryFutureExt};
|
||||
use workspace::Settings;
|
||||
use workspace::{settings::SoftWrap, Settings};
|
||||
|
||||
const MESSAGE_LOADING_THRESHOLD: usize = 50;
|
||||
|
||||
|
@ -52,21 +52,14 @@ impl ChatPanel {
|
|||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let input_editor = cx.add_view(|cx| {
|
||||
Editor::auto_height(
|
||||
let mut editor = Editor::auto_height(
|
||||
4,
|
||||
{
|
||||
let settings = settings.clone();
|
||||
Arc::new(move |_| {
|
||||
let settings = settings.borrow();
|
||||
EditorSettings {
|
||||
tab_size: settings.tab_size,
|
||||
style: settings.theme.chat_panel.input_editor.as_editor(),
|
||||
soft_wrap: editor::SoftWrap::EditorWidth,
|
||||
}
|
||||
})
|
||||
},
|
||||
settings.clone(),
|
||||
Some(|theme| theme.chat_panel.input_editor.clone()),
|
||||
cx,
|
||||
)
|
||||
);
|
||||
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
|
||||
editor
|
||||
});
|
||||
let channel_select = cx.add_view(|cx| {
|
||||
let channel_list = channel_list.clone();
|
||||
|
|
|
@ -7,7 +7,7 @@ use editor::{
|
|||
display_map::{BlockDisposition, BlockId, BlockProperties, RenderBlock},
|
||||
highlight_diagnostic_message,
|
||||
items::BufferItemHandle,
|
||||
Autoscroll, BuildSettings, Editor, ExcerptId, MultiBuffer, ToOffset,
|
||||
Autoscroll, Editor, ExcerptId, MultiBuffer, ToOffset,
|
||||
};
|
||||
use gpui::{
|
||||
action, elements::*, fonts::TextStyle, keymap::Binding, AnyViewHandle, AppContext, Entity,
|
||||
|
@ -62,7 +62,6 @@ struct ProjectDiagnosticsEditor {
|
|||
excerpts: ModelHandle<MultiBuffer>,
|
||||
path_states: Vec<PathState>,
|
||||
paths_to_update: BTreeSet<ProjectPath>,
|
||||
build_settings: BuildSettings,
|
||||
settings: watch::Receiver<workspace::Settings>,
|
||||
}
|
||||
|
||||
|
@ -142,12 +141,11 @@ impl ProjectDiagnosticsEditor {
|
|||
.detach();
|
||||
|
||||
let excerpts = cx.add_model(|cx| MultiBuffer::new(project.read(cx).replica_id()));
|
||||
let build_settings = editor::settings_builder(excerpts.downgrade(), settings.clone());
|
||||
let editor = cx.add_view(|cx| {
|
||||
let mut editor = Editor::for_buffer(
|
||||
excerpts.clone(),
|
||||
build_settings.clone(),
|
||||
Some(project.clone()),
|
||||
settings.clone(),
|
||||
cx,
|
||||
);
|
||||
editor.set_vertical_scroll_margin(5, cx);
|
||||
|
@ -164,7 +162,6 @@ impl ProjectDiagnosticsEditor {
|
|||
workspace,
|
||||
excerpts,
|
||||
editor,
|
||||
build_settings,
|
||||
settings,
|
||||
path_states: Default::default(),
|
||||
paths_to_update,
|
||||
|
@ -360,7 +357,7 @@ impl ProjectDiagnosticsEditor {
|
|||
height: 2,
|
||||
render: diagnostic_header_renderer(
|
||||
primary,
|
||||
self.build_settings.clone(),
|
||||
self.settings.clone(),
|
||||
),
|
||||
disposition: BlockDisposition::Above,
|
||||
});
|
||||
|
@ -382,7 +379,7 @@ impl ProjectDiagnosticsEditor {
|
|||
render: diagnostic_block_renderer(
|
||||
diagnostic,
|
||||
true,
|
||||
self.build_settings.clone(),
|
||||
self.settings.clone(),
|
||||
),
|
||||
disposition: BlockDisposition::Below,
|
||||
});
|
||||
|
@ -644,20 +641,21 @@ impl workspace::ItemView for ProjectDiagnosticsEditor {
|
|||
|
||||
fn diagnostic_header_renderer(
|
||||
diagnostic: Diagnostic,
|
||||
build_settings: BuildSettings,
|
||||
settings: watch::Receiver<workspace::Settings>,
|
||||
) -> RenderBlock {
|
||||
let (message, highlights) = highlight_diagnostic_message(&diagnostic.message);
|
||||
Arc::new(move |cx| {
|
||||
let settings = build_settings(cx);
|
||||
let style = &settings.style.diagnostic_header;
|
||||
let font_size = (style.text_scale_factor * settings.style.text.font_size).round();
|
||||
let settings = settings.borrow();
|
||||
let theme = &settings.theme.editor;
|
||||
let style = &theme.diagnostic_header;
|
||||
let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
|
||||
let icon_width = cx.em_width * style.icon_width_factor;
|
||||
let icon = if diagnostic.severity == DiagnosticSeverity::ERROR {
|
||||
Svg::new("icons/diagnostic-error-10.svg")
|
||||
.with_color(settings.style.error_diagnostic.message.text.color)
|
||||
.with_color(theme.error_diagnostic.message.text.color)
|
||||
} else {
|
||||
Svg::new("icons/diagnostic-warning-10.svg")
|
||||
.with_color(settings.style.warning_diagnostic.message.text.color)
|
||||
.with_color(theme.warning_diagnostic.message.text.color)
|
||||
};
|
||||
|
||||
Flex::row()
|
||||
|
|
|
@ -14,6 +14,7 @@ test-support = [
|
|||
"gpui/test-support",
|
||||
"project/test-support",
|
||||
"util/test-support",
|
||||
"workspace/test-support",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
|
@ -50,6 +51,7 @@ lsp = { path = "../lsp", features = ["test-support"] }
|
|||
gpui = { path = "../gpui", features = ["test-support"] }
|
||||
util = { path = "../util", features = ["test-support"] }
|
||||
project = { path = "../project", features = ["test-support"] }
|
||||
workspace = { path = "../workspace", features = ["test-support"] }
|
||||
ctor = "0.1"
|
||||
env_logger = "0.8"
|
||||
rand = "0.8"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,9 @@
|
|||
use super::{
|
||||
display_map::{BlockContext, ToDisplayPoint},
|
||||
Anchor, DisplayPoint, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, Input,
|
||||
Scroll, Select, SelectPhase, SoftWrap, ToPoint, MAX_LINE_LEN,
|
||||
Anchor, DisplayPoint, Editor, EditorMode, EditorSnapshot, Input, Scroll, Select, SelectPhase,
|
||||
SoftWrap, ToPoint, MAX_LINE_LEN,
|
||||
};
|
||||
use crate::display_map::TransformBlock;
|
||||
use crate::{display_map::TransformBlock, EditorStyle};
|
||||
use clock::ReplicaId;
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use gpui::{
|
||||
|
@ -31,12 +31,12 @@ use std::{
|
|||
|
||||
pub struct EditorElement {
|
||||
view: WeakViewHandle<Editor>,
|
||||
settings: EditorSettings,
|
||||
style: EditorStyle,
|
||||
}
|
||||
|
||||
impl EditorElement {
|
||||
pub fn new(view: WeakViewHandle<Editor>, settings: EditorSettings) -> Self {
|
||||
Self { view, settings }
|
||||
pub fn new(view: WeakViewHandle<Editor>, style: EditorStyle) -> Self {
|
||||
Self { view, style }
|
||||
}
|
||||
|
||||
fn view<'a>(&self, cx: &'a AppContext) -> &'a Editor {
|
||||
|
@ -209,16 +209,15 @@ impl EditorElement {
|
|||
let bounds = gutter_bounds.union_rect(text_bounds);
|
||||
let scroll_top = layout.snapshot.scroll_position().y() * layout.line_height;
|
||||
let editor = self.view(cx.app);
|
||||
let style = &self.settings.style;
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: gutter_bounds,
|
||||
background: Some(style.gutter_background),
|
||||
background: Some(self.style.gutter_background),
|
||||
border: Border::new(0., Color::transparent_black()),
|
||||
corner_radius: 0.,
|
||||
});
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: text_bounds,
|
||||
background: Some(style.background),
|
||||
background: Some(self.style.background),
|
||||
border: Border::new(0., Color::transparent_black()),
|
||||
corner_radius: 0.,
|
||||
});
|
||||
|
@ -245,7 +244,7 @@ impl EditorElement {
|
|||
);
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: RectF::new(origin, size),
|
||||
background: Some(style.active_line_background),
|
||||
background: Some(self.style.active_line_background),
|
||||
border: Border::default(),
|
||||
corner_radius: 0.,
|
||||
});
|
||||
|
@ -264,7 +263,7 @@ impl EditorElement {
|
|||
);
|
||||
cx.scene.push_quad(Quad {
|
||||
bounds: RectF::new(origin, size),
|
||||
background: Some(style.highlighted_line_background),
|
||||
background: Some(self.style.highlighted_line_background),
|
||||
border: Border::default(),
|
||||
corner_radius: 0.,
|
||||
});
|
||||
|
@ -308,7 +307,7 @@ impl EditorElement {
|
|||
cx: &mut PaintContext,
|
||||
) {
|
||||
let view = self.view(cx.app);
|
||||
let style = &self.settings.style;
|
||||
let style = &self.style;
|
||||
let local_replica_id = view.replica_id(cx);
|
||||
let scroll_position = layout.snapshot.scroll_position();
|
||||
let start_row = scroll_position.y() as u32;
|
||||
|
@ -498,7 +497,7 @@ impl EditorElement {
|
|||
|
||||
fn max_line_number_width(&self, snapshot: &EditorSnapshot, cx: &LayoutContext) -> f32 {
|
||||
let digit_count = (snapshot.max_buffer_row() as f32).log10().floor() as usize + 1;
|
||||
let style = &self.settings.style;
|
||||
let style = &self.style;
|
||||
|
||||
cx.text_layout_cache
|
||||
.layout_str(
|
||||
|
@ -523,7 +522,7 @@ impl EditorElement {
|
|||
snapshot: &EditorSnapshot,
|
||||
cx: &LayoutContext,
|
||||
) -> Vec<Option<text_layout::Line>> {
|
||||
let style = &self.settings.style;
|
||||
let style = &self.style;
|
||||
let include_line_numbers = snapshot.mode == EditorMode::Full;
|
||||
let mut line_number_layouts = Vec::with_capacity(rows.len());
|
||||
let mut line_number = String::new();
|
||||
|
@ -576,7 +575,11 @@ impl EditorElement {
|
|||
|
||||
// When the editor is empty and unfocused, then show the placeholder.
|
||||
if snapshot.is_empty() && !snapshot.is_focused() {
|
||||
let placeholder_style = self.settings.style.placeholder_text();
|
||||
let placeholder_style = self
|
||||
.style
|
||||
.placeholder_text
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| &self.style.text);
|
||||
let placeholder_text = snapshot.placeholder_text();
|
||||
let placeholder_lines = placeholder_text
|
||||
.as_ref()
|
||||
|
@ -601,7 +604,7 @@ impl EditorElement {
|
|||
})
|
||||
.collect();
|
||||
} else {
|
||||
let style = &self.settings.style;
|
||||
let style = &self.style;
|
||||
let chunks = snapshot.chunks(rows.clone(), true).map(|chunk| {
|
||||
let highlight_style = chunk
|
||||
.highlight_id
|
||||
|
@ -688,10 +691,9 @@ impl EditorElement {
|
|||
..
|
||||
} => {
|
||||
if *starts_new_buffer {
|
||||
let style = &self.settings.style.diagnostic_path_header;
|
||||
let font_size = (style.text_scale_factor
|
||||
* self.settings.style.text.font_size)
|
||||
.round();
|
||||
let style = &self.style.diagnostic_path_header;
|
||||
let font_size =
|
||||
(style.text_scale_factor * self.style.text.font_size).round();
|
||||
|
||||
let mut filename = None;
|
||||
let mut parent_path = None;
|
||||
|
@ -729,7 +731,7 @@ impl EditorElement {
|
|||
.expanded()
|
||||
.named("path header block")
|
||||
} else {
|
||||
let text_style = self.settings.style.text.clone();
|
||||
let text_style = self.style.text.clone();
|
||||
Label::new("…".to_string(), text_style)
|
||||
.contained()
|
||||
.with_padding_left(gutter_padding + scroll_x * em_width)
|
||||
|
@ -766,7 +768,7 @@ impl Element for EditorElement {
|
|||
}
|
||||
|
||||
let snapshot = self.snapshot(cx.app);
|
||||
let style = self.settings.style.clone();
|
||||
let style = self.style.clone();
|
||||
let line_height = style.text.line_height(cx.font_cache);
|
||||
|
||||
let gutter_padding;
|
||||
|
@ -786,12 +788,15 @@ impl Element for EditorElement {
|
|||
let em_width = style.text.em_width(cx.font_cache);
|
||||
let em_advance = style.text.em_advance(cx.font_cache);
|
||||
let overscroll = vec2f(em_width, 0.);
|
||||
let wrap_width = match self.settings.soft_wrap {
|
||||
SoftWrap::None => None,
|
||||
SoftWrap::EditorWidth => Some(text_width - gutter_margin - overscroll.x() - em_width),
|
||||
SoftWrap::Column(column) => Some(column as f32 * em_advance),
|
||||
};
|
||||
let snapshot = self.update_view(cx.app, |view, cx| {
|
||||
let wrap_width = match view.soft_wrap_mode(cx) {
|
||||
SoftWrap::None => None,
|
||||
SoftWrap::EditorWidth => {
|
||||
Some(text_width - gutter_margin - overscroll.x() - em_width)
|
||||
}
|
||||
SoftWrap::Column(column) => Some(column as f32 * em_advance),
|
||||
};
|
||||
|
||||
if view.set_wrap_width(wrap_width, cx) {
|
||||
view.snapshot(cx)
|
||||
} else {
|
||||
|
@ -907,7 +912,7 @@ impl Element for EditorElement {
|
|||
}
|
||||
}
|
||||
|
||||
let style = self.settings.style.clone();
|
||||
let style = self.style.clone();
|
||||
let longest_line_width = layout_line(
|
||||
snapshot.longest_row(),
|
||||
&snapshot,
|
||||
|
@ -951,12 +956,14 @@ impl Element for EditorElement {
|
|||
.to_display_point(&snapshot);
|
||||
|
||||
if (start_row..end_row).contains(&newest_selection_head.row()) {
|
||||
let style = view.style(cx);
|
||||
if view.context_menu_visible() {
|
||||
context_menu = view.render_context_menu(newest_selection_head, cx);
|
||||
context_menu =
|
||||
view.render_context_menu(newest_selection_head, style.clone(), cx);
|
||||
}
|
||||
|
||||
code_actions_indicator = view
|
||||
.render_code_actions_indicator(cx)
|
||||
.render_code_actions_indicator(&style, cx)
|
||||
.map(|indicator| (newest_selection_head.row(), indicator));
|
||||
}
|
||||
});
|
||||
|
@ -1370,26 +1377,19 @@ fn scale_horizontal_mouse_autoscroll_delta(delta: f32) -> f32 {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{Editor, EditorSettings, MultiBuffer};
|
||||
use std::sync::Arc;
|
||||
use crate::{Editor, MultiBuffer};
|
||||
use postage::watch;
|
||||
use util::test::sample_text;
|
||||
use workspace::Settings;
|
||||
|
||||
#[gpui::test]
|
||||
fn test_layout_line_numbers(cx: &mut gpui::MutableAppContext) {
|
||||
let settings = EditorSettings::test(cx);
|
||||
let settings = watch::channel_with(Settings::test(cx));
|
||||
let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
|
||||
let (window_id, editor) = cx.add_window(Default::default(), |cx| {
|
||||
Editor::for_buffer(
|
||||
buffer,
|
||||
{
|
||||
let settings = settings.clone();
|
||||
Arc::new(move |_| settings.clone())
|
||||
},
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
Editor::new(EditorMode::Full, buffer, None, settings.1, None, cx)
|
||||
});
|
||||
let element = EditorElement::new(editor.downgrade(), settings);
|
||||
let element = EditorElement::new(editor.downgrade(), editor.read(cx).style(cx));
|
||||
|
||||
let layouts = editor.update(cx, |editor, cx| {
|
||||
let snapshot = editor.snapshot(cx);
|
||||
|
|
|
@ -56,12 +56,11 @@ impl ItemHandle for BufferItemHandle {
|
|||
cx: &mut MutableAppContext,
|
||||
) -> Box<dyn ItemViewHandle> {
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(self.0.clone(), cx));
|
||||
let weak_buffer = buffer.downgrade();
|
||||
Box::new(cx.add_view(window_id, |cx| {
|
||||
let mut editor = Editor::for_buffer(
|
||||
buffer,
|
||||
crate::settings_builder(weak_buffer, workspace.settings()),
|
||||
Some(workspace.project().clone()),
|
||||
workspace.settings(),
|
||||
cx,
|
||||
);
|
||||
editor.nav_history = Some(ItemNavHistory::new(nav_history, &cx.handle()));
|
||||
|
@ -101,12 +100,11 @@ impl ItemHandle for MultiBufferItemHandle {
|
|||
nav_history: Rc<RefCell<NavHistory>>,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Box<dyn ItemViewHandle> {
|
||||
let weak_buffer = self.0.downgrade();
|
||||
Box::new(cx.add_view(window_id, |cx| {
|
||||
let mut editor = Editor::for_buffer(
|
||||
self.0.clone(),
|
||||
crate::settings_builder(weak_buffer, workspace.settings()),
|
||||
Some(workspace.project().clone()),
|
||||
workspace.settings(),
|
||||
cx,
|
||||
);
|
||||
editor.nav_history = Some(ItemNavHistory::new(nav_history, &cx.handle()));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use editor::{Editor, EditorSettings};
|
||||
use editor::Editor;
|
||||
use fuzzy::PathMatch;
|
||||
use gpui::{
|
||||
action,
|
||||
|
@ -266,17 +266,8 @@ impl FileFinder {
|
|||
|
||||
let query_editor = cx.add_view(|cx| {
|
||||
Editor::single_line(
|
||||
{
|
||||
let settings = settings.clone();
|
||||
Arc::new(move |_| {
|
||||
let settings = settings.borrow();
|
||||
EditorSettings {
|
||||
style: settings.theme.selector.input_editor.as_editor(),
|
||||
tab_size: settings.tab_size,
|
||||
soft_wrap: editor::SoftWrap::None,
|
||||
}
|
||||
})
|
||||
},
|
||||
settings.clone(),
|
||||
Some(|theme| theme.selector.input_editor.clone()),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
|
|
@ -2,8 +2,7 @@ use aho_corasick::AhoCorasickBuilder;
|
|||
use anyhow::Result;
|
||||
use collections::HashMap;
|
||||
use editor::{
|
||||
char_kind, display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor, EditorSettings,
|
||||
MultiBufferSnapshot,
|
||||
char_kind, display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor, MultiBufferSnapshot,
|
||||
};
|
||||
use gpui::{
|
||||
action, elements::*, keymap::Binding, platform::CursorStyle, Entity, MutableAppContext,
|
||||
|
@ -15,7 +14,6 @@ use smol::future::yield_now;
|
|||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
ops::Range,
|
||||
sync::Arc,
|
||||
};
|
||||
use workspace::{ItemViewHandle, Pane, Settings, Toolbar, Workspace};
|
||||
|
||||
|
@ -179,17 +177,8 @@ impl FindBar {
|
|||
let query_editor = cx.add_view(|cx| {
|
||||
Editor::auto_height(
|
||||
2,
|
||||
{
|
||||
let settings = settings.clone();
|
||||
Arc::new(move |_| {
|
||||
let settings = settings.borrow();
|
||||
EditorSettings {
|
||||
style: settings.theme.find.editor.input.as_editor(),
|
||||
tab_size: settings.tab_size,
|
||||
soft_wrap: editor::SoftWrap::None,
|
||||
}
|
||||
})
|
||||
},
|
||||
settings.clone(),
|
||||
Some(|theme| theme.find.editor.input.clone()),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
@ -645,7 +634,7 @@ async fn regex_search(
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use editor::{DisplayPoint, Editor, EditorSettings, MultiBuffer};
|
||||
use editor::{DisplayPoint, Editor, MultiBuffer};
|
||||
use gpui::{color::Color, TestAppContext};
|
||||
use std::sync::Arc;
|
||||
use unindent::Unindent as _;
|
||||
|
@ -656,6 +645,7 @@ mod tests {
|
|||
let mut theme = gpui::fonts::with_font_cache(fonts.clone(), || theme::Theme::default());
|
||||
theme.find.match_background = Color::red();
|
||||
let settings = Settings::new("Courier", &fonts, Arc::new(theme)).unwrap();
|
||||
let settings = watch::channel_with(settings).1;
|
||||
|
||||
let buffer = cx.update(|cx| {
|
||||
MultiBuffer::build_simple(
|
||||
|
@ -670,11 +660,11 @@ mod tests {
|
|||
)
|
||||
});
|
||||
let editor = cx.add_view(Default::default(), |cx| {
|
||||
Editor::new(buffer.clone(), Arc::new(EditorSettings::test), None, cx)
|
||||
Editor::for_buffer(buffer.clone(), None, settings.clone(), cx)
|
||||
});
|
||||
|
||||
let find_bar = cx.add_view(Default::default(), |cx| {
|
||||
let mut find_bar = FindBar::new(watch::channel_with(settings).1, cx);
|
||||
let mut find_bar = FindBar::new(settings, cx);
|
||||
find_bar.active_item_changed(Some(Box::new(editor.clone())), cx);
|
||||
find_bar
|
||||
});
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor, EditorSettings};
|
||||
use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor};
|
||||
use gpui::{
|
||||
action, elements::*, geometry::vector::Vector2F, keymap::Binding, Axis, Entity,
|
||||
MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
|
||||
};
|
||||
use postage::watch;
|
||||
use std::sync::Arc;
|
||||
use text::{Bias, Point};
|
||||
use workspace::{Settings, Workspace};
|
||||
|
||||
|
@ -42,17 +41,8 @@ impl GoToLine {
|
|||
) -> Self {
|
||||
let line_editor = cx.add_view(|cx| {
|
||||
Editor::single_line(
|
||||
{
|
||||
let settings = settings.clone();
|
||||
Arc::new(move |_| {
|
||||
let settings = settings.borrow();
|
||||
EditorSettings {
|
||||
tab_size: settings.tab_size,
|
||||
style: settings.theme.selector.input_editor.as_editor(),
|
||||
soft_wrap: editor::SoftWrap::None,
|
||||
}
|
||||
})
|
||||
},
|
||||
settings.clone(),
|
||||
Some(|theme| theme.selector.input_editor.clone()),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use editor::{
|
||||
combine_syntax_and_fuzzy_match_highlights, display_map::ToDisplayPoint, Anchor, AnchorRangeExt,
|
||||
Autoscroll, DisplayPoint, Editor, EditorSettings, ToPoint,
|
||||
Autoscroll, DisplayPoint, Editor, ToPoint,
|
||||
};
|
||||
use fuzzy::StringMatch;
|
||||
use gpui::{
|
||||
|
@ -14,10 +14,7 @@ use gpui::{
|
|||
use language::Outline;
|
||||
use ordered_float::OrderedFloat;
|
||||
use postage::watch;
|
||||
use std::{
|
||||
cmp::{self, Reverse},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::cmp::{self, Reverse};
|
||||
use workspace::{
|
||||
menu::{Confirm, SelectFirst, SelectLast, SelectNext, SelectPrev},
|
||||
Settings, Workspace,
|
||||
|
@ -107,17 +104,8 @@ impl OutlineView {
|
|||
) -> Self {
|
||||
let query_editor = cx.add_view(|cx| {
|
||||
Editor::single_line(
|
||||
{
|
||||
let settings = settings.clone();
|
||||
Arc::new(move |_| {
|
||||
let settings = settings.borrow();
|
||||
EditorSettings {
|
||||
style: settings.theme.selector.input_editor.as_editor(),
|
||||
tab_size: settings.tab_size,
|
||||
soft_wrap: editor::SoftWrap::None,
|
||||
}
|
||||
})
|
||||
},
|
||||
settings.clone(),
|
||||
Some(|theme| theme.selector.input_editor.clone()),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use editor::{
|
||||
combine_syntax_and_fuzzy_match_highlights, items::BufferItemHandle, styled_runs_for_code_label,
|
||||
Autoscroll, Bias, Editor, EditorSettings,
|
||||
Autoscroll, Bias, Editor,
|
||||
};
|
||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||
use gpui::{
|
||||
|
@ -16,7 +16,6 @@ use project::{Project, Symbol};
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
cmp::{self, Reverse},
|
||||
sync::Arc,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use workspace::{
|
||||
|
@ -105,17 +104,8 @@ impl ProjectSymbolsView {
|
|||
) -> Self {
|
||||
let query_editor = cx.add_view(|cx| {
|
||||
Editor::single_line(
|
||||
{
|
||||
let settings = settings.clone();
|
||||
Arc::new(move |_| {
|
||||
let settings = settings.borrow();
|
||||
EditorSettings {
|
||||
style: settings.theme.selector.input_editor.as_editor(),
|
||||
tab_size: settings.tab_size,
|
||||
soft_wrap: editor::SoftWrap::None,
|
||||
}
|
||||
})
|
||||
},
|
||||
settings.clone(),
|
||||
Some(|theme| theme.selector.input_editor.clone()),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
|
|
@ -1177,8 +1177,8 @@ mod tests {
|
|||
EstablishConnectionError, UserStore,
|
||||
},
|
||||
editor::{
|
||||
self, ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, EditorSettings,
|
||||
Input, MultiBuffer, Redo, Rename, ToOffset, ToggleCodeActions, Undo,
|
||||
self, ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, Input, MultiBuffer,
|
||||
Redo, Rename, ToOffset, ToggleCodeActions, Undo,
|
||||
},
|
||||
fs::{FakeFs, Fs as _},
|
||||
language::{
|
||||
|
@ -1187,7 +1187,7 @@ mod tests {
|
|||
},
|
||||
lsp,
|
||||
project::{DiagnosticSummary, Project, ProjectPath},
|
||||
workspace::{Workspace, WorkspaceParams},
|
||||
workspace::{Settings, Workspace, WorkspaceParams},
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1298,7 +1298,12 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let editor_b = cx_b.add_view(window_b, |cx| {
|
||||
Editor::for_buffer(buffer_b, Arc::new(|cx| EditorSettings::test(cx)), None, cx)
|
||||
Editor::for_buffer(
|
||||
buffer_b,
|
||||
None,
|
||||
watch::channel_with(Settings::test(cx)).1,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
// TODO
|
||||
|
@ -2330,8 +2335,8 @@ mod tests {
|
|||
let editor_b = cx_b.add_view(window_b, |cx| {
|
||||
Editor::for_buffer(
|
||||
cx.add_model(|cx| MultiBuffer::singleton(buffer_b.clone(), cx)),
|
||||
Arc::new(|cx| EditorSettings::test(cx)),
|
||||
Some(project_b.clone()),
|
||||
watch::channel_with(Settings::test(cx)).1,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
|
|
@ -23,7 +23,7 @@ pub struct Theme {
|
|||
pub contacts_panel: ContactsPanel,
|
||||
pub project_panel: ProjectPanel,
|
||||
pub selector: Selector,
|
||||
pub editor: EditorStyle,
|
||||
pub editor: Editor,
|
||||
pub find: Find,
|
||||
pub project_diagnostics: ProjectDiagnostics,
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ pub struct Find {
|
|||
#[derive(Clone, Deserialize, Default)]
|
||||
pub struct FindEditor {
|
||||
#[serde(flatten)]
|
||||
pub input: InputEditorStyle,
|
||||
pub input: FieldEditor,
|
||||
pub max_width: f32,
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ pub struct ChatPanel {
|
|||
pub message: ChatMessage,
|
||||
pub pending_message: ChatMessage,
|
||||
pub channel_select: ChannelSelect,
|
||||
pub input_editor: InputEditorStyle,
|
||||
pub input_editor: FieldEditor,
|
||||
pub sign_in_prompt: TextStyle,
|
||||
pub hovered_sign_in_prompt: TextStyle,
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ pub struct Selector {
|
|||
#[serde(flatten)]
|
||||
pub container: ContainerStyle,
|
||||
pub empty: ContainedLabel,
|
||||
pub input_editor: InputEditorStyle,
|
||||
pub input_editor: FieldEditor,
|
||||
pub item: ContainedLabel,
|
||||
pub active_item: ContainedLabel,
|
||||
}
|
||||
|
@ -269,10 +269,9 @@ pub struct ProjectDiagnostics {
|
|||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Default)]
|
||||
pub struct EditorStyle {
|
||||
pub text: TextStyle,
|
||||
pub struct Editor {
|
||||
pub text_color: Color,
|
||||
#[serde(default)]
|
||||
pub placeholder_text: Option<TextStyle>,
|
||||
pub background: Color,
|
||||
pub selection: SelectionStyle,
|
||||
pub gutter_background: Color,
|
||||
|
@ -345,7 +344,7 @@ pub struct SelectionStyle {
|
|||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Default)]
|
||||
pub struct InputEditorStyle {
|
||||
pub struct FieldEditor {
|
||||
#[serde(flatten)]
|
||||
pub container: ContainerStyle,
|
||||
pub text: TextStyle,
|
||||
|
@ -354,11 +353,7 @@ pub struct InputEditorStyle {
|
|||
pub selection: SelectionStyle,
|
||||
}
|
||||
|
||||
impl EditorStyle {
|
||||
pub fn placeholder_text(&self) -> &TextStyle {
|
||||
self.placeholder_text.as_ref().unwrap_or(&self.text)
|
||||
}
|
||||
|
||||
impl Editor {
|
||||
pub fn replica_selection_style(&self, replica_id: u16) -> &SelectionStyle {
|
||||
let style_ix = replica_id as usize % (self.guest_selections.len() + 1);
|
||||
if style_ix == 0 {
|
||||
|
@ -369,72 +364,6 @@ impl EditorStyle {
|
|||
}
|
||||
}
|
||||
|
||||
impl InputEditorStyle {
|
||||
pub fn as_editor(&self) -> EditorStyle {
|
||||
let default_diagnostic_style = DiagnosticStyle {
|
||||
message: self.text.clone().into(),
|
||||
header: Default::default(),
|
||||
text_scale_factor: 1.,
|
||||
};
|
||||
EditorStyle {
|
||||
text: self.text.clone(),
|
||||
placeholder_text: self.placeholder_text.clone(),
|
||||
background: self
|
||||
.container
|
||||
.background_color
|
||||
.unwrap_or(Color::transparent_black()),
|
||||
selection: self.selection,
|
||||
gutter_background: Default::default(),
|
||||
gutter_padding_factor: Default::default(),
|
||||
active_line_background: Default::default(),
|
||||
highlighted_line_background: Default::default(),
|
||||
document_highlight_read_background: Default::default(),
|
||||
document_highlight_write_background: Default::default(),
|
||||
diff_background_deleted: Default::default(),
|
||||
diff_background_inserted: Default::default(),
|
||||
line_number: Default::default(),
|
||||
line_number_active: Default::default(),
|
||||
guest_selections: Default::default(),
|
||||
syntax: Default::default(),
|
||||
diagnostic_path_header: DiagnosticPathHeader {
|
||||
container: Default::default(),
|
||||
filename: ContainedText {
|
||||
container: Default::default(),
|
||||
text: self.text.clone(),
|
||||
},
|
||||
path: ContainedText {
|
||||
container: Default::default(),
|
||||
text: self.text.clone(),
|
||||
},
|
||||
text_scale_factor: 1.,
|
||||
},
|
||||
diagnostic_header: DiagnosticHeader {
|
||||
container: Default::default(),
|
||||
message: ContainedLabel {
|
||||
container: Default::default(),
|
||||
label: self.text.clone().into(),
|
||||
},
|
||||
code: ContainedText {
|
||||
container: Default::default(),
|
||||
text: self.text.clone(),
|
||||
},
|
||||
icon_width_factor: Default::default(),
|
||||
text_scale_factor: 1.,
|
||||
},
|
||||
error_diagnostic: default_diagnostic_style.clone(),
|
||||
invalid_error_diagnostic: default_diagnostic_style.clone(),
|
||||
warning_diagnostic: default_diagnostic_style.clone(),
|
||||
invalid_warning_diagnostic: default_diagnostic_style.clone(),
|
||||
information_diagnostic: default_diagnostic_style.clone(),
|
||||
invalid_information_diagnostic: default_diagnostic_style.clone(),
|
||||
hint_diagnostic: default_diagnostic_style.clone(),
|
||||
invalid_hint_diagnostic: default_diagnostic_style.clone(),
|
||||
autocomplete: Default::default(),
|
||||
code_actions_indicator: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SyntaxTheme {
|
||||
pub highlights: Vec<(String, HighlightStyle)>,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use editor::{Editor, EditorSettings};
|
||||
use editor::Editor;
|
||||
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
|
||||
use gpui::{
|
||||
action,
|
||||
|
@ -63,17 +63,8 @@ impl ThemeSelector {
|
|||
) -> Self {
|
||||
let query_editor = cx.add_view(|cx| {
|
||||
Editor::single_line(
|
||||
{
|
||||
let settings = settings.clone();
|
||||
Arc::new(move |_| {
|
||||
let settings = settings.borrow();
|
||||
EditorSettings {
|
||||
tab_size: settings.tab_size,
|
||||
style: settings.theme.selector.input_editor.as_editor(),
|
||||
soft_wrap: editor::SoftWrap::None,
|
||||
}
|
||||
})
|
||||
},
|
||||
settings.clone(),
|
||||
Some(|theme| theme.selector.input_editor.clone()),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
|
|
@ -72,4 +72,17 @@ impl Settings {
|
|||
.and_then(|settings| settings.preferred_line_length)
|
||||
.unwrap_or(self.preferred_line_length)
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn test(cx: &gpui::AppContext) -> Settings {
|
||||
Settings {
|
||||
buffer_font_family: cx.font_cache().load_family(&["Monaco"]).unwrap(),
|
||||
buffer_font_size: 14.,
|
||||
tab_size: 4,
|
||||
soft_wrap: SoftWrap::None,
|
||||
preferred_line_length: 80,
|
||||
overrides: Default::default(),
|
||||
theme: gpui::fonts::with_font_cache(cx.font_cache().clone(), || Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ background = "$state.hover"
|
|||
text = "$text.0"
|
||||
|
||||
[editor]
|
||||
text = "$text.1"
|
||||
text_color = "$text.1.color"
|
||||
background = "$surface.1"
|
||||
gutter_background = "$surface.1"
|
||||
gutter_padding_factor = 2.5
|
||||
|
@ -282,8 +282,8 @@ header.border = { width = 1, top = true, color = "$border.0" }
|
|||
text_scale_factor = 0.857
|
||||
|
||||
[editor.error_diagnostic.message]
|
||||
text = { extends = "$editor.text", size = 14, color = "$status.bad" }
|
||||
highlight_text = { extends = "$editor.text", size = 14, color = "$status.bad", weight = "bold" }
|
||||
text = { extends = "$text.1", size = 14, color = "$status.bad" }
|
||||
highlight_text = { extends = "$text.1", size = 14, color = "$status.bad", weight = "bold" }
|
||||
|
||||
[editor.warning_diagnostic]
|
||||
extends = "$editor.error_diagnostic"
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::{assets::Assets, build_window_options, build_workspace, AppState};
|
||||
use client::{test::FakeHttpClient, ChannelList, Client, UserStore};
|
||||
use gpui::{AssetSource, MutableAppContext};
|
||||
use gpui::MutableAppContext;
|
||||
use language::LanguageRegistry;
|
||||
use parking_lot::Mutex;
|
||||
use postage::watch;
|
||||
use project::fs::FakeFs;
|
||||
use std::sync::Arc;
|
||||
use theme::{Theme, ThemeRegistry, DEFAULT_THEME_NAME};
|
||||
use theme::ThemeRegistry;
|
||||
use workspace::Settings;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -20,7 +20,7 @@ fn init_logger() {
|
|||
pub fn test_app_state(cx: &mut MutableAppContext) -> Arc<AppState> {
|
||||
let mut path_openers = Vec::new();
|
||||
editor::init(cx, &mut path_openers);
|
||||
let (settings_tx, settings) = watch::channel_with(build_settings(cx));
|
||||
let (settings_tx, settings) = watch::channel_with(Settings::test(cx));
|
||||
let themes = ThemeRegistry::new(Assets, cx.font_cache().clone());
|
||||
let http = FakeHttpClient::with_404_response();
|
||||
let client = Client::new(http.clone());
|
||||
|
@ -48,27 +48,3 @@ pub fn test_app_state(cx: &mut MutableAppContext) -> Arc<AppState> {
|
|||
build_workspace: &build_workspace,
|
||||
})
|
||||
}
|
||||
|
||||
fn build_settings(cx: &gpui::AppContext) -> Settings {
|
||||
lazy_static::lazy_static! {
|
||||
static ref DEFAULT_THEME: parking_lot::Mutex<Option<Arc<Theme>>> = Default::default();
|
||||
static ref FONTS: Vec<Arc<Vec<u8>>> = vec![
|
||||
Assets.load("fonts/zed-sans/zed-sans-regular.ttf").unwrap().to_vec().into()
|
||||
];
|
||||
}
|
||||
|
||||
cx.platform().fonts().add_fonts(&FONTS).unwrap();
|
||||
|
||||
let mut theme_guard = DEFAULT_THEME.lock();
|
||||
let theme = if let Some(theme) = theme_guard.as_ref() {
|
||||
theme.clone()
|
||||
} else {
|
||||
let theme = ThemeRegistry::new(Assets, cx.font_cache().clone())
|
||||
.get(DEFAULT_THEME_NAME)
|
||||
.expect("failed to load default theme in tests");
|
||||
*theme_guard = Some(theme.clone());
|
||||
theme
|
||||
};
|
||||
|
||||
Settings::new("Zed Sans", cx.font_cache(), theme).unwrap()
|
||||
}
|
||||
|
|
|
@ -133,9 +133,11 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::assets::Assets;
|
||||
|
||||
use super::*;
|
||||
use editor::{DisplayPoint, Editor};
|
||||
use gpui::{MutableAppContext, TestAppContext, ViewHandle};
|
||||
use gpui::{AssetSource, MutableAppContext, TestAppContext, ViewHandle};
|
||||
use project::{Fs, ProjectPath};
|
||||
use serde_json::json;
|
||||
use std::{
|
||||
|
@ -143,7 +145,7 @@ mod tests {
|
|||
path::{Path, PathBuf},
|
||||
};
|
||||
use test::test_app_state;
|
||||
use theme::DEFAULT_THEME_NAME;
|
||||
use theme::{Theme, ThemeRegistry, DEFAULT_THEME_NAME};
|
||||
use util::test::temp_tree;
|
||||
use workspace::{
|
||||
open_paths, pane, ItemView, ItemViewHandle, OpenNew, Pane, SplitDirection, WorkspaceHandle,
|
||||
|
@ -862,10 +864,20 @@ mod tests {
|
|||
|
||||
#[gpui::test]
|
||||
fn test_bundled_themes(cx: &mut MutableAppContext) {
|
||||
let app_state = test_app_state(cx);
|
||||
let themes = ThemeRegistry::new(Assets, cx.font_cache().clone());
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref DEFAULT_THEME: parking_lot::Mutex<Option<Arc<Theme>>> = Default::default();
|
||||
static ref FONTS: Vec<Arc<Vec<u8>>> = vec![
|
||||
Assets.load("fonts/zed-sans/zed-sans-regular.ttf").unwrap().to_vec().into()
|
||||
];
|
||||
}
|
||||
|
||||
cx.platform().fonts().add_fonts(&FONTS).unwrap();
|
||||
|
||||
let mut has_default_theme = false;
|
||||
for theme_name in app_state.themes.list() {
|
||||
let theme = app_state.themes.get(&theme_name).unwrap();
|
||||
for theme_name in themes.list() {
|
||||
let theme = themes.get(&theme_name).unwrap();
|
||||
if theme.name == DEFAULT_THEME_NAME {
|
||||
has_default_theme = true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue