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:
Max Brunsfeld 2022-02-24 15:27:11 -08:00
parent 39ebaebd83
commit 47b654063e
18 changed files with 377 additions and 556 deletions

View file

@ -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();

View file

@ -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()

View file

@ -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

View file

@ -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);

View file

@ -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()));

View file

@ -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,
)
});

View file

@ -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
});

View file

@ -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,
)
});

View file

@ -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,
)
});

View file

@ -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,
)
});

View file

@ -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,
)
});

View file

@ -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)>,

View file

@ -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,
)
});

View file

@ -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()),
}
}
}

View file

@ -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"

View file

@ -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()
}

View file

@ -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;
}