From 47b654063e69bac8b20be1e50ffefd9d58ea85fb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 24 Feb 2022 15:27:11 -0800 Subject: [PATCH] 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 --- crates/chat_panel/src/chat_panel.rs | 23 +- crates/diagnostics/src/diagnostics.rs | 24 +- crates/editor/Cargo.toml | 2 + crates/editor/src/editor.rs | 513 ++++++++---------- crates/editor/src/element.rs | 86 +-- crates/editor/src/items.rs | 6 +- crates/file_finder/src/file_finder.rs | 15 +- crates/find/src/find.rs | 24 +- crates/go_to_line/src/go_to_line.rs | 16 +- crates/outline/src/outline.rs | 20 +- crates/project_symbols/src/project_symbols.rs | 16 +- crates/server/src/rpc.rs | 15 +- crates/theme/src/theme.rs | 87 +-- crates/theme_selector/src/theme_selector.rs | 15 +- crates/workspace/src/settings.rs | 13 + crates/zed/assets/themes/_base.toml | 6 +- crates/zed/src/test.rs | 30 +- crates/zed/src/zed.rs | 22 +- 18 files changed, 377 insertions(+), 556 deletions(-) diff --git a/crates/chat_panel/src/chat_panel.rs b/crates/chat_panel/src/chat_panel.rs index 6b04bd485d..5b3df14f33 100644 --- a/crates/chat_panel/src/chat_panel.rs +++ b/crates/chat_panel/src/chat_panel.rs @@ -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 { 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(); diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index b9ffbc64d0..198a2be493 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -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, path_states: Vec, paths_to_update: BTreeSet, - build_settings: BuildSettings, settings: watch::Receiver, } @@ -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, ) -> 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() diff --git a/crates/editor/Cargo.toml b/crates/editor/Cargo.toml index 23ce651d9b..aeb7523374 100644 --- a/crates/editor/Cargo.toml +++ b/crates/editor/Cargo.toml @@ -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" diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index d3c6beaa97..87b3814589 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -26,7 +26,7 @@ use gpui::{ platform::CursorStyle, text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, - WeakModelHandle, WeakViewHandle, + WeakViewHandle, }; use items::{BufferItemHandle, MultiBufferItemHandle}; use itertools::Itertools as _; @@ -57,9 +57,9 @@ use std::{ }; pub use sum_tree::Bias; use text::rope::TextDimension; -use theme::{DiagnosticStyle, EditorStyle}; +use theme::DiagnosticStyle; use util::{post_inc, ResultExt, TryFutureExt}; -use workspace::{ItemNavHistory, PathOpener, Workspace}; +use workspace::{settings, ItemNavHistory, PathOpener, Settings, Workspace}; const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500); const MAX_LINE_LEN: usize = 1024; @@ -388,13 +388,6 @@ pub enum EditorMode { Full, } -#[derive(Clone)] -pub struct EditorSettings { - pub tab_size: usize, - pub soft_wrap: SoftWrap, - pub style: EditorStyle, -} - #[derive(Clone)] pub enum SoftWrap { None, @@ -402,9 +395,16 @@ pub enum SoftWrap { Column(u32), } +#[derive(Clone)] +pub struct EditorStyle { + pub text: TextStyle, + pub placeholder_text: Option, + pub theme: theme::Editor, +} + type CompletionId = usize; -pub type BuildSettings = Arc EditorSettings>; +pub type GetFieldEditorTheme = fn(&theme::Theme) -> theme::FieldEditor; pub struct Editor { handle: WeakViewHandle, @@ -425,7 +425,9 @@ pub struct Editor { scroll_position: Vector2F, scroll_top_anchor: Option, autoscroll_request: Option, - build_settings: BuildSettings, + settings: watch::Receiver, + soft_wrap_mode_override: Option, + get_field_editor_theme: Option, project: Option>, focused: bool, show_local_cursors: bool, @@ -531,12 +533,12 @@ impl ContextMenu { fn render( &self, cursor_position: DisplayPoint, - build_settings: BuildSettings, + style: EditorStyle, cx: &AppContext, ) -> (DisplayPoint, ElementBox) { match self { - ContextMenu::Completions(menu) => (cursor_position, menu.render(build_settings, cx)), - ContextMenu::CodeActions(menu) => menu.render(cursor_position, build_settings, cx), + ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)), + ContextMenu::CodeActions(menu) => menu.render(cursor_position, style), } } } @@ -573,15 +575,14 @@ impl CompletionsMenu { !self.matches.is_empty() } - fn render(&self, build_settings: BuildSettings, cx: &AppContext) -> ElementBox { + fn render(&self, style: EditorStyle, _: &AppContext) -> ElementBox { enum CompletionTag {} - let settings = build_settings(cx); let completions = self.completions.clone(); let matches = self.matches.clone(); let selected_item = self.selected_item; + let container_style = style.autocomplete.container; UniformList::new(self.list.clone(), matches.len(), move |range, items, cx| { - let settings = build_settings(cx); let start_ix = range.start; for (ix, mat) in matches[range].iter().enumerate() { let completion = &completions[mat.candidate_id]; @@ -592,22 +593,22 @@ impl CompletionsMenu { cx, |state, _| { let item_style = if item_ix == selected_item { - settings.style.autocomplete.selected_item + style.autocomplete.selected_item } else if state.hovered { - settings.style.autocomplete.hovered_item + style.autocomplete.hovered_item } else { - settings.style.autocomplete.item + style.autocomplete.item }; - Text::new(completion.label.text.clone(), settings.style.text.clone()) + Text::new(completion.label.text.clone(), style.text.clone()) .with_soft_wrap(false) .with_highlights(combine_syntax_and_fuzzy_match_highlights( &completion.label.text, - settings.style.text.color.into(), + style.text.color.into(), styled_runs_for_code_label( &completion.label, - settings.style.text.color, - &settings.style.syntax, + style.text.color, + &style.syntax, ), &mat.positions, )) @@ -638,7 +639,7 @@ impl CompletionsMenu { .map(|(ix, _)| ix), ) .contained() - .with_style(settings.style.autocomplete.container) + .with_style(container_style) .boxed() } @@ -714,31 +715,29 @@ impl CodeActionsMenu { fn render( &self, mut cursor_position: DisplayPoint, - build_settings: BuildSettings, - cx: &AppContext, + style: EditorStyle, ) -> (DisplayPoint, ElementBox) { enum ActionTag {} - let settings = build_settings(cx); + let container_style = style.autocomplete.container; let actions = self.actions.clone(); let selected_item = self.selected_item; let element = UniformList::new(self.list.clone(), actions.len(), move |range, items, cx| { - let settings = build_settings(cx); let start_ix = range.start; for (ix, action) in actions[range].iter().enumerate() { let item_ix = start_ix + ix; items.push( MouseEventHandler::new::(item_ix, cx, |state, _| { let item_style = if item_ix == selected_item { - settings.style.autocomplete.selected_item + style.autocomplete.selected_item } else if state.hovered { - settings.style.autocomplete.hovered_item + style.autocomplete.hovered_item } else { - settings.style.autocomplete.item + style.autocomplete.item }; - Text::new(action.lsp_action.title.clone(), settings.style.text.clone()) + Text::new(action.lsp_action.title.clone(), style.text.clone()) .with_soft_wrap(false) .contained() .with_style(item_style) @@ -760,7 +759,7 @@ impl CodeActionsMenu { .map(|(ix, _)| ix), ) .contained() - .with_style(settings.style.autocomplete.container) + .with_style(container_style) .boxed(); if self.deployed_from_indicator { @@ -791,40 +790,57 @@ pub struct NavigationData { } impl Editor { - pub fn single_line(build_settings: BuildSettings, cx: &mut ViewContext) -> Self { + pub fn single_line( + settings: watch::Receiver, + field_editor_style: Option, + cx: &mut ViewContext, + ) -> Self { let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx)); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let mut view = Self::for_buffer(buffer, build_settings, None, cx); - view.mode = EditorMode::SingleLine; - view + Self::new( + EditorMode::SingleLine, + buffer, + None, + settings, + field_editor_style, + cx, + ) } pub fn auto_height( max_lines: usize, - build_settings: BuildSettings, + settings: watch::Receiver, + field_editor_style: Option, cx: &mut ViewContext, ) -> Self { let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx)); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let mut view = Self::for_buffer(buffer, build_settings, None, cx); - view.mode = EditorMode::AutoHeight { max_lines }; - view + Self::new( + EditorMode::AutoHeight { max_lines }, + buffer, + None, + settings, + field_editor_style, + cx, + ) } pub fn for_buffer( buffer: ModelHandle, - build_settings: BuildSettings, project: Option>, + settings: watch::Receiver, cx: &mut ViewContext, ) -> Self { - Self::new(buffer, build_settings, project, cx) + Self::new(EditorMode::Full, buffer, project, settings, None, cx) } pub fn clone(&self, cx: &mut ViewContext) -> Self { let mut clone = Self::new( + self.mode, self.buffer.clone(), - self.build_settings.clone(), self.project.clone(), + self.settings.clone(), + self.get_field_editor_theme, cx, ); clone.scroll_position = self.scroll_position; @@ -836,19 +852,22 @@ impl Editor { clone } - pub fn new( + fn new( + mode: EditorMode, buffer: ModelHandle, - build_settings: BuildSettings, project: Option>, + settings: watch::Receiver, + get_field_editor_theme: Option, cx: &mut ViewContext, ) -> Self { - let settings = build_settings(cx); let display_map = cx.add_model(|cx| { + let settings = settings.borrow(); + let style = build_style(&*settings, get_field_editor_theme, cx); DisplayMap::new( buffer.clone(), settings.tab_size, - settings.style.text.font_id, - settings.style.text.font_size, + style.text.font_id, + style.text.font_size, None, 2, 1, @@ -884,7 +903,9 @@ impl Editor { snippet_stack: Default::default(), select_larger_syntax_node_stack: Vec::new(), active_diagnostics: None, - build_settings, + settings, + soft_wrap_mode_override: None, + get_field_editor_theme, project, scroll_position: Vector2F::zero(), scroll_top_anchor: None, @@ -893,7 +914,7 @@ impl Editor { show_local_cursors: false, blink_epoch: 0, blinking_paused: false, - mode: EditorMode::Full, + mode, vertical_scroll_margin: 3.0, placeholder_text: None, highlighted_rows: None, @@ -951,6 +972,10 @@ impl Editor { self.buffer.read(cx).language(cx) } + fn style(&self, cx: &AppContext) -> EditorStyle { + build_style(&*self.settings.borrow(), self.get_field_editor_theme, cx) + } + pub fn set_placeholder_text( &mut self, placeholder_text: impl Into>, @@ -2253,12 +2278,8 @@ impl Editor { let editor = workspace.open_item(MultiBufferItemHandle(excerpt_buffer), cx); if let Some(editor) = editor.act_as::(cx) { editor.update(cx, |editor, cx| { - let settings = (editor.build_settings)(cx); - editor.highlight_ranges::( - ranges_to_highlight, - settings.style.highlighted_line_background, - cx, - ); + let color = editor.style(cx).highlighted_line_background; + editor.highlight_ranges::(ranges_to_highlight, color, cx); }); } }); @@ -2322,7 +2343,9 @@ impl Editor { this.update(&mut cx, |this, cx| { let buffer_id = cursor_position.buffer_id; let excerpt_id = cursor_position.excerpt_id.clone(); - let settings = (this.build_settings)(cx); + let style = this.style(cx); + let read_background = style.document_highlight_read_background; + let write_background = style.document_highlight_write_background; let buffer = this.buffer.read(cx); if !buffer .text_anchor_for_position(cursor_position, cx) @@ -2352,12 +2375,12 @@ impl Editor { this.highlight_ranges::( read_ranges, - settings.style.document_highlight_read_background, + read_background, cx, ); this.highlight_ranges::( write_ranges, - settings.style.document_highlight_write_background, + write_background, cx, ); cx.notify(); @@ -2367,10 +2390,13 @@ impl Editor { None } - pub fn render_code_actions_indicator(&self, cx: &mut ViewContext) -> Option { + pub fn render_code_actions_indicator( + &self, + style: &EditorStyle, + cx: &mut ViewContext, + ) -> Option { if self.available_code_actions.is_some() { enum Tag {} - let style = (self.build_settings)(cx).style; Some( MouseEventHandler::new::(0, cx, |_, _| { Svg::new("icons/zap.svg") @@ -2398,11 +2424,12 @@ impl Editor { pub fn render_context_menu( &self, cursor_position: DisplayPoint, + style: EditorStyle, cx: &AppContext, ) -> Option<(DisplayPoint, ElementBox)> { self.context_menu .as_ref() - .map(|menu| menu.render(cursor_position, self.build_settings.clone(), cx)) + .map(|menu| menu.render(cursor_position, style, cx)) } fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext) { @@ -2578,7 +2605,7 @@ impl Editor { } self.start_transaction(cx); - let tab_size = (self.build_settings)(cx).tab_size; + let tab_size = self.settings.borrow().tab_size; let mut selections = self.local_selections::(cx); let mut last_indent = None; self.buffer.update(cx, |buffer, cx| { @@ -2655,7 +2682,7 @@ impl Editor { } self.start_transaction(cx); - let tab_size = (self.build_settings)(cx).tab_size; + let tab_size = self.settings.borrow().tab_size; let selections = self.local_selections::(cx); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let mut deletion_ranges = Vec::new(); @@ -4234,12 +4261,8 @@ impl Editor { let editor = workspace.open_item(MultiBufferItemHandle(excerpt_buffer), cx); if let Some(editor) = editor.act_as::(cx) { editor.update(cx, |editor, cx| { - let settings = (editor.build_settings)(cx); - editor.highlight_ranges::( - ranges_to_highlight, - settings.style.highlighted_line_background, - cx, - ); + let color = editor.style(cx).highlighted_line_background; + editor.highlight_ranges::(ranges_to_highlight, color, cx); }); } }); @@ -4282,7 +4305,7 @@ impl Editor { this.update(&mut cx, |this, cx| { this.take_rename(cx); - let settings = (this.build_settings)(cx); + let style = this.style(cx); let buffer = this.buffer.read(cx).read(cx); let cursor_offset = selection.head().to_offset(&buffer); let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range); @@ -4295,7 +4318,7 @@ impl Editor { // Position the selection in the rename editor so that it matches the current selection. let rename_editor = cx.add_view(|cx| { - let mut editor = Editor::single_line(this.build_settings.clone(), cx); + let mut editor = Editor::single_line(this.settings.clone(), None, cx); editor .buffer .update(cx, |buffer, cx| buffer.edit([0..0], &old_name, cx)); @@ -4306,14 +4329,14 @@ impl Editor { ); editor.highlight_ranges::( vec![Anchor::min()..Anchor::max()], - settings.style.diff_background_inserted, + style.diff_background_inserted, cx, ); editor }); this.highlight_ranges::( vec![range.clone()], - settings.style.diff_background_deleted, + style.diff_background_deleted, cx, ); this.update_selections( @@ -4483,7 +4506,7 @@ impl Editor { diagnostic_block_renderer( diagnostic.clone(), is_valid, - self.build_settings.clone(), + self.settings.clone(), ), ); } @@ -4522,14 +4545,16 @@ impl Editor { let blocks = display_map .insert_blocks( diagnostic_group.iter().map(|entry| { - let build_settings = self.build_settings.clone(); let diagnostic = entry.diagnostic.clone(); let message_height = diagnostic.message.lines().count() as u8; - BlockProperties { position: buffer.anchor_after(entry.range.start), height: message_height, - render: diagnostic_block_renderer(diagnostic, true, build_settings), + render: diagnostic_block_renderer( + diagnostic, + true, + self.settings.clone(), + ), disposition: BlockDisposition::Below, } }), @@ -5126,6 +5151,26 @@ impl Editor { .text() } + pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap { + let language = self.language(cx); + let settings = self.settings.borrow(); + let mode = self + .soft_wrap_mode_override + .unwrap_or_else(|| settings.soft_wrap(language)); + match mode { + settings::SoftWrap::None => SoftWrap::None, + settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth, + settings::SoftWrap::PreferredLineLength => { + SoftWrap::Column(settings.preferred_line_length(language)) + } + } + } + + pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext) { + self.soft_wrap_mode_override = Some(mode); + cx.notify(); + } + pub fn set_wrap_width(&self, width: Option, cx: &mut MutableAppContext) -> bool { self.display_map .update(cx, |map, cx| map.set_wrap_width(width, cx)) @@ -5327,94 +5372,6 @@ impl Deref for EditorSnapshot { } } -impl EditorSettings { - #[cfg(any(test, feature = "test-support"))] - pub fn test(cx: &AppContext) -> Self { - use theme::{ContainedLabel, ContainedText, DiagnosticHeader, DiagnosticPathHeader}; - - Self { - tab_size: 4, - soft_wrap: SoftWrap::None, - style: { - let font_cache: &gpui::FontCache = cx.font_cache(); - let font_family_name = Arc::from("Monaco"); - let font_properties = Default::default(); - let font_family_id = font_cache.load_family(&[&font_family_name]).unwrap(); - let font_id = font_cache - .select_font(font_family_id, &font_properties) - .unwrap(); - let text = gpui::fonts::TextStyle { - font_family_name, - font_family_id, - font_id, - font_size: 14., - color: gpui::color::Color::from_u32(0xff0000ff), - font_properties, - underline: None, - }; - let default_diagnostic_style = DiagnosticStyle { - message: text.clone().into(), - header: Default::default(), - text_scale_factor: 1., - }; - EditorStyle { - text: text.clone(), - placeholder_text: None, - background: Default::default(), - gutter_background: Default::default(), - gutter_padding_factor: 2., - active_line_background: Default::default(), - highlighted_line_background: Default::default(), - diff_background_deleted: Default::default(), - diff_background_inserted: Default::default(), - document_highlight_read_background: Default::default(), - document_highlight_write_background: Default::default(), - line_number: Default::default(), - line_number_active: Default::default(), - selection: Default::default(), - guest_selections: Default::default(), - syntax: Default::default(), - diagnostic_path_header: DiagnosticPathHeader { - container: Default::default(), - filename: ContainedText { - container: Default::default(), - text: text.clone(), - }, - path: ContainedText { - container: Default::default(), - text: text.clone(), - }, - text_scale_factor: 1., - }, - diagnostic_header: DiagnosticHeader { - container: Default::default(), - message: ContainedLabel { - container: Default::default(), - label: text.clone().into(), - }, - code: ContainedText { - container: Default::default(), - text: text.clone(), - }, - icon_width_factor: 1., - 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(), - } - }, - } - } -} - fn compute_scroll_position( snapshot: &DisplaySnapshot, mut scroll_position: Vector2F, @@ -5447,15 +5404,11 @@ impl Entity for Editor { impl View for Editor { fn render(&mut self, cx: &mut RenderContext) -> ElementBox { - let settings = (self.build_settings)(cx); + let style = self.style(cx); self.display_map.update(cx, |map, cx| { - map.set_font( - settings.style.text.font_id, - settings.style.text.font_size, - cx, - ) + map.set_font(style.text.font_id, style.text.font_size, cx) }); - EditorElement::new(self.handle.clone(), settings).boxed() + EditorElement::new(self.handle.clone(), style.clone()).boxed() } fn ui_name() -> &'static str { @@ -5505,6 +5458,44 @@ impl View for Editor { } } +fn build_style( + settings: &Settings, + get_field_editor_theme: Option, + cx: &AppContext, +) -> EditorStyle { + let theme = settings.theme.editor.clone(); + if let Some(get_field_editor_theme) = get_field_editor_theme { + let field_editor_theme = get_field_editor_theme(&settings.theme); + EditorStyle { + text: field_editor_theme.text, + placeholder_text: field_editor_theme.placeholder_text, + theme, + } + } else { + let font_cache = cx.font_cache(); + let font_family_id = settings.buffer_font_family; + let font_family_name = cx.font_cache().family_name(font_family_id).unwrap(); + let font_properties = Default::default(); + let font_id = font_cache + .select_font(font_family_id, &font_properties) + .unwrap(); + let font_size = settings.buffer_font_size; + EditorStyle { + text: TextStyle { + color: settings.theme.editor.text_color, + font_family_name, + font_family_id, + font_id, + font_size, + font_properties, + underline: None, + }, + placeholder_text: None, + theme, + } + } +} + impl SelectionExt for Selection { fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range { let start = self.start.to_point(buffer); @@ -5619,10 +5610,18 @@ impl InvalidationRegion for SnippetState { } } +impl Deref for EditorStyle { + type Target = theme::Editor; + + fn deref(&self) -> &Self::Target { + &self.theme + } +} + pub fn diagnostic_block_renderer( diagnostic: Diagnostic, is_valid: bool, - build_settings: BuildSettings, + settings: watch::Receiver, ) -> RenderBlock { let mut highlighted_lines = Vec::new(); for line in diagnostic.message.lines() { @@ -5630,9 +5629,10 @@ pub fn diagnostic_block_renderer( } Arc::new(move |cx: &BlockContext| { - let settings = build_settings(cx); - let style = diagnostic_style(diagnostic.severity, is_valid, &settings.style); - let font_size = (style.text_scale_factor * settings.style.text.font_size).round(); + let settings = settings.borrow(); + let theme = &settings.theme.editor; + let style = diagnostic_style(diagnostic.severity, is_valid, theme); + let font_size = (style.text_scale_factor * settings.buffer_font_size).round(); Flex::column() .with_children(highlighted_lines.iter().map(|(line, highlights)| { Label::new( @@ -5675,67 +5675,21 @@ pub fn highlight_diagnostic_message(message: &str) -> (String, Vec) { pub fn diagnostic_style( severity: DiagnosticSeverity, valid: bool, - style: &EditorStyle, + theme: &theme::Editor, ) -> DiagnosticStyle { match (severity, valid) { - (DiagnosticSeverity::ERROR, true) => style.error_diagnostic.clone(), - (DiagnosticSeverity::ERROR, false) => style.invalid_error_diagnostic.clone(), - (DiagnosticSeverity::WARNING, true) => style.warning_diagnostic.clone(), - (DiagnosticSeverity::WARNING, false) => style.invalid_warning_diagnostic.clone(), - (DiagnosticSeverity::INFORMATION, true) => style.information_diagnostic.clone(), - (DiagnosticSeverity::INFORMATION, false) => style.invalid_information_diagnostic.clone(), - (DiagnosticSeverity::HINT, true) => style.hint_diagnostic.clone(), - (DiagnosticSeverity::HINT, false) => style.invalid_hint_diagnostic.clone(), - _ => DiagnosticStyle { - message: style.text.clone().into(), - header: Default::default(), - text_scale_factor: 1., - }, + (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(), + (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(), + (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(), + (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(), + (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(), + (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(), + (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(), + (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(), + _ => theme.invalid_hint_diagnostic.clone(), } } -pub fn settings_builder( - buffer: WeakModelHandle, - settings: watch::Receiver, -) -> BuildSettings { - Arc::new(move |cx| { - let settings = settings.borrow(); - let font_cache = cx.font_cache(); - let font_family_id = settings.buffer_font_family; - let font_family_name = cx.font_cache().family_name(font_family_id).unwrap(); - let font_properties = Default::default(); - let font_id = font_cache - .select_font(font_family_id, &font_properties) - .unwrap(); - let font_size = settings.buffer_font_size; - - let mut theme = settings.theme.editor.clone(); - theme.text = TextStyle { - color: theme.text.color, - font_family_name, - font_family_id, - font_id, - font_size, - font_properties, - underline: None, - }; - let language = buffer.upgrade(cx).and_then(|buf| buf.read(cx).language(cx)); - let soft_wrap = match settings.soft_wrap(language) { - workspace::settings::SoftWrap::None => SoftWrap::None, - workspace::settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth, - workspace::settings::SoftWrap::PreferredLineLength => { - SoftWrap::Column(settings.preferred_line_length(language).saturating_sub(1)) - } - }; - - EditorSettings { - tab_size: settings.tab_size, - soft_wrap, - style: theme, - } - }) -} - pub fn combine_syntax_and_fuzzy_match_highlights( text: &str, default_style: HighlightStyle, @@ -5874,7 +5828,7 @@ mod tests { let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx)); let group_interval = buffer.read(cx).transaction_group_interval(); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); - let settings = EditorSettings::test(cx); + let settings = Settings::test(cx); let (_, editor) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -5942,7 +5896,7 @@ mod tests { #[gpui::test] fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx); - let settings = EditorSettings::test(cx); + let settings = Settings::test(cx); let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); @@ -6009,7 +5963,7 @@ mod tests { #[gpui::test] fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx); - let settings = EditorSettings::test(cx); + let settings = Settings::test(cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -6043,7 +5997,7 @@ mod tests { cx.add_window(Default::default(), |cx| { use workspace::ItemView; let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default())); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple(&sample_text(30, 5, 'a'), cx); let mut editor = build_editor(buffer.clone(), settings, cx); editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle())); @@ -6098,7 +6052,7 @@ mod tests { #[gpui::test] fn test_cancel(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx); - let settings = EditorSettings::test(cx); + let settings = Settings::test(cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -6158,7 +6112,7 @@ mod tests { .unindent(), cx, ); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -6225,7 +6179,7 @@ mod tests { #[gpui::test] fn test_move_cursor(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -6301,7 +6255,7 @@ mod tests { #[gpui::test] fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -6404,7 +6358,7 @@ mod tests { #[gpui::test] fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -6451,7 +6405,7 @@ mod tests { #[gpui::test] fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("abc\n def", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { view.select_display_ranges( @@ -6592,7 +6546,7 @@ mod tests { #[gpui::test] fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n {baz.qux()}", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { view.select_display_ranges( @@ -6730,7 +6684,7 @@ mod tests { #[gpui::test] fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("use one::{\n two::three::four::five\n};", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -6783,7 +6737,7 @@ mod tests { #[gpui::test] fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("one two three four", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -6822,7 +6776,7 @@ mod tests { #[gpui::test] fn test_newline(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("aaaa\n bbbb\n", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -6859,7 +6813,7 @@ mod tests { cx, ); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, editor) = cx.add_window(Default::default(), |cx| { let mut editor = build_editor(buffer.clone(), settings, cx); editor.select_ranges( @@ -6931,7 +6885,7 @@ mod tests { fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, editor) = cx.add_window(Default::default(), |cx| { let mut editor = build_editor(buffer.clone(), settings, cx); editor.select_ranges([3..4, 11..12, 19..20], None, cx); @@ -6958,7 +6912,7 @@ mod tests { #[gpui::test] fn test_indent_outdent(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple(" one two\nthree\n four", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -7035,7 +6989,7 @@ mod tests { fn test_backspace(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -7065,7 +7019,7 @@ mod tests { fn test_delete(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -7093,7 +7047,7 @@ mod tests { #[gpui::test] fn test_delete_line(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -7116,7 +7070,7 @@ mod tests { ); }); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -7132,7 +7086,7 @@ mod tests { #[gpui::test] fn test_duplicate_line(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -7158,7 +7112,7 @@ mod tests { ); }); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -7183,7 +7137,7 @@ mod tests { #[gpui::test] fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -7279,7 +7233,7 @@ mod tests { #[gpui::test] fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx); let snapshot = buffer.read(cx).snapshot(cx); let (_, editor) = @@ -7302,7 +7256,7 @@ mod tests { #[gpui::test] fn test_clipboard(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let view = cx .add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) @@ -7433,7 +7387,7 @@ mod tests { #[gpui::test] fn test_select_all(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { view.select_all(&SelectAll, cx); @@ -7446,7 +7400,7 @@ mod tests { #[gpui::test] fn test_select_line(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -7491,7 +7445,7 @@ mod tests { #[gpui::test] fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { @@ -7557,7 +7511,7 @@ mod tests { #[gpui::test] fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); @@ -7726,7 +7680,7 @@ mod tests { #[gpui::test] async fn test_select_larger_smaller_syntax_node(mut cx: gpui::TestAppContext) { - let settings = cx.read(EditorSettings::test); + let settings = cx.read(Settings::test); let language = Arc::new(Language::new( LanguageConfig::default(), Some(tree_sitter_rust::language()), @@ -7867,7 +7821,7 @@ mod tests { #[gpui::test] async fn test_autoindent_selections(mut cx: gpui::TestAppContext) { - let settings = cx.read(EditorSettings::test); + let settings = cx.read(Settings::test); let language = Arc::new( Language::new( LanguageConfig { @@ -7924,7 +7878,7 @@ mod tests { #[gpui::test] async fn test_autoclose_pairs(mut cx: gpui::TestAppContext) { - let settings = cx.read(EditorSettings::test); + let settings = cx.read(Settings::test); let language = Arc::new(Language::new( LanguageConfig { brackets: vec![ @@ -8035,7 +7989,7 @@ mod tests { #[gpui::test] async fn test_snippets(mut cx: gpui::TestAppContext) { - let settings = cx.read(EditorSettings::test); + let settings = cx.read(Settings::test); let text = " a. b @@ -8142,7 +8096,7 @@ mod tests { #[gpui::test] async fn test_completion(mut cx: gpui::TestAppContext) { - let settings = cx.read(EditorSettings::test); + let settings = cx.read(Settings::test); let (language_server, mut fake) = cx.update(|cx| { lsp::LanguageServer::fake_with_capabilities( lsp::ServerCapabilities { @@ -8375,7 +8329,7 @@ mod tests { #[gpui::test] async fn test_toggle_comment(mut cx: gpui::TestAppContext) { - let settings = cx.read(EditorSettings::test); + let settings = cx.read(Settings::test); let language = Arc::new(Language::new( LanguageConfig { line_comment: Some("// ".to_string()), @@ -8455,7 +8409,7 @@ mod tests { #[gpui::test] fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(cx); + let settings = Settings::test(cx); let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx)); let multibuffer = cx.add_model(|cx| { let mut multibuffer = MultiBuffer::new(0); @@ -8500,7 +8454,7 @@ mod tests { #[gpui::test] fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(cx); + let settings = Settings::test(cx); let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx)); let multibuffer = cx.add_model(|cx| { let mut multibuffer = MultiBuffer::new(0); @@ -8557,7 +8511,7 @@ mod tests { #[gpui::test] fn test_refresh_selections(cx: &mut gpui::MutableAppContext) { - let settings = EditorSettings::test(cx); + let settings = Settings::test(cx); let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx)); let mut excerpt1_id = None; let multibuffer = cx.add_model(|cx| { @@ -8632,7 +8586,7 @@ mod tests { #[gpui::test] async fn test_extra_newline_insertion(mut cx: gpui::TestAppContext) { - let settings = cx.read(EditorSettings::test); + let settings = cx.read(Settings::test); let language = Arc::new(Language::new( LanguageConfig { brackets: vec![ @@ -8700,7 +8654,7 @@ mod tests { #[gpui::test] fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) { let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx); - let settings = EditorSettings::test(&cx); + let settings = Settings::test(&cx); let (_, editor) = cx.add_window(Default::default(), |cx| { build_editor(buffer.clone(), settings, cx) }); @@ -8855,10 +8809,11 @@ mod tests { fn build_editor( buffer: ModelHandle, - settings: EditorSettings, + settings: Settings, cx: &mut ViewContext, ) -> Editor { - Editor::for_buffer(buffer, Arc::new(move |_| settings.clone()), None, cx) + let settings = watch::channel_with(settings); + Editor::new(EditorMode::Full, buffer, None, settings.1, None, cx) } } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 222acdb919..f4277713b1 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -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, - settings: EditorSettings, + style: EditorStyle, } impl EditorElement { - pub fn new(view: WeakViewHandle, settings: EditorSettings) -> Self { - Self { view, settings } + pub fn new(view: WeakViewHandle, 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> { - 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); diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index af12cae947..1d89bd567f 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -56,12 +56,11 @@ impl ItemHandle for BufferItemHandle { cx: &mut MutableAppContext, ) -> Box { 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>, cx: &mut MutableAppContext, ) -> Box { - 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())); diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index e950dc0fcb..1ecbad6d12 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -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, ) }); diff --git a/crates/find/src/find.rs b/crates/find/src/find.rs index 76beed1f2e..60dd4cefb7 100644 --- a/crates/find/src/find.rs +++ b/crates/find/src/find.rs @@ -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 }); diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index 5a87aa6bc1..0b35ef7dbd 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -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, ) }); diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 4518ae6afc..4d2dc125c6 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -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, ) }); diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 1fa8add221..174239ff52 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -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, ) }); diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 593ad32bcd..35617c048f 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -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, ) }); diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 145996c6e9..34640211f6 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -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, 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)>, diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 5e536394e0..9ac35339ab 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -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, ) }); diff --git a/crates/workspace/src/settings.rs b/crates/workspace/src/settings.rs index 7073c1144c..242ecbbce2 100644 --- a/crates/workspace/src/settings.rs +++ b/crates/workspace/src/settings.rs @@ -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()), + } + } } diff --git a/crates/zed/assets/themes/_base.toml b/crates/zed/assets/themes/_base.toml index 45448ae189..de1344239a 100644 --- a/crates/zed/assets/themes/_base.toml +++ b/crates/zed/assets/themes/_base.toml @@ -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" diff --git a/crates/zed/src/test.rs b/crates/zed/src/test.rs index 77b092b0bb..11205fe25b 100644 --- a/crates/zed/src/test.rs +++ b/crates/zed/src/test.rs @@ -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 { 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 { build_workspace: &build_workspace, }) } - -fn build_settings(cx: &gpui::AppContext) -> Settings { - lazy_static::lazy_static! { - static ref DEFAULT_THEME: parking_lot::Mutex>> = Default::default(); - static ref FONTS: Vec>> = 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() -} diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index fc1dcdff1d..02430aae1a 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -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>> = Default::default(); + static ref FONTS: Vec>> = 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; }