From a7a52ef3f79f0befe70deb3fe1b1b3c01892c615 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Sun, 27 Mar 2022 17:58:28 -0700 Subject: [PATCH 01/68] Add word and line movement in vim normal mode Add jump to start and end of the document Move vim tests to relevant vim files Rename VimTestAppContext to VimTestContext for brevity Improve VimTestContext assertions to pretty print locations when selection position assertion panics --- crates/editor/src/editor.rs | 34 +-- crates/language/src/buffer.rs | 10 + crates/vim/src/editor_events.rs | 2 +- crates/vim/src/insert.rs | 19 +- crates/vim/src/mode.rs | 44 +++- crates/vim/src/normal.rs | 376 ++++++++++++++++++++++++++++- crates/vim/src/normal/g_prefix.rs | 82 +++++++ crates/vim/src/vim.rs | 45 +++- crates/vim/src/vim_test_context.rs | 179 ++++++++++++++ crates/vim/src/vim_tests.rs | 253 ------------------- 10 files changed, 766 insertions(+), 278 deletions(-) create mode 100644 crates/vim/src/normal/g_prefix.rs create mode 100644 crates/vim/src/vim_test_context.rs delete mode 100644 crates/vim/src/vim_tests.rs diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f9327ee251..0be43fee96 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1281,6 +1281,24 @@ impl Editor { } } + pub fn replace_selections_with( + &mut self, + cx: &mut ViewContext, + find_replacement: impl Fn(&DisplaySnapshot) -> DisplayPoint, + ) { + let display_map = self.snapshot(cx); + let cursor = find_replacement(&display_map); + let selection = Selection { + id: post_inc(&mut self.next_selection_id), + start: cursor, + end: cursor, + reversed: false, + goal: SelectionGoal::None, + } + .map(|display_point| display_point.to_point(&display_map)); + self.update_selections(vec![selection], None, cx); + } + pub fn move_selections( &mut self, cx: &mut ViewContext, @@ -1291,21 +1309,9 @@ impl Editor { .local_selections::(cx) .into_iter() .map(|selection| { - let mut selection = Selection { - id: selection.id, - start: selection.start.to_display_point(&display_map), - end: selection.end.to_display_point(&display_map), - reversed: selection.reversed, - goal: selection.goal, - }; + let mut selection = selection.map(|point| point.to_display_point(&display_map)); move_selection(&display_map, &mut selection); - Selection { - id: selection.id, - start: selection.start.to_point(&display_map), - end: selection.end.to_point(&display_map), - reversed: selection.reversed, - goal: selection.goal, - } + selection.map(|display_point| display_point.to_point(&display_map)) }) .collect(); self.update_selections(selections, Some(Autoscroll::Fit), cx); diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 535798083e..8c20036487 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -276,6 +276,16 @@ pub enum CharKind { Word, } +impl CharKind { + pub fn coerce_punctuation(self, treat_punctuation_as_word: bool) -> Self { + if treat_punctuation_as_word && self == CharKind::Punctuation { + CharKind::Word + } else { + self + } + } +} + impl Buffer { pub fn new>>( replica_id: ReplicaId, diff --git a/crates/vim/src/editor_events.rs b/crates/vim/src/editor_events.rs index 7e49b473f9..e4035197fd 100644 --- a/crates/vim/src/editor_events.rs +++ b/crates/vim/src/editor_events.rs @@ -21,7 +21,7 @@ fn editor_focused(EditorFocused(editor): &EditorFocused, cx: &mut MutableAppCont let mode = if matches!(editor.read(cx).mode(), EditorMode::SingleLine) { Mode::Insert } else { - Mode::Normal + Mode::normal() }; VimState::update_global(cx, |state, cx| { diff --git a/crates/vim/src/insert.rs b/crates/vim/src/insert.rs index c027ff2c1f..9c1e36a90e 100644 --- a/crates/vim/src/insert.rs +++ b/crates/vim/src/insert.rs @@ -25,6 +25,23 @@ fn normal_before(_: &mut Workspace, _: &NormalBefore, cx: &mut ViewContext CursorShape { match self { - Mode::Normal => CursorShape::Block, + Mode::Normal(_) => CursorShape::Block, Mode::Insert => CursorShape::Bar, } } @@ -20,17 +20,53 @@ impl Mode { context.map.insert( "vim_mode".to_string(), match self { - Self::Normal => "normal", + Self::Normal(_) => "normal", Self::Insert => "insert", } .to_string(), ); + + match self { + Self::Normal(normal_state) => normal_state.set_context(&mut context), + _ => {} + } context } + + pub fn normal() -> Mode { + Mode::Normal(Default::default()) + } } impl Default for Mode { fn default() -> Self { - Self::Normal + Self::Normal(Default::default()) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum NormalState { + None, + GPrefix, +} + +impl NormalState { + pub fn set_context(&self, context: &mut Context) { + let sub_mode = match self { + Self::GPrefix => Some("g"), + _ => None, + }; + + if let Some(sub_mode) = sub_mode { + context + .map + .insert("vim_sub_mode".to_string(), sub_mode.to_string()); + } + } +} + +impl Default for NormalState { + fn default() -> Self { + NormalState::None } } diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 232a76a030..5bf1a3c417 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -1,30 +1,55 @@ -use editor::{movement, Bias}; +mod g_prefix; + +use editor::{char_kind, movement, Bias}; use gpui::{action, keymap::Binding, MutableAppContext, ViewContext}; use language::SelectionGoal; use workspace::Workspace; -use crate::{Mode, SwitchMode, VimState}; +use crate::{mode::NormalState, Mode, SwitchMode, VimState}; -action!(InsertBefore); +action!(GPrefix); action!(MoveLeft); action!(MoveDown); action!(MoveUp); action!(MoveRight); +action!(MoveToStartOfLine); +action!(MoveToEndOfLine); +action!(MoveToEnd); +action!(MoveToNextWordStart, bool); +action!(MoveToNextWordEnd, bool); +action!(MoveToPreviousWordStart, bool); pub fn init(cx: &mut MutableAppContext) { let context = Some("Editor && vim_mode == normal"); cx.add_bindings(vec![ Binding::new("i", SwitchMode(Mode::Insert), context), + Binding::new("g", SwitchMode(Mode::Normal(NormalState::GPrefix)), context), Binding::new("h", MoveLeft, context), Binding::new("j", MoveDown, context), Binding::new("k", MoveUp, context), Binding::new("l", MoveRight, context), + Binding::new("0", MoveToStartOfLine, context), + Binding::new("shift-$", MoveToEndOfLine, context), + Binding::new("shift-G", MoveToEnd, context), + Binding::new("w", MoveToNextWordStart(false), context), + Binding::new("shift-W", MoveToNextWordStart(true), context), + Binding::new("e", MoveToNextWordEnd(false), context), + Binding::new("shift-E", MoveToNextWordEnd(true), context), + Binding::new("b", MoveToPreviousWordStart(false), context), + Binding::new("shift-B", MoveToPreviousWordStart(true), context), ]); + g_prefix::init(cx); cx.add_action(move_left); cx.add_action(move_down); cx.add_action(move_up); cx.add_action(move_right); + cx.add_action(move_to_start_of_line); + cx.add_action(move_to_end_of_line); + cx.add_action(move_to_end); + cx.add_action(move_to_next_word_start); + cx.add_action(move_to_next_word_end); + cx.add_action(move_to_previous_word_start); } fn move_left(_: &mut Workspace, _: &MoveLeft, cx: &mut ViewContext) { @@ -64,3 +89,348 @@ fn move_right(_: &mut Workspace, _: &MoveRight, cx: &mut ViewContext) }); }); } + +fn move_to_start_of_line( + _: &mut Workspace, + _: &MoveToStartOfLine, + cx: &mut ViewContext, +) { + VimState::update_global(cx, |state, cx| { + state.update_active_editor(cx, |editor, cx| { + editor.move_cursors(cx, |map, cursor, _| { + ( + movement::line_beginning(map, cursor, false), + SelectionGoal::None, + ) + }); + }); + }); +} + +fn move_to_end_of_line(_: &mut Workspace, _: &MoveToEndOfLine, cx: &mut ViewContext) { + VimState::update_global(cx, |state, cx| { + state.update_active_editor(cx, |editor, cx| { + editor.move_cursors(cx, |map, cursor, _| { + ( + map.clip_point(movement::line_end(map, cursor, false), Bias::Left), + SelectionGoal::None, + ) + }); + }); + }); +} + +fn move_to_end(_: &mut Workspace, _: &MoveToEnd, cx: &mut ViewContext) { + VimState::update_global(cx, |state, cx| { + state.update_active_editor(cx, |editor, cx| { + editor.replace_selections_with(cx, |map| map.clip_point(map.max_point(), Bias::Left)); + }); + }); +} + +fn move_to_next_word_start( + _: &mut Workspace, + &MoveToNextWordStart(treat_punctuation_as_word): &MoveToNextWordStart, + cx: &mut ViewContext, +) { + VimState::update_global(cx, |state, cx| { + state.update_active_editor(cx, |editor, cx| { + editor.move_cursors(cx, |map, mut cursor, _| { + let mut crossed_newline = false; + cursor = movement::find_boundary(map, cursor, |left, right| { + let left_kind = char_kind(left).coerce_punctuation(treat_punctuation_as_word); + let right_kind = char_kind(right).coerce_punctuation(treat_punctuation_as_word); + let at_newline = right == '\n'; + + let found = (left_kind != right_kind && !right.is_whitespace()) + || (at_newline && crossed_newline) + || (at_newline && left == '\n'); // Prevents skipping repeated empty lines + + if at_newline { + crossed_newline = true; + } + found + }); + (cursor, SelectionGoal::None) + }); + }); + }); +} + +fn move_to_next_word_end( + _: &mut Workspace, + &MoveToNextWordEnd(treat_punctuation_as_word): &MoveToNextWordEnd, + cx: &mut ViewContext, +) { + VimState::update_global(cx, |state, cx| { + state.update_active_editor(cx, |editor, cx| { + editor.move_cursors(cx, |map, mut cursor, _| { + *cursor.column_mut() += 1; + cursor = movement::find_boundary(map, cursor, |left, right| { + let left_kind = char_kind(left).coerce_punctuation(treat_punctuation_as_word); + let right_kind = char_kind(right).coerce_punctuation(treat_punctuation_as_word); + + left_kind != right_kind && !left.is_whitespace() + }); + // find_boundary clips, so if the character after the next character is a newline or at the end of the document, we know + // we have backtraced already + if !map + .chars_at(cursor) + .skip(1) + .next() + .map(|c| c == '\n') + .unwrap_or(true) + { + *cursor.column_mut() = cursor.column().saturating_sub(1); + } + (map.clip_point(cursor, Bias::Left), SelectionGoal::None) + }); + }); + }); +} + +fn move_to_previous_word_start( + _: &mut Workspace, + &MoveToPreviousWordStart(treat_punctuation_as_word): &MoveToPreviousWordStart, + cx: &mut ViewContext, +) { + VimState::update_global(cx, |state, cx| { + state.update_active_editor(cx, |editor, cx| { + editor.move_cursors(cx, |map, mut cursor, _| { + // This works even though find_preceding_boundary is called for every character in the line containing + // cursor because the newline is checked only once. + cursor = movement::find_preceding_boundary(map, cursor, |left, right| { + let left_kind = char_kind(left).coerce_punctuation(treat_punctuation_as_word); + let right_kind = char_kind(right).coerce_punctuation(treat_punctuation_as_word); + + (left_kind != right_kind && !right.is_whitespace()) || left == '\n' + }); + (cursor, SelectionGoal::None) + }); + }); + }); +} + +#[cfg(test)] +mod test { + use indoc::indoc; + use util::test::marked_text; + + use crate::vim_test_context::VimTestContext; + + #[gpui::test] + async fn test_hjkl(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true, "Test\nTestTest\nTest").await; + cx.simulate_keystroke("l"); + cx.assert_editor_state(indoc! {" + T|est + TestTest + Test"}); + cx.simulate_keystroke("h"); + cx.assert_editor_state(indoc! {" + |Test + TestTest + Test"}); + cx.simulate_keystroke("j"); + cx.assert_editor_state(indoc! {" + Test + |TestTest + Test"}); + cx.simulate_keystroke("k"); + cx.assert_editor_state(indoc! {" + |Test + TestTest + Test"}); + cx.simulate_keystroke("j"); + cx.assert_editor_state(indoc! {" + Test + |TestTest + Test"}); + + // When moving left, cursor does not wrap to the previous line + cx.simulate_keystroke("h"); + cx.assert_editor_state(indoc! {" + Test + |TestTest + Test"}); + + // When moving right, cursor does not reach the line end or wrap to the next line + for _ in 0..9 { + cx.simulate_keystroke("l"); + } + cx.assert_editor_state(indoc! {" + Test + TestTes|t + Test"}); + + // Goal column respects the inability to reach the end of the line + cx.simulate_keystroke("k"); + cx.assert_editor_state(indoc! {" + Tes|t + TestTest + Test"}); + cx.simulate_keystroke("j"); + cx.assert_editor_state(indoc! {" + Test + TestTes|t + Test"}); + } + + #[gpui::test] + async fn test_jump_to_line_boundaries(cx: &mut gpui::TestAppContext) { + let initial_content = indoc! {" + Test Test + + T"}; + let mut cx = VimTestContext::new(cx, true, initial_content).await; + + cx.simulate_keystroke("shift-$"); + cx.assert_editor_state(indoc! {" + Test Tes|t + + T"}); + cx.simulate_keystroke("0"); + cx.assert_editor_state(indoc! {" + |Test Test + + T"}); + + cx.simulate_keystroke("j"); + cx.simulate_keystroke("shift-$"); + cx.assert_editor_state(indoc! {" + Test Test + | + T"}); + cx.simulate_keystroke("0"); + cx.assert_editor_state(indoc! {" + Test Test + | + T"}); + + cx.simulate_keystroke("j"); + cx.simulate_keystroke("shift-$"); + cx.assert_editor_state(indoc! {" + Test Test + + |T"}); + cx.simulate_keystroke("0"); + cx.assert_editor_state(indoc! {" + Test Test + + |T"}); + } + + #[gpui::test] + async fn test_jump_to_end(cx: &mut gpui::TestAppContext) { + let initial_content = indoc! {" + The quick + + brown fox jumps + over the lazy dog"}; + let mut cx = VimTestContext::new(cx, true, initial_content).await; + + cx.simulate_keystroke("shift-G"); + cx.assert_editor_state(indoc! {" + The quick + + brown fox jumps + over the lazy do|g"}); + + // Repeat the action doesn't move + cx.simulate_keystroke("shift-G"); + cx.assert_editor_state(indoc! {" + The quick + + brown fox jumps + over the lazy do|g"}); + } + + #[gpui::test] + async fn test_next_word_start(cx: &mut gpui::TestAppContext) { + let (initial_content, cursor_offsets) = marked_text(indoc! {" + The |quick|-|brown + | + | + |fox_jumps |over + |th||e"}); + let mut cx = VimTestContext::new(cx, true, &initial_content).await; + + for cursor_offset in cursor_offsets { + cx.simulate_keystroke("w"); + cx.assert_newest_selection_head_offset(cursor_offset); + } + + // Reset and test ignoring punctuation + cx.simulate_keystrokes(&["g", "g"]); + let (_, cursor_offsets) = marked_text(indoc! {" + The |quick-brown + | + | + |fox_jumps |over + |th||e"}); + + for cursor_offset in cursor_offsets { + cx.simulate_keystroke("shift-W"); + cx.assert_newest_selection_head_offset(cursor_offset); + } + } + + #[gpui::test] + async fn test_next_word_end(cx: &mut gpui::TestAppContext) { + let (initial_content, cursor_offsets) = marked_text(indoc! {" + Th|e quic|k|-brow|n + + + fox_jump|s ove|r + th|e"}); + let mut cx = VimTestContext::new(cx, true, &initial_content).await; + + for cursor_offset in cursor_offsets { + cx.simulate_keystroke("e"); + cx.assert_newest_selection_head_offset(cursor_offset); + } + + // Reset and test ignoring punctuation + cx.simulate_keystrokes(&["g", "g"]); + let (_, cursor_offsets) = marked_text(indoc! {" + Th|e quick-brow|n + + + fox_jump|s ove|r + th||e"}); + for cursor_offset in cursor_offsets { + cx.simulate_keystroke("shift-E"); + cx.assert_newest_selection_head_offset(cursor_offset); + } + } + + #[gpui::test] + async fn test_previous_word_start(cx: &mut gpui::TestAppContext) { + let (initial_content, cursor_offsets) = marked_text(indoc! {" + ||The |quick|-|brown + | + | + |fox_jumps |over + |the"}); + let mut cx = VimTestContext::new(cx, true, &initial_content).await; + cx.simulate_keystroke("shift-G"); + + for cursor_offset in cursor_offsets.into_iter().rev() { + cx.simulate_keystroke("b"); + cx.assert_newest_selection_head_offset(cursor_offset); + } + + // Reset and test ignoring punctuation + cx.simulate_keystroke("shift-G"); + let (_, cursor_offsets) = marked_text(indoc! {" + ||The |quick-brown + | + | + |fox_jumps |over + |the"}); + for cursor_offset in cursor_offsets.into_iter().rev() { + cx.simulate_keystroke("shift-B"); + cx.assert_newest_selection_head_offset(cursor_offset); + } + } +} diff --git a/crates/vim/src/normal/g_prefix.rs b/crates/vim/src/normal/g_prefix.rs new file mode 100644 index 0000000000..82510c0cf9 --- /dev/null +++ b/crates/vim/src/normal/g_prefix.rs @@ -0,0 +1,82 @@ +use gpui::{action, keymap::Binding, MutableAppContext, ViewContext}; +use workspace::Workspace; + +use crate::{mode::Mode, SwitchMode, VimState}; + +action!(MoveToStart); + +pub fn init(cx: &mut MutableAppContext) { + let context = Some("Editor && vim_mode == normal && vim_sub_mode == g"); + cx.add_bindings(vec![ + Binding::new("g", MoveToStart, context), + Binding::new("escape", SwitchMode(Mode::normal()), context), + ]); + + cx.add_action(move_to_start); +} + +fn move_to_start(_: &mut Workspace, _: &MoveToStart, cx: &mut ViewContext) { + VimState::update_global(cx, |state, cx| { + state.update_active_editor(cx, |editor, cx| { + editor.move_to_beginning(&editor::MoveToBeginning, cx); + }); + state.switch_mode(&SwitchMode(Mode::normal()), cx); + }) +} + +#[cfg(test)] +mod test { + use indoc::indoc; + + use crate::{ + mode::{Mode, NormalState}, + vim_test_context::VimTestContext, + }; + + #[gpui::test] + async fn test_g_prefix_and_abort(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true, "").await; + + // Can abort with escape to get back to normal mode + cx.simulate_keystroke("g"); + assert_eq!(cx.mode(), Mode::Normal(NormalState::GPrefix)); + cx.simulate_keystroke("escape"); + assert_eq!(cx.mode(), Mode::normal()); + } + + #[gpui::test] + async fn test_move_to_start(cx: &mut gpui::TestAppContext) { + let initial_content = indoc! {" + The quick + + brown fox jumps + over the lazy dog"}; + let mut cx = VimTestContext::new(cx, true, initial_content).await; + + // Jump to the end to + cx.simulate_keystroke("shift-G"); + cx.assert_editor_state(indoc! {" + The quick + + brown fox jumps + over the lazy do|g"}); + + // Jump to the start + cx.simulate_keystrokes(&["g", "g"]); + cx.assert_editor_state(indoc! {" + |The quick + + brown fox jumps + over the lazy dog"}); + assert_eq!(cx.mode(), Mode::normal()); + + // Repeat action doesn't change + cx.simulate_keystrokes(&["g", "g"]); + cx.assert_editor_state(indoc! {" + |The quick + + brown fox jumps + over the lazy dog"}); + assert_eq!(cx.mode(), Mode::normal()); + } +} diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 26f7e24cf2..609843d969 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -3,7 +3,7 @@ mod insert; mod mode; mod normal; #[cfg(test)] -mod vim_tests; +mod vim_test_context; use collections::HashMap; use editor::{CursorShape, Editor}; @@ -65,8 +65,9 @@ impl VimState { fn set_enabled(&mut self, enabled: bool, cx: &mut MutableAppContext) { if self.enabled != enabled { self.enabled = enabled; + self.mode = Default::default(); if enabled { - self.mode = Mode::Normal; + self.mode = Mode::normal(); } self.sync_editor_options(cx); } @@ -95,3 +96,43 @@ impl VimState { } } } + +#[cfg(test)] +mod test { + use crate::{mode::Mode, vim_test_context::VimTestContext}; + + #[gpui::test] + async fn test_initially_disabled(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, false, "").await; + cx.simulate_keystrokes(&["h", "j", "k", "l"]); + cx.assert_editor_state("hjkl|"); + } + + #[gpui::test] + async fn test_toggle_through_settings(cx: &mut gpui::TestAppContext) { + let mut cx = VimTestContext::new(cx, true, "").await; + + cx.simulate_keystroke("i"); + assert_eq!(cx.mode(), Mode::Insert); + + // Editor acts as though vim is disabled + cx.disable_vim(); + cx.simulate_keystrokes(&["h", "j", "k", "l"]); + cx.assert_editor_state("hjkl|"); + + // Enabling dynamically sets vim mode again and restores normal mode + cx.enable_vim(); + assert_eq!(cx.mode(), Mode::normal()); + cx.simulate_keystrokes(&["h", "h", "h", "l"]); + assert_eq!(cx.editor_text(), "hjkl".to_owned()); + cx.assert_editor_state("hj|kl"); + cx.simulate_keystrokes(&["i", "T", "e", "s", "t"]); + cx.assert_editor_state("hjTest|kl"); + + // Disabling and enabling resets to normal mode + assert_eq!(cx.mode(), Mode::Insert); + cx.disable_vim(); + cx.enable_vim(); + assert_eq!(cx.mode(), Mode::normal()); + } +} diff --git a/crates/vim/src/vim_test_context.rs b/crates/vim/src/vim_test_context.rs new file mode 100644 index 0000000000..91acc8de6c --- /dev/null +++ b/crates/vim/src/vim_test_context.rs @@ -0,0 +1,179 @@ +use std::ops::Deref; + +use editor::{display_map::ToDisplayPoint, Bias, DisplayPoint}; +use gpui::{json::json, keymap::Keystroke, ViewHandle}; +use language::{Point, Selection}; +use util::test::marked_text; +use workspace::{WorkspaceHandle, WorkspaceParams}; + +use crate::*; + +pub struct VimTestContext<'a> { + cx: &'a mut gpui::TestAppContext, + window_id: usize, + editor: ViewHandle, +} + +impl<'a> VimTestContext<'a> { + pub async fn new( + cx: &'a mut gpui::TestAppContext, + enabled: bool, + initial_editor_text: &str, + ) -> VimTestContext<'a> { + cx.update(|cx| { + editor::init(cx); + crate::init(cx); + }); + let params = cx.update(WorkspaceParams::test); + + cx.update(|cx| { + cx.update_global(|settings: &mut Settings, _| { + settings.vim_mode = enabled; + }); + }); + + params + .fs + .as_fake() + .insert_tree( + "/root", + json!({ "dir": { "test.txt": initial_editor_text } }), + ) + .await; + + let (window_id, workspace) = cx.add_window(|cx| Workspace::new(¶ms, cx)); + params + .project + .update(cx, |project, cx| { + project.find_or_create_local_worktree("/root", true, cx) + }) + .await + .unwrap(); + cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx)) + .await; + + let file = cx.read(|cx| workspace.file_project_paths(cx)[0].clone()); + let item = workspace + .update(cx, |workspace, cx| workspace.open_path(file, cx)) + .await + .expect("Could not open test file"); + + let editor = cx.update(|cx| { + item.act_as::(cx) + .expect("Opened test file wasn't an editor") + }); + editor.update(cx, |_, cx| cx.focus_self()); + + Self { + cx, + window_id, + editor, + } + } + + pub fn enable_vim(&mut self) { + self.cx.update(|cx| { + cx.update_global(|settings: &mut Settings, _| { + settings.vim_mode = true; + }); + }) + } + + pub fn disable_vim(&mut self) { + self.cx.update(|cx| { + cx.update_global(|settings: &mut Settings, _| { + settings.vim_mode = false; + }); + }) + } + + pub fn newest_selection(&mut self) -> Selection { + self.editor.update(self.cx, |editor, cx| { + let snapshot = editor.snapshot(cx); + editor + .newest_selection::(cx) + .map(|point| point.to_display_point(&snapshot.display_snapshot)) + }) + } + + pub fn mode(&mut self) -> Mode { + self.cx.update(|cx| cx.global::().mode) + } + + pub fn editor_text(&mut self) -> String { + self.editor + .update(self.cx, |editor, cx| editor.snapshot(cx).text()) + } + + pub fn simulate_keystroke(&mut self, keystroke_text: &str) { + let keystroke = Keystroke::parse(keystroke_text).unwrap(); + let input = if keystroke.modified() { + None + } else { + Some(keystroke.key.clone()) + }; + self.cx + .dispatch_keystroke(self.window_id, keystroke, input, false); + } + + pub fn simulate_keystrokes(&mut self, keystroke_texts: &[&str]) { + for keystroke_text in keystroke_texts.into_iter() { + self.simulate_keystroke(keystroke_text); + } + } + + pub fn assert_newest_selection_head_offset(&mut self, expected_offset: usize) { + let actual_head = self.newest_selection().head(); + let (actual_offset, expected_head) = self.editor.update(self.cx, |editor, cx| { + let snapshot = editor.snapshot(cx); + ( + actual_head.to_offset(&snapshot, Bias::Left), + expected_offset.to_display_point(&snapshot), + ) + }); + let mut actual_position_text = self.editor_text(); + let mut expected_position_text = actual_position_text.clone(); + actual_position_text.insert(actual_offset, '|'); + expected_position_text.insert(expected_offset, '|'); + assert_eq!( + actual_head, expected_head, + "\nActual Position: {}\nExpected Position: {}", + actual_position_text, expected_position_text + ) + } + + pub fn assert_editor_state(&mut self, text: &str) { + let (unmarked_text, markers) = marked_text(&text); + let editor_text = self.editor_text(); + assert_eq!( + editor_text, unmarked_text, + "Unmarked text doesn't match editor text" + ); + let expected_offset = markers[0]; + let actual_head = self.newest_selection().head(); + let (actual_offset, expected_head) = self.editor.update(self.cx, |editor, cx| { + let snapshot = editor.snapshot(cx); + ( + actual_head.to_offset(&snapshot, Bias::Left), + expected_offset.to_display_point(&snapshot), + ) + }); + let mut actual_position_text = self.editor_text(); + let mut expected_position_text = actual_position_text.clone(); + actual_position_text.insert(actual_offset, '|'); + expected_position_text.insert(expected_offset, '|'); + assert_eq!( + actual_head, expected_head, + "\nActual Position: {}\nExpected Position: {}", + actual_position_text, expected_position_text + ) + } +} + +impl<'a> Deref for VimTestContext<'a> { + type Target = gpui::TestAppContext; + + fn deref(&self) -> &Self::Target { + self.cx + } +} diff --git a/crates/vim/src/vim_tests.rs b/crates/vim/src/vim_tests.rs deleted file mode 100644 index 051ff21ce7..0000000000 --- a/crates/vim/src/vim_tests.rs +++ /dev/null @@ -1,253 +0,0 @@ -use indoc::indoc; -use std::ops::Deref; - -use editor::{display_map::ToDisplayPoint, DisplayPoint}; -use gpui::{json::json, keymap::Keystroke, ViewHandle}; -use language::{Point, Selection}; -use util::test::marked_text; -use workspace::{WorkspaceHandle, WorkspaceParams}; - -use crate::*; - -#[gpui::test] -async fn test_insert_mode(cx: &mut gpui::TestAppContext) { - let mut cx = VimTestAppContext::new(cx, true, "").await; - cx.simulate_keystroke("i"); - assert_eq!(cx.mode(), Mode::Insert); - cx.simulate_keystrokes(&["T", "e", "s", "t"]); - cx.assert_newest_selection_head("Test|"); - cx.simulate_keystroke("escape"); - assert_eq!(cx.mode(), Mode::Normal); - cx.assert_newest_selection_head("Tes|t"); -} - -#[gpui::test] -async fn test_normal_hjkl(cx: &mut gpui::TestAppContext) { - let mut cx = VimTestAppContext::new(cx, true, "Test\nTestTest\nTest").await; - cx.simulate_keystroke("l"); - cx.assert_newest_selection_head(indoc! {" - T|est - TestTest - Test"}); - cx.simulate_keystroke("h"); - cx.assert_newest_selection_head(indoc! {" - |Test - TestTest - Test"}); - cx.simulate_keystroke("j"); - cx.assert_newest_selection_head(indoc! {" - Test - |TestTest - Test"}); - cx.simulate_keystroke("k"); - cx.assert_newest_selection_head(indoc! {" - |Test - TestTest - Test"}); - cx.simulate_keystroke("j"); - cx.assert_newest_selection_head(indoc! {" - Test - |TestTest - Test"}); - - // When moving left, cursor does not wrap to the previous line - cx.simulate_keystroke("h"); - cx.assert_newest_selection_head(indoc! {" - Test - |TestTest - Test"}); - - // When moving right, cursor does not reach the line end or wrap to the next line - for _ in 0..9 { - cx.simulate_keystroke("l"); - } - cx.assert_newest_selection_head(indoc! {" - Test - TestTes|t - Test"}); - - // Goal column respects the inability to reach the end of the line - cx.simulate_keystroke("k"); - cx.assert_newest_selection_head(indoc! {" - Tes|t - TestTest - Test"}); - cx.simulate_keystroke("j"); - cx.assert_newest_selection_head(indoc! {" - Test - TestTes|t - Test"}); -} - -#[gpui::test] -async fn test_toggle_through_settings(cx: &mut gpui::TestAppContext) { - let mut cx = VimTestAppContext::new(cx, true, "").await; - - cx.simulate_keystroke("i"); - assert_eq!(cx.mode(), Mode::Insert); - - // Editor acts as though vim is disabled - cx.disable_vim(); - cx.simulate_keystrokes(&["h", "j", "k", "l"]); - cx.assert_newest_selection_head("hjkl|"); - - // Enabling dynamically sets vim mode again and restores normal mode - cx.enable_vim(); - assert_eq!(cx.mode(), Mode::Normal); - cx.simulate_keystrokes(&["h", "h", "h", "l"]); - assert_eq!(cx.editor_text(), "hjkl".to_owned()); - cx.assert_newest_selection_head("hj|kl"); - cx.simulate_keystrokes(&["i", "T", "e", "s", "t"]); - cx.assert_newest_selection_head("hjTest|kl"); - - // Disabling and enabling resets to normal mode - assert_eq!(cx.mode(), Mode::Insert); - cx.disable_vim(); - assert_eq!(cx.mode(), Mode::Insert); - cx.enable_vim(); - assert_eq!(cx.mode(), Mode::Normal); -} - -#[gpui::test] -async fn test_initially_disabled(cx: &mut gpui::TestAppContext) { - let mut cx = VimTestAppContext::new(cx, false, "").await; - cx.simulate_keystrokes(&["h", "j", "k", "l"]); - cx.assert_newest_selection_head("hjkl|"); -} - -struct VimTestAppContext<'a> { - cx: &'a mut gpui::TestAppContext, - window_id: usize, - editor: ViewHandle, -} - -impl<'a> VimTestAppContext<'a> { - async fn new( - cx: &'a mut gpui::TestAppContext, - enabled: bool, - initial_editor_text: &str, - ) -> VimTestAppContext<'a> { - cx.update(|cx| { - editor::init(cx); - crate::init(cx); - }); - let params = cx.update(WorkspaceParams::test); - - cx.update(|cx| { - cx.update_global(|settings: &mut Settings, _| { - settings.vim_mode = enabled; - }); - }); - - params - .fs - .as_fake() - .insert_tree( - "/root", - json!({ "dir": { "test.txt": initial_editor_text } }), - ) - .await; - - let (window_id, workspace) = cx.add_window(|cx| Workspace::new(¶ms, cx)); - params - .project - .update(cx, |project, cx| { - project.find_or_create_local_worktree("/root", true, cx) - }) - .await - .unwrap(); - cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx)) - .await; - - let file = cx.read(|cx| workspace.file_project_paths(cx)[0].clone()); - let item = workspace - .update(cx, |workspace, cx| workspace.open_path(file, cx)) - .await - .expect("Could not open test file"); - - let editor = cx.update(|cx| { - item.act_as::(cx) - .expect("Opened test file wasn't an editor") - }); - editor.update(cx, |_, cx| cx.focus_self()); - - Self { - cx, - window_id, - editor, - } - } - - fn enable_vim(&mut self) { - self.cx.update(|cx| { - cx.update_global(|settings: &mut Settings, _| { - settings.vim_mode = true; - }); - }) - } - - fn disable_vim(&mut self) { - self.cx.update(|cx| { - cx.update_global(|settings: &mut Settings, _| { - settings.vim_mode = false; - }); - }) - } - - fn newest_selection(&mut self) -> Selection { - self.editor.update(self.cx, |editor, cx| { - let snapshot = editor.snapshot(cx); - editor - .newest_selection::(cx) - .map(|point| point.to_display_point(&snapshot.display_snapshot)) - }) - } - - fn mode(&mut self) -> Mode { - self.cx.update(|cx| cx.global::().mode) - } - - fn editor_text(&mut self) -> String { - self.editor - .update(self.cx, |editor, cx| editor.snapshot(cx).text()) - } - - fn simulate_keystroke(&mut self, keystroke_text: &str) { - let keystroke = Keystroke::parse(keystroke_text).unwrap(); - let input = if keystroke.modified() { - None - } else { - Some(keystroke.key.clone()) - }; - self.cx - .dispatch_keystroke(self.window_id, keystroke, input, false); - } - - fn simulate_keystrokes(&mut self, keystroke_texts: &[&str]) { - for keystroke_text in keystroke_texts.into_iter() { - self.simulate_keystroke(keystroke_text); - } - } - - fn assert_newest_selection_head(&mut self, text: &str) { - let (unmarked_text, markers) = marked_text(&text); - assert_eq!( - self.editor_text(), - unmarked_text, - "Unmarked text doesn't match editor text" - ); - let newest_selection = self.newest_selection(); - let expected_head = self.editor.update(self.cx, |editor, cx| { - markers[0].to_display_point(&editor.snapshot(cx)) - }); - assert_eq!(newest_selection.head(), expected_head) - } -} - -impl<'a> Deref for VimTestAppContext<'a> { - type Target = gpui::TestAppContext; - - fn deref(&self) -> &Self::Target { - self.cx - } -} From 4d456d384706f1bf037c0383e3c15d4c307d23ef Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 28 Mar 2022 18:01:29 -0700 Subject: [PATCH 02/68] Remove duplication in build_language_registry --- crates/language/src/language.rs | 4 +- crates/zed/src/language.rs | 125 +++++++++++++++++--------------- 2 files changed, 67 insertions(+), 62 deletions(-) diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 3fbc00c72d..bdc2e120df 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -465,8 +465,8 @@ impl Language { Ok(self) } - pub fn with_lsp_adapter(mut self, lsp_adapter: impl LspAdapter) -> Self { - self.adapter = Some(Arc::new(lsp_adapter)); + pub fn with_lsp_adapter(mut self, lsp_adapter: Arc) -> Self { + self.adapter = Some(lsp_adapter); self } diff --git a/crates/zed/src/language.rs b/crates/zed/src/language.rs index 0d69ebee69..166ec2a839 100644 --- a/crates/zed/src/language.rs +++ b/crates/zed/src/language.rs @@ -534,71 +534,68 @@ impl LspAdapter for JsonLspAdapter { pub fn build_language_registry(login_shell_env_loaded: Task<()>) -> LanguageRegistry { let languages = LanguageRegistry::new(login_shell_env_loaded); - languages.add(Arc::new(c())); - languages.add(Arc::new(json())); - languages.add(Arc::new(rust())); - languages.add(Arc::new(markdown())); + for (name, grammar, lsp_adapter) in [ + ( + "c", + tree_sitter_c::language(), + Some(Arc::new(CLspAdapter) as Arc), + ), + ( + "json", + tree_sitter_json::language(), + Some(Arc::new(JsonLspAdapter)), + ), + ( + "markdown", + tree_sitter_markdown::language(), + None, // + ), + ( + "rust", + tree_sitter_rust::language(), + Some(Arc::new(RustLspAdapter)), + ), + ] { + languages.add(Arc::new(language(name, grammar, lsp_adapter))); + } languages } -fn rust() -> Language { - let grammar = tree_sitter_rust::language(); - let config = toml::from_slice(&LanguageDir::get("rust/config.toml").unwrap().data).unwrap(); - Language::new(config, Some(grammar)) - .with_highlights_query(load_query("rust/highlights.scm").as_ref()) - .unwrap() - .with_brackets_query(load_query("rust/brackets.scm").as_ref()) - .unwrap() - .with_indents_query(load_query("rust/indents.scm").as_ref()) - .unwrap() - .with_outline_query(load_query("rust/outline.scm").as_ref()) - .unwrap() - .with_lsp_adapter(RustLspAdapter) +fn language( + name: &str, + grammar: tree_sitter::Language, + lsp_adapter: Option>, +) -> Language { + let config = toml::from_slice( + &LanguageDir::get(&format!("{}/config.toml", name)) + .unwrap() + .data, + ) + .unwrap(); + let mut language = Language::new(config, Some(grammar)); + if let Some(query) = load_query(&format!("{}/highlights.scm", name)) { + language = language.with_highlights_query(query.as_ref()).unwrap(); + } + if let Some(query) = load_query(&format!("{}/brackets.scm", name)) { + language = language.with_brackets_query(query.as_ref()).unwrap(); + } + if let Some(query) = load_query(&format!("{}/indents.scm", name)) { + language = language.with_indents_query(query.as_ref()).unwrap(); + } + if let Some(query) = load_query(&format!("{}/outline.scm", name)) { + language = language.with_outline_query(query.as_ref()).unwrap(); + } + if let Some(lsp_adapter) = lsp_adapter { + language = language.with_lsp_adapter(lsp_adapter) + } + language } -fn c() -> Language { - let grammar = tree_sitter_c::language(); - let config = toml::from_slice(&LanguageDir::get("c/config.toml").unwrap().data).unwrap(); - Language::new(config, Some(grammar)) - .with_highlights_query(load_query("c/highlights.scm").as_ref()) - .unwrap() - .with_brackets_query(load_query("c/brackets.scm").as_ref()) - .unwrap() - .with_indents_query(load_query("c/indents.scm").as_ref()) - .unwrap() - .with_outline_query(load_query("c/outline.scm").as_ref()) - .unwrap() - .with_lsp_adapter(CLspAdapter) -} - -fn json() -> Language { - let grammar = tree_sitter_json::language(); - let config = toml::from_slice(&LanguageDir::get("json/config.toml").unwrap().data).unwrap(); - Language::new(config, Some(grammar)) - .with_highlights_query(load_query("json/highlights.scm").as_ref()) - .unwrap() - .with_brackets_query(load_query("json/brackets.scm").as_ref()) - .unwrap() - .with_indents_query(load_query("json/indents.scm").as_ref()) - .unwrap() - .with_outline_query(load_query("json/outline.scm").as_ref()) - .unwrap() - .with_lsp_adapter(JsonLspAdapter) -} - -fn markdown() -> Language { - let grammar = tree_sitter_markdown::language(); - let config = toml::from_slice(&LanguageDir::get("markdown/config.toml").unwrap().data).unwrap(); - Language::new(config, Some(grammar)) - .with_highlights_query(load_query("markdown/highlights.scm").as_ref()) - .unwrap() -} - -fn load_query(path: &str) -> Cow<'static, str> { - match LanguageDir::get(path).unwrap().data { +fn load_query(path: &str) -> Option> { + LanguageDir::get(path).map(|item| match item.data { Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), - } + }) } #[cfg(test)] @@ -651,7 +648,11 @@ mod tests { #[test] fn test_rust_label_for_completion() { - let language = rust(); + let language = language( + "rust", + tree_sitter_rust::language(), + Some(Arc::new(RustLspAdapter)), + ); let grammar = language.grammar().unwrap(); let theme = SyntaxTheme::new(vec![ ("type".into(), Color::green().into()), @@ -726,7 +727,11 @@ mod tests { #[test] fn test_rust_label_for_symbol() { - let language = rust(); + let language = language( + "rust", + tree_sitter_rust::language(), + Some(Arc::new(RustLspAdapter)), + ); let grammar = language.grammar().unwrap(); let theme = SyntaxTheme::new(vec![ ("type".into(), Color::green().into()), From a8600e76a3de34968ed27c984ed32c4f17427f46 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 28 Mar 2022 18:14:49 -0700 Subject: [PATCH 03/68] Make language's language server config non-optional --- crates/editor/src/editor.rs | 4 ++-- crates/language/src/language.rs | 24 +++++++----------------- crates/language/src/tests.rs | 1 - crates/project/src/project.rs | 24 +++++++++--------------- crates/server/src/rpc.rs | 22 +++++++++++----------- crates/zed/languages/c/config.toml | 3 --- crates/zed/languages/json/config.toml | 3 --- crates/zed/src/language.rs | 5 +++++ 8 files changed, 34 insertions(+), 52 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f861b6ac60..dac7adfdf8 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -8889,7 +8889,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -8979,7 +8979,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index bdc2e120df..5b917c0fdf 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -51,7 +51,7 @@ lazy_static! { brackets: Default::default(), autoclose_before: Default::default(), line_comment: None, - language_server: None, + language_server: Default::default(), }, None, )); @@ -113,7 +113,8 @@ pub struct LanguageConfig { #[serde(default)] pub autoclose_before: String, pub line_comment: Option, - pub language_server: Option, + #[serde(default)] + pub language_server: LanguageServerConfig, } impl Default for LanguageConfig { @@ -251,20 +252,12 @@ impl LanguageRegistry { cx: &mut MutableAppContext, ) -> Option>> { #[cfg(any(test, feature = "test-support"))] - if language - .config - .language_server - .as_ref() - .and_then(|config| config.fake_config.as_ref()) - .is_some() - { + if language.config.language_server.fake_config.is_some() { let language = language.clone(); return Some(cx.spawn(|mut cx| async move { let fake_config = language .config .language_server - .as_ref() - .unwrap() .fake_config .as_ref() .unwrap(); @@ -478,18 +471,15 @@ impl Language { self.config.line_comment.as_deref() } - pub fn disk_based_diagnostic_sources(&self) -> Option<&HashSet> { - self.config - .language_server - .as_ref() - .map(|config| &config.disk_based_diagnostic_sources) + pub fn disk_based_diagnostic_sources(&self) -> &HashSet { + &self.config.language_server.disk_based_diagnostic_sources } pub fn disk_based_diagnostics_progress_token(&self) -> Option<&String> { self.config .language_server + .disk_based_diagnostics_progress_token .as_ref() - .and_then(|config| config.disk_based_diagnostics_progress_token.as_ref()) } pub fn process_diagnostics(&self, diagnostics: &mut lsp::PublishDiagnosticsParams) { diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index 98ecf63a46..8af4ff247e 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -869,7 +869,6 @@ fn rust_lang() -> Language { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: None, ..Default::default() }, Some(tree_sitter_rust::language()), diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 404d867069..1a41475909 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1599,14 +1599,8 @@ impl Project { ), ); } - self.update_diagnostics( - params, - language - .disk_based_diagnostic_sources() - .unwrap_or(&Default::default()), - cx, - ) - .log_err(); + self.update_diagnostics(params, language.disk_based_diagnostic_sources(), cx) + .log_err(); if disk_diagnostics_token.is_none() { self.disk_based_diagnostics_finished(cx); self.broadcast_language_server_update( @@ -4697,7 +4691,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(rust_lsp_config), + language_server: rust_lsp_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -4706,7 +4700,7 @@ mod tests { LanguageConfig { name: "JSON".into(), path_suffixes: vec!["json".to_string()], - language_server: Some(json_lsp_config), + language_server: json_lsp_config, ..Default::default() }, None, @@ -4906,7 +4900,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -5023,7 +5017,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(lsp_config), + language_server: lsp_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -5394,7 +5388,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(lsp_config), + language_server: lsp_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -5744,7 +5738,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -6680,7 +6674,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 374aaf6a7e..b329839de2 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -2050,7 +2050,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -2279,7 +2279,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -2474,7 +2474,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -2589,7 +2589,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -2732,7 +2732,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -2972,7 +2972,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -3119,7 +3119,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -3252,7 +3252,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -3349,7 +3349,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -3585,7 +3585,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -5456,7 +5456,7 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: Some(language_server_config), + language_server: language_server_config, ..Default::default() }, None, diff --git a/crates/zed/languages/c/config.toml b/crates/zed/languages/c/config.toml index aeee919ac6..b7e1f07443 100644 --- a/crates/zed/languages/c/config.toml +++ b/crates/zed/languages/c/config.toml @@ -9,6 +9,3 @@ brackets = [ { start = "\"", end = "\"", close = true, newline = false }, { start = "/*", end = " */", close = true, newline = false }, ] - -[language_server] -disk_based_diagnostic_sources = [] \ No newline at end of file diff --git a/crates/zed/languages/json/config.toml b/crates/zed/languages/json/config.toml index 27d1193b0d..ad87dcf633 100644 --- a/crates/zed/languages/json/config.toml +++ b/crates/zed/languages/json/config.toml @@ -6,6 +6,3 @@ brackets = [ { start = "[", end = "]", close = true, newline = true }, { start = "\"", end = "\"", close = true, newline = false }, ] - -[language_server] -disk_based_diagnostic_sources = [] \ No newline at end of file diff --git a/crates/zed/src/language.rs b/crates/zed/src/language.rs index 166ec2a839..fbf413c644 100644 --- a/crates/zed/src/language.rs +++ b/crates/zed/src/language.rs @@ -555,6 +555,11 @@ pub fn build_language_registry(login_shell_env_loaded: Task<()>) -> LanguageRegi tree_sitter_rust::language(), Some(Arc::new(RustLspAdapter)), ), + ( + "typescript", + tree_sitter_typescript::language_typescript(), + None, // + ), ] { languages.add(Arc::new(language(name, grammar, lsp_adapter))); } From dd1c88afa5c703ced5bb36205415d2501ce4cb23 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 28 Mar 2022 18:18:49 -0700 Subject: [PATCH 04/68] Add basic TypeScript and TSX support Co-Authored-By: Keith Simmons --- Cargo.lock | 11 + crates/zed/Cargo.toml | 1 + crates/zed/languages/tsx/brackets.scm | 1 + crates/zed/languages/tsx/config.toml | 12 + crates/zed/languages/tsx/highlights-jsx.scm | 0 crates/zed/languages/tsx/highlights.scm | 1 + crates/zed/languages/tsx/indents.scm | 1 + crates/zed/languages/tsx/outline.scm | 1 + crates/zed/languages/typescript/brackets.scm | 5 + crates/zed/languages/typescript/config.toml | 12 + .../zed/languages/typescript/highlights.scm | 219 ++++++++++++++++++ crates/zed/languages/typescript/indents.scm | 15 ++ crates/zed/languages/typescript/outline.scm | 55 +++++ crates/zed/src/language.rs | 52 +++-- 14 files changed, 373 insertions(+), 13 deletions(-) create mode 120000 crates/zed/languages/tsx/brackets.scm create mode 100644 crates/zed/languages/tsx/config.toml create mode 100644 crates/zed/languages/tsx/highlights-jsx.scm create mode 120000 crates/zed/languages/tsx/highlights.scm create mode 120000 crates/zed/languages/tsx/indents.scm create mode 120000 crates/zed/languages/tsx/outline.scm create mode 100644 crates/zed/languages/typescript/brackets.scm create mode 100644 crates/zed/languages/typescript/config.toml create mode 100644 crates/zed/languages/typescript/highlights.scm create mode 100644 crates/zed/languages/typescript/indents.scm create mode 100644 crates/zed/languages/typescript/outline.scm diff --git a/Cargo.lock b/Cargo.lock index 9c36923964..a90a6d2adf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5415,6 +5415,16 @@ dependencies = [ "tree-sitter", ] +[[package]] +name = "tree-sitter-typescript" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8ed0ecb931cdff13c6a13f45ccd615156e2779d9ffb0395864e05505e6e86d" +dependencies = [ + "cc", + "tree-sitter", +] + [[package]] name = "ttf-parser" version = "0.9.0" @@ -6025,6 +6035,7 @@ dependencies = [ "tree-sitter-json", "tree-sitter-markdown", "tree-sitter-rust", + "tree-sitter-typescript", "unindent", "url", "util", diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index fc9946b778..869a6a9999 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -98,6 +98,7 @@ tree-sitter-c = "0.20.1" tree-sitter-json = "0.19.0" tree-sitter-rust = "0.20.1" tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" } +tree-sitter-typescript = "0.20.1" url = "2.2" [dev-dependencies] diff --git a/crates/zed/languages/tsx/brackets.scm b/crates/zed/languages/tsx/brackets.scm new file mode 120000 index 0000000000..e6835c943b --- /dev/null +++ b/crates/zed/languages/tsx/brackets.scm @@ -0,0 +1 @@ +../typescript/brackets.scm \ No newline at end of file diff --git a/crates/zed/languages/tsx/config.toml b/crates/zed/languages/tsx/config.toml new file mode 100644 index 0000000000..62717266df --- /dev/null +++ b/crates/zed/languages/tsx/config.toml @@ -0,0 +1,12 @@ +name = "TSX" +path_suffixes = ["tsx"] +line_comment = "// " +autoclose_before = ";:.,=}])>" +brackets = [ + { start = "{", end = "}", close = true, newline = true }, + { start = "[", end = "]", close = true, newline = true }, + { start = "(", end = ")", close = true, newline = true }, + { start = "<", end = ">", close = false, newline = true }, + { start = "\"", end = "\"", close = true, newline = false }, + { start = "/*", end = " */", close = true, newline = false }, +] diff --git a/crates/zed/languages/tsx/highlights-jsx.scm b/crates/zed/languages/tsx/highlights-jsx.scm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/crates/zed/languages/tsx/highlights.scm b/crates/zed/languages/tsx/highlights.scm new file mode 120000 index 0000000000..226302a5d1 --- /dev/null +++ b/crates/zed/languages/tsx/highlights.scm @@ -0,0 +1 @@ +../typescript/highlights.scm \ No newline at end of file diff --git a/crates/zed/languages/tsx/indents.scm b/crates/zed/languages/tsx/indents.scm new file mode 120000 index 0000000000..502c2a060a --- /dev/null +++ b/crates/zed/languages/tsx/indents.scm @@ -0,0 +1 @@ +../typescript/indents.scm \ No newline at end of file diff --git a/crates/zed/languages/tsx/outline.scm b/crates/zed/languages/tsx/outline.scm new file mode 120000 index 0000000000..a0df409fda --- /dev/null +++ b/crates/zed/languages/tsx/outline.scm @@ -0,0 +1 @@ +../typescript/outline.scm \ No newline at end of file diff --git a/crates/zed/languages/typescript/brackets.scm b/crates/zed/languages/typescript/brackets.scm new file mode 100644 index 0000000000..63395f81d8 --- /dev/null +++ b/crates/zed/languages/typescript/brackets.scm @@ -0,0 +1,5 @@ +("(" @open ")" @close) +("[" @open "]" @close) +("{" @open "}" @close) +("<" @open ">" @close) +("\"" @open "\"" @close) diff --git a/crates/zed/languages/typescript/config.toml b/crates/zed/languages/typescript/config.toml new file mode 100644 index 0000000000..5d491d2d32 --- /dev/null +++ b/crates/zed/languages/typescript/config.toml @@ -0,0 +1,12 @@ +name = "TypeScript" +path_suffixes = ["ts"] +line_comment = "// " +autoclose_before = ";:.,=}])>" +brackets = [ + { start = "{", end = "}", close = true, newline = true }, + { start = "[", end = "]", close = true, newline = true }, + { start = "(", end = ")", close = true, newline = true }, + { start = "<", end = ">", close = false, newline = true }, + { start = "\"", end = "\"", close = true, newline = false }, + { start = "/*", end = " */", close = true, newline = false }, +] diff --git a/crates/zed/languages/typescript/highlights.scm b/crates/zed/languages/typescript/highlights.scm new file mode 100644 index 0000000000..cb4e82b33d --- /dev/null +++ b/crates/zed/languages/typescript/highlights.scm @@ -0,0 +1,219 @@ +; Variables + +(identifier) @variable + +; Properties + +(property_identifier) @property + +; Function and method calls + +(call_expression + function: (identifier) @function) + +(call_expression + function: (member_expression + property: (property_identifier) @function.method)) + +; Function and method definitions + +(function + name: (identifier) @function) +(function_declaration + name: (identifier) @function) +(method_definition + name: (property_identifier) @function.method) + +(pair + key: (property_identifier) @function.method + value: [(function) (arrow_function)]) + +(assignment_expression + left: (member_expression + property: (property_identifier) @function.method) + right: [(function) (arrow_function)]) + +(variable_declarator + name: (identifier) @function + value: [(function) (arrow_function)]) + +(assignment_expression + left: (identifier) @function + right: [(function) (arrow_function)]) + +; Special identifiers + +((identifier) @constructor + (#match? @constructor "^[A-Z]")) + +([ + (identifier) + (shorthand_property_identifier) + (shorthand_property_identifier_pattern) + ] @constant + (#match? @constant "^[A-Z_][A-Z\\d_]+$")) + +; Literals + +(this) @variable.builtin +(super) @variable.builtin + +[ + (true) + (false) + (null) + (undefined) +] @constant.builtin + +(comment) @comment + +[ + (string) + (template_string) +] @string + +(regex) @string.special +(number) @number + +; Tokens + +(template_substitution + "${" @punctuation.special + "}" @punctuation.special) @embedded + +[ + ";" + "?." + "." + "," +] @punctuation.delimiter + +[ + "-" + "--" + "-=" + "+" + "++" + "+=" + "*" + "*=" + "**" + "**=" + "/" + "/=" + "%" + "%=" + "<" + "<=" + "<<" + "<<=" + "=" + "==" + "===" + "!" + "!=" + "!==" + "=>" + ">" + ">=" + ">>" + ">>=" + ">>>" + ">>>=" + "~" + "^" + "&" + "|" + "^=" + "&=" + "|=" + "&&" + "||" + "??" + "&&=" + "||=" + "??=" +] @operator + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +[ + "as" + "async" + "await" + "break" + "case" + "catch" + "class" + "const" + "continue" + "debugger" + "default" + "delete" + "do" + "else" + "export" + "extends" + "finally" + "for" + "from" + "function" + "get" + "if" + "import" + "in" + "instanceof" + "let" + "new" + "of" + "return" + "set" + "static" + "switch" + "target" + "throw" + "try" + "typeof" + "var" + "void" + "while" + "with" + "yield" +] @keyword + +; Types + +(type_identifier) @type +(predefined_type) @type.builtin + +((identifier) @type + (#match? @type "^[A-Z]")) + +(type_arguments + "<" @punctuation.bracket + ">" @punctuation.bracket) + +; Keywords + +[ "abstract" + "declare" + "enum" + "export" + "implements" + "interface" + "keyof" + "namespace" + "private" + "protected" + "public" + "type" + "readonly" + "override" +] @keyword \ No newline at end of file diff --git a/crates/zed/languages/typescript/indents.scm b/crates/zed/languages/typescript/indents.scm new file mode 100644 index 0000000000..107e6ff8e0 --- /dev/null +++ b/crates/zed/languages/typescript/indents.scm @@ -0,0 +1,15 @@ +[ + (call_expression) + (assignment_expression) + (member_expression) + (lexical_declaration) + (variable_declaration) + (assignment_expression) + (if_statement) + (for_statement) +] @indent + +(_ "[" "]" @end) @indent +(_ "<" ">" @end) @indent +(_ "{" "}" @end) @indent +(_ "(" ")" @end) @indent diff --git a/crates/zed/languages/typescript/outline.scm b/crates/zed/languages/typescript/outline.scm new file mode 100644 index 0000000000..f8691fa41d --- /dev/null +++ b/crates/zed/languages/typescript/outline.scm @@ -0,0 +1,55 @@ +(internal_module + "namespace" @context + name: (_) @name) @item + +(enum_declaration + "enum" @context + name: (_) @name) @item + +(function_declaration + "async"? @context + "function" @context + name: (_) @name + parameters: (formal_parameters + "(" @context + ")" @context)) @item + +(interface_declaration + "interface" @context + name: (_) @name) @item + +(program + (lexical_declaration + ["let" "const"] @context + (variable_declarator + name: (_) @name) @item)) + +(class_declaration + "class" @context + name: (_) @name) @item + +(method_definition + [ + "get" + "set" + "async" + "*" + "readonly" + "static" + (override_modifier) + (accessibility_modifier) + ]* @context + name: (_) @name + parameters: (formal_parameters + "(" @context + ")" @context)) @item + +(public_field_definition + [ + "declare" + "readonly" + "abstract" + "static" + (accessibility_modifier) + ]* @context + name: (_) @name) @item diff --git a/crates/zed/src/language.rs b/crates/zed/src/language.rs index fbf413c644..50540bc82c 100644 --- a/crates/zed/src/language.rs +++ b/crates/zed/src/language.rs @@ -555,6 +555,11 @@ pub fn build_language_registry(login_shell_env_loaded: Task<()>) -> LanguageRegi tree_sitter_rust::language(), Some(Arc::new(RustLspAdapter)), ), + ( + "tsx", + tree_sitter_typescript::language_tsx(), + None, // + ), ( "typescript", tree_sitter_typescript::language_typescript(), @@ -578,17 +583,26 @@ fn language( ) .unwrap(); let mut language = Language::new(config, Some(grammar)); - if let Some(query) = load_query(&format!("{}/highlights.scm", name)) { - language = language.with_highlights_query(query.as_ref()).unwrap(); + + if let Some(query) = load_query(name, "/highlights") { + language = language + .with_highlights_query(query.as_ref()) + .expect("failed to evaluate highlights query"); } - if let Some(query) = load_query(&format!("{}/brackets.scm", name)) { - language = language.with_brackets_query(query.as_ref()).unwrap(); + if let Some(query) = load_query(name, "/brackets") { + language = language + .with_brackets_query(query.as_ref()) + .expect("failed to load brackets query"); } - if let Some(query) = load_query(&format!("{}/indents.scm", name)) { - language = language.with_indents_query(query.as_ref()).unwrap(); + if let Some(query) = load_query(name, "/indents") { + language = language + .with_indents_query(query.as_ref()) + .expect("failed to load indents query"); } - if let Some(query) = load_query(&format!("{}/outline.scm", name)) { - language = language.with_outline_query(query.as_ref()).unwrap(); + if let Some(query) = load_query(name, "/outline") { + language = language + .with_outline_query(query.as_ref()) + .expect("failed to load outline query"); } if let Some(lsp_adapter) = lsp_adapter { language = language.with_lsp_adapter(lsp_adapter) @@ -596,11 +610,23 @@ fn language( language } -fn load_query(path: &str) -> Option> { - LanguageDir::get(path).map(|item| match item.data { - Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), - Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), - }) +fn load_query(name: &str, filename_prefix: &str) -> Option> { + let mut result = None; + for path in LanguageDir::iter() { + if let Some(remainder) = path.strip_prefix(name) { + if remainder.starts_with(filename_prefix) { + let contents = match LanguageDir::get(path.as_ref()).unwrap().data { + Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), + Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), + }; + match &mut result { + None => result = Some(contents), + Some(r) => r.to_mut().push_str(contents.as_ref()), + } + } + } + } + result } #[cfg(test)] From d466768eed098a2185d68b6d5b19daa57175a6fc Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 29 Mar 2022 11:06:08 -0700 Subject: [PATCH 05/68] WIP --- crates/zed/src/languages.rs | 125 ++++++ crates/zed/src/languages/c.rs | 136 +++++++ crates/zed/{ => src}/languages/c/brackets.scm | 0 crates/zed/{ => src}/languages/c/config.toml | 0 .../zed/{ => src}/languages/c/highlights.scm | 0 crates/zed/{ => src}/languages/c/indents.scm | 0 crates/zed/{ => src}/languages/c/outline.scm | 0 crates/zed/src/languages/json.rs | 131 +++++++ .../zed/{ => src}/languages/json/brackets.scm | 0 .../zed/{ => src}/languages/json/config.toml | 0 .../{ => src}/languages/json/highlights.scm | 0 .../zed/{ => src}/languages/json/indents.scm | 0 .../zed/{ => src}/languages/json/outline.scm | 0 .../{ => src}/languages/markdown/config.toml | 0 .../languages/markdown/highlights.scm | 0 .../src/{language.rs => languages/rust.rs} | 370 +----------------- .../zed/{ => src}/languages/rust/brackets.scm | 0 .../zed/{ => src}/languages/rust/config.toml | 0 .../{ => src}/languages/rust/highlights.scm | 0 .../zed/{ => src}/languages/rust/indents.scm | 0 .../zed/{ => src}/languages/rust/outline.scm | 0 .../zed/{ => src}/languages/tsx/brackets.scm | 0 .../zed/{ => src}/languages/tsx/config.toml | 0 .../languages/tsx/highlights-jsx.scm | 0 .../{ => src}/languages/tsx/highlights.scm | 0 .../zed/{ => src}/languages/tsx/indents.scm | 0 .../zed/{ => src}/languages/tsx/outline.scm | 0 crates/zed/src/languages/typescript.rs | 121 ++++++ .../languages/typescript/brackets.scm | 0 .../languages/typescript/config.toml | 0 .../languages/typescript/highlights.scm | 0 .../languages/typescript/indents.scm | 0 .../languages/typescript/outline.scm | 0 crates/zed/src/main.rs | 6 +- crates/zed/src/zed.rs | 6 +- 35 files changed, 523 insertions(+), 372 deletions(-) create mode 100644 crates/zed/src/languages.rs create mode 100644 crates/zed/src/languages/c.rs rename crates/zed/{ => src}/languages/c/brackets.scm (100%) rename crates/zed/{ => src}/languages/c/config.toml (100%) rename crates/zed/{ => src}/languages/c/highlights.scm (100%) rename crates/zed/{ => src}/languages/c/indents.scm (100%) rename crates/zed/{ => src}/languages/c/outline.scm (100%) create mode 100644 crates/zed/src/languages/json.rs rename crates/zed/{ => src}/languages/json/brackets.scm (100%) rename crates/zed/{ => src}/languages/json/config.toml (100%) rename crates/zed/{ => src}/languages/json/highlights.scm (100%) rename crates/zed/{ => src}/languages/json/indents.scm (100%) rename crates/zed/{ => src}/languages/json/outline.scm (100%) rename crates/zed/{ => src}/languages/markdown/config.toml (100%) rename crates/zed/{ => src}/languages/markdown/highlights.scm (100%) rename crates/zed/src/{language.rs => languages/rust.rs} (57%) rename crates/zed/{ => src}/languages/rust/brackets.scm (100%) rename crates/zed/{ => src}/languages/rust/config.toml (100%) rename crates/zed/{ => src}/languages/rust/highlights.scm (100%) rename crates/zed/{ => src}/languages/rust/indents.scm (100%) rename crates/zed/{ => src}/languages/rust/outline.scm (100%) rename crates/zed/{ => src}/languages/tsx/brackets.scm (100%) rename crates/zed/{ => src}/languages/tsx/config.toml (100%) rename crates/zed/{ => src}/languages/tsx/highlights-jsx.scm (100%) rename crates/zed/{ => src}/languages/tsx/highlights.scm (100%) rename crates/zed/{ => src}/languages/tsx/indents.scm (100%) rename crates/zed/{ => src}/languages/tsx/outline.scm (100%) create mode 100644 crates/zed/src/languages/typescript.rs rename crates/zed/{ => src}/languages/typescript/brackets.scm (100%) rename crates/zed/{ => src}/languages/typescript/config.toml (100%) rename crates/zed/{ => src}/languages/typescript/highlights.scm (100%) rename crates/zed/{ => src}/languages/typescript/indents.scm (100%) rename crates/zed/{ => src}/languages/typescript/outline.scm (100%) diff --git a/crates/zed/src/languages.rs b/crates/zed/src/languages.rs new file mode 100644 index 0000000000..607f4c30bb --- /dev/null +++ b/crates/zed/src/languages.rs @@ -0,0 +1,125 @@ +use client::http::{self, HttpClient, Method}; +use gpui::Task; +pub use language::*; +use rust_embed::RustEmbed; +use serde::Deserialize; +use std::{borrow::Cow, str, sync::Arc}; + +mod c; +mod json; +mod rust; +mod typescript; + +#[derive(RustEmbed)] +#[folder = "src/languages"] +#[exclude = "*.rs"] +struct LanguageDir; + +#[derive(Deserialize)] +struct GithubRelease { + name: String, + assets: Vec, +} + +#[derive(Deserialize)] +struct GithubReleaseAsset { + name: String, + browser_download_url: http::Url, +} + +pub fn build_language_registry(login_shell_env_loaded: Task<()>) -> LanguageRegistry { + let languages = LanguageRegistry::new(login_shell_env_loaded); + for (name, grammar, lsp_adapter) in [ + ( + "c", + tree_sitter_c::language(), + Some(Arc::new(c::CLspAdapter) as Arc), + ), + ( + "json", + tree_sitter_json::language(), + Some(Arc::new(json::JsonLspAdapter)), + ), + ( + "markdown", + tree_sitter_markdown::language(), + None, // + ), + ( + "rust", + tree_sitter_rust::language(), + Some(Arc::new(rust::RustLspAdapter)), + ), + ( + "tsx", + tree_sitter_typescript::language_tsx(), + None, // + ), + ( + "typescript", + tree_sitter_typescript::language_typescript(), + Some(Arc::new(typescript::TypeScriptLspAdapter)), + ), + ] { + languages.add(Arc::new(language(name, grammar, lsp_adapter))); + } + languages +} + +fn language( + name: &str, + grammar: tree_sitter::Language, + lsp_adapter: Option>, +) -> Language { + let config = toml::from_slice( + &LanguageDir::get(&format!("{}/config.toml", name)) + .unwrap() + .data, + ) + .unwrap(); + let mut language = Language::new(config, Some(grammar)); + + if let Some(query) = load_query(name, "/highlights") { + language = language + .with_highlights_query(query.as_ref()) + .expect("failed to evaluate highlights query"); + } + if let Some(query) = load_query(name, "/brackets") { + language = language + .with_brackets_query(query.as_ref()) + .expect("failed to load brackets query"); + } + if let Some(query) = load_query(name, "/indents") { + language = language + .with_indents_query(query.as_ref()) + .expect("failed to load indents query"); + } + if let Some(query) = load_query(name, "/outline") { + language = language + .with_outline_query(query.as_ref()) + .expect("failed to load outline query"); + } + if let Some(lsp_adapter) = lsp_adapter { + language = language.with_lsp_adapter(lsp_adapter) + } + language +} + +fn load_query(name: &str, filename_prefix: &str) -> Option> { + let mut result = None; + for path in LanguageDir::iter() { + if let Some(remainder) = path.strip_prefix(name) { + if remainder.starts_with(filename_prefix) { + let contents = match LanguageDir::get(path.as_ref()).unwrap().data { + Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), + Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), + }; + match &mut result { + None => result = Some(contents), + Some(r) => r.to_mut().push_str(contents.as_ref()), + } + } + } + } + result +} diff --git a/crates/zed/src/languages/c.rs b/crates/zed/src/languages/c.rs new file mode 100644 index 0000000000..9ce3eab2f7 --- /dev/null +++ b/crates/zed/src/languages/c.rs @@ -0,0 +1,136 @@ +use anyhow::{anyhow, Result}; +use client::http::{self, HttpClient, Method}; +use futures::{future::BoxFuture, FutureExt, StreamExt}; +pub use language::*; +use smol::fs::{self, File}; +use std::{path::PathBuf, str, sync::Arc}; +use util::{ResultExt, TryFutureExt}; + +use super::GithubRelease; + +pub struct CLspAdapter; + +impl super::LspAdapter for CLspAdapter { + fn name(&self) -> &'static str { + "clangd" + } + + fn fetch_latest_server_version( + &self, + http: Arc, + ) -> BoxFuture<'static, Result> { + async move { + let release = http + .send( + surf::RequestBuilder::new( + Method::Get, + http::Url::parse( + "https://api.github.com/repos/clangd/clangd/releases/latest", + ) + .unwrap(), + ) + .middleware(surf::middleware::Redirect::default()) + .build(), + ) + .await + .map_err(|err| anyhow!("error fetching latest release: {}", err))? + .body_json::() + .await + .map_err(|err| anyhow!("error parsing latest release: {}", err))?; + let asset_name = format!("clangd-mac-{}.zip", release.name); + let asset = release + .assets + .iter() + .find(|asset| asset.name == asset_name) + .ok_or_else(|| anyhow!("no release found matching {:?}", asset_name))?; + Ok(LspBinaryVersion { + name: release.name, + url: Some(asset.browser_download_url.clone()), + }) + } + .boxed() + } + + fn fetch_server_binary( + &self, + version: LspBinaryVersion, + http: Arc, + container_dir: PathBuf, + ) -> BoxFuture<'static, Result> { + async move { + let zip_path = container_dir.join(format!("clangd_{}.zip", version.name)); + let version_dir = container_dir.join(format!("clangd_{}", version.name)); + let binary_path = version_dir.join("bin/clangd"); + + if fs::metadata(&binary_path).await.is_err() { + let response = http + .send( + surf::RequestBuilder::new(Method::Get, version.url.unwrap()) + .middleware(surf::middleware::Redirect::default()) + .build(), + ) + .await + .map_err(|err| anyhow!("error downloading release: {}", err))?; + let mut file = File::create(&zip_path).await?; + if !response.status().is_success() { + Err(anyhow!( + "download failed with status {}", + response.status().to_string() + ))?; + } + futures::io::copy(response, &mut file).await?; + + let unzip_status = smol::process::Command::new("unzip") + .current_dir(&container_dir) + .arg(&zip_path) + .output() + .await? + .status; + if !unzip_status.success() { + Err(anyhow!("failed to unzip clangd archive"))?; + } + + if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() { + while let Some(entry) = entries.next().await { + if let Some(entry) = entry.log_err() { + let entry_path = entry.path(); + if entry_path.as_path() != version_dir { + fs::remove_dir_all(&entry_path).await.log_err(); + } + } + } + } + } + + Ok(binary_path) + } + .boxed() + } + + fn cached_server_binary(&self, container_dir: PathBuf) -> BoxFuture<'static, Option> { + async move { + let mut last_clangd_dir = None; + let mut entries = fs::read_dir(&container_dir).await?; + while let Some(entry) = entries.next().await { + let entry = entry?; + if entry.file_type().await?.is_dir() { + last_clangd_dir = Some(entry.path()); + } + } + let clangd_dir = last_clangd_dir.ok_or_else(|| anyhow!("no cached binary"))?; + let clangd_bin = clangd_dir.join("bin/clangd"); + if clangd_bin.exists() { + Ok(clangd_bin) + } else { + Err(anyhow!( + "missing clangd binary in directory {:?}", + clangd_dir + )) + } + } + .log_err() + .boxed() + } + + fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {} +} diff --git a/crates/zed/languages/c/brackets.scm b/crates/zed/src/languages/c/brackets.scm similarity index 100% rename from crates/zed/languages/c/brackets.scm rename to crates/zed/src/languages/c/brackets.scm diff --git a/crates/zed/languages/c/config.toml b/crates/zed/src/languages/c/config.toml similarity index 100% rename from crates/zed/languages/c/config.toml rename to crates/zed/src/languages/c/config.toml diff --git a/crates/zed/languages/c/highlights.scm b/crates/zed/src/languages/c/highlights.scm similarity index 100% rename from crates/zed/languages/c/highlights.scm rename to crates/zed/src/languages/c/highlights.scm diff --git a/crates/zed/languages/c/indents.scm b/crates/zed/src/languages/c/indents.scm similarity index 100% rename from crates/zed/languages/c/indents.scm rename to crates/zed/src/languages/c/indents.scm diff --git a/crates/zed/languages/c/outline.scm b/crates/zed/src/languages/c/outline.scm similarity index 100% rename from crates/zed/languages/c/outline.scm rename to crates/zed/src/languages/c/outline.scm diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs new file mode 100644 index 0000000000..bb7744714f --- /dev/null +++ b/crates/zed/src/languages/json.rs @@ -0,0 +1,131 @@ +use anyhow::{anyhow, Context, Result}; +use client::http::HttpClient; +use futures::{future::BoxFuture, FutureExt, StreamExt}; +use language::{LspAdapter, LspBinaryVersion}; +use serde::Deserialize; +use serde_json::json; +use smol::fs; +use std::{path::PathBuf, sync::Arc}; +use util::ResultExt; + +pub struct JsonLspAdapter; + +impl JsonLspAdapter { + const BIN_PATH: &'static str = + "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver"; +} + +impl LspAdapter for JsonLspAdapter { + fn name(&self) -> &'static str { + "vscode-json-languageserver" + } + + fn server_args(&self) -> &[&str] { + &["--stdio"] + } + + fn fetch_latest_server_version( + &self, + _: Arc, + ) -> BoxFuture<'static, Result> { + async move { + #[derive(Deserialize)] + struct NpmInfo { + versions: Vec, + } + + let output = smol::process::Command::new("npm") + .args(["info", "vscode-json-languageserver", "--json"]) + .output() + .await?; + if !output.status.success() { + Err(anyhow!("failed to execute npm info"))?; + } + let mut info: NpmInfo = serde_json::from_slice(&output.stdout)?; + + Ok(LspBinaryVersion { + name: info + .versions + .pop() + .ok_or_else(|| anyhow!("no versions found in npm info"))?, + url: Default::default(), + }) + } + .boxed() + } + + fn fetch_server_binary( + &self, + version: LspBinaryVersion, + _: Arc, + container_dir: PathBuf, + ) -> BoxFuture<'static, Result> { + async move { + let version_dir = container_dir.join(&version.name); + fs::create_dir_all(&version_dir) + .await + .context("failed to create version directory")?; + let binary_path = version_dir.join(Self::BIN_PATH); + + if fs::metadata(&binary_path).await.is_err() { + let output = smol::process::Command::new("npm") + .current_dir(&version_dir) + .arg("install") + .arg(format!("vscode-json-languageserver@{}", version.name)) + .output() + .await + .context("failed to run npm install")?; + if !output.status.success() { + Err(anyhow!("failed to install vscode-json-languageserver"))?; + } + + if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() { + while let Some(entry) = entries.next().await { + if let Some(entry) = entry.log_err() { + let entry_path = entry.path(); + if entry_path.as_path() != version_dir { + fs::remove_dir_all(&entry_path).await.log_err(); + } + } + } + } + } + + Ok(binary_path) + } + .boxed() + } + + fn cached_server_binary(&self, container_dir: PathBuf) -> BoxFuture<'static, Option> { + async move { + let mut last_version_dir = None; + let mut entries = fs::read_dir(&container_dir).await?; + while let Some(entry) = entries.next().await { + let entry = entry?; + if entry.file_type().await?.is_dir() { + last_version_dir = Some(entry.path()); + } + } + let last_version_dir = last_version_dir.ok_or_else(|| anyhow!("no cached binary"))?; + let bin_path = last_version_dir.join(Self::BIN_PATH); + if bin_path.exists() { + Ok(bin_path) + } else { + Err(anyhow!( + "missing executable in directory {:?}", + last_version_dir + )) + } + } + .log_err() + .boxed() + } + + fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {} + + fn initialization_options(&self) -> Option { + Some(json!({ + "provideFormatter": true + })) + } +} diff --git a/crates/zed/languages/json/brackets.scm b/crates/zed/src/languages/json/brackets.scm similarity index 100% rename from crates/zed/languages/json/brackets.scm rename to crates/zed/src/languages/json/brackets.scm diff --git a/crates/zed/languages/json/config.toml b/crates/zed/src/languages/json/config.toml similarity index 100% rename from crates/zed/languages/json/config.toml rename to crates/zed/src/languages/json/config.toml diff --git a/crates/zed/languages/json/highlights.scm b/crates/zed/src/languages/json/highlights.scm similarity index 100% rename from crates/zed/languages/json/highlights.scm rename to crates/zed/src/languages/json/highlights.scm diff --git a/crates/zed/languages/json/indents.scm b/crates/zed/src/languages/json/indents.scm similarity index 100% rename from crates/zed/languages/json/indents.scm rename to crates/zed/src/languages/json/indents.scm diff --git a/crates/zed/languages/json/outline.scm b/crates/zed/src/languages/json/outline.scm similarity index 100% rename from crates/zed/languages/json/outline.scm rename to crates/zed/src/languages/json/outline.scm diff --git a/crates/zed/languages/markdown/config.toml b/crates/zed/src/languages/markdown/config.toml similarity index 100% rename from crates/zed/languages/markdown/config.toml rename to crates/zed/src/languages/markdown/config.toml diff --git a/crates/zed/languages/markdown/highlights.scm b/crates/zed/src/languages/markdown/highlights.scm similarity index 100% rename from crates/zed/languages/markdown/highlights.scm rename to crates/zed/src/languages/markdown/highlights.scm diff --git a/crates/zed/src/language.rs b/crates/zed/src/languages/rust.rs similarity index 57% rename from crates/zed/src/language.rs rename to crates/zed/src/languages/rust.rs index 50540bc82c..2d4c6b3d36 100644 --- a/crates/zed/src/language.rs +++ b/crates/zed/src/languages/rust.rs @@ -1,37 +1,17 @@ -use anyhow::{anyhow, Context, Result}; +use anyhow::{anyhow, Result}; use async_compression::futures::bufread::GzipDecoder; use client::http::{self, HttpClient, Method}; use futures::{future::BoxFuture, FutureExt, StreamExt}; -use gpui::Task; pub use language::*; use lazy_static::lazy_static; use regex::Regex; -use rust_embed::RustEmbed; -use serde::Deserialize; -use serde_json::json; use smol::fs::{self, File}; use std::{borrow::Cow, env::consts, path::PathBuf, str, sync::Arc}; use util::{ResultExt, TryFutureExt}; -#[derive(RustEmbed)] -#[folder = "languages"] -struct LanguageDir; +use super::GithubRelease; -struct RustLspAdapter; -struct CLspAdapter; -struct JsonLspAdapter; - -#[derive(Deserialize)] -struct GithubRelease { - name: String, - assets: Vec, -} - -#[derive(Deserialize)] -struct GithubReleaseAsset { - name: String, - browser_download_url: http::Url, -} +pub struct RustLspAdapter; impl LspAdapter for RustLspAdapter { fn name(&self) -> &'static str { @@ -287,353 +267,11 @@ impl LspAdapter for RustLspAdapter { } } -impl LspAdapter for CLspAdapter { - fn name(&self) -> &'static str { - "clangd" - } - - fn fetch_latest_server_version( - &self, - http: Arc, - ) -> BoxFuture<'static, Result> { - async move { - let release = http - .send( - surf::RequestBuilder::new( - Method::Get, - http::Url::parse( - "https://api.github.com/repos/clangd/clangd/releases/latest", - ) - .unwrap(), - ) - .middleware(surf::middleware::Redirect::default()) - .build(), - ) - .await - .map_err(|err| anyhow!("error fetching latest release: {}", err))? - .body_json::() - .await - .map_err(|err| anyhow!("error parsing latest release: {}", err))?; - let asset_name = format!("clangd-mac-{}.zip", release.name); - let asset = release - .assets - .iter() - .find(|asset| asset.name == asset_name) - .ok_or_else(|| anyhow!("no release found matching {:?}", asset_name))?; - Ok(LspBinaryVersion { - name: release.name, - url: Some(asset.browser_download_url.clone()), - }) - } - .boxed() - } - - fn fetch_server_binary( - &self, - version: LspBinaryVersion, - http: Arc, - container_dir: PathBuf, - ) -> BoxFuture<'static, Result> { - async move { - let zip_path = container_dir.join(format!("clangd_{}.zip", version.name)); - let version_dir = container_dir.join(format!("clangd_{}", version.name)); - let binary_path = version_dir.join("bin/clangd"); - - if fs::metadata(&binary_path).await.is_err() { - let response = http - .send( - surf::RequestBuilder::new(Method::Get, version.url.unwrap()) - .middleware(surf::middleware::Redirect::default()) - .build(), - ) - .await - .map_err(|err| anyhow!("error downloading release: {}", err))?; - let mut file = File::create(&zip_path).await?; - if !response.status().is_success() { - Err(anyhow!( - "download failed with status {}", - response.status().to_string() - ))?; - } - futures::io::copy(response, &mut file).await?; - - let unzip_status = smol::process::Command::new("unzip") - .current_dir(&container_dir) - .arg(&zip_path) - .output() - .await? - .status; - if !unzip_status.success() { - Err(anyhow!("failed to unzip clangd archive"))?; - } - - if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() { - while let Some(entry) = entries.next().await { - if let Some(entry) = entry.log_err() { - let entry_path = entry.path(); - if entry_path.as_path() != version_dir { - fs::remove_dir_all(&entry_path).await.log_err(); - } - } - } - } - } - - Ok(binary_path) - } - .boxed() - } - - fn cached_server_binary(&self, container_dir: PathBuf) -> BoxFuture<'static, Option> { - async move { - let mut last_clangd_dir = None; - let mut entries = fs::read_dir(&container_dir).await?; - while let Some(entry) = entries.next().await { - let entry = entry?; - if entry.file_type().await?.is_dir() { - last_clangd_dir = Some(entry.path()); - } - } - let clangd_dir = last_clangd_dir.ok_or_else(|| anyhow!("no cached binary"))?; - let clangd_bin = clangd_dir.join("bin/clangd"); - if clangd_bin.exists() { - Ok(clangd_bin) - } else { - Err(anyhow!( - "missing clangd binary in directory {:?}", - clangd_dir - )) - } - } - .log_err() - .boxed() - } - - fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {} -} - -impl JsonLspAdapter { - const BIN_PATH: &'static str = - "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver"; -} - -impl LspAdapter for JsonLspAdapter { - fn name(&self) -> &'static str { - "vscode-json-languageserver" - } - - fn server_args(&self) -> &[&str] { - &["--stdio"] - } - - fn fetch_latest_server_version( - &self, - _: Arc, - ) -> BoxFuture<'static, Result> { - async move { - #[derive(Deserialize)] - struct NpmInfo { - versions: Vec, - } - - let output = smol::process::Command::new("npm") - .args(["info", "vscode-json-languageserver", "--json"]) - .output() - .await?; - if !output.status.success() { - Err(anyhow!("failed to execute npm info"))?; - } - let mut info: NpmInfo = serde_json::from_slice(&output.stdout)?; - - Ok(LspBinaryVersion { - name: info - .versions - .pop() - .ok_or_else(|| anyhow!("no versions found in npm info"))?, - url: Default::default(), - }) - } - .boxed() - } - - fn fetch_server_binary( - &self, - version: LspBinaryVersion, - _: Arc, - container_dir: PathBuf, - ) -> BoxFuture<'static, Result> { - async move { - let version_dir = container_dir.join(&version.name); - fs::create_dir_all(&version_dir) - .await - .context("failed to create version directory")?; - let binary_path = version_dir.join(Self::BIN_PATH); - - if fs::metadata(&binary_path).await.is_err() { - let output = smol::process::Command::new("npm") - .current_dir(&version_dir) - .arg("install") - .arg(format!("vscode-json-languageserver@{}", version.name)) - .output() - .await - .context("failed to run npm install")?; - if !output.status.success() { - Err(anyhow!("failed to install vscode-json-languageserver"))?; - } - - if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() { - while let Some(entry) = entries.next().await { - if let Some(entry) = entry.log_err() { - let entry_path = entry.path(); - if entry_path.as_path() != version_dir { - fs::remove_dir_all(&entry_path).await.log_err(); - } - } - } - } - } - - Ok(binary_path) - } - .boxed() - } - - fn cached_server_binary(&self, container_dir: PathBuf) -> BoxFuture<'static, Option> { - async move { - let mut last_version_dir = None; - let mut entries = fs::read_dir(&container_dir).await?; - while let Some(entry) = entries.next().await { - let entry = entry?; - if entry.file_type().await?.is_dir() { - last_version_dir = Some(entry.path()); - } - } - let last_version_dir = last_version_dir.ok_or_else(|| anyhow!("no cached binary"))?; - let bin_path = last_version_dir.join(Self::BIN_PATH); - if bin_path.exists() { - Ok(bin_path) - } else { - Err(anyhow!( - "missing executable in directory {:?}", - last_version_dir - )) - } - } - .log_err() - .boxed() - } - - fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {} - - fn initialization_options(&self) -> Option { - Some(json!({ - "provideFormatter": true - })) - } -} - -pub fn build_language_registry(login_shell_env_loaded: Task<()>) -> LanguageRegistry { - let languages = LanguageRegistry::new(login_shell_env_loaded); - for (name, grammar, lsp_adapter) in [ - ( - "c", - tree_sitter_c::language(), - Some(Arc::new(CLspAdapter) as Arc), - ), - ( - "json", - tree_sitter_json::language(), - Some(Arc::new(JsonLspAdapter)), - ), - ( - "markdown", - tree_sitter_markdown::language(), - None, // - ), - ( - "rust", - tree_sitter_rust::language(), - Some(Arc::new(RustLspAdapter)), - ), - ( - "tsx", - tree_sitter_typescript::language_tsx(), - None, // - ), - ( - "typescript", - tree_sitter_typescript::language_typescript(), - None, // - ), - ] { - languages.add(Arc::new(language(name, grammar, lsp_adapter))); - } - languages -} - -fn language( - name: &str, - grammar: tree_sitter::Language, - lsp_adapter: Option>, -) -> Language { - let config = toml::from_slice( - &LanguageDir::get(&format!("{}/config.toml", name)) - .unwrap() - .data, - ) - .unwrap(); - let mut language = Language::new(config, Some(grammar)); - - if let Some(query) = load_query(name, "/highlights") { - language = language - .with_highlights_query(query.as_ref()) - .expect("failed to evaluate highlights query"); - } - if let Some(query) = load_query(name, "/brackets") { - language = language - .with_brackets_query(query.as_ref()) - .expect("failed to load brackets query"); - } - if let Some(query) = load_query(name, "/indents") { - language = language - .with_indents_query(query.as_ref()) - .expect("failed to load indents query"); - } - if let Some(query) = load_query(name, "/outline") { - language = language - .with_outline_query(query.as_ref()) - .expect("failed to load outline query"); - } - if let Some(lsp_adapter) = lsp_adapter { - language = language.with_lsp_adapter(lsp_adapter) - } - language -} - -fn load_query(name: &str, filename_prefix: &str) -> Option> { - let mut result = None; - for path in LanguageDir::iter() { - if let Some(remainder) = path.strip_prefix(name) { - if remainder.starts_with(filename_prefix) { - let contents = match LanguageDir::get(path.as_ref()).unwrap().data { - Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), - Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()), - }; - match &mut result { - None => result = Some(contents), - Some(r) => r.to_mut().push_str(contents.as_ref()), - } - } - } - } - result -} - #[cfg(test)] mod tests { use super::*; + use crate::languages::{language, LspAdapter}; use gpui::color::Color; - use language::LspAdapter; use theme::SyntaxTheme; #[test] diff --git a/crates/zed/languages/rust/brackets.scm b/crates/zed/src/languages/rust/brackets.scm similarity index 100% rename from crates/zed/languages/rust/brackets.scm rename to crates/zed/src/languages/rust/brackets.scm diff --git a/crates/zed/languages/rust/config.toml b/crates/zed/src/languages/rust/config.toml similarity index 100% rename from crates/zed/languages/rust/config.toml rename to crates/zed/src/languages/rust/config.toml diff --git a/crates/zed/languages/rust/highlights.scm b/crates/zed/src/languages/rust/highlights.scm similarity index 100% rename from crates/zed/languages/rust/highlights.scm rename to crates/zed/src/languages/rust/highlights.scm diff --git a/crates/zed/languages/rust/indents.scm b/crates/zed/src/languages/rust/indents.scm similarity index 100% rename from crates/zed/languages/rust/indents.scm rename to crates/zed/src/languages/rust/indents.scm diff --git a/crates/zed/languages/rust/outline.scm b/crates/zed/src/languages/rust/outline.scm similarity index 100% rename from crates/zed/languages/rust/outline.scm rename to crates/zed/src/languages/rust/outline.scm diff --git a/crates/zed/languages/tsx/brackets.scm b/crates/zed/src/languages/tsx/brackets.scm similarity index 100% rename from crates/zed/languages/tsx/brackets.scm rename to crates/zed/src/languages/tsx/brackets.scm diff --git a/crates/zed/languages/tsx/config.toml b/crates/zed/src/languages/tsx/config.toml similarity index 100% rename from crates/zed/languages/tsx/config.toml rename to crates/zed/src/languages/tsx/config.toml diff --git a/crates/zed/languages/tsx/highlights-jsx.scm b/crates/zed/src/languages/tsx/highlights-jsx.scm similarity index 100% rename from crates/zed/languages/tsx/highlights-jsx.scm rename to crates/zed/src/languages/tsx/highlights-jsx.scm diff --git a/crates/zed/languages/tsx/highlights.scm b/crates/zed/src/languages/tsx/highlights.scm similarity index 100% rename from crates/zed/languages/tsx/highlights.scm rename to crates/zed/src/languages/tsx/highlights.scm diff --git a/crates/zed/languages/tsx/indents.scm b/crates/zed/src/languages/tsx/indents.scm similarity index 100% rename from crates/zed/languages/tsx/indents.scm rename to crates/zed/src/languages/tsx/indents.scm diff --git a/crates/zed/languages/tsx/outline.scm b/crates/zed/src/languages/tsx/outline.scm similarity index 100% rename from crates/zed/languages/tsx/outline.scm rename to crates/zed/src/languages/tsx/outline.scm diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs new file mode 100644 index 0000000000..59b7d225f9 --- /dev/null +++ b/crates/zed/src/languages/typescript.rs @@ -0,0 +1,121 @@ +pub struct TypeScriptLspAdapter; + +impl TypeScriptLspAdapter { + const BIN_PATH: &'static str = + "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver"; +} + +impl super::LspAdapter for TypeScriptLspAdapter { + fn name(&self) -> &'static str { + "typescript-language-server" + } + + fn server_args(&self) -> &[&str] { + &["--stdio"] + } + + fn fetch_latest_server_version( + &self, + _: Arc, + ) -> BoxFuture<'static, Result> { + async move { + #[derive(Deserialize)] + struct NpmInfo { + versions: Vec, + } + + let output = smol::process::Command::new("npm") + .args(["info", "vscode-json-languageserver", "--json"]) + .output() + .await?; + if !output.status.success() { + Err(anyhow!("failed to execute npm info"))?; + } + let mut info: NpmInfo = serde_json::from_slice(&output.stdout)?; + + Ok(LspBinaryVersion { + name: info + .versions + .pop() + .ok_or_else(|| anyhow!("no versions found in npm info"))?, + url: Default::default(), + }) + } + .boxed() + } + + fn fetch_server_binary( + &self, + version: LspBinaryVersion, + _: Arc, + container_dir: PathBuf, + ) -> BoxFuture<'static, Result> { + async move { + let version_dir = container_dir.join(&version.name); + fs::create_dir_all(&version_dir) + .await + .context("failed to create version directory")?; + let binary_path = version_dir.join(Self::BIN_PATH); + + if fs::metadata(&binary_path).await.is_err() { + let output = smol::process::Command::new("npm") + .current_dir(&version_dir) + .arg("install") + .arg(format!("vscode-json-languageserver@{}", version.name)) + .output() + .await + .context("failed to run npm install")?; + if !output.status.success() { + Err(anyhow!("failed to install vscode-json-languageserver"))?; + } + + if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() { + while let Some(entry) = entries.next().await { + if let Some(entry) = entry.log_err() { + let entry_path = entry.path(); + if entry_path.as_path() != version_dir { + fs::remove_dir_all(&entry_path).await.log_err(); + } + } + } + } + } + + Ok(binary_path) + } + .boxed() + } + + fn cached_server_binary(&self, container_dir: PathBuf) -> BoxFuture<'static, Option> { + async move { + let mut last_version_dir = None; + let mut entries = fs::read_dir(&container_dir).await?; + while let Some(entry) = entries.next().await { + let entry = entry?; + if entry.file_type().await?.is_dir() { + last_version_dir = Some(entry.path()); + } + } + let last_version_dir = last_version_dir.ok_or_else(|| anyhow!("no cached binary"))?; + let bin_path = last_version_dir.join(Self::BIN_PATH); + if bin_path.exists() { + Ok(bin_path) + } else { + Err(anyhow!( + "missing executable in directory {:?}", + last_version_dir + )) + } + } + .log_err() + .boxed() + } + + fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {} + + fn initialization_options(&self) -> Option { + Some(json!({ + "provideFormatter": true + })) + } +} diff --git a/crates/zed/languages/typescript/brackets.scm b/crates/zed/src/languages/typescript/brackets.scm similarity index 100% rename from crates/zed/languages/typescript/brackets.scm rename to crates/zed/src/languages/typescript/brackets.scm diff --git a/crates/zed/languages/typescript/config.toml b/crates/zed/src/languages/typescript/config.toml similarity index 100% rename from crates/zed/languages/typescript/config.toml rename to crates/zed/src/languages/typescript/config.toml diff --git a/crates/zed/languages/typescript/highlights.scm b/crates/zed/src/languages/typescript/highlights.scm similarity index 100% rename from crates/zed/languages/typescript/highlights.scm rename to crates/zed/src/languages/typescript/highlights.scm diff --git a/crates/zed/languages/typescript/indents.scm b/crates/zed/src/languages/typescript/indents.scm similarity index 100% rename from crates/zed/languages/typescript/indents.scm rename to crates/zed/src/languages/typescript/indents.scm diff --git a/crates/zed/languages/typescript/outline.scm b/crates/zed/src/languages/typescript/outline.scm similarity index 100% rename from crates/zed/languages/typescript/outline.scm rename to crates/zed/src/languages/typescript/outline.scm diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 63721346c3..49efc9ade2 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -19,7 +19,7 @@ use workspace::{ AppState, OpenNew, OpenParams, OpenPaths, Settings, }; use zed::{ - self, assets::Assets, build_window_options, build_workspace, fs::RealFs, language, menus, + self, assets::Assets, build_window_options, build_workspace, fs::RealFs, languages, menus, }; fn main() { @@ -34,7 +34,7 @@ fn main() { let default_settings = Settings::new("Zed Mono", &app.font_cache(), theme) .unwrap() .with_overrides( - language::PLAIN_TEXT.name(), + languages::PLAIN_TEXT.name(), settings::LanguageOverride { soft_wrap: Some(settings::SoftWrap::PreferredLineLength), ..Default::default() @@ -60,7 +60,7 @@ fn main() { app.run(move |cx| { let http = http::client(); let client = client::Client::new(http.clone()); - let mut languages = language::build_language_registry(login_shell_env_loaded); + let mut languages = languages::build_language_registry(login_shell_env_loaded); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx)); let channel_list = cx.add_model(|cx| ChannelList::new(user_store.clone(), client.clone(), cx)); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 1302d54067..25aa011c9b 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,5 +1,5 @@ pub mod assets; -pub mod language; +pub mod languages; pub mod menus; #[cfg(any(test, feature = "test-support"))] pub mod test; @@ -557,7 +557,7 @@ mod tests { assert_eq!(editor.title(cx), "untitled"); assert!(Arc::ptr_eq( editor.language(cx).unwrap(), - &language::PLAIN_TEXT + &languages::PLAIN_TEXT )); editor.handle_input(&editor::Input("hi".into()), cx); assert!(editor.is_dirty(cx)); @@ -647,7 +647,7 @@ mod tests { editor.update(cx, |editor, cx| { assert!(Arc::ptr_eq( editor.language(cx).unwrap(), - &language::PLAIN_TEXT + &languages::PLAIN_TEXT )); editor.handle_input(&editor::Input("hi".into()), cx); assert!(editor.is_dirty(cx.as_ref())); From 0e1d371a67b1483e4ab7a426b12938cb5b0abdde Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Tue, 29 Mar 2022 13:42:21 -0700 Subject: [PATCH 06/68] Add typescript language server Currently not tested for tsx files Co-authored-by: Max Brunsfeld --- crates/language/src/language.rs | 9 ++-- crates/project/src/project.rs | 8 +-- crates/zed/src/languages.rs | 4 +- crates/zed/src/languages/c.rs | 15 +++--- crates/zed/src/languages/json.rs | 23 ++++----- crates/zed/src/languages/rust.rs | 15 +++--- crates/zed/src/languages/typescript.rs | 69 +++++++++++++++++++------- 7 files changed, 90 insertions(+), 53 deletions(-) diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 5b917c0fdf..6e400c4a6f 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -20,6 +20,7 @@ use parking_lot::{Mutex, RwLock}; use serde::Deserialize; use serde_json::Value; use std::{ + any::Any, cell::RefCell, ops::Range, path::{Path, PathBuf}, @@ -61,9 +62,9 @@ pub trait ToLspPosition { fn to_lsp_position(self) -> lsp::Position; } -pub struct LspBinaryVersion { +pub struct GitHubLspBinaryVersion { pub name: String, - pub url: Option, + pub url: http::Url, } pub trait LspAdapter: 'static + Send + Sync { @@ -71,10 +72,10 @@ pub trait LspAdapter: 'static + Send + Sync { fn fetch_latest_server_version( &self, http: Arc, - ) -> BoxFuture<'static, Result>; + ) -> BoxFuture<'static, Result>>; fn fetch_server_binary( &self, - version: LspBinaryVersion, + version: Box, http: Arc, container_dir: PathBuf, ) -> BoxFuture<'static, Result>; diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 1a41475909..f4d5e9ee11 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2278,11 +2278,12 @@ impl Project { Ok(completions .into_iter() .filter_map(|lsp_completion| { - let (old_range, new_text) = match lsp_completion.text_edit.as_ref()? { - lsp::CompletionTextEdit::Edit(edit) => { + let (old_range, new_text) = match lsp_completion.text_edit.as_ref() { + Some(lsp::CompletionTextEdit::Edit(edit)) => { (range_from_lsp(edit.range), edit.new_text.clone()) } - lsp::CompletionTextEdit::InsertAndReplace(_) => { + None => (position..position, lsp_completion.label.clone()), + Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => { log::info!("unsupported insert/replace completion"); return None; } @@ -2307,6 +2308,7 @@ impl Project { lsp_completion, }) } else { + log::info!("completion out of expected range"); None } }) diff --git a/crates/zed/src/languages.rs b/crates/zed/src/languages.rs index 607f4c30bb..cc22247025 100644 --- a/crates/zed/src/languages.rs +++ b/crates/zed/src/languages.rs @@ -1,4 +1,4 @@ -use client::http::{self, HttpClient, Method}; +use client::http; use gpui::Task; pub use language::*; use rust_embed::RustEmbed; @@ -53,7 +53,7 @@ pub fn build_language_registry(login_shell_env_loaded: Task<()>) -> LanguageRegi ( "tsx", tree_sitter_typescript::language_tsx(), - None, // + Some(Arc::new(typescript::TypeScriptLspAdapter)), ), ( "typescript", diff --git a/crates/zed/src/languages/c.rs b/crates/zed/src/languages/c.rs index 9ce3eab2f7..cf4e219967 100644 --- a/crates/zed/src/languages/c.rs +++ b/crates/zed/src/languages/c.rs @@ -3,7 +3,7 @@ use client::http::{self, HttpClient, Method}; use futures::{future::BoxFuture, FutureExt, StreamExt}; pub use language::*; use smol::fs::{self, File}; -use std::{path::PathBuf, str, sync::Arc}; +use std::{any::Any, path::PathBuf, str, sync::Arc}; use util::{ResultExt, TryFutureExt}; use super::GithubRelease; @@ -18,7 +18,7 @@ impl super::LspAdapter for CLspAdapter { fn fetch_latest_server_version( &self, http: Arc, - ) -> BoxFuture<'static, Result> { + ) -> BoxFuture<'static, Result>> { async move { let release = http .send( @@ -43,20 +43,21 @@ impl super::LspAdapter for CLspAdapter { .iter() .find(|asset| asset.name == asset_name) .ok_or_else(|| anyhow!("no release found matching {:?}", asset_name))?; - Ok(LspBinaryVersion { + Ok(Box::new(GitHubLspBinaryVersion { name: release.name, - url: Some(asset.browser_download_url.clone()), - }) + url: asset.browser_download_url.clone(), + }) as Box<_>) } .boxed() } fn fetch_server_binary( &self, - version: LspBinaryVersion, + version: Box, http: Arc, container_dir: PathBuf, ) -> BoxFuture<'static, Result> { + let version = version.downcast::().unwrap(); async move { let zip_path = container_dir.join(format!("clangd_{}.zip", version.name)); let version_dir = container_dir.join(format!("clangd_{}", version.name)); @@ -65,7 +66,7 @@ impl super::LspAdapter for CLspAdapter { if fs::metadata(&binary_path).await.is_err() { let response = http .send( - surf::RequestBuilder::new(Method::Get, version.url.unwrap()) + surf::RequestBuilder::new(Method::Get, version.url) .middleware(surf::middleware::Redirect::default()) .build(), ) diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs index bb7744714f..c1d0db2ed6 100644 --- a/crates/zed/src/languages/json.rs +++ b/crates/zed/src/languages/json.rs @@ -1,12 +1,12 @@ use anyhow::{anyhow, Context, Result}; use client::http::HttpClient; use futures::{future::BoxFuture, FutureExt, StreamExt}; -use language::{LspAdapter, LspBinaryVersion}; +use language::LspAdapter; use serde::Deserialize; use serde_json::json; use smol::fs; -use std::{path::PathBuf, sync::Arc}; -use util::ResultExt; +use std::{any::Any, path::PathBuf, sync::Arc}; +use util::{ResultExt, TryFutureExt}; pub struct JsonLspAdapter; @@ -27,7 +27,7 @@ impl LspAdapter for JsonLspAdapter { fn fetch_latest_server_version( &self, _: Arc, - ) -> BoxFuture<'static, Result> { + ) -> BoxFuture<'static, Result>> { async move { #[derive(Deserialize)] struct NpmInfo { @@ -43,25 +43,24 @@ impl LspAdapter for JsonLspAdapter { } let mut info: NpmInfo = serde_json::from_slice(&output.stdout)?; - Ok(LspBinaryVersion { - name: info - .versions + Ok(Box::new( + info.versions .pop() .ok_or_else(|| anyhow!("no versions found in npm info"))?, - url: Default::default(), - }) + ) as Box<_>) } .boxed() } fn fetch_server_binary( &self, - version: LspBinaryVersion, + version: Box, _: Arc, container_dir: PathBuf, ) -> BoxFuture<'static, Result> { + let version = version.downcast::().unwrap(); async move { - let version_dir = container_dir.join(&version.name); + let version_dir = container_dir.join(version.as_str()); fs::create_dir_all(&version_dir) .await .context("failed to create version directory")?; @@ -71,7 +70,7 @@ impl LspAdapter for JsonLspAdapter { let output = smol::process::Command::new("npm") .current_dir(&version_dir) .arg("install") - .arg(format!("vscode-json-languageserver@{}", version.name)) + .arg(format!("vscode-json-languageserver@{}", version)) .output() .await .context("failed to run npm install")?; diff --git a/crates/zed/src/languages/rust.rs b/crates/zed/src/languages/rust.rs index 2d4c6b3d36..8b06c5cbd7 100644 --- a/crates/zed/src/languages/rust.rs +++ b/crates/zed/src/languages/rust.rs @@ -6,7 +6,7 @@ pub use language::*; use lazy_static::lazy_static; use regex::Regex; use smol::fs::{self, File}; -use std::{borrow::Cow, env::consts, path::PathBuf, str, sync::Arc}; +use std::{any::Any, borrow::Cow, env::consts, path::PathBuf, str, sync::Arc}; use util::{ResultExt, TryFutureExt}; use super::GithubRelease; @@ -21,7 +21,7 @@ impl LspAdapter for RustLspAdapter { fn fetch_latest_server_version( &self, http: Arc, - ) -> BoxFuture<'static, Result> { + ) -> BoxFuture<'static, Result>> { async move { let release = http .send( @@ -46,27 +46,28 @@ impl LspAdapter for RustLspAdapter { .iter() .find(|asset| asset.name == asset_name) .ok_or_else(|| anyhow!("no release found matching {:?}", asset_name))?; - Ok(LspBinaryVersion { + Ok(Box::new(GitHubLspBinaryVersion { name: release.name, - url: Some(asset.browser_download_url.clone()), - }) + url: asset.browser_download_url.clone(), + }) as Box<_>) } .boxed() } fn fetch_server_binary( &self, - version: LspBinaryVersion, + version: Box, http: Arc, container_dir: PathBuf, ) -> BoxFuture<'static, Result> { async move { + let version = version.downcast::().unwrap(); let destination_path = container_dir.join(format!("rust-analyzer-{}", version.name)); if fs::metadata(&destination_path).await.is_err() { let response = http .send( - surf::RequestBuilder::new(Method::Get, version.url.unwrap()) + surf::RequestBuilder::new(Method::Get, version.url) .middleware(surf::middleware::Redirect::default()) .build(), ) diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs index 59b7d225f9..f7547fdd4e 100644 --- a/crates/zed/src/languages/typescript.rs +++ b/crates/zed/src/languages/typescript.rs @@ -1,57 +1,86 @@ +use anyhow::{anyhow, Context, Result}; +use client::http::HttpClient; +use futures::{future::BoxFuture, FutureExt, StreamExt}; +use language::LspAdapter; +use serde::Deserialize; +use serde_json::json; +use smol::fs; +use std::{any::Any, path::PathBuf, sync::Arc}; +use util::{ResultExt, TryFutureExt}; + pub struct TypeScriptLspAdapter; impl TypeScriptLspAdapter { - const BIN_PATH: &'static str = - "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver"; + const BIN_PATH: &'static str = "node_modules/typescript-language-server/lib/cli.js"; } -impl super::LspAdapter for TypeScriptLspAdapter { +struct Versions { + typescript_version: String, + server_version: String, +} + +impl LspAdapter for TypeScriptLspAdapter { fn name(&self) -> &'static str { "typescript-language-server" } fn server_args(&self) -> &[&str] { - &["--stdio"] + &["--stdio", "--tsserver-path", "node_modules/typescript/lib"] } fn fetch_latest_server_version( &self, _: Arc, - ) -> BoxFuture<'static, Result> { + ) -> BoxFuture<'static, Result>> { async move { #[derive(Deserialize)] struct NpmInfo { versions: Vec, } - let output = smol::process::Command::new("npm") - .args(["info", "vscode-json-languageserver", "--json"]) + let typescript_output = smol::process::Command::new("npm") + .args(["info", "typescript", "--json"]) .output() .await?; - if !output.status.success() { + if !typescript_output.status.success() { Err(anyhow!("failed to execute npm info"))?; } - let mut info: NpmInfo = serde_json::from_slice(&output.stdout)?; + let mut typescript_info: NpmInfo = serde_json::from_slice(&typescript_output.stdout)?; - Ok(LspBinaryVersion { - name: info + let server_output = smol::process::Command::new("npm") + .args(["info", "typescript-language-server", "--json"]) + .output() + .await?; + if !server_output.status.success() { + Err(anyhow!("failed to execute npm info"))?; + } + let mut server_info: NpmInfo = serde_json::from_slice(&server_output.stdout)?; + + Ok(Box::new(Versions { + typescript_version: typescript_info .versions .pop() - .ok_or_else(|| anyhow!("no versions found in npm info"))?, - url: Default::default(), - }) + .ok_or_else(|| anyhow!("no versions found in typescript npm info"))?, + server_version: server_info.versions.pop().ok_or_else(|| { + anyhow!("no versions found in typescript language server npm info") + })?, + }) as Box<_>) } .boxed() } fn fetch_server_binary( &self, - version: LspBinaryVersion, + versions: Box, _: Arc, container_dir: PathBuf, ) -> BoxFuture<'static, Result> { + let versions = versions.downcast::().unwrap(); async move { - let version_dir = container_dir.join(&version.name); + let version_dir = container_dir.join(&format!( + "typescript-{}:server-{}", + versions.typescript_version, versions.server_version + )); fs::create_dir_all(&version_dir) .await .context("failed to create version directory")?; @@ -61,12 +90,16 @@ impl super::LspAdapter for TypeScriptLspAdapter { let output = smol::process::Command::new("npm") .current_dir(&version_dir) .arg("install") - .arg(format!("vscode-json-languageserver@{}", version.name)) + .arg(format!("typescript@{}", versions.typescript_version)) + .arg(format!( + "typescript-language-server@{}", + versions.server_version + )) .output() .await .context("failed to run npm install")?; if !output.status.success() { - Err(anyhow!("failed to install vscode-json-languageserver"))?; + Err(anyhow!("failed to install typescript-language-server"))?; } if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() { From 158d9879652b4cd24fb2b381b1e938b1543b1892 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 29 Mar 2022 16:57:18 -0700 Subject: [PATCH 07/68] Start work on allowing language servers to support multiple languages --- crates/language/src/language.rs | 32 ++++-- crates/project/src/lsp_command.rs | 23 ++-- crates/project/src/project.rs | 141 +++++++++++++------------ crates/rpc/proto/zed.proto | 2 +- crates/zed/src/languages/c.rs | 6 +- crates/zed/src/languages/json.rs | 6 +- crates/zed/src/languages/rust.rs | 4 +- crates/zed/src/languages/typescript.rs | 6 +- 8 files changed, 118 insertions(+), 102 deletions(-) diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 6e400c4a6f..8d573574fd 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -8,7 +8,7 @@ mod tests; use anyhow::{anyhow, Context, Result}; use client::http::{self, HttpClient}; -use collections::HashSet; +use collections::{HashMap, HashSet}; use futures::{ future::{BoxFuture, Shared}, FutureExt, TryFutureExt, @@ -67,8 +67,11 @@ pub struct GitHubLspBinaryVersion { pub url: http::Url, } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct LanguageServerName(pub Arc); + pub trait LspAdapter: 'static + Send + Sync { - fn name(&self) -> &'static str; + fn name(&self) -> LanguageServerName; fn fetch_latest_server_version( &self, http: Arc, @@ -159,7 +162,6 @@ pub struct Language { pub(crate) config: LanguageConfig, pub(crate) grammar: Option>, pub(crate) adapter: Option>, - lsp_binary_path: Mutex>>>>>, } pub struct Grammar { @@ -186,6 +188,12 @@ pub struct LanguageRegistry { lsp_binary_statuses_tx: async_broadcast::Sender<(Arc, LanguageServerBinaryStatus)>, lsp_binary_statuses_rx: async_broadcast::Receiver<(Arc, LanguageServerBinaryStatus)>, login_shell_env_loaded: Shared>, + lsp_binary_paths: Mutex< + HashMap< + LanguageServerName, + Shared>>>, + >, + >, } impl LanguageRegistry { @@ -197,6 +205,7 @@ impl LanguageRegistry { lsp_binary_statuses_tx, lsp_binary_statuses_rx, login_shell_env_loaded: login_shell_env_loaded.shared(), + lsp_binary_paths: Default::default(), } } @@ -246,7 +255,7 @@ impl LanguageRegistry { } pub fn start_language_server( - &self, + self: &Arc, language: Arc, root_path: Arc, http_client: Arc, @@ -291,16 +300,18 @@ impl LanguageRegistry { .ok_or_else(|| anyhow!("language server download directory has not been assigned")) .log_err()?; + let this = self.clone(); let adapter = language.adapter.clone()?; let background = cx.background().clone(); let lsp_binary_statuses = self.lsp_binary_statuses_tx.clone(); let login_shell_env_loaded = self.login_shell_env_loaded.clone(); Some(cx.background().spawn(async move { login_shell_env_loaded.await; - let server_binary_path = language - .lsp_binary_path + let server_binary_path = this + .lsp_binary_paths .lock() - .get_or_insert_with(|| { + .entry(adapter.name()) + .or_insert_with(|| { get_server_binary_path( adapter.clone(), language.clone(), @@ -342,7 +353,7 @@ async fn get_server_binary_path( download_dir: Arc, statuses: async_broadcast::Sender<(Arc, LanguageServerBinaryStatus)>, ) -> Result { - let container_dir = download_dir.join(adapter.name()); + let container_dir = download_dir.join(adapter.name().0.as_ref()); if !container_dir.exists() { smol::fs::create_dir_all(&container_dir) .await @@ -415,10 +426,13 @@ impl Language { }) }), adapter: None, - lsp_binary_path: Default::default(), } } + pub fn lsp_adapter(&self) -> Option> { + self.adapter.clone() + } + pub fn with_highlights_query(mut self, source: &str) -> Result { let grammar = self .grammar diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 4867ada7cb..b6f007659d 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -223,22 +223,19 @@ impl LspCommand for PerformRename { mut cx: AsyncAppContext, ) -> Result { if let Some(edit) = message { - let language_server = project + let (lsp_adapter, lsp_server) = project .read_with(&cx, |project, cx| { project .language_server_for_buffer(buffer.read(cx), cx) .cloned() }) .ok_or_else(|| anyhow!("no language server found for buffer"))?; - let language = buffer - .read_with(&cx, |buffer, _| buffer.language().cloned()) - .ok_or_else(|| anyhow!("no language for buffer"))?; Project::deserialize_workspace_edit( project, edit, self.push_to_history, - language.name(), - language_server, + lsp_adapter, + lsp_server, &mut cx, ) .await @@ -343,16 +340,13 @@ impl LspCommand for GetDefinition { mut cx: AsyncAppContext, ) -> Result> { let mut definitions = Vec::new(); - let language_server = project + let (lsp_adapter, language_server) = project .read_with(&cx, |project, cx| { project .language_server_for_buffer(buffer.read(cx), cx) .cloned() }) .ok_or_else(|| anyhow!("no language server found for buffer"))?; - let language = buffer - .read_with(&cx, |buffer, _| buffer.language().cloned()) - .ok_or_else(|| anyhow!("no language for buffer"))?; if let Some(message) = message { let mut unresolved_locations = Vec::new(); @@ -377,7 +371,7 @@ impl LspCommand for GetDefinition { .update(&mut cx, |this, cx| { this.open_local_buffer_via_lsp( target_uri, - language.name(), + lsp_adapter.clone(), language_server.clone(), cx, ) @@ -521,16 +515,13 @@ impl LspCommand for GetReferences { mut cx: AsyncAppContext, ) -> Result> { let mut references = Vec::new(); - let language_server = project + let (lsp_adapter, language_server) = project .read_with(&cx, |project, cx| { project .language_server_for_buffer(buffer.read(cx), cx) .cloned() }) .ok_or_else(|| anyhow!("no language server found for buffer"))?; - let language = buffer - .read_with(&cx, |buffer, _| buffer.language().cloned()) - .ok_or_else(|| anyhow!("no language for buffer"))?; if let Some(locations) = locations { for lsp_location in locations { @@ -538,7 +529,7 @@ impl LspCommand for GetReferences { .update(&mut cx, |this, cx| { this.open_local_buffer_via_lsp( lsp_location.uri, - language.name(), + lsp_adapter.clone(), language_server.clone(), cx, ) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index f4d5e9ee11..6f550d1020 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -18,8 +18,8 @@ use language::{ proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, range_from_lsp, Anchor, Bias, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, Language, LanguageRegistry, - LocalFile, OffsetRangeExt, Operation, Patch, PointUtf16, TextBufferSnapshot, ToLspPosition, - ToOffset, ToPointUtf16, Transaction, + LanguageServerName, LocalFile, LspAdapter, OffsetRangeExt, Operation, Patch, PointUtf16, + TextBufferSnapshot, ToLspPosition, ToOffset, ToPointUtf16, Transaction, }; use lsp::{DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer}; use lsp_command::*; @@ -57,8 +57,10 @@ pub struct Project { worktrees: Vec, active_entry: Option, languages: Arc, - language_servers: HashMap<(WorktreeId, Arc), Arc>, - started_language_servers: HashMap<(WorktreeId, Arc), Task>>>, + language_servers: + HashMap<(WorktreeId, LanguageServerName), (Arc, Arc)>, + started_language_servers: + HashMap<(WorktreeId, LanguageServerName), Task>>>, language_server_statuses: BTreeMap, language_server_settings: Arc>, next_language_server_id: usize, @@ -185,7 +187,7 @@ pub struct DocumentHighlight { pub struct Symbol { pub source_worktree_id: WorktreeId, pub worktree_id: WorktreeId, - pub language_name: String, + pub language_server_name: LanguageServerName, pub path: PathBuf, pub label: CodeLabel, pub name: String, @@ -957,8 +959,8 @@ impl Project { fn open_local_buffer_via_lsp( &mut self, abs_path: lsp::Url, - lang_name: Arc, - lang_server: Arc, + lsp_adapter: Arc, + lsp_server: Arc, cx: &mut ModelContext, ) -> Task>> { cx.spawn(|this, mut cx| async move { @@ -976,8 +978,10 @@ impl Project { }) .await?; this.update(&mut cx, |this, cx| { - this.language_servers - .insert((worktree.read(cx).id(), lang_name), lang_server); + this.language_servers.insert( + (worktree.read(cx).id(), lsp_adapter.name()), + (lsp_adapter, lsp_server), + ); }); (worktree, PathBuf::new()) }; @@ -1120,7 +1124,7 @@ impl Project { } } - if let Some(server) = language_server { + if let Some((_, server)) = language_server { server .notify::( lsp::DidOpenTextDocumentParams { @@ -1153,7 +1157,7 @@ impl Project { if let Some(file) = File::from_dyn(buffer.file()) { if file.is_local() { let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap(); - if let Some(server) = this.language_server_for_buffer(buffer, cx) { + if let Some((_, server)) = this.language_server_for_buffer(buffer, cx) { server .notify::( lsp::DidCloseTextDocumentParams { @@ -1189,7 +1193,7 @@ impl Project { cx.background().spawn(request).detach_and_log_err(cx); } BufferEvent::Edited { .. } => { - let language_server = self + let (_, language_server) = self .language_server_for_buffer(buffer.read(cx), cx)? .clone(); let buffer = buffer.read(cx); @@ -1262,11 +1266,11 @@ impl Project { fn language_servers_for_worktree( &self, worktree_id: WorktreeId, - ) -> impl Iterator)> { + ) -> impl Iterator, Arc)> { self.language_servers.iter().filter_map( - move |((language_server_worktree_id, language_name), server)| { + move |((language_server_worktree_id, _), server)| { if *language_server_worktree_id == worktree_id { - Some((language_name.as_ref(), server)) + Some(server) } else { None } @@ -1302,7 +1306,12 @@ impl Project { language: Arc, cx: &mut ModelContext, ) { - let key = (worktree_id, language.name()); + let adapter = if let Some(adapter) = language.lsp_adapter() { + adapter + } else { + return; + }; + let key = (worktree_id, adapter.name()); self.started_language_servers .entry(key.clone()) .or_insert_with(|| { @@ -1416,7 +1425,7 @@ impl Project { let language_server = language_server.initialize().await.log_err()?; this.update(&mut cx, |this, cx| { this.language_servers - .insert(key.clone(), language_server.clone()); + .insert(key.clone(), (adapter, language_server.clone())); this.language_server_statuses.insert( server_id, LanguageServerStatus { @@ -1459,7 +1468,10 @@ impl Project { } else { continue; }; - if (file.worktree.read(cx).id(), language.name()) != key { + if file.worktree.read(cx).id() != key.0 + || language.lsp_adapter().map(|a| a.name()) + != Some(key.1.clone()) + { continue; } @@ -1675,7 +1687,7 @@ impl Project { } pub fn set_language_server_settings(&mut self, settings: serde_json::Value) { - for server in self.language_servers.values() { + for (_, server) in self.language_servers.values() { server .notify::( lsp::DidChangeConfigurationParams { @@ -1925,7 +1937,7 @@ impl Project { let buffer = buffer_handle.read(cx); if let Some(file) = File::from_dyn(buffer.file()) { if let Some(buffer_abs_path) = file.as_local().map(|f| f.abs_path(cx)) { - if let Some(server) = self.language_server_for_buffer(buffer, cx) { + if let Some((_, server)) = self.language_server_for_buffer(buffer, cx) { local_buffers.push((buffer_handle, buffer_abs_path, server.clone())); } } else { @@ -2062,25 +2074,24 @@ impl Project { pub fn symbols(&self, query: &str, cx: &mut ModelContext) -> Task>> { if self.is_local() { let mut language_servers = HashMap::default(); - for ((worktree_id, language_name), language_server) in self.language_servers.iter() { - if let Some((worktree, language)) = self + for ((worktree_id, _), (lsp_adapter, language_server)) in self.language_servers.iter() { + if let Some(worktree) = self .worktree_for_id(*worktree_id, cx) .and_then(|worktree| worktree.read(cx).as_local()) - .zip(self.languages.get_language(language_name)) { language_servers .entry(Arc::as_ptr(language_server)) .or_insert(( + lsp_adapter.clone(), language_server.clone(), *worktree_id, worktree.abs_path().clone(), - language.clone(), )); } } let mut requests = Vec::new(); - for (language_server, _, _, _) in language_servers.values() { + for (_, language_server, _, _) in language_servers.values() { requests.push(language_server.request::( lsp::WorkspaceSymbolParams { query: query.to_string(), @@ -2095,7 +2106,7 @@ impl Project { let mut symbols = Vec::new(); if let Some(this) = this.upgrade(&cx) { this.read_with(&cx, |this, cx| { - for ((_, source_worktree_id, worktree_abs_path, language), lsp_symbols) in + for ((adapter, _, source_worktree_id, worktree_abs_path), lsp_symbols) in language_servers.into_values().zip(responses) { symbols.extend(lsp_symbols.into_iter().flatten().filter_map( @@ -2112,8 +2123,13 @@ impl Project { path = relativize_path(&worktree_abs_path, &abs_path); } - let label = language - .label_for_symbol(&lsp_symbol.name, lsp_symbol.kind) + let label = this + .languages + .select_language(&path) + .and_then(|language| { + language + .label_for_symbol(&lsp_symbol.name, lsp_symbol.kind) + }) .unwrap_or_else(|| { CodeLabel::plain(lsp_symbol.name.clone(), None) }); @@ -2122,7 +2138,7 @@ impl Project { Some(Symbol { source_worktree_id, worktree_id, - language_name: language.name().to_string(), + language_server_name: adapter.name(), name: lsp_symbol.name, kind: lsp_symbol.kind, label, @@ -2169,9 +2185,9 @@ impl Project { cx: &mut ModelContext, ) -> Task>> { if self.is_local() { - let language_server = if let Some(server) = self.language_servers.get(&( + let (lsp_adapter, language_server) = if let Some(server) = self.language_servers.get(&( symbol.source_worktree_id, - Arc::from(symbol.language_name.as_str()), + symbol.language_server_name.clone(), )) { server.clone() } else { @@ -2196,12 +2212,7 @@ impl Project { return Task::ready(Err(anyhow!("invalid symbol path"))); }; - self.open_local_buffer_via_lsp( - symbol_uri, - Arc::from(symbol.language_name.as_str()), - language_server, - cx, - ) + self.open_local_buffer_via_lsp(symbol_uri, lsp_adapter, language_server, cx) } else if let Some(project_id) = self.remote_id() { let request = self.client.request(proto::OpenBufferForSymbol { project_id, @@ -2242,7 +2253,7 @@ impl Project { if worktree.read(cx).as_local().is_some() { let buffer_abs_path = buffer_abs_path.unwrap(); - let lang_server = + let (_, lang_server) = if let Some(server) = self.language_server_for_buffer(source_buffer, cx) { server.clone() } else { @@ -2356,7 +2367,8 @@ impl Project { let buffer_id = buffer.remote_id(); if self.is_local() { - let lang_server = if let Some(server) = self.language_server_for_buffer(buffer, cx) { + let (_, lang_server) = if let Some(server) = self.language_server_for_buffer(buffer, cx) + { server.clone() } else { return Task::ready(Ok(Default::default())); @@ -2447,7 +2459,8 @@ impl Project { if worktree.read(cx).as_local().is_some() { let buffer_abs_path = buffer_abs_path.unwrap(); - let lang_server = if let Some(server) = self.language_server_for_buffer(buffer, cx) { + let (_, lang_server) = if let Some(server) = self.language_server_for_buffer(buffer, cx) + { server.clone() } else { return Task::ready(Ok(Default::default())); @@ -2534,16 +2547,12 @@ impl Project { ) -> Task> { if self.is_local() { let buffer = buffer_handle.read(cx); - let lang_name = if let Some(lang) = buffer.language() { - lang.name() - } else { - return Task::ready(Ok(Default::default())); - }; - let lang_server = if let Some(server) = self.language_server_for_buffer(buffer, cx) { - server.clone() - } else { - return Task::ready(Ok(Default::default())); - }; + let (lsp_adapter, lang_server) = + if let Some(server) = self.language_server_for_buffer(buffer, cx) { + server.clone() + } else { + return Task::ready(Ok(Default::default())); + }; let range = action.range.to_point_utf16(buffer); cx.spawn(|this, mut cx| async move { @@ -2580,7 +2589,7 @@ impl Project { this, edit, push_to_history, - lang_name, + lsp_adapter, lang_server, &mut cx, ) @@ -2616,7 +2625,7 @@ impl Project { this: ModelHandle, edit: lsp::WorkspaceEdit, push_to_history: bool, - language_name: Arc, + lsp_adapter: Arc, language_server: Arc, cx: &mut AsyncAppContext, ) -> Result { @@ -2693,7 +2702,7 @@ impl Project { .update(cx, |this, cx| { this.open_local_buffer_via_lsp( op.text_document.uri, - language_name.clone(), + lsp_adapter.clone(), language_server.clone(), cx, ) @@ -2988,7 +2997,7 @@ impl Project { let buffer = buffer_handle.read(cx); if self.is_local() { let file = File::from_dyn(buffer.file()).and_then(File::as_local); - if let Some((file, language_server)) = + if let Some((file, (_, language_server))) = file.zip(self.language_server_for_buffer(buffer, cx).cloned()) { let lsp_params = request.to_lsp(&file.abs_path(cx), cx); @@ -4086,9 +4095,8 @@ impl Project { } fn deserialize_symbol(&self, serialized_symbol: proto::Symbol) -> Result { - let language = self - .languages - .get_language(&serialized_symbol.language_name); + let source_worktree_id = WorktreeId::from_proto(serialized_symbol.source_worktree_id); + let worktree_id = WorktreeId::from_proto(serialized_symbol.worktree_id); let start = serialized_symbol .start .ok_or_else(|| anyhow!("invalid start"))?; @@ -4096,15 +4104,17 @@ impl Project { .end .ok_or_else(|| anyhow!("invalid end"))?; let kind = unsafe { mem::transmute(serialized_symbol.kind) }; + let path = PathBuf::from(serialized_symbol.path); + let language = self.languages.select_language(&path); Ok(Symbol { - source_worktree_id: WorktreeId::from_proto(serialized_symbol.source_worktree_id), - worktree_id: WorktreeId::from_proto(serialized_symbol.worktree_id), - language_name: serialized_symbol.language_name.clone(), + source_worktree_id, + worktree_id, + language_server_name: LanguageServerName(serialized_symbol.language_server_name.into()), label: language .and_then(|language| language.label_for_symbol(&serialized_symbol.name, kind)) .unwrap_or_else(|| CodeLabel::plain(serialized_symbol.name.clone(), None)), name: serialized_symbol.name, - path: PathBuf::from(serialized_symbol.path), + path, range: PointUtf16::new(start.row, start.column)..PointUtf16::new(end.row, end.column), kind, signature: serialized_symbol @@ -4349,10 +4359,11 @@ impl Project { &self, buffer: &Buffer, cx: &AppContext, - ) -> Option<&Arc> { + ) -> Option<&(Arc, Arc)> { if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) { let worktree_id = file.worktree_id(cx); - self.language_servers.get(&(worktree_id, language.name())) + self.language_servers + .get(&(worktree_id, language.lsp_adapter()?.name())) } else { None } @@ -4466,7 +4477,7 @@ impl Entity for Project { let shutdown_futures = self .language_servers .drain() - .filter_map(|(_, server)| server.shutdown()) + .filter_map(|(_, (_, server))| server.shutdown()) .collect::>(); Some( async move { @@ -4537,7 +4548,7 @@ fn serialize_symbol(symbol: &Symbol) -> proto::Symbol { proto::Symbol { source_worktree_id: symbol.source_worktree_id.to_proto(), worktree_id: symbol.worktree_id.to_proto(), - language_name: symbol.language_name.clone(), + language_server_name: symbol.language_server_name.0.to_string(), name: symbol.name.clone(), kind: unsafe { mem::transmute(symbol.kind) }, path: symbol.path.to_string_lossy().to_string(), diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 9d25e66190..cef0e60f0f 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -229,7 +229,7 @@ message GetProjectSymbolsResponse { message Symbol { uint64 source_worktree_id = 1; uint64 worktree_id = 2; - string language_name = 3; + string language_server_name = 3; string name = 4; int32 kind = 5; string path = 6; diff --git a/crates/zed/src/languages/c.rs b/crates/zed/src/languages/c.rs index cf4e219967..56994db425 100644 --- a/crates/zed/src/languages/c.rs +++ b/crates/zed/src/languages/c.rs @@ -3,7 +3,7 @@ use client::http::{self, HttpClient, Method}; use futures::{future::BoxFuture, FutureExt, StreamExt}; pub use language::*; use smol::fs::{self, File}; -use std::{any::Any, path::PathBuf, str, sync::Arc}; +use std::{any::Any, path::PathBuf, sync::Arc}; use util::{ResultExt, TryFutureExt}; use super::GithubRelease; @@ -11,8 +11,8 @@ use super::GithubRelease; pub struct CLspAdapter; impl super::LspAdapter for CLspAdapter { - fn name(&self) -> &'static str { - "clangd" + fn name(&self) -> LanguageServerName { + LanguageServerName("clangd".into()) } fn fetch_latest_server_version( diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs index c1d0db2ed6..4069413f11 100644 --- a/crates/zed/src/languages/json.rs +++ b/crates/zed/src/languages/json.rs @@ -1,7 +1,7 @@ use anyhow::{anyhow, Context, Result}; use client::http::HttpClient; use futures::{future::BoxFuture, FutureExt, StreamExt}; -use language::LspAdapter; +use language::{LanguageServerName, LspAdapter}; use serde::Deserialize; use serde_json::json; use smol::fs; @@ -16,8 +16,8 @@ impl JsonLspAdapter { } impl LspAdapter for JsonLspAdapter { - fn name(&self) -> &'static str { - "vscode-json-languageserver" + fn name(&self) -> LanguageServerName { + LanguageServerName("vscode-json-languageserver".into()) } fn server_args(&self) -> &[&str] { diff --git a/crates/zed/src/languages/rust.rs b/crates/zed/src/languages/rust.rs index 8b06c5cbd7..4034e5effa 100644 --- a/crates/zed/src/languages/rust.rs +++ b/crates/zed/src/languages/rust.rs @@ -14,8 +14,8 @@ use super::GithubRelease; pub struct RustLspAdapter; impl LspAdapter for RustLspAdapter { - fn name(&self) -> &'static str { - "rust-analyzer" + fn name(&self) -> LanguageServerName { + LanguageServerName("rust-analyzer".into()) } fn fetch_latest_server_version( diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs index f7547fdd4e..4d7af34c38 100644 --- a/crates/zed/src/languages/typescript.rs +++ b/crates/zed/src/languages/typescript.rs @@ -1,7 +1,7 @@ use anyhow::{anyhow, Context, Result}; use client::http::HttpClient; use futures::{future::BoxFuture, FutureExt, StreamExt}; -use language::LspAdapter; +use language::{LanguageServerName, LspAdapter}; use serde::Deserialize; use serde_json::json; use smol::fs; @@ -20,8 +20,8 @@ struct Versions { } impl LspAdapter for TypeScriptLspAdapter { - fn name(&self) -> &'static str { - "typescript-language-server" + fn name(&self) -> LanguageServerName { + LanguageServerName("typescript-language-server".into()) } fn server_args(&self) -> &[&str] { From ebc711f9f500bd5c10d774659e6d3d0b6f078c27 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 29 Mar 2022 17:54:29 -0700 Subject: [PATCH 08/68] Restructure fake language server setup Replace FakeLanguageServerConfig with FakeLanguageServerAdapter --- crates/editor/src/editor.rs | 51 ++- crates/language/src/language.rs | 101 +++-- crates/project/src/project.rs | 124 +++--- crates/server/src/rpc.rs | 729 ++++++++++++++++---------------- 4 files changed, 503 insertions(+), 502 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index dac7adfdf8..b9428fc1f5 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -6438,13 +6438,12 @@ pub fn styled_runs_for_code_label<'a>( #[cfg(test)] mod tests { - use super::*; use gpui::{ geometry::rect::RectF, platform::{WindowBounds, WindowOptions}, }; - use language::{LanguageConfig, LanguageServerConfig}; + use language::{FakeLspAdapter, LanguageConfig}; use lsp::FakeLanguageServer; use project::FakeFs; use smol::stream::StreamExt; @@ -8880,26 +8879,27 @@ mod tests { cx.foreground().forbid_parking(); cx.update(populate_settings); - let (mut language_server_config, mut fake_servers) = LanguageServerConfig::fake(); - language_server_config.set_fake_capabilities(lsp::ServerCapabilities { - document_formatting_provider: Some(lsp::OneOf::Left(true)), - ..Default::default() - }); - let language = Arc::new(Language::new( + let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), - )); + ); + let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter { + capabilities: lsp::ServerCapabilities { + document_formatting_provider: Some(lsp::OneOf::Left(true)), + ..Default::default() + }, + ..Default::default() + }); let fs = FakeFs::new(cx.background().clone()); fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, cx); - project.update(cx, |project, _| project.languages().add(language)); + project.update(cx, |project, _| project.languages().add(Arc::new(language))); let worktree_id = project .update(cx, |project, cx| { @@ -8913,6 +8913,8 @@ mod tests { .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx)) .await .unwrap(); + + cx.foreground().start_waiting(); let mut fake_server = fake_servers.next().await.unwrap(); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); @@ -8934,6 +8936,7 @@ mod tests { }) .next() .await; + cx.foreground().start_waiting(); save.await.unwrap(); assert_eq!( editor.read_with(cx, |editor, cx| editor.text(cx)), @@ -8955,6 +8958,7 @@ mod tests { }); let save = cx.update(|cx| editor.save(project.clone(), cx)); cx.foreground().advance_clock(items::FORMAT_TIMEOUT); + cx.foreground().start_waiting(); save.await.unwrap(); assert_eq!( editor.read_with(cx, |editor, cx| editor.text(cx)), @@ -8967,23 +8971,24 @@ mod tests { async fn test_completion(cx: &mut gpui::TestAppContext) { cx.update(populate_settings); - let (mut language_server_config, mut fake_servers) = LanguageServerConfig::fake(); - language_server_config.set_fake_capabilities(lsp::ServerCapabilities { - completion_provider: Some(lsp::CompletionOptions { - trigger_characters: Some(vec![".".to_string(), ":".to_string()]), - ..Default::default() - }), - ..Default::default() - }); - let language = Arc::new(Language::new( + let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), - )); + ); + let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter { + capabilities: lsp::ServerCapabilities { + completion_provider: Some(lsp::CompletionOptions { + trigger_characters: Some(vec![".".to_string(), ":".to_string()]), + ..Default::default() + }), + ..Default::default() + }, + ..Default::default() + }); let text = " one @@ -8996,7 +9001,7 @@ mod tests { fs.insert_file("/file.rs", text).await; let project = Project::test(fs, cx); - project.update(cx, |project, _| project.languages().add(language)); + project.update(cx, |project, _| project.languages().add(Arc::new(language))); let worktree_id = project .update(cx, |project, cx| { diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 8d573574fd..a98f1a9845 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -138,16 +138,13 @@ impl Default for LanguageConfig { pub struct LanguageServerConfig { pub disk_based_diagnostic_sources: HashSet, pub disk_based_diagnostics_progress_token: Option, - #[cfg(any(test, feature = "test-support"))] - #[serde(skip)] - fake_config: Option, } #[cfg(any(test, feature = "test-support"))] -struct FakeLanguageServerConfig { - servers_tx: mpsc::UnboundedSender, - capabilities: lsp::ServerCapabilities, - initializer: Option>, +pub struct FakeLspAdapter { + pub name: &'static str, + pub capabilities: lsp::ServerCapabilities, + pub initializer: Option>, } #[derive(Clone, Debug, Deserialize)] @@ -162,6 +159,12 @@ pub struct Language { pub(crate) config: LanguageConfig, pub(crate) grammar: Option>, pub(crate) adapter: Option>, + + #[cfg(any(test, feature = "test-support"))] + fake_adapter: Option<( + mpsc::UnboundedSender, + Arc, + )>, } pub struct Grammar { @@ -262,26 +265,22 @@ impl LanguageRegistry { cx: &mut MutableAppContext, ) -> Option>> { #[cfg(any(test, feature = "test-support"))] - if language.config.language_server.fake_config.is_some() { + if language.fake_adapter.is_some() { let language = language.clone(); return Some(cx.spawn(|mut cx| async move { - let fake_config = language - .config - .language_server - .fake_config - .as_ref() - .unwrap(); + let (servers_tx, fake_adapter) = language.fake_adapter.as_ref().unwrap(); let (server, mut fake_server) = cx.update(|cx| { lsp::LanguageServer::fake_with_capabilities( - fake_config.capabilities.clone(), + fake_adapter.capabilities.clone(), cx, ) }); - if let Some(initializer) = &fake_config.initializer { + + if let Some(initializer) = &fake_adapter.initializer { initializer(&mut fake_server); } - let servers_tx = fake_config.servers_tx.clone(); + let servers_tx = servers_tx.clone(); cx.background() .spawn(async move { fake_server @@ -426,6 +425,9 @@ impl Language { }) }), adapter: None, + + #[cfg(any(test, feature = "test-support"))] + fake_adapter: None, } } @@ -478,6 +480,18 @@ impl Language { self } + #[cfg(any(test, feature = "test-support"))] + pub fn set_fake_lsp_adapter( + &mut self, + fake_lsp_adapter: FakeLspAdapter, + ) -> mpsc::UnboundedReceiver { + let (servers_tx, servers_rx) = mpsc::unbounded(); + let adapter = Arc::new(fake_lsp_adapter); + self.fake_adapter = Some((servers_tx, adapter.clone())); + self.adapter = Some(adapter); + servers_rx + } + pub fn name(&self) -> Arc { self.config.name.clone() } @@ -601,33 +615,42 @@ impl CodeLabel { } #[cfg(any(test, feature = "test-support"))] -impl LanguageServerConfig { - pub fn fake() -> (Self, mpsc::UnboundedReceiver) { - let (servers_tx, servers_rx) = mpsc::unbounded(); - ( - Self { - fake_config: Some(FakeLanguageServerConfig { - servers_tx, - capabilities: lsp::LanguageServer::full_capabilities(), - initializer: None, - }), - disk_based_diagnostics_progress_token: Some("fakeServer/check".to_string()), - ..Default::default() - }, - servers_rx, - ) +impl Default for FakeLspAdapter { + fn default() -> Self { + Self { + name: "the-fake-language-server", + capabilities: lsp::LanguageServer::full_capabilities(), + initializer: None, + } + } +} + +impl LspAdapter for FakeLspAdapter { + fn name(&self) -> LanguageServerName { + LanguageServerName(self.name.into()) } - pub fn set_fake_capabilities(&mut self, capabilities: lsp::ServerCapabilities) { - self.fake_config.as_mut().unwrap().capabilities = capabilities; + fn fetch_latest_server_version( + &self, + _: Arc, + ) -> BoxFuture<'static, Result>> { + unreachable!(); } - pub fn set_fake_initializer( - &mut self, - initializer: impl 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer), - ) { - self.fake_config.as_mut().unwrap().initializer = Some(Box::new(initializer)); + fn fetch_server_binary( + &self, + _: Box, + _: Arc, + _: PathBuf, + ) -> BoxFuture<'static, Result> { + unreachable!(); } + + fn cached_server_binary(&self, _: PathBuf) -> BoxFuture<'static, Option> { + unreachable!(); + } + + fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {} } impl ToLspPosition for PointUtf16 { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 6f550d1020..1dd0f907f7 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -4606,8 +4606,8 @@ mod tests { use futures::StreamExt; use gpui::test::subscribe; use language::{ - tree_sitter_rust, Diagnostic, LanguageConfig, LanguageServerConfig, OffsetRangeExt, Point, - ToPoint, + tree_sitter_rust, Diagnostic, FakeLspAdapter, LanguageConfig, LanguageServerConfig, + OffsetRangeExt, Point, ToPoint, }; use lsp::Url; use serde_json::json; @@ -4683,41 +4683,44 @@ mod tests { async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) { cx.foreground().forbid_parking(); - let (mut rust_lsp_config, mut fake_rust_servers) = LanguageServerConfig::fake(); - let (mut json_lsp_config, mut fake_json_servers) = LanguageServerConfig::fake(); - rust_lsp_config.set_fake_capabilities(lsp::ServerCapabilities { - completion_provider: Some(lsp::CompletionOptions { - trigger_characters: Some(vec![".".to_string(), "::".to_string()]), - ..Default::default() - }), - ..Default::default() - }); - json_lsp_config.set_fake_capabilities(lsp::ServerCapabilities { - completion_provider: Some(lsp::CompletionOptions { - trigger_characters: Some(vec![":".to_string()]), - ..Default::default() - }), - ..Default::default() - }); - - let rust_language = Arc::new(Language::new( + let mut rust_language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: rust_lsp_config, ..Default::default() }, Some(tree_sitter_rust::language()), - )); - let json_language = Arc::new(Language::new( + ); + let mut json_language = Language::new( LanguageConfig { name: "JSON".into(), path_suffixes: vec!["json".to_string()], - language_server: json_lsp_config, ..Default::default() }, None, - )); + ); + let mut fake_rust_servers = rust_language.set_fake_lsp_adapter(FakeLspAdapter { + name: "the-rust-language-server", + capabilities: lsp::ServerCapabilities { + completion_provider: Some(lsp::CompletionOptions { + trigger_characters: Some(vec![".".to_string(), "::".to_string()]), + ..Default::default() + }), + ..Default::default() + }, + ..Default::default() + }); + let mut fake_json_servers = json_language.set_fake_lsp_adapter(FakeLspAdapter { + name: "the-json-language-server", + capabilities: lsp::ServerCapabilities { + completion_provider: Some(lsp::CompletionOptions { + trigger_characters: Some(vec![":".to_string()]), + ..Default::default() + }), + ..Default::default() + }, + ..Default::default() + }); let fs = FakeFs::new(cx.background()); fs.insert_tree( @@ -4733,8 +4736,8 @@ mod tests { let project = Project::test(fs, cx); project.update(cx, |project, _| { - project.languages.add(rust_language); - project.languages.add(json_language); + project.languages.add(Arc::new(rust_language)); + project.languages.add(Arc::new(json_language)); }); let worktree_id = project @@ -4903,21 +4906,20 @@ mod tests { async fn test_disk_based_diagnostics_progress(cx: &mut gpui::TestAppContext) { cx.foreground().forbid_parking(); - let (language_server_config, mut fake_servers) = LanguageServerConfig::fake(); - let progress_token = language_server_config - .disk_based_diagnostics_progress_token - .clone() - .unwrap(); - - let language = Arc::new(Language::new( + let progress_token = "the-progress-token".to_string(); + let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, + language_server: LanguageServerConfig { + disk_based_diagnostics_progress_token: Some(progress_token.clone()), + ..Default::default() + }, ..Default::default() }, Some(tree_sitter_rust::language()), - )); + ); + let mut fake_servers = language.set_fake_lsp_adapter(Default::default()); let fs = FakeFs::new(cx.background()); fs.insert_tree( @@ -4930,7 +4932,7 @@ mod tests { .await; let project = Project::test(fs, cx); - project.update(cx, |project, _| project.languages.add(language)); + project.update(cx, |project, _| project.languages.add(Arc::new(language))); let (tree, _) = project .update(cx, |project, cx| { @@ -5022,19 +5024,20 @@ mod tests { async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { cx.foreground().forbid_parking(); - let (mut lsp_config, mut fake_servers) = LanguageServerConfig::fake(); - lsp_config - .disk_based_diagnostic_sources - .insert("disk".to_string()); - let language = Arc::new(Language::new( + // let (mut lsp_config, mut fake_servers) = LanguageServerConfig::fake(); + let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: lsp_config, + language_server: LanguageServerConfig { + disk_based_diagnostic_sources: ["disk".to_string()].into_iter().collect(), + ..Default::default() + }, ..Default::default() }, Some(tree_sitter_rust::language()), - )); + ); + let mut fake_servers = language.set_fake_lsp_adapter(Default::default()); let text = " fn a() { A } @@ -5047,7 +5050,7 @@ mod tests { fs.insert_tree("/dir", json!({ "a.rs": text })).await; let project = Project::test(fs, cx); - project.update(cx, |project, _| project.languages.add(language)); + project.update(cx, |project, _| project.languages.add(Arc::new(language))); let worktree_id = project .update(cx, |project, cx| { @@ -5396,16 +5399,15 @@ mod tests { async fn test_edits_from_lsp_with_past_version(cx: &mut gpui::TestAppContext) { cx.foreground().forbid_parking(); - let (lsp_config, mut fake_servers) = LanguageServerConfig::fake(); - let language = Arc::new(Language::new( + let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: lsp_config, ..Default::default() }, Some(tree_sitter_rust::language()), - )); + ); + let mut fake_servers = language.set_fake_lsp_adapter(Default::default()); let text = " fn a() { @@ -5430,7 +5432,7 @@ mod tests { .await; let project = Project::test(fs, cx); - project.update(cx, |project, _| project.languages.add(language)); + project.update(cx, |project, _| project.languages.add(Arc::new(language))); let worktree_id = project .update(cx, |project, cx| { @@ -5746,16 +5748,15 @@ mod tests { #[gpui::test] async fn test_definition(cx: &mut gpui::TestAppContext) { - let (language_server_config, mut fake_servers) = LanguageServerConfig::fake(); - let language = Arc::new(Language::new( + let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), - )); + ); + let mut fake_servers = language.set_fake_lsp_adapter(Default::default()); let fs = FakeFs::new(cx.background()); fs.insert_tree( @@ -5768,9 +5769,7 @@ mod tests { .await; let project = Project::test(fs, cx); - project.update(cx, |project, _| { - Arc::get_mut(&mut project.languages).unwrap().add(language); - }); + project.update(cx, |project, _| project.languages.add(Arc::new(language))); let (tree, _) = project .update(cx, |project, cx| { @@ -6682,16 +6681,15 @@ mod tests { async fn test_rename(cx: &mut gpui::TestAppContext) { cx.foreground().forbid_parking(); - let (language_server_config, mut fake_servers) = LanguageServerConfig::fake(); - let language = Arc::new(Language::new( + let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), - )); + ); + let mut fake_servers = language.set_fake_lsp_adapter(Default::default()); let fs = FakeFs::new(cx.background()); fs.insert_tree( @@ -6704,9 +6702,7 @@ mod tests { .await; let project = Project::test(fs.clone(), cx); - project.update(cx, |project, _| { - Arc::get_mut(&mut project.languages).unwrap().add(language); - }); + project.update(cx, |project, _| project.languages.add(Arc::new(language))); let (tree, _) = project .update(cx, |project, cx| { diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index b329839de2..0f8720c673 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -1088,10 +1088,10 @@ mod tests { }; use gpui::{executor, geometry::vector::vec2f, ModelHandle, TestAppContext, ViewHandle}; use language::{ - tree_sitter_rust, Diagnostic, DiagnosticEntry, Language, LanguageConfig, LanguageRegistry, - LanguageServerConfig, OffsetRangeExt, Point, ToLspPosition, + tree_sitter_rust, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, LanguageConfig, + LanguageRegistry, OffsetRangeExt, Point, ToLspPosition, }; - use lsp; + use lsp::{self, FakeLanguageServer}; use parking_lot::Mutex; use postage::barrier; use project::{ @@ -2039,22 +2039,20 @@ mod tests { cx_b: &mut TestAppContext, ) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2261,29 +2259,29 @@ mod tests { cx_b: &mut TestAppContext, ) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); // Set up a fake language server. - let (mut language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - language_server_config.set_fake_capabilities(lsp::ServerCapabilities { - completion_provider: Some(lsp::CompletionOptions { - trigger_characters: Some(vec![".".to_string()]), + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], ..Default::default() - }), + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(FakeLspAdapter { + capabilities: lsp::ServerCapabilities { + completion_provider: Some(lsp::CompletionOptions { + trigger_characters: Some(vec![".".to_string()]), + ..Default::default() + }), + ..Default::default() + }, ..Default::default() }); - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2463,22 +2461,20 @@ mod tests { #[gpui::test(iterations = 10)] async fn test_formatting_buffer(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2563,7 +2559,7 @@ mod tests { #[gpui::test(iterations = 10)] async fn test_definition(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); fs.insert_tree( "/root-1", @@ -2582,18 +2578,16 @@ mod tests { .await; // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2705,7 +2699,7 @@ mod tests { #[gpui::test(iterations = 10)] async fn test_references(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); fs.insert_tree( "/root-1", @@ -2725,18 +2719,16 @@ mod tests { .await; // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -2967,16 +2959,16 @@ mod tests { .await; // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - lang_registry.add(Arc::new(Language::new( + let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, ..Default::default() }, Some(tree_sitter_rust::language()), - ))); + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -3092,7 +3084,7 @@ mod tests { #[gpui::test(iterations = 10)] async fn test_project_symbols(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); fs.insert_tree( "/code", @@ -3112,18 +3104,16 @@ mod tests { .await; // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -3231,7 +3221,7 @@ mod tests { mut rng: StdRng, ) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); fs.insert_tree( "/root", @@ -3244,19 +3234,16 @@ mod tests { .await; // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -3337,23 +3324,21 @@ mod tests { cx_b: &mut TestAppContext, ) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); cx_b.update(|cx| editor::init(cx)); // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -3573,23 +3558,21 @@ mod tests { #[gpui::test(iterations = 10)] async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { cx_a.foreground().forbid_parking(); - let mut lang_registry = Arc::new(LanguageRegistry::test()); + let lang_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx_a.background()); cx_b.update(|cx| editor::init(cx)); // Set up a fake language server. - let (language_server_config, mut fake_language_servers) = LanguageServerConfig::fake(); - Arc::get_mut(&mut lang_registry) - .unwrap() - .add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - Some(tree_sitter_rust::language()), - ))); + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + lang_registry.add(Arc::new(language)); // Connect to a server as 2 clients. let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; @@ -4838,7 +4821,7 @@ mod tests { let rng = Arc::new(Mutex::new(rng)); let guest_lang_registry = Arc::new(LanguageRegistry::test()); - let (language_server_config, _fake_language_servers) = LanguageServerConfig::fake(); + let host_language_registry = Arc::new(LanguageRegistry::test()); let fs = FakeFs::new(cx.background()); fs.insert_tree( @@ -4852,6 +4835,7 @@ mod tests { let operations = Rc::new(Cell::new(0)); let mut server = TestServer::start(cx.foreground(), cx.background()).await; let mut clients = Vec::new(); + let files = Arc::new(Mutex::new(Vec::new())); let mut next_entity_id = 100000; let mut host_cx = TestAppContext::new( @@ -4868,7 +4852,7 @@ mod tests { Project::local( host.client.clone(), host.user_store.clone(), - Arc::new(LanguageRegistry::test()), + host_language_registry.clone(), fs.clone(), cx, ) @@ -4891,9 +4875,138 @@ mod tests { .await .unwrap(); + // Set up fake language servers. + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + None, + ); + let _fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter { + name: "the-fake-language-server", + capabilities: lsp::LanguageServer::full_capabilities(), + initializer: Some(Box::new({ + let rng = rng.clone(); + let files = files.clone(); + let project = host_project.downgrade(); + move |fake_server: &mut FakeLanguageServer| { + fake_server.handle_request::( + |_, _| async move { + Some(lsp::CompletionResponse::Array(vec![lsp::CompletionItem { + text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { + range: lsp::Range::new( + lsp::Position::new(0, 0), + lsp::Position::new(0, 0), + ), + new_text: "the-new-text".to_string(), + })), + ..Default::default() + }])) + }, + ); + + fake_server.handle_request::( + |_, _| async move { + Some(vec![lsp::CodeActionOrCommand::CodeAction( + lsp::CodeAction { + title: "the-code-action".to_string(), + ..Default::default() + }, + )]) + }, + ); + + fake_server.handle_request::( + |params, _| async move { + Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( + params.position, + params.position, + ))) + }, + ); + + fake_server.handle_request::({ + let files = files.clone(); + let rng = rng.clone(); + move |_, _| { + let files = files.clone(); + let rng = rng.clone(); + async move { + let files = files.lock(); + let mut rng = rng.lock(); + let count = rng.gen_range::(1..3); + let files = (0..count) + .map(|_| files.choose(&mut *rng).unwrap()) + .collect::>(); + log::info!("LSP: Returning definitions in files {:?}", &files); + Some(lsp::GotoDefinitionResponse::Array( + files + .into_iter() + .map(|file| lsp::Location { + uri: lsp::Url::from_file_path(file).unwrap(), + range: Default::default(), + }) + .collect(), + )) + } + } + }); + + fake_server.handle_request::({ + let rng = rng.clone(); + let project = project.clone(); + move |params, mut cx| { + let highlights = if let Some(project) = project.upgrade(&cx) { + project.update(&mut cx, |project, cx| { + let path = params + .text_document_position_params + .text_document + .uri + .to_file_path() + .unwrap(); + let (worktree, relative_path) = + project.find_local_worktree(&path, cx)?; + let project_path = + ProjectPath::from((worktree.read(cx).id(), relative_path)); + let buffer = + project.get_open_buffer(&project_path, cx)?.read(cx); + + let mut highlights = Vec::new(); + let highlight_count = rng.lock().gen_range(1..=5); + let mut prev_end = 0; + for _ in 0..highlight_count { + let range = + buffer.random_byte_range(prev_end, &mut *rng.lock()); + let start = buffer + .offset_to_point_utf16(range.start) + .to_lsp_position(); + let end = buffer + .offset_to_point_utf16(range.end) + .to_lsp_position(); + highlights.push(lsp::DocumentHighlight { + range: lsp::Range::new(start, end), + kind: Some(lsp::DocumentHighlightKind::READ), + }); + prev_end = range.end; + } + Some(highlights) + }) + } else { + None + }; + async move { highlights } + } + }); + } + })), + }); + host_language_registry.add(Arc::new(language)); + clients.push(cx.foreground().spawn(host.simulate_host( host_project, - language_server_config, + files, operations.clone(), max_operations, rng.clone(), @@ -5324,264 +5437,128 @@ mod tests { }) } - fn simulate_host( + async fn simulate_host( mut self, project: ModelHandle, - mut language_server_config: LanguageServerConfig, + files: Arc>>, operations: Rc>, max_operations: usize, rng: Arc>, mut cx: TestAppContext, - ) -> impl Future { - let files: Arc>> = Default::default(); + ) -> (Self, TestAppContext) { + let fs = project.read_with(&cx, |project, _| project.fs().clone()); + while operations.get() < max_operations { + operations.set(operations.get() + 1); - // Set up a fake language server. - language_server_config.set_fake_initializer({ - let rng = rng.clone(); - let files = files.clone(); - let project = project.downgrade(); - move |fake_server| { - fake_server.handle_request::( - |_, _| async move { - Some(lsp::CompletionResponse::Array(vec![lsp::CompletionItem { - text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { - range: lsp::Range::new( - lsp::Position::new(0, 0), - lsp::Position::new(0, 0), - ), - new_text: "the-new-text".to_string(), - })), - ..Default::default() - }])) - }, - ); - - fake_server.handle_request::( - |_, _| async move { - Some(vec![lsp::CodeActionOrCommand::CodeAction( - lsp::CodeAction { - title: "the-code-action".to_string(), - ..Default::default() - }, - )]) - }, - ); - - fake_server.handle_request::( - |params, _| async move { - Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( - params.position, - params.position, - ))) - }, - ); - - fake_server.handle_request::({ - let files = files.clone(); - let rng = rng.clone(); - move |_, _| { - let files = files.clone(); - let rng = rng.clone(); - async move { - let files = files.lock(); - let mut rng = rng.lock(); - let count = rng.gen_range::(1..3); - let files = (0..count) - .map(|_| files.choose(&mut *rng).unwrap()) - .collect::>(); - log::info!("LSP: Returning definitions in files {:?}", &files); - Some(lsp::GotoDefinitionResponse::Array( - files - .into_iter() - .map(|file| lsp::Location { - uri: lsp::Url::from_file_path(file).unwrap(), - range: Default::default(), - }) - .collect(), - )) - } - } - }); - - fake_server.handle_request::({ - let rng = rng.clone(); - let project = project.clone(); - move |params, mut cx| { - let highlights = if let Some(project) = project.upgrade(&cx) { - project.update(&mut cx, |project, cx| { - let path = params - .text_document_position_params - .text_document - .uri - .to_file_path() - .unwrap(); - let (worktree, relative_path) = - project.find_local_worktree(&path, cx)?; - let project_path = - ProjectPath::from((worktree.read(cx).id(), relative_path)); - let buffer = - project.get_open_buffer(&project_path, cx)?.read(cx); - - let mut highlights = Vec::new(); - let highlight_count = rng.lock().gen_range(1..=5); - let mut prev_end = 0; - for _ in 0..highlight_count { - let range = - buffer.random_byte_range(prev_end, &mut *rng.lock()); - let start = buffer - .offset_to_point_utf16(range.start) - .to_lsp_position(); - let end = buffer - .offset_to_point_utf16(range.end) - .to_lsp_position(); - highlights.push(lsp::DocumentHighlight { - range: lsp::Range::new(start, end), - kind: Some(lsp::DocumentHighlightKind::READ), - }); - prev_end = range.end; - } - Some(highlights) - }) - } else { - None - }; - async move { highlights } - } - }); - } - }); - - project.update(&mut cx, |project, _| { - project.languages().add(Arc::new(Language::new( - LanguageConfig { - name: "Rust".into(), - path_suffixes: vec!["rs".to_string()], - language_server: language_server_config, - ..Default::default() - }, - None, - ))); - }); - - async move { - let fs = project.read_with(&cx, |project, _| project.fs().clone()); - while operations.get() < max_operations { - operations.set(operations.get() + 1); - - let distribution = rng.lock().gen_range::(0..100); - match distribution { - 0..=20 if !files.lock().is_empty() => { - let path = files.lock().choose(&mut *rng.lock()).unwrap().clone(); - let mut path = path.as_path(); - while let Some(parent_path) = path.parent() { - path = parent_path; - if rng.lock().gen() { - break; - } - } - - log::info!("Host: find/create local worktree {:?}", path); - let find_or_create_worktree = project.update(&mut cx, |project, cx| { - project.find_or_create_local_worktree(path, true, cx) - }); - let find_or_create_worktree = async move { - find_or_create_worktree.await.unwrap(); - }; + let distribution = rng.lock().gen_range::(0..100); + match distribution { + 0..=20 if !files.lock().is_empty() => { + let path = files.lock().choose(&mut *rng.lock()).unwrap().clone(); + let mut path = path.as_path(); + while let Some(parent_path) = path.parent() { + path = parent_path; if rng.lock().gen() { - cx.background().spawn(find_or_create_worktree).detach(); - } else { - find_or_create_worktree.await; - } - } - 10..=80 if !files.lock().is_empty() => { - let buffer = if self.buffers.is_empty() || rng.lock().gen() { - let file = files.lock().choose(&mut *rng.lock()).unwrap().clone(); - let (worktree, path) = project - .update(&mut cx, |project, cx| { - project.find_or_create_local_worktree( - file.clone(), - true, - cx, - ) - }) - .await - .unwrap(); - let project_path = - worktree.read_with(&cx, |worktree, _| (worktree.id(), path)); - log::info!( - "Host: opening path {:?}, worktree {}, relative_path {:?}", - file, - project_path.0, - project_path.1 - ); - let buffer = project - .update(&mut cx, |project, cx| { - project.open_buffer(project_path, cx) - }) - .await - .unwrap(); - self.buffers.insert(buffer.clone()); - buffer - } else { - self.buffers - .iter() - .choose(&mut *rng.lock()) - .unwrap() - .clone() - }; - - if rng.lock().gen_bool(0.1) { - cx.update(|cx| { - log::info!( - "Host: dropping buffer {:?}", - buffer.read(cx).file().unwrap().full_path(cx) - ); - self.buffers.remove(&buffer); - drop(buffer); - }); - } else { - buffer.update(&mut cx, |buffer, cx| { - log::info!( - "Host: updating buffer {:?} ({})", - buffer.file().unwrap().full_path(cx), - buffer.remote_id() - ); - buffer.randomly_edit(&mut *rng.lock(), 5, cx) - }); - } - } - _ => loop { - let path_component_count = rng.lock().gen_range::(1..=5); - let mut path = PathBuf::new(); - path.push("/"); - for _ in 0..path_component_count { - let letter = rng.lock().gen_range(b'a'..=b'z'); - path.push(std::str::from_utf8(&[letter]).unwrap()); - } - path.set_extension("rs"); - let parent_path = path.parent().unwrap(); - - log::info!("Host: creating file {:?}", path,); - - if fs.create_dir(&parent_path).await.is_ok() - && fs.create_file(&path, Default::default()).await.is_ok() - { - files.lock().push(path); break; - } else { - log::info!("Host: cannot create file"); } - }, - } + } - cx.background().simulate_random_delay().await; + log::info!("Host: find/create local worktree {:?}", path); + let find_or_create_worktree = project.update(&mut cx, |project, cx| { + project.find_or_create_local_worktree(path, true, cx) + }); + let find_or_create_worktree = async move { + find_or_create_worktree.await.unwrap(); + }; + if rng.lock().gen() { + cx.background().spawn(find_or_create_worktree).detach(); + } else { + find_or_create_worktree.await; + } + } + 10..=80 if !files.lock().is_empty() => { + let buffer = if self.buffers.is_empty() || rng.lock().gen() { + let file = files.lock().choose(&mut *rng.lock()).unwrap().clone(); + let (worktree, path) = project + .update(&mut cx, |project, cx| { + project.find_or_create_local_worktree(file.clone(), true, cx) + }) + .await + .unwrap(); + let project_path = + worktree.read_with(&cx, |worktree, _| (worktree.id(), path)); + log::info!( + "Host: opening path {:?}, worktree {}, relative_path {:?}", + file, + project_path.0, + project_path.1 + ); + let buffer = project + .update(&mut cx, |project, cx| { + project.open_buffer(project_path, cx) + }) + .await + .unwrap(); + self.buffers.insert(buffer.clone()); + buffer + } else { + self.buffers + .iter() + .choose(&mut *rng.lock()) + .unwrap() + .clone() + }; + + if rng.lock().gen_bool(0.1) { + cx.update(|cx| { + log::info!( + "Host: dropping buffer {:?}", + buffer.read(cx).file().unwrap().full_path(cx) + ); + self.buffers.remove(&buffer); + drop(buffer); + }); + } else { + buffer.update(&mut cx, |buffer, cx| { + log::info!( + "Host: updating buffer {:?} ({})", + buffer.file().unwrap().full_path(cx), + buffer.remote_id() + ); + buffer.randomly_edit(&mut *rng.lock(), 5, cx) + }); + } + } + _ => loop { + let path_component_count = rng.lock().gen_range::(1..=5); + let mut path = PathBuf::new(); + path.push("/"); + for _ in 0..path_component_count { + let letter = rng.lock().gen_range(b'a'..=b'z'); + path.push(std::str::from_utf8(&[letter]).unwrap()); + } + path.set_extension("rs"); + let parent_path = path.parent().unwrap(); + + log::info!("Host: creating file {:?}", path,); + + if fs.create_dir(&parent_path).await.is_ok() + && fs.create_file(&path, Default::default()).await.is_ok() + { + files.lock().push(path); + break; + } else { + log::info!("Host: cannot create file"); + } + }, } - log::info!("Host done"); - - self.project = Some(project); - (self, cx) + cx.background().simulate_random_delay().await; } + + log::info!("Host done"); + + self.project = Some(project); + (self, cx) } pub async fn simulate_guest( From 3b4cab9094152c3bdf101148910aef2c07fae6ab Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 29 Mar 2022 18:11:14 -0700 Subject: [PATCH 09/68] Move all configuration of individual LSP servers to LspAdapter --- crates/language/src/buffer.rs | 3 +- crates/language/src/language.rs | 46 ++++++++++++------- crates/project/src/project.rs | 55 +++++++++++------------ crates/server/src/rpc.rs | 1 + crates/zed/src/languages/rust.rs | 8 ++++ crates/zed/src/languages/rust/config.toml | 4 -- 6 files changed, 65 insertions(+), 52 deletions(-) diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 535798083e..6cd89aa8bd 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1,8 +1,7 @@ pub use crate::{ diagnostic_set::DiagnosticSet, highlight_map::{HighlightId, HighlightMap}, - proto, BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, LanguageServerConfig, - PLAIN_TEXT, + proto, BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, PLAIN_TEXT, }; use crate::{ diagnostic_set::{DiagnosticEntry, DiagnosticGroup}, diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index a98f1a9845..9c4aee6a30 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -8,7 +8,7 @@ mod tests; use anyhow::{anyhow, Context, Result}; use client::http::{self, HttpClient}; -use collections::{HashMap, HashSet}; +use collections::HashMap; use futures::{ future::{BoxFuture, Shared}, FutureExt, TryFutureExt, @@ -52,7 +52,6 @@ lazy_static! { brackets: Default::default(), autoclose_before: Default::default(), line_comment: None, - language_server: Default::default(), }, None, )); @@ -100,6 +99,14 @@ pub trait LspAdapter: 'static + Send + Sync { fn initialization_options(&self) -> Option { None } + + fn disk_based_diagnostic_sources(&self) -> &'static [&'static str] { + Default::default() + } + + fn disk_based_diagnostics_progress_token(&self) -> Option<&'static str> { + None + } } #[derive(Clone, Debug, PartialEq, Eq)] @@ -117,8 +124,6 @@ pub struct LanguageConfig { #[serde(default)] pub autoclose_before: String, pub line_comment: Option, - #[serde(default)] - pub language_server: LanguageServerConfig, } impl Default for LanguageConfig { @@ -129,22 +134,17 @@ impl Default for LanguageConfig { brackets: Default::default(), autoclose_before: Default::default(), line_comment: Default::default(), - language_server: Default::default(), } } } -#[derive(Default, Deserialize)] -pub struct LanguageServerConfig { - pub disk_based_diagnostic_sources: HashSet, - pub disk_based_diagnostics_progress_token: Option, -} - #[cfg(any(test, feature = "test-support"))] pub struct FakeLspAdapter { pub name: &'static str, pub capabilities: lsp::ServerCapabilities, pub initializer: Option>, + pub disk_based_diagnostics_progress_token: Option<&'static str>, + pub disk_based_diagnostics_sources: &'static [&'static str], } #[derive(Clone, Debug, Deserialize)] @@ -500,15 +500,16 @@ impl Language { self.config.line_comment.as_deref() } - pub fn disk_based_diagnostic_sources(&self) -> &HashSet { - &self.config.language_server.disk_based_diagnostic_sources + pub fn disk_based_diagnostic_sources(&self) -> &'static [&'static str] { + self.adapter.as_ref().map_or(&[] as &[_], |adapter| { + adapter.disk_based_diagnostic_sources() + }) } - pub fn disk_based_diagnostics_progress_token(&self) -> Option<&String> { - self.config - .language_server - .disk_based_diagnostics_progress_token + pub fn disk_based_diagnostics_progress_token(&self) -> Option<&'static str> { + self.adapter .as_ref() + .and_then(|adapter| adapter.disk_based_diagnostics_progress_token()) } pub fn process_diagnostics(&self, diagnostics: &mut lsp::PublishDiagnosticsParams) { @@ -621,10 +622,13 @@ impl Default for FakeLspAdapter { name: "the-fake-language-server", capabilities: lsp::LanguageServer::full_capabilities(), initializer: None, + disk_based_diagnostics_progress_token: None, + disk_based_diagnostics_sources: &[], } } } +#[cfg(any(test, feature = "test-support"))] impl LspAdapter for FakeLspAdapter { fn name(&self) -> LanguageServerName { LanguageServerName(self.name.into()) @@ -651,6 +655,14 @@ impl LspAdapter for FakeLspAdapter { } fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {} + + fn disk_based_diagnostic_sources(&self) -> &'static [&'static str] { + self.disk_based_diagnostics_sources + } + + fn disk_based_diagnostics_progress_token(&self) -> Option<&'static str> { + self.disk_based_diagnostics_progress_token + } } impl ToLspPosition for PointUtf16 { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 1dd0f907f7..b27edcc8d4 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1536,7 +1536,7 @@ impl Project { match event { LanguageServerEvent::WorkStart { token } => { - if Some(&token) == disk_diagnostics_token { + if Some(token.as_str()) == disk_diagnostics_token { language_server_status.pending_diagnostic_updates += 1; if language_server_status.pending_diagnostic_updates == 1 { self.disk_based_diagnostics_started(cx); @@ -1558,7 +1558,7 @@ impl Project { } } LanguageServerEvent::WorkProgress { token, progress } => { - if Some(&token) != disk_diagnostics_token { + if Some(token.as_str()) != disk_diagnostics_token { self.on_lsp_work_progress( language_server_id, token.clone(), @@ -1578,7 +1578,7 @@ impl Project { } } LanguageServerEvent::WorkEnd { token } => { - if Some(&token) == disk_diagnostics_token { + if Some(token.as_str()) == disk_diagnostics_token { language_server_status.pending_diagnostic_updates -= 1; if language_server_status.pending_diagnostic_updates == 0 { self.disk_based_diagnostics_finished(cx); @@ -1708,7 +1708,7 @@ impl Project { pub fn update_diagnostics( &mut self, params: lsp::PublishDiagnosticsParams, - disk_based_sources: &HashSet, + disk_based_sources: &[&str], cx: &mut ModelContext, ) -> Result<()> { let abs_path = params @@ -1751,8 +1751,9 @@ impl Project { ); } else { let group_id = post_inc(&mut next_group_id); - let is_disk_based = - source.map_or(false, |source| disk_based_sources.contains(source)); + let is_disk_based = source.map_or(false, |source| { + disk_based_sources.contains(&source.as_str()) + }); sources_by_group_id.insert(group_id, source); primary_diagnostic_group_ids @@ -4606,8 +4607,8 @@ mod tests { use futures::StreamExt; use gpui::test::subscribe; use language::{ - tree_sitter_rust, Diagnostic, FakeLspAdapter, LanguageConfig, LanguageServerConfig, - OffsetRangeExt, Point, ToPoint, + tree_sitter_rust, Diagnostic, FakeLspAdapter, LanguageConfig, OffsetRangeExt, Point, + ToPoint, }; use lsp::Url; use serde_json::json; @@ -4906,20 +4907,20 @@ mod tests { async fn test_disk_based_diagnostics_progress(cx: &mut gpui::TestAppContext) { cx.foreground().forbid_parking(); - let progress_token = "the-progress-token".to_string(); + let progress_token = "the-progress-token"; let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: LanguageServerConfig { - disk_based_diagnostics_progress_token: Some(progress_token.clone()), - ..Default::default() - }, ..Default::default() }, Some(tree_sitter_rust::language()), ); - let mut fake_servers = language.set_fake_lsp_adapter(Default::default()); + let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter { + disk_based_diagnostics_progress_token: Some(progress_token), + disk_based_diagnostics_sources: &["disk"], + ..Default::default() + }); let fs = FakeFs::new(cx.background()); fs.insert_tree( @@ -4956,15 +4957,15 @@ mod tests { let mut events = subscribe(&project, cx); let mut fake_server = fake_servers.next().await.unwrap(); - fake_server.start_progress(&progress_token).await; + fake_server.start_progress(progress_token).await; assert_eq!( events.next().await.unwrap(), Event::DiskBasedDiagnosticsStarted ); - fake_server.start_progress(&progress_token).await; - fake_server.end_progress(&progress_token).await; - fake_server.start_progress(&progress_token).await; + fake_server.start_progress(progress_token).await; + fake_server.end_progress(progress_token).await; + fake_server.start_progress(progress_token).await; fake_server.notify::( lsp::PublishDiagnosticsParams { @@ -4983,8 +4984,8 @@ mod tests { Event::DiagnosticsUpdated((worktree_id, Path::new("a.rs")).into()) ); - fake_server.end_progress(&progress_token).await; - fake_server.end_progress(&progress_token).await; + fake_server.end_progress(progress_token).await; + fake_server.end_progress(progress_token).await; assert_eq!( events.next().await.unwrap(), Event::DiskBasedDiagnosticsUpdated @@ -5024,20 +5025,18 @@ mod tests { async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { cx.foreground().forbid_parking(); - // let (mut lsp_config, mut fake_servers) = LanguageServerConfig::fake(); let mut language = Language::new( LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - language_server: LanguageServerConfig { - disk_based_diagnostic_sources: ["disk".to_string()].into_iter().collect(), - ..Default::default() - }, ..Default::default() }, Some(tree_sitter_rust::language()), ); - let mut fake_servers = language.set_fake_lsp_adapter(Default::default()); + let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter { + disk_based_diagnostics_sources: &["disk"], + ..Default::default() + }); let text = " fn a() { A } @@ -6551,9 +6550,7 @@ mod tests { }; project - .update(cx, |p, cx| { - p.update_diagnostics(message, &Default::default(), cx) - }) + .update(cx, |p, cx| p.update_diagnostics(message, &[], cx)) .unwrap(); let buffer = buffer.read_with(cx, |buffer, _| buffer.snapshot()); diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 0f8720c673..1b22d09b56 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -5001,6 +5001,7 @@ mod tests { }); } })), + ..Default::default() }); host_language_registry.add(Arc::new(language)); diff --git a/crates/zed/src/languages/rust.rs b/crates/zed/src/languages/rust.rs index 4034e5effa..4f73818042 100644 --- a/crates/zed/src/languages/rust.rs +++ b/crates/zed/src/languages/rust.rs @@ -112,6 +112,14 @@ impl LspAdapter for RustLspAdapter { .boxed() } + fn disk_based_diagnostic_sources(&self) -> &'static [&'static str] { + &["rustc"] + } + + fn disk_based_diagnostics_progress_token(&self) -> Option<&'static str> { + Some("rustAnalyzer/cargo check") + } + fn process_diagnostics(&self, params: &mut lsp::PublishDiagnosticsParams) { lazy_static! { static ref REGEX: Regex = Regex::new("(?m)`([^`]+)\n`$").unwrap(); diff --git a/crates/zed/src/languages/rust/config.toml b/crates/zed/src/languages/rust/config.toml index 97fe231e0f..e4d222cdde 100644 --- a/crates/zed/src/languages/rust/config.toml +++ b/crates/zed/src/languages/rust/config.toml @@ -10,7 +10,3 @@ brackets = [ { start = "\"", end = "\"", close = true, newline = false }, { start = "/*", end = " */", close = true, newline = false }, ] - -[language_server] -disk_based_diagnostic_sources = ["rustc"] -disk_based_diagnostics_progress_token = "rustAnalyzer/cargo check" From 45ad5f343f0e501283669493e618c3d732ba88ef Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 29 Mar 2022 18:14:42 -0700 Subject: [PATCH 10/68] Parse JS as TSX --- crates/zed/src/languages/tsx/config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/zed/src/languages/tsx/config.toml b/crates/zed/src/languages/tsx/config.toml index 62717266df..a6f4a6d2d0 100644 --- a/crates/zed/src/languages/tsx/config.toml +++ b/crates/zed/src/languages/tsx/config.toml @@ -1,5 +1,5 @@ name = "TSX" -path_suffixes = ["tsx"] +path_suffixes = ["tsx", "js"] line_comment = "// " autoclose_before = ";:.,=}])>" brackets = [ From cf9efd70057c129495dc3184b1056ba6aff3fdcc Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 30 Mar 2022 16:48:57 -0700 Subject: [PATCH 11/68] Improve installation of npm-based language servers * Use --prefix flag to guarantee that they are installed in .zed * Use the @latest tag when available * Extract helper functions Co-authored-by: Keith Simmons --- crates/language/src/language.rs | 7 +- crates/zed/src/languages.rs | 15 +-- crates/zed/src/languages/c.rs | 37 ++------ crates/zed/src/languages/installation.rs | 111 +++++++++++++++++++++++ crates/zed/src/languages/rust.rs | 37 ++------ crates/zed/src/languages/typescript.rs | 59 +++--------- 6 files changed, 141 insertions(+), 125 deletions(-) create mode 100644 crates/zed/src/languages/installation.rs diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index fb736736b6..66cafb422b 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -7,7 +7,7 @@ pub mod proto; mod tests; use anyhow::{anyhow, Context, Result}; -use client::http::{self, HttpClient}; +use client::http::HttpClient; use collections::HashMap; use futures::{ future::{BoxFuture, Shared}, @@ -61,11 +61,6 @@ pub trait ToLspPosition { fn to_lsp_position(self) -> lsp::Position; } -pub struct GitHubLspBinaryVersion { - pub name: String, - pub url: http::Url, -} - #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct LanguageServerName(pub Arc); diff --git a/crates/zed/src/languages.rs b/crates/zed/src/languages.rs index cc22247025..75a5030ec6 100644 --- a/crates/zed/src/languages.rs +++ b/crates/zed/src/languages.rs @@ -1,11 +1,10 @@ -use client::http; use gpui::Task; pub use language::*; use rust_embed::RustEmbed; -use serde::Deserialize; use std::{borrow::Cow, str, sync::Arc}; mod c; +mod installation; mod json; mod rust; mod typescript; @@ -15,18 +14,6 @@ mod typescript; #[exclude = "*.rs"] struct LanguageDir; -#[derive(Deserialize)] -struct GithubRelease { - name: String, - assets: Vec, -} - -#[derive(Deserialize)] -struct GithubReleaseAsset { - name: String, - browser_download_url: http::Url, -} - pub fn build_language_registry(login_shell_env_loaded: Task<()>) -> LanguageRegistry { let languages = LanguageRegistry::new(login_shell_env_loaded); for (name, grammar, lsp_adapter) in [ diff --git a/crates/zed/src/languages/c.rs b/crates/zed/src/languages/c.rs index 56994db425..f2ce41a237 100644 --- a/crates/zed/src/languages/c.rs +++ b/crates/zed/src/languages/c.rs @@ -1,13 +1,12 @@ +use super::installation::{latest_github_release, GitHubLspBinaryVersion}; use anyhow::{anyhow, Result}; -use client::http::{self, HttpClient, Method}; +use client::http::{HttpClient, Method}; use futures::{future::BoxFuture, FutureExt, StreamExt}; pub use language::*; use smol::fs::{self, File}; use std::{any::Any, path::PathBuf, sync::Arc}; use util::{ResultExt, TryFutureExt}; -use super::GithubRelease; - pub struct CLspAdapter; impl super::LspAdapter for CLspAdapter { @@ -20,33 +19,11 @@ impl super::LspAdapter for CLspAdapter { http: Arc, ) -> BoxFuture<'static, Result>> { async move { - let release = http - .send( - surf::RequestBuilder::new( - Method::Get, - http::Url::parse( - "https://api.github.com/repos/clangd/clangd/releases/latest", - ) - .unwrap(), - ) - .middleware(surf::middleware::Redirect::default()) - .build(), - ) - .await - .map_err(|err| anyhow!("error fetching latest release: {}", err))? - .body_json::() - .await - .map_err(|err| anyhow!("error parsing latest release: {}", err))?; - let asset_name = format!("clangd-mac-{}.zip", release.name); - let asset = release - .assets - .iter() - .find(|asset| asset.name == asset_name) - .ok_or_else(|| anyhow!("no release found matching {:?}", asset_name))?; - Ok(Box::new(GitHubLspBinaryVersion { - name: release.name, - url: asset.browser_download_url.clone(), - }) as Box<_>) + let version = latest_github_release("clangd/clangd", http, |release_name| { + format!("clangd-mac-{release_name}.zip") + }) + .await?; + Ok(Box::new(version) as Box<_>) } .boxed() } diff --git a/crates/zed/src/languages/installation.rs b/crates/zed/src/languages/installation.rs new file mode 100644 index 0000000000..212ff472fc --- /dev/null +++ b/crates/zed/src/languages/installation.rs @@ -0,0 +1,111 @@ +use anyhow::{anyhow, Context, Result}; +use client::http::{self, HttpClient, Method}; +use serde::Deserialize; +use std::{path::Path, sync::Arc}; + +pub struct GitHubLspBinaryVersion { + pub name: String, + pub url: http::Url, +} + +#[derive(Deserialize)] +#[serde(rename_all = "kebab-case")] +struct NpmInfo { + #[serde(default)] + dist_tags: NpmInfoDistTags, + versions: Vec, +} + +#[derive(Deserialize, Default)] +struct NpmInfoDistTags { + latest: Option, +} + +#[derive(Deserialize)] +pub(crate) struct GithubRelease { + name: String, + assets: Vec, +} + +#[derive(Deserialize)] +pub(crate) struct GithubReleaseAsset { + name: String, + browser_download_url: http::Url, +} + +pub async fn npm_package_latest_version(name: &str) -> Result { + let output = smol::process::Command::new("npm") + .args(["info", name, "--json"]) + .output() + .await?; + if !output.status.success() { + Err(anyhow!( + "failed to execute npm info: {:?}", + String::from_utf8_lossy(&output.stderr) + ))?; + } + let mut info: NpmInfo = serde_json::from_slice(&output.stdout)?; + info.dist_tags + .latest + .or_else(|| info.versions.pop()) + .ok_or_else(|| anyhow!("no version found for npm package {}", name)) +} + +pub async fn npm_install_packages( + packages: impl IntoIterator, + directory: &Path, +) -> Result<()> { + let output = smol::process::Command::new("npm") + .arg("install") + .arg("--prefix") + .arg(directory) + .args( + packages + .into_iter() + .map(|(name, version)| format!("{name}@{version}")), + ) + .output() + .await + .context("failed to run npm install")?; + if !output.status.success() { + Err(anyhow!( + "failed to execute npm install: {:?}", + String::from_utf8_lossy(&output.stderr) + ))?; + } + Ok(()) +} + +pub async fn latest_github_release( + repo_name_with_owner: &str, + http: Arc, + asset_name: impl Fn(&str) -> String, +) -> Result { + let release = http + .send( + surf::RequestBuilder::new( + Method::Get, + http::Url::parse(&format!( + "https://api.github.com/repos/{repo_name_with_owner}/releases/latest" + )) + .unwrap(), + ) + .middleware(surf::middleware::Redirect::default()) + .build(), + ) + .await + .map_err(|err| anyhow!("error fetching latest release: {}", err))? + .body_json::() + .await + .map_err(|err| anyhow!("error parsing latest release: {}", err))?; + let asset_name = asset_name(&release.name); + let asset = release + .assets + .iter() + .find(|asset| asset.name == asset_name) + .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?; + Ok(GitHubLspBinaryVersion { + name: release.name, + url: asset.browser_download_url.clone(), + }) +} diff --git a/crates/zed/src/languages/rust.rs b/crates/zed/src/languages/rust.rs index 4f73818042..f419f59abb 100644 --- a/crates/zed/src/languages/rust.rs +++ b/crates/zed/src/languages/rust.rs @@ -1,6 +1,7 @@ +use super::installation::{latest_github_release, GitHubLspBinaryVersion}; use anyhow::{anyhow, Result}; use async_compression::futures::bufread::GzipDecoder; -use client::http::{self, HttpClient, Method}; +use client::http::{HttpClient, Method}; use futures::{future::BoxFuture, FutureExt, StreamExt}; pub use language::*; use lazy_static::lazy_static; @@ -9,8 +10,6 @@ use smol::fs::{self, File}; use std::{any::Any, borrow::Cow, env::consts, path::PathBuf, str, sync::Arc}; use util::{ResultExt, TryFutureExt}; -use super::GithubRelease; - pub struct RustLspAdapter; impl LspAdapter for RustLspAdapter { @@ -23,33 +22,11 @@ impl LspAdapter for RustLspAdapter { http: Arc, ) -> BoxFuture<'static, Result>> { async move { - let release = http - .send( - surf::RequestBuilder::new( - Method::Get, - http::Url::parse( - "https://api.github.com/repos/rust-analyzer/rust-analyzer/releases/latest", - ) - .unwrap(), - ) - .middleware(surf::middleware::Redirect::default()) - .build(), - ) - .await - .map_err(|err| anyhow!("error fetching latest release: {}", err))? - .body_json::() - .await - .map_err(|err| anyhow!("error parsing latest release: {}", err))?; - let asset_name = format!("rust-analyzer-{}-apple-darwin.gz", consts::ARCH); - let asset = release - .assets - .iter() - .find(|asset| asset.name == asset_name) - .ok_or_else(|| anyhow!("no release found matching {:?}", asset_name))?; - Ok(Box::new(GitHubLspBinaryVersion { - name: release.name, - url: asset.browser_download_url.clone(), - }) as Box<_>) + let version = latest_github_release("rust-analyzer/rust-analyzer", http, |_| { + format!("rust-analyzer-{}-apple-darwin.gz", consts::ARCH) + }) + .await?; + Ok(Box::new(version) as Box<_>) } .boxed() } diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs index 4d7af34c38..d08da116a5 100644 --- a/crates/zed/src/languages/typescript.rs +++ b/crates/zed/src/languages/typescript.rs @@ -1,8 +1,8 @@ +use super::installation::{npm_install_packages, npm_package_latest_version}; use anyhow::{anyhow, Context, Result}; use client::http::HttpClient; use futures::{future::BoxFuture, FutureExt, StreamExt}; use language::{LanguageServerName, LspAdapter}; -use serde::Deserialize; use serde_json::json; use smol::fs; use std::{any::Any, path::PathBuf, sync::Arc}; @@ -33,37 +33,9 @@ impl LspAdapter for TypeScriptLspAdapter { _: Arc, ) -> BoxFuture<'static, Result>> { async move { - #[derive(Deserialize)] - struct NpmInfo { - versions: Vec, - } - - let typescript_output = smol::process::Command::new("npm") - .args(["info", "typescript", "--json"]) - .output() - .await?; - if !typescript_output.status.success() { - Err(anyhow!("failed to execute npm info"))?; - } - let mut typescript_info: NpmInfo = serde_json::from_slice(&typescript_output.stdout)?; - - let server_output = smol::process::Command::new("npm") - .args(["info", "typescript-language-server", "--json"]) - .output() - .await?; - if !server_output.status.success() { - Err(anyhow!("failed to execute npm info"))?; - } - let mut server_info: NpmInfo = serde_json::from_slice(&server_output.stdout)?; - Ok(Box::new(Versions { - typescript_version: typescript_info - .versions - .pop() - .ok_or_else(|| anyhow!("no versions found in typescript npm info"))?, - server_version: server_info.versions.pop().ok_or_else(|| { - anyhow!("no versions found in typescript language server npm info") - })?, + typescript_version: npm_package_latest_version("typescript").await?, + server_version: npm_package_latest_version("typescript-language-server").await?, }) as Box<_>) } .boxed() @@ -87,20 +59,17 @@ impl LspAdapter for TypeScriptLspAdapter { let binary_path = version_dir.join(Self::BIN_PATH); if fs::metadata(&binary_path).await.is_err() { - let output = smol::process::Command::new("npm") - .current_dir(&version_dir) - .arg("install") - .arg(format!("typescript@{}", versions.typescript_version)) - .arg(format!( - "typescript-language-server@{}", - versions.server_version - )) - .output() - .await - .context("failed to run npm install")?; - if !output.status.success() { - Err(anyhow!("failed to install typescript-language-server"))?; - } + npm_install_packages( + [ + ("typescript", versions.typescript_version.as_str()), + ( + "typescript-language-server", + &versions.server_version.as_str(), + ), + ], + &version_dir, + ) + .await?; if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() { while let Some(entry) = entries.next().await { From c280c85ce714575f1fd7ee980a75211a9ce3c993 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 30 Mar 2022 17:08:40 -0700 Subject: [PATCH 12/68] Hard-code LSP formatting options for now This is needed for auto-formatting to work properly in TypeScript and JSON Co-Authored-By: Keith Simmons --- crates/lsp/src/lsp.rs | 2 ++ crates/project/src/project.rs | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index de47381c46..51a68b83c8 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -181,6 +181,7 @@ impl LanguageServer { buffer.resize(message_len, 0); stdout.read_exact(&mut buffer).await?; + log::trace!("incoming message:{}", String::from_utf8_lossy(&buffer)); if let Ok(AnyNotification { id, method, params }) = serde_json::from_slice(&buffer) @@ -229,6 +230,7 @@ impl LanguageServer { let _clear_response_handlers = ClearResponseHandlers(response_handlers); let mut content_len_buffer = Vec::new(); while let Ok(message) = outbound_rx.recv().await { + log::trace!("outgoing message:{}", String::from_utf8_lossy(&message)); content_len_buffer.clear(); write!(content_len_buffer, "{}", message.len()).unwrap(); stdin.write_all(CONTENT_LEN_HEADER.as_bytes()).await?; diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 5a415ca3eb..e859e756f8 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2046,7 +2046,12 @@ impl Project { language_server .request::(lsp::DocumentFormattingParams { text_document, - options: Default::default(), + options: lsp::FormattingOptions { + tab_size: 4, + insert_spaces: true, + insert_final_newline: Some(true), + ..Default::default() + }, work_done_progress_params: Default::default(), }) .await? @@ -2064,7 +2069,12 @@ impl Project { lsp::DocumentRangeFormattingParams { text_document, range: lsp::Range::new(buffer_start, buffer_end), - options: Default::default(), + options: lsp::FormattingOptions { + tab_size: 4, + insert_spaces: true, + insert_final_newline: Some(true), + ..Default::default() + }, work_done_progress_params: Default::default(), }, ) From 263e3d817667211375686ae8853348017f0657ae Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 30 Mar 2022 17:47:25 -0700 Subject: [PATCH 13/68] Start work on interpreting 'label/insertText' completions These completions don't supply a range that should be overwritten, so the client needs to infer it via substring matching. Co-authored-by: Keith Simmons --- crates/project/src/project.rs | 5 ++++- crates/text/src/tests.rs | 9 +++++++++ crates/text/src/text.rs | 7 +++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index e859e756f8..77dfc741c1 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2363,7 +2363,10 @@ impl Project { Some(lsp::CompletionTextEdit::Edit(edit)) => { (range_from_lsp(edit.range), edit.new_text.clone()) } - None => (position..position, lsp_completion.label.clone()), + None => ( + this.common_prefix_at_position(position, &lsp_completion.label), + lsp_completion.label.clone(), + ), Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => { log::info!("unsupported insert/replace completion"); return None; diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs index 7961dccd56..0faf8e19de 100644 --- a/crates/text/src/tests.rs +++ b/crates/text/src/tests.rs @@ -164,6 +164,15 @@ fn test_line_len() { assert_eq!(buffer.line_len(5), 0); } +#[test] +fn test_common_prefix_at_positionn() { + let buffer = Buffer::new(0, 0, History::new("a = (bcd)".into())); + assert_eq!( + buffer.common_prefix_at_position(Point::new(0, 8), "bcdef"), + Point::new(0, 5)..Point::new(0, 8) + ) +} + #[test] fn test_text_summary_for_range() { let buffer = Buffer::new(0, 0, History::new("ab\nefg\nhklm\nnopqrs\ntuvwxyz".into())); diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index b811d08c04..0e742f8a8b 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1508,6 +1508,13 @@ impl BufferSnapshot { .eq(needle.bytes()) } + pub fn common_prefix_at_position(&self, position: T, needle: &str) -> Range + where + T: TextDimension + ToOffset, + { + todo!() + } + pub fn text(&self) -> String { self.visible_text.to_string() } From 9385690b988cacfadf28e55ecbcc799170ca8131 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Thu, 31 Mar 2022 00:55:55 -0700 Subject: [PATCH 14/68] Add test for common_prefix_at and rewrite it to be more readable and pass the new test cases --- crates/project/src/project.rs | 2 +- crates/text/src/tests.rs | 10 +++++++--- crates/text/src/text.rs | 29 ++++++++++++++++++++++++++--- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 77dfc741c1..df84aec0c5 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2364,7 +2364,7 @@ impl Project { (range_from_lsp(edit.range), edit.new_text.clone()) } None => ( - this.common_prefix_at_position(position, &lsp_completion.label), + this.common_prefix_at(position, &lsp_completion.label), lsp_completion.label.clone(), ), Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => { diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs index 0faf8e19de..54e802b521 100644 --- a/crates/text/src/tests.rs +++ b/crates/text/src/tests.rs @@ -7,6 +7,7 @@ use std::{ iter::Iterator, time::{Duration, Instant}, }; +use util::test::marked_text_ranges; #[cfg(test)] #[ctor::ctor] @@ -166,10 +167,13 @@ fn test_line_len() { #[test] fn test_common_prefix_at_positionn() { - let buffer = Buffer::new(0, 0, History::new("a = (bcd)".into())); + let (text, ranges) = marked_text_ranges("a = [bcd]"); + let buffer = Buffer::new(0, 0, History::new(text.into())); + let snapshot = &buffer.snapshot(); + let expected_range = ranges[0].to_offset(&snapshot); assert_eq!( - buffer.common_prefix_at_position(Point::new(0, 8), "bcdef"), - Point::new(0, 5)..Point::new(0, 8) + buffer.common_prefix_at(expected_range.end, "bcdef"), + expected_range ) } diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 0e742f8a8b..ea0af9d21f 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1508,11 +1508,34 @@ impl BufferSnapshot { .eq(needle.bytes()) } - pub fn common_prefix_at_position(&self, position: T, needle: &str) -> Range + pub fn common_prefix_at(&self, position: T, needle: &str) -> Range where - T: TextDimension + ToOffset, + T: Clone + ToOffset + FromAnchor, { - todo!() + let position_offset = position.to_offset(self); + // Get byte indices and char counts for every character in needle in reverse order + let char_indices = needle + .char_indices() + .map(|(index, _)| index) + .chain(std::iter::once(needle.len())) + .enumerate() + // Don't test any prefixes that are bigger than the requested position + .take_while(|(_, prefix_length)| *prefix_length <= position_offset); + + let start = char_indices + // Compute the prefix string and prefix start location + .map(move |(byte_position, char_length)| { + (position_offset - char_length, &needle[..byte_position]) + }) + // Only take strings when the prefix is contained at the expected prefix position + .filter(|(prefix_offset, prefix)| self.contains_str_at(prefix_offset, prefix)) + // Convert offset to T + .map(|(prefix_offset, _)| T::from_anchor(&self.anchor_before(prefix_offset), self)) + .last() + // If no prefix matches, return the passed in position to create an empty range + .unwrap_or(position.clone()); + + start..position } pub fn text(&self) -> String { From 564225c4015340bdd87bfae551b690ea16904119 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Thu, 31 Mar 2022 15:39:52 -0700 Subject: [PATCH 15/68] Provide diagnostic context to codeAction Co-authored-by: Max Brunsfeld --- crates/language/src/diagnostic_set.rs | 17 +++++++++++ crates/language/src/language.rs | 17 ++++++----- crates/project/src/lsp_command.rs | 14 ++++----- crates/project/src/project.rs | 41 +++++++++++++-------------- crates/server/src/rpc.rs | 13 +++------ 5 files changed, 58 insertions(+), 44 deletions(-) diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index 490789a8c8..51c921e61c 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -34,6 +34,23 @@ pub struct Summary { count: usize, } +impl DiagnosticEntry { + // Used to provide diagnostic context to lsp codeAction request + pub fn to_lsp_diagnostic_stub(&self) -> lsp::Diagnostic { + let code = self + .diagnostic + .code + .clone() + .map(lsp::NumberOrString::String); + + lsp::Diagnostic { + code, + severity: Some(self.diagnostic.severity), + ..Default::default() + } + } +} + impl DiagnosticSet { pub fn from_sorted_entries(iter: I, buffer: &text::BufferSnapshot) -> Self where diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 66cafb422b..2435973201 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -662,18 +662,21 @@ impl LspAdapter for FakeLspAdapter { } } -impl ToLspPosition for PointUtf16 { - fn to_lsp_position(self) -> lsp::Position { - lsp::Position::new(self.row, self.column) - } +pub fn point_to_lsp(point: PointUtf16) -> lsp::Position { + lsp::Position::new(point.row, point.column) } pub fn point_from_lsp(point: lsp::Position) -> PointUtf16 { PointUtf16::new(point.line, point.character) } +pub fn range_to_lsp(range: Range) -> lsp::Range { + lsp::Range { + start: point_to_lsp(range.start), + end: point_to_lsp(range.end), + } +} + pub fn range_from_lsp(range: lsp::Range) -> Range { - let start = PointUtf16::new(range.start.line, range.start.character); - let end = PointUtf16::new(range.end.line, range.end.character); - start..end + point_from_lsp(range.start)..point_from_lsp(range.end) } diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index b6f007659d..71ad489d07 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -4,9 +4,9 @@ use async_trait::async_trait; use client::{proto, PeerId}; use gpui::{AppContext, AsyncAppContext, ModelHandle}; use language::{ - point_from_lsp, + point_from_lsp, point_to_lsp, proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, - range_from_lsp, Anchor, Bias, Buffer, PointUtf16, ToLspPosition, ToPointUtf16, + range_from_lsp, Anchor, Bias, Buffer, PointUtf16, ToPointUtf16, }; use lsp::{DocumentHighlightKind, ServerCapabilities}; use std::{cmp::Reverse, ops::Range, path::Path}; @@ -91,7 +91,7 @@ impl LspCommand for PrepareRename { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), } } @@ -208,7 +208,7 @@ impl LspCommand for PerformRename { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), }, new_name: self.new_name.clone(), work_done_progress_params: Default::default(), @@ -325,7 +325,7 @@ impl LspCommand for GetDefinition { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), @@ -497,7 +497,7 @@ impl LspCommand for GetReferences { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), @@ -659,7 +659,7 @@ impl LspCommand for GetDocumentHighlights { text_document: lsp::TextDocumentIdentifier { uri: lsp::Url::from_file_path(path).unwrap(), }, - position: self.position.to_lsp_position(), + position: point_to_lsp(self.position), }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index df84aec0c5..65c943c888 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -15,11 +15,12 @@ use gpui::{ MutableAppContext, Task, UpgradeModelHandle, WeakModelHandle, }; use language::{ + point_to_lsp, proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, - range_from_lsp, Anchor, Bias, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, - DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, Language, LanguageRegistry, - LanguageServerName, LocalFile, LspAdapter, OffsetRangeExt, Operation, Patch, PointUtf16, - TextBufferSnapshot, ToLspPosition, ToOffset, ToPointUtf16, Transaction, + range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CodeAction, CodeLabel, Completion, + Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, Language, + LanguageRegistry, LanguageServerName, LocalFile, LspAdapter, OffsetRangeExt, Operation, Patch, + PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, }; use lsp::{DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer}; use lsp_command::*; @@ -1215,8 +1216,8 @@ impl Project { .collect(); lsp::TextDocumentContentChangeEvent { range: Some(lsp::Range::new( - edit_start.to_lsp_position(), - edit_end.to_lsp_position(), + point_to_lsp(edit_start), + point_to_lsp(edit_end), )), range_length: None, text: new_text, @@ -2061,9 +2062,8 @@ impl Project { .map_or(false, |provider| *provider != lsp::OneOf::Left(false)) { let buffer_start = lsp::Position::new(0, 0); - let buffer_end = buffer - .read_with(&cx, |buffer, _| buffer.max_point_utf16()) - .to_lsp_position(); + let buffer_end = + buffer.read_with(&cx, |buffer, _| point_to_lsp(buffer.max_point_utf16())); language_server .request::( lsp::DocumentRangeFormattingParams { @@ -2337,7 +2337,7 @@ impl Project { lsp::TextDocumentIdentifier::new( lsp::Url::from_file_path(buffer_abs_path).unwrap(), ), - position.to_lsp_position(), + point_to_lsp(position), ), context: Default::default(), work_done_progress_params: Default::default(), @@ -2511,7 +2511,7 @@ impl Project { } } - pub fn code_actions( + pub fn code_actions( &self, buffer_handle: &ModelHandle, range: Range, @@ -2519,6 +2519,11 @@ impl Project { ) -> Task>> { let buffer_handle = buffer_handle.clone(); let buffer = buffer_handle.read(cx); + let snapshot = buffer.snapshot(); + let relevant_diagnostics = snapshot + .diagnostics_in_range::(range.to_offset(&snapshot), false) + .map(|entry| entry.to_lsp_diagnostic_stub()) + .collect(); let buffer_id = buffer.remote_id(); let worktree; let buffer_abs_path; @@ -2539,10 +2544,7 @@ impl Project { return Task::ready(Ok(Default::default())); }; - let lsp_range = lsp::Range::new( - range.start.to_point_utf16(buffer).to_lsp_position(), - range.end.to_point_utf16(buffer).to_lsp_position(), - ); + let lsp_range = range_to_lsp(range.to_point_utf16(buffer)); cx.foreground().spawn(async move { if !lang_server.capabilities().code_action_provider.is_some() { return Ok(Default::default()); @@ -2557,11 +2559,12 @@ impl Project { work_done_progress_params: Default::default(), partial_result_params: Default::default(), context: lsp::CodeActionContext { - diagnostics: Default::default(), + diagnostics: relevant_diagnostics, only: Some(vec![ lsp::CodeActionKind::QUICKFIX, lsp::CodeActionKind::REFACTOR, lsp::CodeActionKind::REFACTOR_EXTRACT, + lsp::CodeActionKind::SOURCE, ]), }, }) @@ -2636,11 +2639,7 @@ impl Project { .and_then(|d| d.get_mut("codeActionParams")) .and_then(|d| d.get_mut("range")) { - *lsp_range = serde_json::to_value(&lsp::Range::new( - range.start.to_lsp_position(), - range.end.to_lsp_position(), - )) - .unwrap(); + *lsp_range = serde_json::to_value(&range_to_lsp(range)).unwrap(); action.lsp_action = lang_server .request::(action.lsp_action) .await?; diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 1b22d09b56..a010e55c32 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -1088,8 +1088,8 @@ mod tests { }; use gpui::{executor, geometry::vector::vec2f, ModelHandle, TestAppContext, ViewHandle}; use language::{ - tree_sitter_rust, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, LanguageConfig, - LanguageRegistry, OffsetRangeExt, Point, ToLspPosition, + range_to_lsp, tree_sitter_rust, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, + LanguageConfig, LanguageRegistry, OffsetRangeExt, Point, }; use lsp::{self, FakeLanguageServer}; use parking_lot::Mutex; @@ -4979,14 +4979,9 @@ mod tests { for _ in 0..highlight_count { let range = buffer.random_byte_range(prev_end, &mut *rng.lock()); - let start = buffer - .offset_to_point_utf16(range.start) - .to_lsp_position(); - let end = buffer - .offset_to_point_utf16(range.end) - .to_lsp_position(); + highlights.push(lsp::DocumentHighlight { - range: lsp::Range::new(start, end), + range: range_to_lsp(range.to_point_utf16(buffer)), kind: Some(lsp::DocumentHighlightKind::READ), }); prev_end = range.end; From afbddc1bcde8543dee73a818c4a660e3116a7efe Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Thu, 31 Mar 2022 18:22:55 -0700 Subject: [PATCH 16/68] Address panic when completions requested and returned to outdated buffer --- crates/project/src/project.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 65c943c888..856405d620 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2331,6 +2331,13 @@ impl Project { }; cx.spawn(|_, cx| async move { + let clipped_position = source_buffer_handle + .read_with(&cx, |this, _| this.clip_point_utf16(position, Bias::Left)); + if clipped_position != position { + log::info!("Completion position out of date"); + return Ok(Default::default()); + } + let completions = lang_server .request::(lsp::CompletionParams { text_document_position: lsp::TextDocumentPositionParams::new( From e987a8ba634dbd5246ec1d4dc4f7ab3f61e4f8b8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 31 Mar 2022 21:52:14 -0700 Subject: [PATCH 17/68] Let fake and real LanguageServer access AsyncAppContext in handler callbacks Also, reimplement FakeLanguageServer by wrapping LanguageServer, instead of duplicating its functionality differently. --- crates/editor/src/editor.rs | 14 +- crates/language/src/language.rs | 18 +- crates/lsp/src/lsp.rs | 504 +++++++++++++------------------- crates/project/src/project.rs | 82 +++--- crates/server/src/rpc.rs | 118 ++++---- 5 files changed, 317 insertions(+), 419 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index c7373d84f2..0dccce37a9 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -8928,7 +8928,7 @@ mod tests { .unwrap(); cx.foreground().start_waiting(); - let mut fake_server = fake_servers.next().await.unwrap(); + let fake_server = fake_servers.next().await.unwrap(); let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx)); @@ -8942,10 +8942,10 @@ mod tests { params.text_document.uri, lsp::Url::from_file_path("/file.rs").unwrap() ); - Some(vec![lsp::TextEdit::new( + Ok(Some(vec![lsp::TextEdit::new( lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)), ", ".to_string(), - )]) + )])) }) .next() .await; @@ -9173,7 +9173,7 @@ mod tests { params.text_document_position.position, lsp::Position::new(position.row, position.column) ); - Some(lsp::CompletionResponse::Array( + Ok(Some(lsp::CompletionResponse::Array( completions .iter() .map(|(range, new_text)| lsp::CompletionItem { @@ -9188,7 +9188,7 @@ mod tests { ..Default::default() }) .collect(), - )) + ))) } }) .next() @@ -9202,7 +9202,7 @@ mod tests { fake.handle_request::(move |_, _| { let edit = edit.clone(); async move { - lsp::CompletionItem { + Ok(lsp::CompletionItem { additional_text_edits: edit.map(|(range, new_text)| { vec![lsp::TextEdit::new( lsp::Range::new( @@ -9213,7 +9213,7 @@ mod tests { )] }), ..Default::default() - } + }) } }) .next() diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 2435973201..322fd19b9e 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -263,14 +263,12 @@ impl LanguageRegistry { #[cfg(any(test, feature = "test-support"))] if language.fake_adapter.is_some() { let language = language.clone(); - return Some(cx.spawn(|mut cx| async move { + return Some(cx.spawn(|cx| async move { let (servers_tx, fake_adapter) = language.fake_adapter.as_ref().unwrap(); - let (server, mut fake_server) = cx.update(|cx| { - lsp::LanguageServer::fake_with_capabilities( - fake_adapter.capabilities.clone(), - cx, - ) - }); + let (server, mut fake_server) = lsp::LanguageServer::fake_with_capabilities( + fake_adapter.capabilities.clone(), + cx.clone(), + ); if let Some(initializer) = &fake_adapter.initializer { initializer(&mut fake_server); @@ -297,10 +295,9 @@ impl LanguageRegistry { let this = self.clone(); let adapter = language.adapter.clone()?; - let background = cx.background().clone(); let lsp_binary_statuses = self.lsp_binary_statuses_tx.clone(); let login_shell_env_loaded = self.login_shell_env_loaded.clone(); - Some(cx.background().spawn(async move { + Some(cx.spawn(|cx| async move { login_shell_env_loaded.await; let server_binary_path = this .lsp_binary_paths @@ -328,8 +325,7 @@ impl LanguageRegistry { &server_binary_path, server_args, &root_path, - adapter.initialization_options(), - background, + cx, )?; Ok(server) })) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 51a68b83c8..6d89b5e870 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -1,15 +1,17 @@ +pub use lsp_types::*; + use anyhow::{anyhow, Context, Result}; use collections::HashMap; use futures::{channel::oneshot, io::BufWriter, AsyncRead, AsyncWrite}; -use gpui::{executor, Task}; -use parking_lot::{Mutex, RwLock}; +use gpui::{executor, AsyncAppContext, Task}; +use parking_lot::Mutex; use postage::{barrier, prelude::Stream}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::{json, value::RawValue, Value}; use smol::{ channel, io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}, - process::Command, + process, }; use std::{ future::Future, @@ -22,15 +24,12 @@ use std::{ }, }; use std::{path::Path, process::Stdio}; -use util::TryFutureExt; - -pub use lsp_types::*; +use util::{ResultExt, TryFutureExt}; const JSON_RPC_VERSION: &'static str = "2.0"; const CONTENT_LEN_HEADER: &'static str = "Content-Length: "; -type NotificationHandler = - Box, &str, &mut channel::Sender>) -> Result<()>>; +type NotificationHandler = Box, &str, AsyncAppContext)>; type ResponseHandler = Box)>; pub struct LanguageServer { @@ -39,18 +38,17 @@ pub struct LanguageServer { outbound_tx: channel::Sender>, name: String, capabilities: ServerCapabilities, - notification_handlers: Arc>>, + notification_handlers: Arc>>, response_handlers: Arc>>, executor: Arc, io_tasks: Mutex>, Task>)>>, output_done_rx: Mutex>, root_path: PathBuf, - options: Option, } pub struct Subscription { method: &'static str, - notification_handlers: Arc>>, + notification_handlers: Arc>>, } #[derive(Serialize, Deserialize)] @@ -61,18 +59,6 @@ struct Request<'a, T> { params: T, } -#[cfg(any(test, feature = "test-support"))] -#[derive(Deserialize)] -struct AnyRequest<'a> { - id: usize, - #[serde(borrow)] - jsonrpc: &'a str, - #[serde(borrow)] - method: &'a str, - #[serde(borrow)] - params: &'a RawValue, -} - #[derive(Serialize, Deserialize)] struct AnyResponse<'a> { id: usize, @@ -85,7 +71,8 @@ struct AnyResponse<'a> { #[derive(Serialize)] struct Response { id: usize, - result: T, + result: Option, + error: Option, } #[derive(Serialize, Deserialize)] @@ -118,15 +105,14 @@ impl LanguageServer { binary_path: &Path, args: &[&str], root_path: &Path, - options: Option, - background: Arc, + cx: AsyncAppContext, ) -> Result { let working_dir = if root_path.is_dir() { root_path } else { root_path.parent().unwrap_or(Path::new("/")) }; - let mut server = Command::new(binary_path) + let mut server = process::Command::new(binary_path) .current_dir(working_dir) .args(args) .stdin(Stdio::piped()) @@ -136,95 +122,91 @@ impl LanguageServer { let stdin = server.stdin.take().unwrap(); let stdout = server.stdout.take().unwrap(); let mut server = - Self::new_internal(server_id, stdin, stdout, root_path, options, background); + Self::new_internal(server_id, stdin, stdout, root_path, cx, |notification| { + log::info!( + "unhandled notification {}:\n{}", + notification.method, + serde_json::to_string_pretty( + &Value::from_str(notification.params.get()).unwrap() + ) + .unwrap() + ); + }); if let Some(name) = binary_path.file_name() { server.name = name.to_string_lossy().to_string(); } Ok(server) } - fn new_internal( + fn new_internal( server_id: usize, stdin: Stdin, stdout: Stdout, root_path: &Path, - options: Option, - executor: Arc, + cx: AsyncAppContext, + mut on_unhandled_notification: F, ) -> Self where Stdin: AsyncWrite + Unpin + Send + 'static, Stdout: AsyncRead + Unpin + Send + 'static, + F: FnMut(AnyNotification) + 'static + Send, { let mut stdin = BufWriter::new(stdin); let mut stdout = BufReader::new(stdout); let (outbound_tx, outbound_rx) = channel::unbounded::>(); let notification_handlers = - Arc::new(RwLock::new(HashMap::<_, NotificationHandler>::default())); + Arc::new(Mutex::new(HashMap::<_, NotificationHandler>::default())); let response_handlers = Arc::new(Mutex::new(HashMap::<_, ResponseHandler>::default())); - let input_task = executor.spawn( - { - let notification_handlers = notification_handlers.clone(); - let response_handlers = response_handlers.clone(); - let mut outbound_tx = outbound_tx.clone(); - async move { - let _clear_response_handlers = ClearResponseHandlers(response_handlers.clone()); - let mut buffer = Vec::new(); - loop { - buffer.clear(); - stdout.read_until(b'\n', &mut buffer).await?; - stdout.read_until(b'\n', &mut buffer).await?; - let message_len: usize = std::str::from_utf8(&buffer)? - .strip_prefix(CONTENT_LEN_HEADER) - .ok_or_else(|| anyhow!("invalid header"))? - .trim_end() - .parse()?; + let input_task = cx.spawn(|cx| { + let notification_handlers = notification_handlers.clone(); + let response_handlers = response_handlers.clone(); + async move { + let _clear_response_handlers = ClearResponseHandlers(response_handlers.clone()); + let mut buffer = Vec::new(); + loop { + buffer.clear(); + stdout.read_until(b'\n', &mut buffer).await?; + stdout.read_until(b'\n', &mut buffer).await?; + let message_len: usize = std::str::from_utf8(&buffer)? + .strip_prefix(CONTENT_LEN_HEADER) + .ok_or_else(|| anyhow!("invalid header"))? + .trim_end() + .parse()?; - buffer.resize(message_len, 0); - stdout.read_exact(&mut buffer).await?; - log::trace!("incoming message:{}", String::from_utf8_lossy(&buffer)); + buffer.resize(message_len, 0); + stdout.read_exact(&mut buffer).await?; + log::trace!("incoming message:{}", String::from_utf8_lossy(&buffer)); - if let Ok(AnyNotification { id, method, params }) = - serde_json::from_slice(&buffer) - { - if let Some(handler) = notification_handlers.write().get_mut(method) { - if let Err(e) = handler(id, params.get(), &mut outbound_tx) { - log::error!("error handling {} message: {:?}", method, e); - } - } else { - log::info!( - "unhandled notification {}:\n{}", - method, - serde_json::to_string_pretty( - &Value::from_str(params.get()).unwrap() - ) - .unwrap() - ); - } - } else if let Ok(AnyResponse { id, error, result }) = - serde_json::from_slice(&buffer) - { - if let Some(handler) = response_handlers.lock().remove(&id) { - if let Some(error) = error { - handler(Err(error)); - } else if let Some(result) = result { - handler(Ok(result.get())); - } else { - handler(Ok("null")); - } - } + if let Ok(msg) = serde_json::from_slice::(&buffer) { + if let Some(handler) = notification_handlers.lock().get_mut(msg.method) { + handler(msg.id, msg.params.get(), cx.clone()); } else { - return Err(anyhow!( - "failed to deserialize message:\n{}", - std::str::from_utf8(&buffer)? - )); + on_unhandled_notification(msg); } + } else if let Ok(AnyResponse { id, error, result }) = + serde_json::from_slice(&buffer) + { + if let Some(handler) = response_handlers.lock().remove(&id) { + if let Some(error) = error { + handler(Err(error)); + } else if let Some(result) = result { + handler(Ok(result.get())); + } else { + handler(Ok("null")); + } + } + } else { + return Err(anyhow!( + "failed to deserialize message:\n{}", + std::str::from_utf8(&buffer)? + )); } } } - .log_err(), - ); + .log_err() + }); let (output_done_tx, output_done_rx) = barrier::channel(); - let output_task = executor.spawn({ + let output_task = cx.background().spawn({ let response_handlers = response_handlers.clone(); async move { let _clear_response_handlers = ClearResponseHandlers(response_handlers); @@ -253,18 +235,15 @@ impl LanguageServer { capabilities: Default::default(), next_id: Default::default(), outbound_tx, - executor: executor.clone(), + executor: cx.background().clone(), io_tasks: Mutex::new(Some((input_task, output_task))), output_done_rx: Mutex::new(Some(output_done_rx)), root_path: root_path.to_path_buf(), - options, } } - pub async fn initialize(mut self) -> Result> { - let options = self.options.take(); - let mut this = Arc::new(self); - let root_uri = Url::from_file_path(&this.root_path).unwrap(); + pub async fn initialize(mut self, options: Option) -> Result> { + let root_uri = Url::from_file_path(&self.root_path).unwrap(); #[allow(deprecated)] let params = InitializeParams { process_id: Default::default(), @@ -290,12 +269,13 @@ impl LanguageServer { value_set: vec![ CodeActionKind::REFACTOR.as_str().into(), CodeActionKind::QUICKFIX.as_str().into(), + CodeActionKind::SOURCE.as_str().into(), ], }, }), data_support: Some(true), resolve_support: Some(CodeActionCapabilityResolveSupport { - properties: vec!["edit".to_string()], + properties: vec!["edit".to_string(), "command".to_string()], }), ..Default::default() }), @@ -326,16 +306,14 @@ impl LanguageServer { locale: Default::default(), }; - let response = this.request::(params).await?; - { - let this = Arc::get_mut(&mut this).unwrap(); - if let Some(info) = response.server_info { - this.name = info.name; - } - this.capabilities = response.capabilities; + let response = self.request::(params).await?; + if let Some(info) = response.server_info { + self.name = info.name; } - this.notify::(InitializedParams {})?; - Ok(this) + self.capabilities = response.capabilities; + + self.notify::(InitializedParams {})?; + Ok(Arc::new(self)) } pub fn shutdown(&self) -> Option>> { @@ -370,37 +348,42 @@ impl LanguageServer { } } - pub fn on_notification(&mut self, f: F) -> Subscription + #[must_use] + pub fn on_notification(&self, f: F) -> Subscription where T: notification::Notification, - F: 'static + Send + Sync + FnMut(T::Params), + F: 'static + Send + FnMut(T::Params, AsyncAppContext), { self.on_custom_notification(T::METHOD, f) } - pub fn on_request(&mut self, f: F) -> Subscription + #[must_use] + pub fn on_request(&self, f: F) -> Subscription where T: request::Request, - F: 'static + Send + Sync + FnMut(T::Params) -> Result, + T::Params: 'static + Send, + F: 'static + Send + FnMut(T::Params, AsyncAppContext) -> Fut, + Fut: 'static + Future>, { self.on_custom_request(T::METHOD, f) } - pub fn on_custom_notification( - &mut self, - method: &'static str, - mut f: F, - ) -> Subscription + pub fn remove_request_handler(&self) { + self.notification_handlers.lock().remove(T::METHOD); + } + + #[must_use] + pub fn on_custom_notification(&self, method: &'static str, mut f: F) -> Subscription where - F: 'static + Send + Sync + FnMut(Params), + F: 'static + Send + FnMut(Params, AsyncAppContext), Params: DeserializeOwned, { - let prev_handler = self.notification_handlers.write().insert( + let prev_handler = self.notification_handlers.lock().insert( method, - Box::new(move |_, params, _| { - let params = serde_json::from_str(params)?; - f(params); - Ok(()) + Box::new(move |_, params, cx| { + if let Some(params) = serde_json::from_str(params).log_err() { + f(params, cx); + } }), ); assert!( @@ -413,26 +396,52 @@ impl LanguageServer { } } - pub fn on_custom_request( - &mut self, + #[must_use] + pub fn on_custom_request( + &self, method: &'static str, mut f: F, ) -> Subscription where - F: 'static + Send + Sync + FnMut(Params) -> Result, - Params: DeserializeOwned, + F: 'static + Send + FnMut(Params, AsyncAppContext) -> Fut, + Fut: 'static + Future>, + Params: DeserializeOwned + Send + 'static, Res: Serialize, { - let prev_handler = self.notification_handlers.write().insert( + let outbound_tx = self.outbound_tx.clone(); + let prev_handler = self.notification_handlers.lock().insert( method, - Box::new(move |id, params, tx| { + Box::new(move |id, params, cx| { if let Some(id) = id { - let params = serde_json::from_str(params)?; - let result = f(params)?; - let response = serde_json::to_vec(&Response { id, result })?; - tx.try_send(response)?; + if let Some(params) = serde_json::from_str(params).log_err() { + let response = f(params, cx.clone()); + cx.foreground() + .spawn({ + let outbound_tx = outbound_tx.clone(); + async move { + let response = match response.await { + Ok(result) => Response { + id, + result: Some(result), + error: None, + }, + Err(error) => Response { + id, + result: None, + error: Some(Error { + message: error.to_string(), + }), + }, + }; + if let Some(response) = serde_json::to_vec(&response).log_err() + { + outbound_tx.try_send(response).ok(); + } + } + }) + .detach(); + } } - Ok(()) }), ); assert!( @@ -458,7 +467,7 @@ impl LanguageServer { } pub fn request( - self: &Arc, + &self, params: T::Params, ) -> impl Future> where @@ -549,36 +558,16 @@ impl Subscription { impl Drop for Subscription { fn drop(&mut self) { - self.notification_handlers.write().remove(self.method); + self.notification_handlers.lock().remove(self.method); } } #[cfg(any(test, feature = "test-support"))] pub struct FakeLanguageServer { - handlers: FakeLanguageServerHandlers, - outgoing_tx: futures::channel::mpsc::UnboundedSender>, - incoming_rx: futures::channel::mpsc::UnboundedReceiver>, - _input_task: Task>, - _output_task: Task>, + server: Arc, + notifications_rx: channel::Receiver<(String, String)>, } -#[cfg(any(test, feature = "test-support"))] -type FakeLanguageServerHandlers = Arc< - Mutex< - HashMap< - &'static str, - Box< - dyn Send - + FnMut( - usize, - &[u8], - gpui::AsyncAppContext, - ) -> futures::future::BoxFuture<'static, Vec>, - >, - >, - >, ->; - #[cfg(any(test, feature = "test-support"))] impl LanguageServer { pub fn full_capabilities() -> ServerCapabilities { @@ -591,177 +580,101 @@ impl LanguageServer { } } - pub fn fake(cx: &mut gpui::MutableAppContext) -> (Self, FakeLanguageServer) { + pub fn fake(cx: AsyncAppContext) -> (Self, FakeLanguageServer) { Self::fake_with_capabilities(Self::full_capabilities(), cx) } pub fn fake_with_capabilities( capabilities: ServerCapabilities, - cx: &mut gpui::MutableAppContext, + cx: AsyncAppContext, ) -> (Self, FakeLanguageServer) { let (stdin_writer, stdin_reader) = async_pipe::pipe(); let (stdout_writer, stdout_reader) = async_pipe::pipe(); + let (notifications_tx, notifications_rx) = channel::unbounded(); - let mut fake = FakeLanguageServer::new(stdin_reader, stdout_writer, cx); - fake.handle_request::({ - let capabilities = capabilities.clone(); - move |_, _| { - let capabilities = capabilities.clone(); - async move { - InitializeResult { - capabilities, - ..Default::default() - } - } - } - }); - - let executor = cx.background().clone(); let server = Self::new_internal( 0, stdin_writer, stdout_reader, Path::new("/"), - None, - executor, + cx.clone(), + |_| {}, ); + let fake = FakeLanguageServer { + server: Arc::new(Self::new_internal( + 0, + stdout_writer, + stdin_reader, + Path::new("/"), + cx.clone(), + move |msg| { + notifications_tx + .try_send((msg.method.to_string(), msg.params.get().to_string())) + .ok(); + }, + )), + notifications_rx, + }; + fake.handle_request::({ + let capabilities = capabilities.clone(); + move |_, _| { + let capabilities = capabilities.clone(); + async move { + Ok(InitializeResult { + capabilities, + ..Default::default() + }) + } + } + }); + (server, fake) } } #[cfg(any(test, feature = "test-support"))] impl FakeLanguageServer { - fn new( - stdin: async_pipe::PipeReader, - stdout: async_pipe::PipeWriter, - cx: &mut gpui::MutableAppContext, - ) -> Self { - use futures::StreamExt as _; - - let (incoming_tx, incoming_rx) = futures::channel::mpsc::unbounded(); - let (outgoing_tx, mut outgoing_rx) = futures::channel::mpsc::unbounded(); - let handlers = FakeLanguageServerHandlers::default(); - - let input_task = cx.spawn(|cx| { - let handlers = handlers.clone(); - let outgoing_tx = outgoing_tx.clone(); - async move { - let mut buffer = Vec::new(); - let mut stdin = smol::io::BufReader::new(stdin); - while Self::receive(&mut stdin, &mut buffer).await.is_ok() { - cx.background().simulate_random_delay().await; - - if let Ok(request) = serde_json::from_slice::(&buffer) { - assert_eq!(request.jsonrpc, JSON_RPC_VERSION); - - let response; - if let Some(handler) = handlers.lock().get_mut(request.method) { - response = - handler(request.id, request.params.get().as_bytes(), cx.clone()) - .await; - log::debug!("handled lsp request. method:{}", request.method); - } else { - response = serde_json::to_vec(&AnyResponse { - id: request.id, - error: Some(Error { - message: "no handler".to_string(), - }), - result: None, - }) - .unwrap(); - log::debug!("unhandled lsp request. method:{}", request.method); - } - outgoing_tx.unbounded_send(response)?; - } else { - incoming_tx.unbounded_send(buffer.clone())?; - } - } - Ok::<_, anyhow::Error>(()) - } - }); - - let output_task = cx.background().spawn(async move { - let mut stdout = smol::io::BufWriter::new(stdout); - while let Some(message) = outgoing_rx.next().await { - stdout.write_all(CONTENT_LEN_HEADER.as_bytes()).await?; - stdout - .write_all((format!("{}", message.len())).as_bytes()) - .await?; - stdout.write_all("\r\n\r\n".as_bytes()).await?; - stdout.write_all(&message).await?; - stdout.flush().await?; - } - Ok(()) - }); - - Self { - outgoing_tx, - incoming_rx, - handlers, - _input_task: input_task, - _output_task: output_task, - } - } - - pub fn notify(&mut self, params: T::Params) { - let message = serde_json::to_vec(&Notification { - jsonrpc: JSON_RPC_VERSION, - method: T::METHOD, - params, - }) - .unwrap(); - self.outgoing_tx.unbounded_send(message).unwrap(); + pub fn notify(&self, params: T::Params) { + self.server.notify::(params).ok(); } pub async fn receive_notification(&mut self) -> T::Params { use futures::StreamExt as _; loop { - let bytes = self.incoming_rx.next().await.unwrap(); - if let Ok(notification) = serde_json::from_slice::>(&bytes) { - assert_eq!(notification.method, T::METHOD); - return notification.params; + let (method, params) = self.notifications_rx.next().await.unwrap(); + if &method == T::METHOD { + return serde_json::from_str::(¶ms).unwrap(); } else { - log::info!( - "skipping message in fake language server {:?}", - std::str::from_utf8(&bytes) - ); + log::info!("skipping message in fake language server {:?}", params); } } } pub fn handle_request( - &mut self, + &self, mut handler: F, ) -> futures::channel::mpsc::UnboundedReceiver<()> where T: 'static + request::Request, + T::Params: 'static + Send, F: 'static + Send + FnMut(T::Params, gpui::AsyncAppContext) -> Fut, - Fut: 'static + Send + Future, + Fut: 'static + Send + Future>, { - use futures::FutureExt as _; - let (responded_tx, responded_rx) = futures::channel::mpsc::unbounded(); - self.handlers.lock().insert( - T::METHOD, - Box::new(move |id, params, cx| { - let result = handler(serde_json::from_slice::(params).unwrap(), cx); + self.server.remove_request_handler::(); + self.server + .on_request::(move |params, cx| { + let result = handler(params, cx.clone()); let responded_tx = responded_tx.clone(); async move { + cx.background().simulate_random_delay().await; let result = result.await; - let result = serde_json::to_string(&result).unwrap(); - let result = serde_json::from_str::<&RawValue>(&result).unwrap(); - let response = AnyResponse { - id, - error: None, - result: Some(result), - }; responded_tx.unbounded_send(()).ok(); - serde_json::to_vec(&response).unwrap() + result } - .boxed() - }), - ); + }) + .detach(); responded_rx } @@ -769,7 +682,7 @@ impl FakeLanguageServer { where T: 'static + request::Request, { - self.handlers.lock().remove(T::METHOD); + self.server.remove_request_handler::(); } pub async fn start_progress(&mut self, token: impl Into) { @@ -785,25 +698,6 @@ impl FakeLanguageServer { value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(Default::default())), }); } - - async fn receive( - stdin: &mut smol::io::BufReader, - buffer: &mut Vec, - ) -> Result<()> { - buffer.clear(); - stdin.read_until(b'\n', buffer).await?; - stdin.read_until(b'\n', buffer).await?; - let message_len: usize = std::str::from_utf8(buffer) - .unwrap() - .strip_prefix(CONTENT_LEN_HEADER) - .ok_or_else(|| anyhow!("invalid content length header"))? - .trim_end() - .parse() - .unwrap(); - buffer.resize(message_len, 0); - stdin.read_exact(buffer).await?; - Ok(()) - } } struct ClearResponseHandlers(Arc>>); @@ -828,22 +722,22 @@ mod tests { #[gpui::test] async fn test_fake(cx: &mut TestAppContext) { - let (mut server, mut fake) = cx.update(LanguageServer::fake); + let (server, mut fake) = LanguageServer::fake(cx.to_async()); let (message_tx, message_rx) = channel::unbounded(); let (diagnostics_tx, diagnostics_rx) = channel::unbounded(); server - .on_notification::(move |params| { + .on_notification::(move |params, _| { message_tx.try_send(params).unwrap() }) .detach(); server - .on_notification::(move |params| { + .on_notification::(move |params, _| { diagnostics_tx.try_send(params).unwrap() }) .detach(); - let server = server.initialize().await.unwrap(); + let server = server.initialize(None).await.unwrap(); server .notify::(DidOpenTextDocumentParams { text_document: TextDocumentItem::new( @@ -878,7 +772,7 @@ mod tests { "file://b/c" ); - fake.handle_request::(|_, _| async move {}); + fake.handle_request::(|_, _| async move { Ok(()) }); drop(server); fake.receive_notification::().await; diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 856405d620..036a3a2931 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1325,7 +1325,7 @@ impl Project { cx, ); cx.spawn_weak(|this, mut cx| async move { - let mut language_server = language_server?.await.log_err()?; + let language_server = language_server?.await.log_err()?; let this = this.upgrade(&cx)?; let (language_server_events_tx, language_server_events_rx) = smol::channel::unbounded(); @@ -1333,7 +1333,7 @@ impl Project { language_server .on_notification::({ let language_server_events_tx = language_server_events_tx.clone(); - move |params| { + move |params, _| { language_server_events_tx .try_send(LanguageServerEvent::DiagnosticsUpdate(params)) .ok(); @@ -1342,31 +1342,33 @@ impl Project { .detach(); language_server - .on_request::({ + .on_request::({ let settings = this .read_with(&cx, |this, _| this.language_server_settings.clone()); - move |params| { - let settings = settings.lock(); - Ok(params - .items - .into_iter() - .map(|item| { - if let Some(section) = &item.section { - settings - .get(section) - .cloned() - .unwrap_or(serde_json::Value::Null) - } else { - settings.clone() - } - }) - .collect()) + move |params, _| { + let settings = settings.lock().clone(); + async move { + Ok(params + .items + .into_iter() + .map(|item| { + if let Some(section) = &item.section { + settings + .get(section) + .cloned() + .unwrap_or(serde_json::Value::Null) + } else { + settings.clone() + } + }) + .collect()) + } } }) .detach(); language_server - .on_notification::(move |params| { + .on_notification::(move |params, _| { let token = match params.token { lsp::NumberOrString::String(token) => token, lsp::NumberOrString::Number(token) => { @@ -1406,6 +1408,11 @@ impl Project { }) .detach(); + let language_server = language_server + .initialize(adapter.initialization_options()) + .await + .log_err()?; + // Process all the LSP events. cx.spawn(|mut cx| { let this = this.downgrade(); @@ -1424,7 +1431,6 @@ impl Project { }) .detach(); - let language_server = language_server.initialize().await.log_err()?; this.update(&mut cx, |this, cx| { this.language_servers .insert(key.clone(), (adapter, language_server.clone())); @@ -4974,9 +4980,9 @@ mod tests { }); let mut rust_shutdown_requests = fake_rust_server - .handle_request::(|_, _| future::ready(())); + .handle_request::(|_, _| future::ready(Ok(()))); let mut json_shutdown_requests = fake_json_server - .handle_request::(|_, _| future::ready(())); + .handle_request::(|_, _| future::ready(Ok(()))); futures::join!(rust_shutdown_requests.next(), json_shutdown_requests.next()); let mut fake_rust_server = fake_rust_servers.next().await.unwrap(); @@ -5917,19 +5923,11 @@ mod tests { .await; let buffer = project - .update(cx, |project, cx| { - project.open_buffer( - ProjectPath { - worktree_id, - path: Path::new("").into(), - }, - cx, - ) - }) + .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx)) .await .unwrap(); - let mut fake_server = fake_servers.next().await.unwrap(); + let fake_server = fake_servers.next().await.unwrap(); fake_server.handle_request::(|params, _| async move { let params = params.text_document_position_params; assert_eq!( @@ -5938,9 +5936,11 @@ mod tests { ); assert_eq!(params.position, lsp::Position::new(0, 22)); - Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location::new( - lsp::Url::from_file_path("/dir/a.rs").unwrap(), - lsp::Range::new(lsp::Position::new(0, 9), lsp::Position::new(0, 10)), + Ok(Some(lsp::GotoDefinitionResponse::Scalar( + lsp::Location::new( + lsp::Url::from_file_path("/dir/a.rs").unwrap(), + lsp::Range::new(lsp::Position::new(0, 9), lsp::Position::new(0, 10)), + ), ))) }); @@ -6854,7 +6854,7 @@ mod tests { .await .unwrap(); - let mut fake_server = fake_servers.next().await.unwrap(); + let fake_server = fake_servers.next().await.unwrap(); let response = project.update(cx, |project, cx| { project.prepare_rename(buffer.clone(), 7, cx) @@ -6863,10 +6863,10 @@ mod tests { .handle_request::(|params, _| async move { assert_eq!(params.text_document.uri.as_str(), "file:///dir/one.rs"); assert_eq!(params.position, lsp::Position::new(0, 7)); - Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( + Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( lsp::Position::new(0, 6), lsp::Position::new(0, 9), - ))) + )))) }) .next() .await @@ -6889,7 +6889,7 @@ mod tests { lsp::Position::new(0, 7) ); assert_eq!(params.new_name, "THREE"); - Some(lsp::WorkspaceEdit { + Ok(Some(lsp::WorkspaceEdit { changes: Some( [ ( @@ -6926,7 +6926,7 @@ mod tests { .collect(), ), ..Default::default() - }) + })) }) .next() .await diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index a010e55c32..b158a17e87 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -2342,7 +2342,7 @@ mod tests { Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx) }); - let mut fake_language_server = fake_language_servers.next().await.unwrap(); + let fake_language_server = fake_language_servers.next().await.unwrap(); buffer_b .condition(&cx_b, |buffer, _| !buffer.completion_triggers().is_empty()) .await; @@ -2368,7 +2368,7 @@ mod tests { lsp::Position::new(0, 14), ); - Some(lsp::CompletionResponse::Array(vec![ + Ok(Some(lsp::CompletionResponse::Array(vec![ lsp::CompletionItem { label: "first_method(…)".into(), detail: Some("fn(&mut self, B) -> C".into()), @@ -2395,7 +2395,7 @@ mod tests { insert_text_format: Some(lsp::InsertTextFormat::SNIPPET), ..Default::default() }, - ])) + ]))) }) .next() .await @@ -2425,7 +2425,7 @@ mod tests { fake_language_server.handle_request::( |params, _| async move { assert_eq!(params.label, "first_method(…)"); - lsp::CompletionItem { + Ok(lsp::CompletionItem { label: "first_method(…)".into(), detail: Some("fn(&mut self, B) -> C".into()), text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { @@ -2441,7 +2441,7 @@ mod tests { }]), insert_text_format: Some(lsp::InsertTextFormat::SNIPPET), ..Default::default() - } + }) }, ); @@ -2530,9 +2530,9 @@ mod tests { .await .unwrap(); - let mut fake_language_server = fake_language_servers.next().await.unwrap(); + let fake_language_server = fake_language_servers.next().await.unwrap(); fake_language_server.handle_request::(|_, _| async move { - Some(vec![ + Ok(Some(vec![ lsp::TextEdit { range: lsp::Range::new(lsp::Position::new(0, 4), lsp::Position::new(0, 4)), new_text: "h".to_string(), @@ -2541,7 +2541,7 @@ mod tests { range: lsp::Range::new(lsp::Position::new(0, 7), lsp::Position::new(0, 7)), new_text: "y".to_string(), }, - ]) + ])) }); project_b @@ -2637,12 +2637,14 @@ mod tests { .unwrap(); // Request the definition of a symbol as the guest. - let mut fake_language_server = fake_language_servers.next().await.unwrap(); + let fake_language_server = fake_language_servers.next().await.unwrap(); fake_language_server.handle_request::( |_, _| async move { - Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location::new( - lsp::Url::from_file_path("/root-2/b.rs").unwrap(), - lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), + Ok(Some(lsp::GotoDefinitionResponse::Scalar( + lsp::Location::new( + lsp::Url::from_file_path("/root-2/b.rs").unwrap(), + lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), + ), ))) }, ); @@ -2669,9 +2671,11 @@ mod tests { // the previous call to `definition`. fake_language_server.handle_request::( |_, _| async move { - Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location::new( - lsp::Url::from_file_path("/root-2/b.rs").unwrap(), - lsp::Range::new(lsp::Position::new(1, 6), lsp::Position::new(1, 11)), + Ok(Some(lsp::GotoDefinitionResponse::Scalar( + lsp::Location::new( + lsp::Url::from_file_path("/root-2/b.rs").unwrap(), + lsp::Range::new(lsp::Position::new(1, 6), lsp::Position::new(1, 11)), + ), ))) }, ); @@ -2778,14 +2782,14 @@ mod tests { .unwrap(); // Request references to a symbol as the guest. - let mut fake_language_server = fake_language_servers.next().await.unwrap(); + let fake_language_server = fake_language_servers.next().await.unwrap(); fake_language_server.handle_request::( |params, _| async move { assert_eq!( params.text_document_position.text_document.uri.as_str(), "file:///root-1/one.rs" ); - Some(vec![ + Ok(Some(vec![ lsp::Location { uri: lsp::Url::from_file_path("/root-1/two.rs").unwrap(), range: lsp::Range::new( @@ -2807,7 +2811,7 @@ mod tests { lsp::Position::new(0, 40), ), }, - ]) + ])) }, ); @@ -3018,7 +3022,7 @@ mod tests { .unwrap(); // Request document highlights as the guest. - let mut fake_language_server = fake_language_servers.next().await.unwrap(); + let fake_language_server = fake_language_servers.next().await.unwrap(); fake_language_server.handle_request::( |params, _| async move { assert_eq!( @@ -3033,7 +3037,7 @@ mod tests { params.text_document_position_params.position, lsp::Position::new(0, 34) ); - Some(vec![ + Ok(Some(vec![ lsp::DocumentHighlight { kind: Some(lsp::DocumentHighlightKind::WRITE), range: lsp::Range::new( @@ -3055,7 +3059,7 @@ mod tests { lsp::Position::new(0, 47), ), }, - ]) + ])) }, ); @@ -3162,11 +3166,11 @@ mod tests { .await .unwrap(); - let mut fake_language_server = fake_language_servers.next().await.unwrap(); + let fake_language_server = fake_language_servers.next().await.unwrap(); fake_language_server.handle_request::( |_, _| async move { #[allow(deprecated)] - Some(vec![lsp::SymbolInformation { + Ok(Some(vec![lsp::SymbolInformation { name: "TWO".into(), location: lsp::Location { uri: lsp::Url::from_file_path("/code/crate-2/two.rs").unwrap(), @@ -3176,7 +3180,7 @@ mod tests { tags: None, container_name: None, deprecated: None, - }]) + }])) }, ); @@ -3292,12 +3296,14 @@ mod tests { .await .unwrap(); - let mut fake_language_server = fake_language_servers.next().await.unwrap(); + let fake_language_server = fake_language_servers.next().await.unwrap(); fake_language_server.handle_request::( |_, _| async move { - Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location::new( - lsp::Url::from_file_path("/root/b.rs").unwrap(), - lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), + Ok(Some(lsp::GotoDefinitionResponse::Scalar( + lsp::Location::new( + lsp::Url::from_file_path("/root/b.rs").unwrap(), + lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)), + ), ))) }, ); @@ -3413,7 +3419,7 @@ mod tests { ); assert_eq!(params.range.start, lsp::Position::new(0, 0)); assert_eq!(params.range.end, lsp::Position::new(0, 0)); - None + Ok(None) }) .next() .await; @@ -3433,7 +3439,7 @@ mod tests { assert_eq!(params.range.start, lsp::Position::new(1, 31)); assert_eq!(params.range.end, lsp::Position::new(1, 31)); - Some(vec![lsp::CodeActionOrCommand::CodeAction( + Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction( lsp::CodeAction { title: "Inline into all callers".to_string(), edit: Some(lsp::WorkspaceEdit { @@ -3475,7 +3481,7 @@ mod tests { })), ..Default::default() }, - )]) + )])) }) .next() .await; @@ -3498,7 +3504,7 @@ mod tests { .unwrap(); fake_language_server.handle_request::( |_, _| async move { - lsp::CodeAction { + Ok(lsp::CodeAction { title: "Inline into all callers".to_string(), edit: Some(lsp::WorkspaceEdit { changes: Some( @@ -3530,7 +3536,7 @@ mod tests { ..Default::default() }), ..Default::default() - } + }) }, ); @@ -3637,7 +3643,7 @@ mod tests { .unwrap() .downcast::() .unwrap(); - let mut fake_language_server = fake_language_servers.next().await.unwrap(); + let fake_language_server = fake_language_servers.next().await.unwrap(); // Move cursor to a location that can be renamed. let prepare_rename = editor_b.update(cx_b, |editor, cx| { @@ -3649,10 +3655,10 @@ mod tests { .handle_request::(|params, _| async move { assert_eq!(params.text_document.uri.as_str(), "file:///dir/one.rs"); assert_eq!(params.position, lsp::Position::new(0, 7)); - Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( + Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( lsp::Position::new(0, 6), lsp::Position::new(0, 9), - ))) + )))) }) .next() .await @@ -3686,7 +3692,7 @@ mod tests { lsp::Position::new(0, 6) ); assert_eq!(params.new_name, "THREE"); - Some(lsp::WorkspaceEdit { + Ok(Some(lsp::WorkspaceEdit { changes: Some( [ ( @@ -3723,7 +3729,7 @@ mod tests { .collect(), ), ..Default::default() - }) + })) }) .next() .await @@ -4894,36 +4900,38 @@ mod tests { move |fake_server: &mut FakeLanguageServer| { fake_server.handle_request::( |_, _| async move { - Some(lsp::CompletionResponse::Array(vec![lsp::CompletionItem { - text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { - range: lsp::Range::new( - lsp::Position::new(0, 0), - lsp::Position::new(0, 0), - ), - new_text: "the-new-text".to_string(), - })), - ..Default::default() - }])) + Ok(Some(lsp::CompletionResponse::Array(vec![ + lsp::CompletionItem { + text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { + range: lsp::Range::new( + lsp::Position::new(0, 0), + lsp::Position::new(0, 0), + ), + new_text: "the-new-text".to_string(), + })), + ..Default::default() + }, + ]))) }, ); fake_server.handle_request::( |_, _| async move { - Some(vec![lsp::CodeActionOrCommand::CodeAction( + Ok(Some(vec![lsp::CodeActionOrCommand::CodeAction( lsp::CodeAction { title: "the-code-action".to_string(), ..Default::default() }, - )]) + )])) }, ); fake_server.handle_request::( |params, _| async move { - Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( + Ok(Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( params.position, params.position, - ))) + )))) }, ); @@ -4941,7 +4949,7 @@ mod tests { .map(|_| files.choose(&mut *rng).unwrap()) .collect::>(); log::info!("LSP: Returning definitions in files {:?}", &files); - Some(lsp::GotoDefinitionResponse::Array( + Ok(Some(lsp::GotoDefinitionResponse::Array( files .into_iter() .map(|file| lsp::Location { @@ -4949,7 +4957,7 @@ mod tests { range: Default::default(), }) .collect(), - )) + ))) } } }); @@ -4991,7 +4999,7 @@ mod tests { } else { None }; - async move { highlights } + async move { Ok(highlights) } } }); } From fed5d141bcd34e9188d4e9c5d88db6d4c8ec8ff5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 31 Mar 2022 22:03:52 -0700 Subject: [PATCH 18/68] Start work on applying code actions that use commands Co-Authored-By: Keith Simmons --- crates/project/src/project.rs | 334 +++++++++++++++++++++++++--------- 1 file changed, 247 insertions(+), 87 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 036a3a2931..e37124dda0 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -143,6 +143,7 @@ enum LanguageServerEvent { token: String, }, DiagnosticsUpdate(lsp::PublishDiagnosticsParams), + WorkspaceEdit(lsp::ApplyWorkspaceEditParams), } pub struct LanguageServerStatus { @@ -1367,6 +1368,24 @@ impl Project { }) .detach(); + language_server + .on_request::({ + let language_server_events_tx = language_server_events_tx.clone(); + move |params, _| { + language_server_events_tx + .try_send(LanguageServerEvent::WorkspaceEdit(params)) + .ok(); + async move { + Ok(lsp::ApplyWorkspaceEditResponse { + applied: true, + failed_change: None, + failure_reason: None, + }) + } + } + }) + .detach(); + language_server .on_notification::(move |params, _| { let token = match params.token { @@ -1416,12 +1435,20 @@ impl Project { // Process all the LSP events. cx.spawn(|mut cx| { let this = this.downgrade(); + let adapter = adapter.clone(); + let language_server = language_server.clone(); async move { while let Ok(event) = language_server_events_rx.recv().await { let this = this.upgrade(&cx)?; - this.update(&mut cx, |this, cx| { - this.on_lsp_event(server_id, event, &language, cx) - }); + Self::on_lsp_event( + this, + server_id, + &adapter, + &language_server, + event, + &mut cx, + ) + .await; // Don't starve the main thread when lots of events arrive all at once. smol::future::yield_now().await; @@ -1585,109 +1612,142 @@ impl Project { .detach(); } - fn on_lsp_event( - &mut self, + async fn on_lsp_event( + this: ModelHandle, language_server_id: usize, + adapter: &Arc, + language_server: &Arc, event: LanguageServerEvent, - language: &Arc, - cx: &mut ModelContext, + cx: &mut AsyncAppContext, ) { - let disk_diagnostics_token = language.disk_based_diagnostics_progress_token(); - let language_server_status = - if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) { - status - } else { - return; - }; - + let disk_based_diagnostics_progress_token = adapter.disk_based_diagnostics_progress_token(); match event { LanguageServerEvent::WorkStart { token } => { - if Some(token.as_str()) == disk_diagnostics_token { - language_server_status.pending_diagnostic_updates += 1; - if language_server_status.pending_diagnostic_updates == 1 { - self.disk_based_diagnostics_started(cx); - self.broadcast_language_server_update( + this.update(cx, |this, cx| { + let language_server_status = if let Some(status) = + this.language_server_statuses.get_mut(&language_server_id) + { + status + } else { + return; + }; + + if Some(token.as_str()) == disk_based_diagnostics_progress_token { + language_server_status.pending_diagnostic_updates += 1; + if language_server_status.pending_diagnostic_updates == 1 { + this.disk_based_diagnostics_started(cx); + this.broadcast_language_server_update( + language_server_id, + proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( + proto::LspDiskBasedDiagnosticsUpdating {}, + ), + ); + } + } else { + this.on_lsp_work_start(language_server_id, token.clone(), cx); + this.broadcast_language_server_update( + language_server_id, + proto::update_language_server::Variant::WorkStart( + proto::LspWorkStart { token }, + ), + ); + } + }); + } + LanguageServerEvent::WorkProgress { token, progress } => { + this.update(cx, |this, cx| { + if Some(token.as_str()) != disk_based_diagnostics_progress_token { + this.on_lsp_work_progress( + language_server_id, + token.clone(), + progress.clone(), + cx, + ); + this.broadcast_language_server_update( + language_server_id, + proto::update_language_server::Variant::WorkProgress( + proto::LspWorkProgress { + token, + message: progress.message, + percentage: progress.percentage.map(|p| p as u32), + }, + ), + ); + } + }); + } + LanguageServerEvent::WorkEnd { token } => { + this.update(cx, |this, cx| { + if Some(token.as_str()) == disk_based_diagnostics_progress_token { + let language_server_status = if let Some(status) = + this.language_server_statuses.get_mut(&language_server_id) + { + status + } else { + return; + }; + + language_server_status.pending_diagnostic_updates -= 1; + if language_server_status.pending_diagnostic_updates == 0 { + this.disk_based_diagnostics_finished(cx); + this.broadcast_language_server_update( + language_server_id, + proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( + proto::LspDiskBasedDiagnosticsUpdated {}, + ), + ); + } + } else { + this.on_lsp_work_end(language_server_id, token.clone(), cx); + this.broadcast_language_server_update( + language_server_id, + proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd { + token, + }), + ); + } + }); + } + LanguageServerEvent::DiagnosticsUpdate(mut params) => { + this.update(cx, |this, cx| { + adapter.process_diagnostics(&mut params); + + if disk_based_diagnostics_progress_token.is_none() { + this.disk_based_diagnostics_started(cx); + this.broadcast_language_server_update( language_server_id, proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( proto::LspDiskBasedDiagnosticsUpdating {}, ), ); } - } else { - self.on_lsp_work_start(language_server_id, token.clone(), cx); - self.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::WorkStart(proto::LspWorkStart { - token, - }), - ); - } - } - LanguageServerEvent::WorkProgress { token, progress } => { - if Some(token.as_str()) != disk_diagnostics_token { - self.on_lsp_work_progress( - language_server_id, - token.clone(), - progress.clone(), - cx, - ); - self.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::WorkProgress( - proto::LspWorkProgress { - token, - message: progress.message, - percentage: progress.percentage.map(|p| p as u32), - }, - ), - ); - } - } - LanguageServerEvent::WorkEnd { token } => { - if Some(token.as_str()) == disk_diagnostics_token { - language_server_status.pending_diagnostic_updates -= 1; - if language_server_status.pending_diagnostic_updates == 0 { - self.disk_based_diagnostics_finished(cx); - self.broadcast_language_server_update( + this.update_diagnostics(params, adapter.disk_based_diagnostic_sources(), cx) + .log_err(); + if disk_based_diagnostics_progress_token.is_none() { + this.disk_based_diagnostics_finished(cx); + this.broadcast_language_server_update( language_server_id, proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( proto::LspDiskBasedDiagnosticsUpdated {}, ), ); } - } else { - self.on_lsp_work_end(language_server_id, token.clone(), cx); - self.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd { - token, - }), - ); - } + }); } - LanguageServerEvent::DiagnosticsUpdate(mut params) => { - language.process_diagnostics(&mut params); + LanguageServerEvent::WorkspaceEdit(params) => { + let transaction = Self::deserialize_workspace_edit( + this, + params.edit, + false, + adapter.clone(), + language_server.clone(), + cx, + ) + .await + .log_err(); - if disk_diagnostics_token.is_none() { - self.disk_based_diagnostics_started(cx); - self.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( - proto::LspDiskBasedDiagnosticsUpdating {}, - ), - ); - } - self.update_diagnostics(params, language.disk_based_diagnostic_sources(), cx) - .log_err(); - if disk_diagnostics_token.is_none() { - self.disk_based_diagnostics_finished(cx); - self.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( - proto::LspDiskBasedDiagnosticsUpdated {}, - ), - ); - } + // Check if there is a code action currently running, using the state that is + // set in `start_code_action`. If so, then store the transaction for later use. } } } @@ -2679,6 +2739,16 @@ impl Project { &mut cx, ) .await + } else if let Some(command) = action.lsp_action.command { + this.update(&mut cx, |this, _| this.start_code_action()); + lang_server + .request::(lsp::ExecuteCommandParams { + command: command.command, + arguments: command.arguments.unwrap_or_default(), + ..Default::default() + }) + .await?; + Ok(this.update(&mut cx, |this, cx| this.finish_code_action(cx))) } else { Ok(ProjectTransaction::default()) } @@ -2837,6 +2907,17 @@ impl Project { Ok(project_transaction) } + fn start_code_action(&mut self) { + // Set some state that will be read inside of `on_lsp_event` when handling a `WorkspaceEdit` + // event, and will cause the `ProjectTransaction` to be stored. + } + + fn finish_code_action(&mut self, cx: &mut ModelContext) -> ProjectTransaction { + // Retrieve all stored `ProjectTransactions` that have been received since `start_code_action` + // was called, and combine them together. + Default::default() + } + pub fn prepare_rename( &self, buffer: ModelHandle, @@ -5992,6 +6073,85 @@ mod tests { } } + #[gpui::test] + async fn test_apply_code_action(cx: &mut gpui::TestAppContext) { + let mut language = Language::new( + LanguageConfig { + name: "TypeScript".into(), + path_suffixes: vec!["ts".to_string()], + ..Default::default() + }, + None, + ); + let mut fake_language_servers = language.set_fake_lsp_adapter(Default::default()); + + let fs = FakeFs::new(cx.background()); + fs.insert_tree( + "/dir", + json!({ + "a.ts": "", + }), + ) + .await; + + let project = Project::test(fs, cx); + project.update(cx, |project, _| project.languages.add(Arc::new(language))); + + let (tree, _) = project + .update(cx, |project, cx| { + project.find_or_create_local_worktree("/dir", true, cx) + }) + .await + .unwrap(); + let worktree_id = tree.read_with(cx, |tree, _| tree.id()); + cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) + .await; + + let buffer = project + .update(cx, |p, cx| p.open_buffer((worktree_id, "a.ts"), cx)) + .await + .unwrap(); + + let fake_server = fake_language_servers.next().await.unwrap(); + + let actions = project.update(cx, |project, cx| project.code_actions(&buffer, 0..0, cx)); + fake_server + .handle_request::(|params, _| async move { + Ok(Some(vec![ + lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction { + title: "The code action".into(), + command: Some(lsp::Command { + title: "The command".into(), + command: "_the/command".into(), + arguments: Some(vec![json!("the-argument")]), + }), + ..Default::default() + }), + lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction { + title: "two".into(), + ..Default::default() + }), + ])) + }) + .next() + .await; + + let action = actions.await.unwrap()[0].clone(); + let apply = project.update(cx, |project, cx| { + project.apply_code_action(buffer.clone(), action, true, cx) + }); + fake_server.handle_request::( + |action, _| async move { Ok(action) }, + ); + fake_server + .handle_request::(move |params, cx| async move { + // fake_server.send(); + Ok(Some(json!(null))) + }) + .next() + .await; + } + #[gpui::test] async fn test_save_file(cx: &mut gpui::TestAppContext) { let fs = FakeFs::new(cx.background()); From 65048760b2fdff02f44f916b07584ac8608061c6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 1 Apr 2022 14:01:56 +0200 Subject: [PATCH 19/68] Allow explicit reload of buffers via `Project::reload_buffers` --- crates/language/src/buffer.rs | 65 ++++++++++-------- crates/language/src/tests.rs | 8 ++- crates/project/src/project.rs | 94 ++++++++++++++++++++++++++ crates/rpc/proto/zed.proto | 77 ++++++++++++---------- crates/rpc/src/proto.rs | 4 ++ crates/rpc/src/rpc.rs | 2 +- crates/server/src/rpc.rs | 120 +++++++++++++++++++++++++++++++++- 7 files changed, 306 insertions(+), 64 deletions(-) diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 0c1ce7c228..f2c9d209b1 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -498,6 +498,30 @@ impl Buffer { cx.notify(); } + pub fn reload(&mut self, cx: &mut ModelContext) -> Task>> { + cx.spawn(|this, mut cx| async move { + if let Some((new_mtime, new_text)) = this.read_with(&cx, |this, cx| { + let file = this.file.as_ref()?.as_local()?; + Some((file.mtime(), file.load(cx))) + }) { + let new_text = new_text.await?; + let diff = this + .read_with(&cx, |this, cx| this.diff(new_text.into(), cx)) + .await; + this.update(&mut cx, |this, cx| { + if let Some(transaction) = this.apply_diff(diff, cx).cloned() { + this.did_reload(this.version(), new_mtime, cx); + Ok(Some(transaction)) + } else { + Ok(None) + } + }) + } else { + Ok(None) + } + }) + } + pub fn did_reload( &mut self, version: clock::Global, @@ -543,29 +567,8 @@ impl Buffer { file_changed = true; if !self.is_dirty() { - task = cx.spawn(|this, mut cx| { - async move { - let new_text = this.read_with(&cx, |this, cx| { - this.file - .as_ref() - .and_then(|file| file.as_local().map(|f| f.load(cx))) - }); - if let Some(new_text) = new_text { - let new_text = new_text.await?; - let diff = this - .read_with(&cx, |this, cx| this.diff(new_text.into(), cx)) - .await; - this.update(&mut cx, |this, cx| { - if this.apply_diff(diff, cx) { - this.did_reload(this.version(), new_mtime, cx); - } - }); - } - Ok(()) - } - .log_err() - .map(drop) - }); + let reload = self.reload(cx).log_err().map(drop); + task = cx.foreground().spawn(reload); } } } @@ -902,8 +905,13 @@ impl Buffer { }) } - pub(crate) fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext) -> bool { + pub(crate) fn apply_diff( + &mut self, + diff: Diff, + cx: &mut ModelContext, + ) -> Option<&Transaction> { if self.version == diff.base_version { + self.finalize_last_transaction(); self.start_transaction(); let mut offset = diff.start_offset; for (tag, len) in diff.changes { @@ -924,10 +932,13 @@ impl Buffer { } } } - self.end_transaction(cx); - true + if self.end_transaction(cx).is_some() { + self.finalize_last_transaction() + } else { + None + } } else { - false + None } } diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index 3eb87cefb6..e980865cb4 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -136,12 +136,16 @@ async fn test_apply_diff(cx: &mut gpui::TestAppContext) { let text = "a\nccc\ndddd\nffffff\n"; let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await; - buffer.update(cx, |b, cx| b.apply_diff(diff, cx)); + buffer.update(cx, |buffer, cx| { + buffer.apply_diff(diff, cx).unwrap(); + }); cx.read(|cx| assert_eq!(buffer.read(cx).text(), text)); let text = "a\n1\n\nccc\ndd2dd\nffffff\n"; let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await; - buffer.update(cx, |b, cx| b.apply_diff(diff, cx)); + buffer.update(cx, |buffer, cx| { + buffer.apply_diff(diff, cx).unwrap(); + }); cx.read(|cx| assert_eq!(buffer.read(cx).text(), text)); } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 4ec856f199..2316f4d80e 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -270,6 +270,7 @@ impl Project { client.add_model_message_handler(Self::handle_update_worktree); client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion); client.add_model_request_handler(Self::handle_apply_code_action); + client.add_model_request_handler(Self::handle_reload_buffers); client.add_model_request_handler(Self::handle_format_buffers); client.add_model_request_handler(Self::handle_get_code_actions); client.add_model_request_handler(Self::handle_get_completions); @@ -1973,6 +1974,70 @@ impl Project { Ok(()) } + pub fn reload_buffers( + &self, + buffers: HashSet>, + push_to_history: bool, + cx: &mut ModelContext, + ) -> Task> { + let mut local_buffers = Vec::new(); + let mut remote_buffers = None; + for buffer_handle in buffers { + let buffer = buffer_handle.read(cx); + if buffer.is_dirty() { + if let Some(file) = File::from_dyn(buffer.file()) { + if file.is_local() { + local_buffers.push(buffer_handle); + } else { + remote_buffers.get_or_insert(Vec::new()).push(buffer_handle); + } + } + } + } + + let remote_buffers = self.remote_id().zip(remote_buffers); + let client = self.client.clone(); + + cx.spawn(|this, mut cx| async move { + let mut project_transaction = ProjectTransaction::default(); + + if let Some((project_id, remote_buffers)) = remote_buffers { + let response = client + .request(proto::ReloadBuffers { + project_id, + buffer_ids: remote_buffers + .iter() + .map(|buffer| buffer.read_with(&cx, |buffer, _| buffer.remote_id())) + .collect(), + }) + .await? + .transaction + .ok_or_else(|| anyhow!("missing transaction"))?; + project_transaction = this + .update(&mut cx, |this, cx| { + this.deserialize_project_transaction(response, push_to_history, cx) + }) + .await?; + } + + for buffer in local_buffers { + let transaction = buffer + .update(&mut cx, |buffer, cx| buffer.reload(cx)) + .await?; + buffer.update(&mut cx, |buffer, cx| { + if let Some(transaction) = transaction { + if !push_to_history { + buffer.forget_transaction(transaction.id); + } + project_transaction.0.insert(cx.handle(), transaction); + } + }); + } + + Ok(project_transaction) + }) + } + pub fn format( &self, buffers: HashSet>, @@ -3667,6 +3732,35 @@ impl Project { }) } + async fn handle_reload_buffers( + this: ModelHandle, + envelope: TypedEnvelope, + _: Arc, + mut cx: AsyncAppContext, + ) -> Result { + let sender_id = envelope.original_sender_id()?; + let reload = this.update(&mut cx, |this, cx| { + let mut buffers = HashSet::default(); + for buffer_id in &envelope.payload.buffer_ids { + buffers.insert( + this.opened_buffers + .get(buffer_id) + .map(|buffer| buffer.upgrade(cx).unwrap()) + .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?, + ); + } + Ok::<_, anyhow::Error>(this.reload_buffers(buffers, false, cx)) + })?; + + let project_transaction = reload.await?; + let project_transaction = this.update(&mut cx, |this, cx| { + this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx) + }); + Ok(proto::ReloadBuffersResponse { + transaction: Some(project_transaction), + }) + } + async fn handle_format_buffers( this: ModelHandle, envelope: TypedEnvelope, diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 9d25e66190..e86a9a556e 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -48,43 +48,45 @@ message Envelope { SaveBuffer save_buffer = 40; BufferSaved buffer_saved = 41; BufferReloaded buffer_reloaded = 42; - FormatBuffers format_buffers = 43; - FormatBuffersResponse format_buffers_response = 44; - GetCompletions get_completions = 45; - GetCompletionsResponse get_completions_response = 46; - ApplyCompletionAdditionalEdits apply_completion_additional_edits = 47; - ApplyCompletionAdditionalEditsResponse apply_completion_additional_edits_response = 48; - GetCodeActions get_code_actions = 49; - GetCodeActionsResponse get_code_actions_response = 50; - ApplyCodeAction apply_code_action = 51; - ApplyCodeActionResponse apply_code_action_response = 52; - PrepareRename prepare_rename = 53; - PrepareRenameResponse prepare_rename_response = 54; - PerformRename perform_rename = 55; - PerformRenameResponse perform_rename_response = 56; - SearchProject search_project = 57; - SearchProjectResponse search_project_response = 58; + ReloadBuffers reload_buffers = 43; + ReloadBuffersResponse reload_buffers_response = 44; + FormatBuffers format_buffers = 45; + FormatBuffersResponse format_buffers_response = 46; + GetCompletions get_completions = 47; + GetCompletionsResponse get_completions_response = 48; + ApplyCompletionAdditionalEdits apply_completion_additional_edits = 49; + ApplyCompletionAdditionalEditsResponse apply_completion_additional_edits_response = 50; + GetCodeActions get_code_actions = 51; + GetCodeActionsResponse get_code_actions_response = 52; + ApplyCodeAction apply_code_action = 53; + ApplyCodeActionResponse apply_code_action_response = 54; + PrepareRename prepare_rename = 55; + PrepareRenameResponse prepare_rename_response = 56; + PerformRename perform_rename = 57; + PerformRenameResponse perform_rename_response = 58; + SearchProject search_project = 59; + SearchProjectResponse search_project_response = 60; - GetChannels get_channels = 59; - GetChannelsResponse get_channels_response = 60; - JoinChannel join_channel = 61; - JoinChannelResponse join_channel_response = 62; - LeaveChannel leave_channel = 63; - SendChannelMessage send_channel_message = 64; - SendChannelMessageResponse send_channel_message_response = 65; - ChannelMessageSent channel_message_sent = 66; - GetChannelMessages get_channel_messages = 67; - GetChannelMessagesResponse get_channel_messages_response = 68; + GetChannels get_channels = 61; + GetChannelsResponse get_channels_response = 62; + JoinChannel join_channel = 63; + JoinChannelResponse join_channel_response = 64; + LeaveChannel leave_channel = 65; + SendChannelMessage send_channel_message = 66; + SendChannelMessageResponse send_channel_message_response = 67; + ChannelMessageSent channel_message_sent = 68; + GetChannelMessages get_channel_messages = 69; + GetChannelMessagesResponse get_channel_messages_response = 70; - UpdateContacts update_contacts = 69; + UpdateContacts update_contacts = 71; - GetUsers get_users = 70; - GetUsersResponse get_users_response = 71; + GetUsers get_users = 72; + GetUsersResponse get_users_response = 73; - Follow follow = 72; - FollowResponse follow_response = 73; - UpdateFollowers update_followers = 74; - Unfollow unfollow = 75; + Follow follow = 74; + FollowResponse follow_response = 75; + UpdateFollowers update_followers = 76; + Unfollow unfollow = 77; } } @@ -299,6 +301,15 @@ message BufferReloaded { Timestamp mtime = 4; } +message ReloadBuffers { + uint64 project_id = 1; + repeated uint64 buffer_ids = 2; +} + +message ReloadBuffersResponse { + ProjectTransaction transaction = 1; +} + message FormatBuffers { uint64 project_id = 1; repeated uint64 buffer_ids = 2; diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index 59d6773451..a9f6b80f8e 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -190,6 +190,8 @@ messages!( (Ping, Foreground), (RegisterProject, Foreground), (RegisterWorktree, Foreground), + (ReloadBuffers, Foreground), + (ReloadBuffersResponse, Foreground), (RemoveProjectCollaborator, Foreground), (SaveBuffer, Foreground), (SearchProject, Background), @@ -237,6 +239,7 @@ request_messages!( (PrepareRename, PrepareRenameResponse), (RegisterProject, RegisterProjectResponse), (RegisterWorktree, Ack), + (ReloadBuffers, ReloadBuffersResponse), (SaveBuffer, BufferSaved), (SearchProject, SearchProjectResponse), (SendChannelMessage, SendChannelMessageResponse), @@ -268,6 +271,7 @@ entity_messages!( OpenBufferForSymbol, PerformRename, PrepareRename, + ReloadBuffers, RemoveProjectCollaborator, SaveBuffer, SearchProject, diff --git a/crates/rpc/src/rpc.rs b/crates/rpc/src/rpc.rs index cfe780d511..9ee18faae2 100644 --- a/crates/rpc/src/rpc.rs +++ b/crates/rpc/src/rpc.rs @@ -5,4 +5,4 @@ pub mod proto; pub use conn::Connection; pub use peer::*; -pub const PROTOCOL_VERSION: u32 = 12; +pub const PROTOCOL_VERSION: u32 = 13; diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 374aaf6a7e..4d23f61ef7 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -102,6 +102,7 @@ impl Server { .add_request_handler(Server::forward_project_request::) .add_request_handler(Server::forward_project_request::) .add_request_handler(Server::forward_project_request::) + .add_request_handler(Server::forward_project_request::) .add_request_handler(Server::forward_project_request::) .add_request_handler(Server::update_buffer) .add_message_handler(Server::update_buffer_file) @@ -1089,7 +1090,7 @@ mod tests { use gpui::{executor, geometry::vector::vec2f, ModelHandle, TestAppContext, ViewHandle}; use language::{ tree_sitter_rust, Diagnostic, DiagnosticEntry, Language, LanguageConfig, LanguageRegistry, - LanguageServerConfig, OffsetRangeExt, Point, ToLspPosition, + LanguageServerConfig, OffsetRangeExt, Point, Rope, ToLspPosition, }; use lsp; use parking_lot::Mutex; @@ -2460,6 +2461,123 @@ mod tests { .await; } + #[gpui::test(iterations = 10)] + async fn test_reloading_buffer_manually(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { + cx_a.foreground().forbid_parking(); + let lang_registry = Arc::new(LanguageRegistry::test()); + let fs = FakeFs::new(cx_a.background()); + + // Connect to a server as 2 clients. + let mut server = TestServer::start(cx_a.foreground(), cx_a.background()).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + + // Share a project as client A + fs.insert_tree( + "/a", + json!({ + ".zed.toml": r#"collaborators = ["user_b"]"#, + "a.rs": "let one = 1;", + }), + ) + .await; + let project_a = cx_a.update(|cx| { + Project::local( + client_a.clone(), + client_a.user_store.clone(), + lang_registry.clone(), + fs.clone(), + cx, + ) + }); + let (worktree_a, _) = project_a + .update(cx_a, |p, cx| { + p.find_or_create_local_worktree("/a", true, cx) + }) + .await + .unwrap(); + worktree_a + .read_with(cx_a, |tree, _| tree.as_local().unwrap().scan_complete()) + .await; + let project_id = project_a.update(cx_a, |p, _| p.next_remote_id()).await; + let worktree_id = worktree_a.read_with(cx_a, |tree, _| tree.id()); + project_a.update(cx_a, |p, cx| p.share(cx)).await.unwrap(); + let buffer_a = project_a + .update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx)) + .await + .unwrap(); + + // Join the worktree as client B. + let project_b = Project::remote( + project_id, + client_b.clone(), + client_b.user_store.clone(), + lang_registry.clone(), + fs.clone(), + &mut cx_b.to_async(), + ) + .await + .unwrap(); + + let buffer_b = cx_b + .background() + .spawn(project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx))) + .await + .unwrap(); + buffer_b.update(cx_b, |buffer, cx| { + buffer.edit([4..7], "six", cx); + buffer.edit([10..11], "6", cx); + assert_eq!(buffer.text(), "let six = 6;"); + assert!(buffer.is_dirty()); + assert!(!buffer.has_conflict()); + }); + buffer_a + .condition(cx_a, |buffer, _| buffer.text() == "let six = 6;") + .await; + + fs.save(Path::new("/a/a.rs"), &Rope::from("let seven = 7;")) + .await + .unwrap(); + buffer_a + .condition(cx_a, |buffer, _| buffer.has_conflict()) + .await; + buffer_b + .condition(cx_b, |buffer, _| buffer.has_conflict()) + .await; + + project_b + .update(cx_b, |project, cx| { + project.reload_buffers(HashSet::from_iter([buffer_b.clone()]), true, cx) + }) + .await + .unwrap(); + buffer_a.read_with(cx_a, |buffer, _| { + assert_eq!(buffer.text(), "let seven = 7;"); + assert!(!buffer.is_dirty()); + assert!(!buffer.has_conflict()); + }); + buffer_b.read_with(cx_b, |buffer, _| { + assert_eq!(buffer.text(), "let seven = 7;"); + assert!(!buffer.is_dirty()); + assert!(!buffer.has_conflict()); + }); + + buffer_a.update(cx_a, |buffer, cx| { + // Undoing on the host is a no-op when the reload was initiated by the guest. + buffer.undo(cx); + assert_eq!(buffer.text(), "let seven = 7;"); + assert!(!buffer.is_dirty()); + assert!(!buffer.has_conflict()); + }); + buffer_b.update(cx_b, |buffer, cx| { + // Undoing on the guest rolls back the buffer to before it was reloaded but the conflict gets cleared. + buffer.undo(cx); + assert_eq!(buffer.text(), "let six = 6;"); + assert!(buffer.is_dirty()); + assert!(!buffer.has_conflict()); + }); + } + #[gpui::test(iterations = 10)] async fn test_formatting_buffer(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) { cx_a.foreground().forbid_parking(); From 703f1c3be086844405be3950a513e17b6eb4bed3 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 1 Apr 2022 14:02:49 +0200 Subject: [PATCH 20/68] Introduce `workspace::Item::reload` to manually trigger a reload --- crates/diagnostics/src/diagnostics.rs | 8 ++++++++ crates/editor/src/items.rs | 25 +++++++++++++++++++++++++ crates/search/src/project_search.rs | 9 +++++++++ crates/workspace/src/workspace.rs | 15 +++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 56de434cf4..da50e99f1e 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -478,6 +478,14 @@ impl workspace::Item for ProjectDiagnosticsEditor { self.editor.save(project, cx) } + fn reload( + &mut self, + project: ModelHandle, + cx: &mut ViewContext, + ) -> Task> { + self.editor.reload(project, cx) + } + fn can_save_as(&self, _: &AppContext) -> bool { false } diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 79b25f8f60..67d5aee773 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -371,6 +371,31 @@ impl Item for Editor { }) } + fn reload( + &mut self, + project: ModelHandle, + cx: &mut ViewContext, + ) -> Task> { + let buffer = self.buffer().clone(); + let buffers = self.buffer.read(cx).all_buffers(); + let reload_buffers = + project.update(cx, |project, cx| project.reload_buffers(buffers, true, cx)); + cx.spawn(|this, mut cx| async move { + let transaction = reload_buffers.log_err().await; + this.update(&mut cx, |editor, cx| { + editor.request_autoscroll(Autoscroll::Fit, cx) + }); + buffer.update(&mut cx, |buffer, _| { + if let Some(transaction) = transaction { + if !buffer.is_singleton() { + buffer.push_transaction(&transaction.0); + } + } + }); + Ok(()) + }) + } + fn should_activate_item_on_event(event: &Event) -> bool { matches!(event, Event::Activate) } diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 65bb07ae46..745f23154f 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -280,6 +280,15 @@ impl Item for ProjectSearchView { unreachable!("save_as should not have been called") } + fn reload( + &mut self, + project: ModelHandle, + cx: &mut ViewContext, + ) -> Task> { + self.results_editor + .update(cx, |editor, cx| editor.reload(project, cx)) + } + fn clone_on_split(&self, cx: &mut ViewContext) -> Option where Self: Sized, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 9929cd9a51..073808e71a 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -237,6 +237,11 @@ pub trait Item: View { abs_path: PathBuf, cx: &mut ViewContext, ) -> Task>; + fn reload( + &mut self, + project: ModelHandle, + cx: &mut ViewContext, + ) -> Task>; fn should_activate_item_on_event(_: &Self::Event) -> bool { false } @@ -380,6 +385,8 @@ pub trait ItemHandle: 'static + fmt::Debug { abs_path: PathBuf, cx: &mut MutableAppContext, ) -> Task>; + fn reload(&self, project: ModelHandle, cx: &mut MutableAppContext) + -> Task>; fn act_as_type(&self, type_id: TypeId, cx: &AppContext) -> Option; fn to_followable_item_handle(&self, cx: &AppContext) -> Option>; } @@ -531,6 +538,14 @@ impl ItemHandle for ViewHandle { self.update(cx, |item, cx| item.save_as(project, abs_path, cx)) } + fn reload( + &self, + project: ModelHandle, + cx: &mut MutableAppContext, + ) -> Task> { + self.update(cx, |item, cx| item.reload(project, cx)) + } + fn is_dirty(&self, cx: &AppContext) -> bool { self.read(cx).is_dirty(cx) } From e93ab4db14e3f1f1bd2e991ce8a83c1e805e8f68 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 1 Apr 2022 14:32:41 +0200 Subject: [PATCH 21/68] Prompt before closing buffer with unsaved changes or conflicts --- crates/workspace/src/pane.rs | 333 +++++++++++++++++++++++++----- crates/workspace/src/workspace.rs | 7 +- crates/zed/src/zed.rs | 29 +-- 3 files changed, 306 insertions(+), 63 deletions(-) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index d48a5711a3..33df9fd4c7 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1,16 +1,17 @@ use super::{ItemHandle, SplitDirection}; use crate::{toolbar::Toolbar, Item, Settings, WeakItemHandle, Workspace}; use collections::{HashMap, VecDeque}; +use futures::StreamExt; use gpui::{ action, elements::*, geometry::{rect::RectF, vector::vec2f}, keymap::Binding, platform::{CursorStyle, NavigationDirection}, - AppContext, Entity, MutableAppContext, Quad, RenderContext, Task, View, ViewContext, - ViewHandle, WeakViewHandle, + AppContext, Entity, ModelHandle, MutableAppContext, PromptLevel, Quad, RenderContext, Task, + View, ViewContext, ViewHandle, WeakViewHandle, }; -use project::{ProjectEntryId, ProjectPath}; +use project::{Project, ProjectEntryId, ProjectPath}; use std::{any::Any, cell::RefCell, cmp, mem, rc::Rc}; use util::ResultExt; @@ -37,13 +38,13 @@ pub fn init(cx: &mut MutableAppContext) { pane.activate_next_item(cx); }); cx.add_action(|pane: &mut Pane, _: &CloseActiveItem, cx| { - pane.close_active_item(cx); + pane.close_active_item(cx).detach(); }); cx.add_action(|pane: &mut Pane, _: &CloseInactiveItems, cx| { - pane.close_inactive_items(cx); + pane.close_inactive_items(cx).detach(); }); cx.add_action(|pane: &mut Pane, action: &CloseItem, cx| { - pane.close_item(action.0, cx); + pane.close_item(action.0, cx).detach(); }); cx.add_action(|pane: &mut Pane, action: &Split, cx| { pane.split(action.0, cx); @@ -97,6 +98,7 @@ pub struct Pane { active_item_index: usize, nav_history: Rc>, toolbar: ViewHandle, + project: ModelHandle, } pub struct ItemNavHistory { @@ -132,12 +134,13 @@ pub struct NavigationEntry { } impl Pane { - pub fn new(cx: &mut ViewContext) -> Self { + pub fn new(project: ModelHandle, cx: &mut ViewContext) -> Self { Self { items: Vec::new(), active_item_index: 0, nav_history: Default::default(), toolbar: cx.add_view(|_| Toolbar::new()), + project, } } @@ -403,65 +406,137 @@ impl Pane { self.activate_item(index, true, cx); } - pub fn close_active_item(&mut self, cx: &mut ViewContext) { - if !self.items.is_empty() { + pub fn close_active_item(&mut self, cx: &mut ViewContext) -> Task<()> { + if self.items.is_empty() { + Task::ready(()) + } else { self.close_item(self.items[self.active_item_index].id(), cx) } } - pub fn close_inactive_items(&mut self, cx: &mut ViewContext) { - if !self.items.is_empty() { + pub fn close_inactive_items(&mut self, cx: &mut ViewContext) -> Task<()> { + if self.items.is_empty() { + Task::ready(()) + } else { let active_item_id = self.items[self.active_item_index].id(); - self.close_items(cx, |id| id != active_item_id); + self.close_items(cx, move |id| id != active_item_id) } } - pub fn close_item(&mut self, view_id_to_close: usize, cx: &mut ViewContext) { - self.close_items(cx, |view_id| view_id == view_id_to_close); + pub fn close_item(&mut self, view_id_to_close: usize, cx: &mut ViewContext) -> Task<()> { + self.close_items(cx, move |view_id| view_id == view_id_to_close) } pub fn close_items( &mut self, cx: &mut ViewContext, - should_close: impl Fn(usize) -> bool, - ) { - let mut item_ix = 0; - let mut new_active_item_index = self.active_item_index; - self.items.retain(|item| { - if should_close(item.id()) { - if item_ix == self.active_item_index { - item.deactivated(cx); + should_close: impl 'static + Fn(usize) -> bool, + ) -> Task<()> { + const CONFLICT_MESSAGE: &'static str = "This file has changed on disk since you started editing it. Do you want to overwrite it?"; + const DIRTY_MESSAGE: &'static str = + "This file contains unsaved edits. Do you want to save it?"; + + let project = self.project.clone(); + cx.spawn(|this, mut cx| async move { + while let Some(item_to_close_ix) = this.read_with(&cx, |this, _| { + this.items.iter().position(|item| should_close(item.id())) + }) { + let item = + this.read_with(&cx, |this, _| this.items[item_to_close_ix].boxed_clone()); + if cx.read(|cx| item.can_save(cx)) { + if cx.read(|cx| item.has_conflict(cx)) { + let mut answer = this.update(&mut cx, |this, cx| { + this.activate_item(item_to_close_ix, true, cx); + cx.prompt( + PromptLevel::Warning, + CONFLICT_MESSAGE, + &["Overwrite", "Discard", "Cancel"], + ) + }); + + match answer.next().await { + Some(0) => { + if cx + .update(|cx| item.save(project.clone(), cx)) + .await + .log_err() + .is_none() + { + break; + } + } + Some(1) => { + if cx + .update(|cx| item.reload(project.clone(), cx)) + .await + .log_err() + .is_none() + { + break; + } + } + _ => break, + } + } else if cx.read(|cx| item.is_dirty(cx)) { + let mut answer = this.update(&mut cx, |this, cx| { + this.activate_item(item_to_close_ix, true, cx); + cx.prompt( + PromptLevel::Warning, + DIRTY_MESSAGE, + &["Save", "Don't Save", "Cancel"], + ) + }); + + match answer.next().await { + Some(0) => { + if cx + .update(|cx| item.save(project.clone(), cx)) + .await + .log_err() + .is_none() + { + break; + } + } + Some(1) => {} + _ => break, + } + } } - if item_ix < self.active_item_index { - new_active_item_index -= 1; - } + this.update(&mut cx, |this, cx| { + if let Some(item_ix) = this.items.iter().position(|i| i.id() == item.id()) { + this.items.remove(item_ix); + if item_ix == this.active_item_index { + item.deactivated(cx); + } + if item_ix < this.active_item_index { + this.active_item_index -= 1; + } + this.active_item_index = + cmp::min(this.active_item_index, this.items.len().saturating_sub(1)); - let mut nav_history = self.nav_history.borrow_mut(); - if let Some(path) = item.project_path(cx) { - nav_history.paths_by_item.insert(item.id(), path); - } else { - nav_history.paths_by_item.remove(&item.id()); - } - - item_ix += 1; - false - } else { - item_ix += 1; - true + let mut nav_history = this.nav_history.borrow_mut(); + if let Some(path) = item.project_path(cx) { + nav_history.paths_by_item.insert(item.id(), path); + } else { + nav_history.paths_by_item.remove(&item.id()); + } + } + }); } - }); - if self.items.is_empty() { - cx.emit(Event::Remove); - } else { - self.active_item_index = cmp::min(new_active_item_index, self.items.len() - 1); - self.focus_active_item(cx); - self.activate(cx); - } - self.update_toolbar(cx); - - cx.notify(); + this.update(&mut cx, |this, cx| { + if this.items.is_empty() { + cx.emit(Event::Remove); + } else { + this.focus_active_item(cx); + this.activate(cx); + } + this.update_toolbar(cx); + cx.notify(); + }) + }) } pub fn focus_active_item(&mut self, cx: &mut ViewContext) { @@ -743,3 +818,165 @@ impl NavHistory { } } } + +#[cfg(test)] +mod tests { + use crate::WorkspaceParams; + + use super::*; + use gpui::TestAppContext; + + #[gpui::test] + async fn test_close_items(cx: &mut TestAppContext) { + cx.foreground().forbid_parking(); + + let params = cx.update(WorkspaceParams::test); + let (window_id, workspace) = cx.add_window(|cx| Workspace::new(¶ms, cx)); + let item1 = cx.add_view(window_id, |_| TestItem::new(false, true)); + let item2 = cx.add_view(window_id, |_| TestItem::new(true, true)); + let item3 = cx.add_view(window_id, |_| TestItem::new(false, true)); + let item4 = cx.add_view(window_id, |_| TestItem::new(true, false)); + let pane = workspace.update(cx, |workspace, cx| { + workspace.add_item(Box::new(item1.clone()), cx); + workspace.add_item(Box::new(item3.clone()), cx); + workspace.add_item(Box::new(item4.clone()), cx); + workspace.add_item(Box::new(item2.clone()), cx); + assert_eq!(workspace.active_item(cx).unwrap().id(), item2.id()); + + workspace.active_pane().clone() + }); + + let close_items = pane.update(cx, |pane, cx| { + let item1_id = item1.id(); + let item3_id = item3.id(); + let item4_id = item4.id(); + pane.close_items(cx, move |id| { + id == item1_id || id == item3_id || id == item4_id + }) + }); + + cx.foreground().run_until_parked(); + pane.read_with(cx, |pane, _| { + assert_eq!(pane.items.len(), 4); + assert_eq!(pane.active_item().unwrap().id(), item1.id()); + }); + + cx.simulate_prompt_answer(window_id, 0); + cx.foreground().run_until_parked(); + pane.read_with(cx, |pane, cx| { + assert_eq!(item1.read(cx).save_count, 1); + assert_eq!(item1.read(cx).reload_count, 0); + assert_eq!(pane.items.len(), 3); + assert_eq!(pane.active_item().unwrap().id(), item3.id()); + }); + + cx.simulate_prompt_answer(window_id, 1); + cx.foreground().run_until_parked(); + pane.read_with(cx, |pane, cx| { + assert_eq!(item3.read(cx).save_count, 0); + assert_eq!(item3.read(cx).reload_count, 1); + assert_eq!(pane.items.len(), 2); + assert_eq!(pane.active_item().unwrap().id(), item4.id()); + }); + + cx.simulate_prompt_answer(window_id, 0); + close_items.await; + pane.read_with(cx, |pane, cx| { + assert_eq!(item4.read(cx).save_count, 1); + assert_eq!(item4.read(cx).reload_count, 0); + assert_eq!(pane.items.len(), 1); + assert_eq!(pane.active_item().unwrap().id(), item2.id()); + }); + } + + struct TestItem { + is_dirty: bool, + has_conflict: bool, + save_count: usize, + reload_count: usize, + } + + impl TestItem { + fn new(is_dirty: bool, has_conflict: bool) -> Self { + Self { + save_count: 0, + reload_count: 0, + is_dirty, + has_conflict, + } + } + } + + impl Entity for TestItem { + type Event = (); + } + + impl View for TestItem { + fn ui_name() -> &'static str { + "TestItem" + } + + fn render(&mut self, _: &mut RenderContext) -> ElementBox { + Empty::new().boxed() + } + } + + impl Item for TestItem { + fn tab_content(&self, _: &theme::Tab, _: &AppContext) -> ElementBox { + Empty::new().boxed() + } + + fn project_path(&self, _: &AppContext) -> Option { + None + } + + fn project_entry_id(&self, _: &AppContext) -> Option { + None + } + + fn set_nav_history(&mut self, _: ItemNavHistory, _: &mut ViewContext) {} + + fn is_dirty(&self, _: &AppContext) -> bool { + self.is_dirty + } + + fn has_conflict(&self, _: &AppContext) -> bool { + self.has_conflict + } + + fn can_save(&self, _: &AppContext) -> bool { + true + } + + fn save( + &mut self, + _: ModelHandle, + _: &mut ViewContext, + ) -> Task> { + self.save_count += 1; + Task::ready(Ok(())) + } + + fn can_save_as(&self, _: &AppContext) -> bool { + false + } + + fn save_as( + &mut self, + _: ModelHandle, + _: std::path::PathBuf, + _: &mut ViewContext, + ) -> Task> { + unreachable!() + } + + fn reload( + &mut self, + _: ModelHandle, + _: &mut ViewContext, + ) -> Task> { + self.reload_count += 1; + Task::ready(Ok(())) + } + } +} diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 073808e71a..c447f3a5fd 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -497,7 +497,8 @@ impl ItemHandle for ViewHandle { } if T::should_close_item_on_event(event) { - pane.update(cx, |pane, cx| pane.close_item(item.id(), cx)); + pane.update(cx, |pane, cx| pane.close_item(item.id(), cx)) + .detach(); return; } @@ -737,7 +738,7 @@ impl Workspace { }) .detach(); - let pane = cx.add_view(|cx| Pane::new(cx)); + let pane = cx.add_view(|cx| Pane::new(params.project.clone(), cx)); let pane_id = pane.id(); cx.observe(&pane, move |me, _, cx| { let active_entry = me.active_project_path(cx); @@ -1069,7 +1070,7 @@ impl Workspace { } fn add_pane(&mut self, cx: &mut ViewContext) -> ViewHandle { - let pane = cx.add_view(|cx| Pane::new(cx)); + let pane = cx.add_view(|cx| Pane::new(self.project.clone(), cx)); let pane_id = pane.id(); cx.observe(&pane, move |me, _, cx| { let active_entry = me.active_project_path(cx); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index c94f8a0e81..24bdf4c0ef 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -867,12 +867,15 @@ mod tests { // Go forward to an item that has been closed, ensuring it gets re-opened at the same // location. - workspace.update(cx, |workspace, cx| { - workspace - .active_pane() - .update(cx, |pane, cx| pane.close_item(editor3.id(), cx)); - drop(editor3); - }); + workspace + .update(cx, |workspace, cx| { + let editor3_id = editor3.id(); + drop(editor3); + workspace + .active_pane() + .update(cx, |pane, cx| pane.close_item(editor3_id, cx)) + }) + .await; workspace .update(cx, |w, cx| Pane::go_forward(w, None, cx)) .await; @@ -884,15 +887,17 @@ mod tests { // Go back to an item that has been closed and removed from disk, ensuring it gets skipped. workspace .update(cx, |workspace, cx| { + let editor2_id = editor2.id(); + drop(editor2); workspace .active_pane() - .update(cx, |pane, cx| pane.close_item(editor2.id(), cx)); - drop(editor2); - app_state - .fs - .as_fake() - .remove_file(Path::new("/root/a/file2"), Default::default()) + .update(cx, |pane, cx| pane.close_item(editor2_id, cx)) }) + .await; + app_state + .fs + .as_fake() + .remove_file(Path::new("/root/a/file2"), Default::default()) .await .unwrap(); workspace From be677a8a4b76b9a974177508bbec69d78c9a3c77 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 1 Apr 2022 15:27:06 +0200 Subject: [PATCH 22/68] Don't assume the `CloseActiveItem` action is synchronous in test --- crates/zed/src/zed.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 24bdf4c0ef..00f57ccccb 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -683,6 +683,8 @@ mod tests { #[gpui::test] async fn test_pane_actions(cx: &mut TestAppContext) { + cx.foreground().forbid_parking(); + cx.update(|cx| pane::init(cx)); let app_state = cx.update(test_app_state); app_state @@ -740,7 +742,9 @@ mod tests { assert_eq!(pane2_item.project_path(cx.as_ref()), Some(file1.clone())); cx.dispatch_action(window_id, vec![pane_2.id()], &workspace::CloseActiveItem); - let workspace = workspace.read(cx); + }); + cx.foreground().run_until_parked(); + workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.panes().len(), 1); assert_eq!(workspace.active_pane(), &pane_1); }); From 56523b5775e780f2755e4683008d8b3c57f27de8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Apr 2022 10:16:26 -0700 Subject: [PATCH 23/68] Allow applying code actions that use commands Co-Authored-By: Antonio Scandurra --- crates/lsp/src/lsp.rs | 3 +- crates/project/src/project.rs | 83 +++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 6d89b5e870..f5fc98640d 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -563,8 +563,9 @@ impl Drop for Subscription { } #[cfg(any(test, feature = "test-support"))] +#[derive(Clone)] pub struct FakeLanguageServer { - server: Arc, + pub server: Arc, notifications_rx: channel::Receiver<(String, String)>, } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index e37124dda0..4225f9657f 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -64,6 +64,7 @@ pub struct Project { HashMap<(WorktreeId, LanguageServerName), Task>>>, language_server_statuses: BTreeMap, language_server_settings: Arc>, + last_workspace_edits_by_language_server: HashMap, next_language_server_id: usize, client: Arc, next_entry_id: Arc, @@ -346,6 +347,7 @@ impl Project { language_servers: Default::default(), started_language_servers: Default::default(), language_server_statuses: Default::default(), + last_workspace_edits_by_language_server: Default::default(), language_server_settings: Default::default(), next_language_server_id: 0, nonce: StdRng::from_entropy().gen(), @@ -433,6 +435,7 @@ impl Project { ) }) .collect(), + last_workspace_edits_by_language_server: Default::default(), next_language_server_id: 0, opened_buffers: Default::default(), buffer_snapshots: Default::default(), @@ -1736,18 +1739,21 @@ impl Project { } LanguageServerEvent::WorkspaceEdit(params) => { let transaction = Self::deserialize_workspace_edit( - this, + this.clone(), params.edit, - false, + true, adapter.clone(), language_server.clone(), cx, ) .await .log_err(); - - // Check if there is a code action currently running, using the state that is - // set in `start_code_action`. If so, then store the transaction for later use. + this.update(cx, |this, _| { + if let Some(transaction) = transaction { + this.last_workspace_edits_by_language_server + .insert(language_server_id, transaction); + } + }); } } } @@ -2740,7 +2746,6 @@ impl Project { ) .await } else if let Some(command) = action.lsp_action.command { - this.update(&mut cx, |this, _| this.start_code_action()); lang_server .request::(lsp::ExecuteCommandParams { command: command.command, @@ -2748,7 +2753,11 @@ impl Project { ..Default::default() }) .await?; - Ok(this.update(&mut cx, |this, cx| this.finish_code_action(cx))) + Ok(this.update(&mut cx, |this, _| { + this.last_workspace_edits_by_language_server + .remove(&lang_server.server_id()) + .unwrap_or_default() + })) } else { Ok(ProjectTransaction::default()) } @@ -2907,17 +2916,6 @@ impl Project { Ok(project_transaction) } - fn start_code_action(&mut self) { - // Set some state that will be read inside of `on_lsp_event` when handling a `WorkspaceEdit` - // event, and will cause the `ProjectTransaction` to be stored. - } - - fn finish_code_action(&mut self, cx: &mut ModelContext) -> ProjectTransaction { - // Retrieve all stored `ProjectTransactions` that have been received since `start_code_action` - // was called, and combine them together. - Default::default() - } - pub fn prepare_rename( &self, buffer: ModelHandle, @@ -6089,7 +6087,7 @@ mod tests { fs.insert_tree( "/dir", json!({ - "a.ts": "", + "a.ts": "a", }), ) .await; @@ -6116,7 +6114,7 @@ mod tests { let actions = project.update(cx, |project, cx| project.code_actions(&buffer, 0..0, cx)); fake_server - .handle_request::(|params, _| async move { + .handle_request::(|_, _| async move { Ok(Some(vec![ lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction { title: "The code action".into(), @@ -6144,12 +6142,51 @@ mod tests { |action, _| async move { Ok(action) }, ); fake_server - .handle_request::(move |params, cx| async move { - // fake_server.send(); - Ok(Some(json!(null))) + .handle_request::({ + let fake = fake_server.clone(); + move |params, _| { + assert_eq!(params.command, "_the/command"); + let fake = fake.clone(); + async move { + fake.server + .request::( + lsp::ApplyWorkspaceEditParams { + label: None, + edit: lsp::WorkspaceEdit { + changes: Some( + [( + lsp::Url::from_file_path("/dir/a.ts").unwrap(), + vec![lsp::TextEdit { + range: lsp::Range::new( + lsp::Position::new(0, 0), + lsp::Position::new(0, 0), + ), + new_text: "X".into(), + }], + )] + .into_iter() + .collect(), + ), + ..Default::default() + }, + }, + ) + .await + .unwrap(); + Ok(Some(json!(null))) + } + } }) .next() .await; + + let transaction = apply.await.unwrap(); + assert!(transaction.0.contains_key(&buffer)); + buffer.update(cx, |buffer, cx| { + assert_eq!(buffer.text(), "Xa"); + buffer.undo(cx); + assert_eq!(buffer.text(), "a"); + }); } #[gpui::test] From ba009724dd89b2f5ace6eb505da2d17aca0e1ed2 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Apr 2022 11:59:21 -0700 Subject: [PATCH 24/68] Handle LSP apply workspace edit request fully before responding --- crates/editor/src/editor.rs | 2 + crates/project/src/project.rs | 366 ++++++++++++++++------------------ 2 files changed, 172 insertions(+), 196 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 0dccce37a9..1135c9b260 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2593,6 +2593,8 @@ impl Editor { } } } + } else { + return Ok(()); } let mut ranges_to_highlight = Vec::new(); diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 4225f9657f..a8311ccf3b 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -132,21 +132,6 @@ pub enum Event { CollaboratorLeft(PeerId), } -enum LanguageServerEvent { - WorkStart { - token: String, - }, - WorkProgress { - token: String, - progress: LanguageServerProgress, - }, - WorkEnd { - token: String, - }, - DiagnosticsUpdate(lsp::PublishDiagnosticsParams), - WorkspaceEdit(lsp::ApplyWorkspaceEditParams), -} - pub struct LanguageServerStatus { pub name: String, pub pending_work: BTreeMap, @@ -1330,17 +1315,30 @@ impl Project { ); cx.spawn_weak(|this, mut cx| async move { let language_server = language_server?.await.log_err()?; + let language_server = language_server + .initialize(adapter.initialization_options()) + .await + .log_err()?; let this = this.upgrade(&cx)?; - let (language_server_events_tx, language_server_events_rx) = - smol::channel::unbounded(); + let disk_based_diagnostics_progress_token = + adapter.disk_based_diagnostics_progress_token(); language_server .on_notification::({ - let language_server_events_tx = language_server_events_tx.clone(); - move |params, _| { - language_server_events_tx - .try_send(LanguageServerEvent::DiagnosticsUpdate(params)) - .ok(); + let this = this.downgrade(); + let adapter = adapter.clone(); + move |params, mut cx| { + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |this, cx| { + this.on_lsp_diagnostics_published( + server_id, + params, + &adapter, + disk_based_diagnostics_progress_token, + cx, + ); + }); + } } }) .detach(); @@ -1373,94 +1371,40 @@ impl Project { language_server .on_request::({ - let language_server_events_tx = language_server_events_tx.clone(); - move |params, _| { - language_server_events_tx - .try_send(LanguageServerEvent::WorkspaceEdit(params)) - .ok(); - async move { - Ok(lsp::ApplyWorkspaceEditResponse { - applied: true, - failed_change: None, - failure_reason: None, - }) - } + let this = this.downgrade(); + let adapter = adapter.clone(); + let language_server = language_server.clone(); + move |params, cx| { + Self::on_lsp_workspace_edit( + this, + params, + server_id, + adapter.clone(), + language_server.clone(), + cx, + ) } }) .detach(); language_server - .on_notification::(move |params, _| { - let token = match params.token { - lsp::NumberOrString::String(token) => token, - lsp::NumberOrString::Number(token) => { - log::info!("skipping numeric progress token {}", token); - return; + .on_notification::({ + let this = this.downgrade(); + move |params, mut cx| { + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |this, cx| { + this.on_lsp_progress( + params, + server_id, + disk_based_diagnostics_progress_token, + cx, + ); + }); } - }; - - match params.value { - lsp::ProgressParamsValue::WorkDone(progress) => match progress { - lsp::WorkDoneProgress::Begin(_) => { - language_server_events_tx - .try_send(LanguageServerEvent::WorkStart { token }) - .ok(); - } - lsp::WorkDoneProgress::Report(report) => { - language_server_events_tx - .try_send(LanguageServerEvent::WorkProgress { - token, - progress: LanguageServerProgress { - message: report.message, - percentage: report - .percentage - .map(|p| p as usize), - last_update_at: Instant::now(), - }, - }) - .ok(); - } - lsp::WorkDoneProgress::End(_) => { - language_server_events_tx - .try_send(LanguageServerEvent::WorkEnd { token }) - .ok(); - } - }, } }) .detach(); - let language_server = language_server - .initialize(adapter.initialization_options()) - .await - .log_err()?; - - // Process all the LSP events. - cx.spawn(|mut cx| { - let this = this.downgrade(); - let adapter = adapter.clone(); - let language_server = language_server.clone(); - async move { - while let Ok(event) = language_server_events_rx.recv().await { - let this = this.upgrade(&cx)?; - Self::on_lsp_event( - this, - server_id, - &adapter, - &language_server, - event, - &mut cx, - ) - .await; - - // Don't starve the main thread when lots of events arrive all at once. - smol::future::yield_now().await; - } - Some(()) - } - }) - .detach(); - this.update(&mut cx, |this, cx| { this.language_servers .insert(key.clone(), (adapter, language_server.clone())); @@ -1615,75 +1559,111 @@ impl Project { .detach(); } - async fn on_lsp_event( - this: ModelHandle, - language_server_id: usize, + fn on_lsp_diagnostics_published( + &mut self, + server_id: usize, + mut params: lsp::PublishDiagnosticsParams, adapter: &Arc, - language_server: &Arc, - event: LanguageServerEvent, - cx: &mut AsyncAppContext, + disk_based_diagnostics_progress_token: Option<&str>, + cx: &mut ModelContext, ) { - let disk_based_diagnostics_progress_token = adapter.disk_based_diagnostics_progress_token(); - match event { - LanguageServerEvent::WorkStart { token } => { - this.update(cx, |this, cx| { - let language_server_status = if let Some(status) = - this.language_server_statuses.get_mut(&language_server_id) - { - status - } else { - return; - }; + adapter.process_diagnostics(&mut params); + if disk_based_diagnostics_progress_token.is_none() { + self.disk_based_diagnostics_started(cx); + self.broadcast_language_server_update( + server_id, + proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( + proto::LspDiskBasedDiagnosticsUpdating {}, + ), + ); + } + self.update_diagnostics(params, adapter.disk_based_diagnostic_sources(), cx) + .log_err(); + if disk_based_diagnostics_progress_token.is_none() { + self.disk_based_diagnostics_finished(cx); + self.broadcast_language_server_update( + server_id, + proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( + proto::LspDiskBasedDiagnosticsUpdated {}, + ), + ); + } + } + + fn on_lsp_progress( + &mut self, + progress: lsp::ProgressParams, + server_id: usize, + disk_based_diagnostics_progress_token: Option<&str>, + cx: &mut ModelContext, + ) { + let token = match progress.token { + lsp::NumberOrString::String(token) => token, + lsp::NumberOrString::Number(token) => { + log::info!("skipping numeric progress token {}", token); + return; + } + }; + + match progress.value { + lsp::ProgressParamsValue::WorkDone(progress) => match progress { + lsp::WorkDoneProgress::Begin(_) => { + let language_server_status = + if let Some(status) = self.language_server_statuses.get_mut(&server_id) { + status + } else { + return; + }; if Some(token.as_str()) == disk_based_diagnostics_progress_token { language_server_status.pending_diagnostic_updates += 1; if language_server_status.pending_diagnostic_updates == 1 { - this.disk_based_diagnostics_started(cx); - this.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( - proto::LspDiskBasedDiagnosticsUpdating {}, - ), - ); + self.disk_based_diagnostics_started(cx); + self.broadcast_language_server_update( + server_id, + proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( + proto::LspDiskBasedDiagnosticsUpdating {}, + ), + ); } } else { - this.on_lsp_work_start(language_server_id, token.clone(), cx); - this.broadcast_language_server_update( - language_server_id, + self.on_lsp_work_start(server_id, token.clone(), cx); + self.broadcast_language_server_update( + server_id, proto::update_language_server::Variant::WorkStart( proto::LspWorkStart { token }, ), ); } - }); - } - LanguageServerEvent::WorkProgress { token, progress } => { - this.update(cx, |this, cx| { + } + lsp::WorkDoneProgress::Report(report) => { if Some(token.as_str()) != disk_based_diagnostics_progress_token { - this.on_lsp_work_progress( - language_server_id, + self.on_lsp_work_progress( + server_id, token.clone(), - progress.clone(), + LanguageServerProgress { + message: report.message.clone(), + percentage: report.percentage.map(|p| p as usize), + last_update_at: Instant::now(), + }, cx, ); - this.broadcast_language_server_update( - language_server_id, + self.broadcast_language_server_update( + server_id, proto::update_language_server::Variant::WorkProgress( proto::LspWorkProgress { token, - message: progress.message, - percentage: progress.percentage.map(|p| p as u32), + message: report.message, + percentage: report.percentage.map(|p| p as u32), }, ), ); } - }); - } - LanguageServerEvent::WorkEnd { token } => { - this.update(cx, |this, cx| { + } + lsp::WorkDoneProgress::End(_) => { if Some(token.as_str()) == disk_based_diagnostics_progress_token { let language_server_status = if let Some(status) = - this.language_server_statuses.get_mut(&language_server_id) + self.language_server_statuses.get_mut(&server_id) { status } else { @@ -1692,69 +1672,25 @@ impl Project { language_server_status.pending_diagnostic_updates -= 1; if language_server_status.pending_diagnostic_updates == 0 { - this.disk_based_diagnostics_finished(cx); - this.broadcast_language_server_update( - language_server_id, + self.disk_based_diagnostics_finished(cx); + self.broadcast_language_server_update( + server_id, proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( proto::LspDiskBasedDiagnosticsUpdated {}, ), ); } } else { - this.on_lsp_work_end(language_server_id, token.clone(), cx); - this.broadcast_language_server_update( - language_server_id, + self.on_lsp_work_end(server_id, token.clone(), cx); + self.broadcast_language_server_update( + server_id, proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd { token, }), ); } - }); - } - LanguageServerEvent::DiagnosticsUpdate(mut params) => { - this.update(cx, |this, cx| { - adapter.process_diagnostics(&mut params); - - if disk_based_diagnostics_progress_token.is_none() { - this.disk_based_diagnostics_started(cx); - this.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( - proto::LspDiskBasedDiagnosticsUpdating {}, - ), - ); - } - this.update_diagnostics(params, adapter.disk_based_diagnostic_sources(), cx) - .log_err(); - if disk_based_diagnostics_progress_token.is_none() { - this.disk_based_diagnostics_finished(cx); - this.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( - proto::LspDiskBasedDiagnosticsUpdated {}, - ), - ); - } - }); - } - LanguageServerEvent::WorkspaceEdit(params) => { - let transaction = Self::deserialize_workspace_edit( - this.clone(), - params.edit, - true, - adapter.clone(), - language_server.clone(), - cx, - ) - .await - .log_err(); - this.update(cx, |this, _| { - if let Some(transaction) = transaction { - this.last_workspace_edits_by_language_server - .insert(language_server_id, transaction); - } - }); - } + } + }, } } @@ -1802,6 +1738,40 @@ impl Project { } } + async fn on_lsp_workspace_edit( + this: WeakModelHandle, + params: lsp::ApplyWorkspaceEditParams, + server_id: usize, + adapter: Arc, + language_server: Arc, + mut cx: AsyncAppContext, + ) -> Result { + let this = this + .upgrade(&cx) + .ok_or_else(|| anyhow!("project project closed"))?; + let transaction = Self::deserialize_workspace_edit( + this.clone(), + params.edit, + true, + adapter.clone(), + language_server.clone(), + &mut cx, + ) + .await + .log_err(); + this.update(&mut cx, |this, _| { + if let Some(transaction) = transaction { + this.last_workspace_edits_by_language_server + .insert(server_id, transaction); + } + }); + Ok(lsp::ApplyWorkspaceEditResponse { + applied: true, + failed_change: None, + failure_reason: None, + }) + } + fn broadcast_language_server_update( &self, language_server_id: usize, @@ -2746,6 +2716,10 @@ impl Project { ) .await } else if let Some(command) = action.lsp_action.command { + this.update(&mut cx, |this, _| { + this.last_workspace_edits_by_language_server + .remove(&lang_server.server_id()); + }); lang_server .request::(lsp::ExecuteCommandParams { command: command.command, @@ -6071,7 +6045,7 @@ mod tests { } } - #[gpui::test] + #[gpui::test(iterations = 100)] async fn test_apply_code_action(cx: &mut gpui::TestAppContext) { let mut language = Language::new( LanguageConfig { From fe8e06e781b312b3a7771b2564f9c8723a9de3c1 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Apr 2022 12:07:41 -0700 Subject: [PATCH 25/68] Fix clipping when using label-only completions --- crates/project/src/project.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index a8311ccf3b..d82629ab67 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2373,13 +2373,6 @@ impl Project { }; cx.spawn(|_, cx| async move { - let clipped_position = source_buffer_handle - .read_with(&cx, |this, _| this.clip_point_utf16(position, Bias::Left)); - if clipped_position != position { - log::info!("Completion position out of date"); - return Ok(Default::default()); - } - let completions = lang_server .request::(lsp::CompletionParams { text_document_position: lsp::TextDocumentPositionParams::new( @@ -2412,10 +2405,21 @@ impl Project { Some(lsp::CompletionTextEdit::Edit(edit)) => { (range_from_lsp(edit.range), edit.new_text.clone()) } - None => ( - this.common_prefix_at(position, &lsp_completion.label), - lsp_completion.label.clone(), - ), + None => { + let clipped_position = + this.clip_point_utf16(position, Bias::Left); + if position != clipped_position { + log::info!("completion out of expected range"); + return None; + } + ( + this.common_prefix_at( + clipped_position, + &lsp_completion.label, + ), + lsp_completion.label.clone(), + ) + } Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => { log::info!("unsupported insert/replace completion"); return None; From 6f28033efe8194699da795dfabd824d5c97a65a9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Apr 2022 13:00:06 -0700 Subject: [PATCH 26/68] Add explanatory comments in unit test for code actions w/ commands --- crates/project/src/project.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index d82629ab67..30865b9d5a 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -6049,8 +6049,8 @@ mod tests { } } - #[gpui::test(iterations = 100)] - async fn test_apply_code_action(cx: &mut gpui::TestAppContext) { + #[gpui::test(iterations = 10)] + async fn test_apply_code_actions_with_commands(cx: &mut gpui::TestAppContext) { let mut language = Language::new( LanguageConfig { name: "TypeScript".into(), @@ -6090,6 +6090,7 @@ mod tests { let fake_server = fake_language_servers.next().await.unwrap(); + // Language server returns code actions that contain commands, and not edits. let actions = project.update(cx, |project, cx| project.code_actions(&buffer, 0..0, cx)); fake_server .handle_request::(|_, _| async move { @@ -6116,9 +6117,15 @@ mod tests { let apply = project.update(cx, |project, cx| { project.apply_code_action(buffer.clone(), action, true, cx) }); + + // Resolving the code action does not populate its edits. In absence of + // edits, we must execute the given command. fake_server.handle_request::( |action, _| async move { Ok(action) }, ); + + // While executing the command, the language server sends the editor + // a `workspaceEdit` request. fake_server .handle_request::({ let fake = fake_server.clone(); @@ -6158,6 +6165,8 @@ mod tests { .next() .await; + // Applying the code action returns a project transaction containing the edits + // sent by the language server in its `workspaceEdit` request. let transaction = apply.await.unwrap(); assert!(transaction.0.contains_key(&buffer)); buffer.update(cx, |buffer, cx| { From 5090e6f146de4bbd00f6a57f1d8f3fd37286e3eb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Apr 2022 14:49:36 -0700 Subject: [PATCH 27/68] Fix common_prefix_at panic when needle contains multibyte chars Also, make the prefix matching case-insensitive, since this is the typical behavior with autocomplete. --- crates/text/src/tests.rs | 50 ++++++++++++++++++++++++++++++++++------ crates/text/src/text.rs | 34 +++++++++++---------------- 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs index 54e802b521..9348ff0ba6 100644 --- a/crates/text/src/tests.rs +++ b/crates/text/src/tests.rs @@ -7,7 +7,6 @@ use std::{ iter::Iterator, time::{Duration, Instant}, }; -use util::test::marked_text_ranges; #[cfg(test)] #[ctor::ctor] @@ -167,14 +166,51 @@ fn test_line_len() { #[test] fn test_common_prefix_at_positionn() { - let (text, ranges) = marked_text_ranges("a = [bcd]"); + let text = "a = str; b = δα"; let buffer = Buffer::new(0, 0, History::new(text.into())); - let snapshot = &buffer.snapshot(); - let expected_range = ranges[0].to_offset(&snapshot); + + let offset1 = offset_after(text, "str"); + let offset2 = offset_after(text, "δα"); + + // the preceding word is a prefix of the suggestion assert_eq!( - buffer.common_prefix_at(expected_range.end, "bcdef"), - expected_range - ) + buffer.common_prefix_at(offset1, "string"), + range_of(text, "str"), + ); + // a suffix of the preceding word is a prefix of the suggestion + assert_eq!( + buffer.common_prefix_at(offset1, "tree"), + range_of(text, "tr"), + ); + // the preceding word is a substring of the suggestion, but not a prefix + assert_eq!( + buffer.common_prefix_at(offset1, "astro"), + empty_range_after(text, "str"), + ); + + // prefix matching is case insenstive. + assert_eq!( + buffer.common_prefix_at(offset1, "Strαngε"), + range_of(text, "str"), + ); + assert_eq!( + buffer.common_prefix_at(offset2, "ΔΑΜΝ"), + range_of(text, "δα"), + ); + + fn offset_after(text: &str, part: &str) -> usize { + text.find(part).unwrap() + part.len() + } + + fn empty_range_after(text: &str, part: &str) -> Range { + let offset = offset_after(text, part); + offset..offset + } + + fn range_of(text: &str, part: &str) -> Range { + let start = text.find(part).unwrap(); + start..start + part.len() + } } #[test] diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index ea0af9d21f..1c351079a7 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1510,31 +1510,25 @@ impl BufferSnapshot { pub fn common_prefix_at(&self, position: T, needle: &str) -> Range where - T: Clone + ToOffset + FromAnchor, + T: ToOffset + TextDimension, { - let position_offset = position.to_offset(self); - // Get byte indices and char counts for every character in needle in reverse order - let char_indices = needle + let offset = position.to_offset(self); + let common_prefix_len = needle .char_indices() .map(|(index, _)| index) - .chain(std::iter::once(needle.len())) - .enumerate() - // Don't test any prefixes that are bigger than the requested position - .take_while(|(_, prefix_length)| *prefix_length <= position_offset); - - let start = char_indices - // Compute the prefix string and prefix start location - .map(move |(byte_position, char_length)| { - (position_offset - char_length, &needle[..byte_position]) + .chain([needle.len()]) + .take_while(|&len| len <= offset) + .filter(|&len| { + let left = self + .chars_for_range(offset - len..offset) + .flat_map(|c| char::to_lowercase(c)); + let right = needle[..len].chars().flat_map(|c| char::to_lowercase(c)); + left.eq(right) }) - // Only take strings when the prefix is contained at the expected prefix position - .filter(|(prefix_offset, prefix)| self.contains_str_at(prefix_offset, prefix)) - // Convert offset to T - .map(|(prefix_offset, _)| T::from_anchor(&self.anchor_before(prefix_offset), self)) .last() - // If no prefix matches, return the passed in position to create an empty range - .unwrap_or(position.clone()); - + .unwrap_or(0); + let start_offset = offset - common_prefix_len; + let start = self.text_summary_for_range(0..start_offset); start..position } From 7ad862673d748f669c2170b36df937a6c42bbf85 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Apr 2022 15:05:03 -0700 Subject: [PATCH 28/68] Add basic syntax highlight colors for typescript completions --- crates/zed/src/languages/typescript.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs index d08da116a5..aca8cdef52 100644 --- a/crates/zed/src/languages/typescript.rs +++ b/crates/zed/src/languages/typescript.rs @@ -115,6 +115,29 @@ impl LspAdapter for TypeScriptLspAdapter { fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {} + fn label_for_completion( + &self, + item: &lsp::CompletionItem, + language: &language::Language, + ) -> Option { + use lsp::CompletionItemKind as Kind; + let len = item.label.len(); + let grammar = language.grammar()?; + let highlight_id = match item.kind? { + Kind::CLASS | Kind::INTERFACE => grammar.highlight_id_for_name("type"), + Kind::CONSTRUCTOR => grammar.highlight_id_for_name("type"), + Kind::CONSTANT => grammar.highlight_id_for_name("constant"), + Kind::FUNCTION | Kind::METHOD => grammar.highlight_id_for_name("function"), + Kind::PROPERTY | Kind::FIELD => grammar.highlight_id_for_name("property"), + _ => None, + }?; + Some(language::CodeLabel { + text: item.label.clone(), + runs: vec![(0..len, highlight_id)], + filter_range: 0..len, + }) + } + fn initialization_options(&self) -> Option { Some(json!({ "provideFormatter": true From c4d3bbf18448e3488eb75b03a23cf4cc3ad30220 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 1 Apr 2022 15:17:30 -0700 Subject: [PATCH 29/68] Bump protocol version --- crates/rpc/src/rpc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc/src/rpc.rs b/crates/rpc/src/rpc.rs index cfe780d511..9ee18faae2 100644 --- a/crates/rpc/src/rpc.rs +++ b/crates/rpc/src/rpc.rs @@ -5,4 +5,4 @@ pub mod proto; pub use conn::Connection; pub use peer::*; -pub const PROTOCOL_VERSION: u32 = 12; +pub const PROTOCOL_VERSION: u32 = 13; From 92256292081c9b18c0fde68dd0a0f46ca90dd807 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sat, 2 Apr 2022 15:51:59 +0200 Subject: [PATCH 30/68] Re-render breadcrumbs on save or when the editor title changes --- crates/breadcrumbs/src/breadcrumbs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/breadcrumbs/src/breadcrumbs.rs b/crates/breadcrumbs/src/breadcrumbs.rs index ce32fb2272..7085712f8c 100644 --- a/crates/breadcrumbs/src/breadcrumbs.rs +++ b/crates/breadcrumbs/src/breadcrumbs.rs @@ -99,7 +99,9 @@ impl ToolbarItemView for Breadcrumbs { if let Some(editor) = item.act_as::(cx) { self.subscriptions .push(cx.subscribe(&editor, |_, _, event, cx| match event { - editor::Event::BufferEdited => cx.notify(), + editor::Event::BufferEdited + | editor::Event::TitleChanged + | editor::Event::Saved => cx.notify(), editor::Event::SelectionsChanged { local } if *local => cx.notify(), _ => {} })); From c39de1f9dc1d59e27be549e62fd99ffe56ecfb0f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sat, 2 Apr 2022 16:10:10 +0200 Subject: [PATCH 31/68] Show full path for file worktrees or when there is more than 1 worktree --- Cargo.lock | 1 + crates/breadcrumbs/Cargo.toml | 1 + crates/breadcrumbs/src/breadcrumbs.rs | 35 +++++++++++++++++---------- crates/editor/src/multi_buffer.rs | 11 +++++++-- crates/zed/src/zed.rs | 27 ++++++++++++--------- 5 files changed, 48 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 276fbf1525..2c64dd0ba7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -727,6 +727,7 @@ dependencies = [ "editor", "gpui", "language", + "project", "search", "theme", "workspace", diff --git a/crates/breadcrumbs/Cargo.toml b/crates/breadcrumbs/Cargo.toml index 2e74fd2090..7dbafdb3be 100644 --- a/crates/breadcrumbs/Cargo.toml +++ b/crates/breadcrumbs/Cargo.toml @@ -12,6 +12,7 @@ collections = { path = "../collections" } editor = { path = "../editor" } gpui = { path = "../gpui" } language = { path = "../language" } +project = { path = "../project" } search = { path = "../search" } theme = { path = "../theme" } workspace = { path = "../workspace" } diff --git a/crates/breadcrumbs/src/breadcrumbs.rs b/crates/breadcrumbs/src/breadcrumbs.rs index 7085712f8c..0f8ac9274e 100644 --- a/crates/breadcrumbs/src/breadcrumbs.rs +++ b/crates/breadcrumbs/src/breadcrumbs.rs @@ -1,10 +1,11 @@ use editor::{Anchor, Editor}; use gpui::{ - elements::*, AppContext, Entity, RenderContext, Subscription, View, ViewContext, ViewHandle, + elements::*, AppContext, Entity, ModelHandle, RenderContext, Subscription, View, ViewContext, + ViewHandle, }; -use language::{BufferSnapshot, OutlineItem}; +use language::{Buffer, OutlineItem}; +use project::Project; use search::ProjectSearchView; -use std::borrow::Cow; use theme::SyntaxTheme; use workspace::{ItemHandle, Settings, ToolbarItemLocation, ToolbarItemView}; @@ -13,14 +14,16 @@ pub enum Event { } pub struct Breadcrumbs { + project: ModelHandle, editor: Option>, project_search: Option>, subscriptions: Vec, } impl Breadcrumbs { - pub fn new() -> Self { + pub fn new(project: ModelHandle) -> Self { Self { + project, editor: Default::default(), subscriptions: Default::default(), project_search: Default::default(), @@ -31,14 +34,14 @@ impl Breadcrumbs { &self, theme: &SyntaxTheme, cx: &AppContext, - ) -> Option<(BufferSnapshot, Vec>)> { + ) -> Option<(ModelHandle, Vec>)> { let editor = self.editor.as_ref()?.read(cx); let cursor = editor.newest_anchor_selection().head(); - let (buffer, symbols) = editor - .buffer() - .read(cx) + let multibuffer = &editor.buffer().read(cx); + let (buffer_id, symbols) = multibuffer .read(cx) .symbols_containing(cursor, Some(theme))?; + let buffer = multibuffer.buffer(buffer_id)?; Some((buffer, symbols)) } } @@ -60,15 +63,21 @@ impl View for Breadcrumbs { } else { return Empty::new().boxed(); }; - - let filename = if let Some(path) = buffer.path() { - path.to_string_lossy() + let buffer = buffer.read(cx); + let filename = if let Some(file) = buffer.file() { + if file.path().file_name().is_none() + || self.project.read(cx).visible_worktrees(cx).count() > 1 + { + file.full_path(cx).to_string_lossy().to_string() + } else { + file.path().to_string_lossy().to_string() + } } else { - Cow::Borrowed("untitled") + "untitled".to_string() }; Flex::row() - .with_child(Label::new(filename.to_string(), theme.breadcrumbs.text.clone()).boxed()) + .with_child(Label::new(filename, theme.breadcrumbs.text.clone()).boxed()) .with_children(symbols.into_iter().flat_map(|symbol| { [ Label::new(" 〉 ".to_string(), theme.breadcrumbs.text.clone()).boxed(), diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index ad3fc3202d..c07df895c9 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1001,6 +1001,13 @@ impl MultiBuffer { .collect() } + pub fn buffer(&self, buffer_id: usize) -> Option> { + self.buffers + .borrow() + .get(&buffer_id) + .map(|state| state.buffer.clone()) + } + pub fn save(&mut self, cx: &mut ModelContext) -> Task> { let mut save_tasks = Vec::new(); for BufferState { buffer, .. } in self.buffers.borrow().values() { @@ -2268,12 +2275,12 @@ impl MultiBufferSnapshot { &self, offset: T, theme: Option<&SyntaxTheme>, - ) -> Option<(BufferSnapshot, Vec>)> { + ) -> Option<(usize, Vec>)> { let anchor = self.anchor_before(offset); let excerpt_id = anchor.excerpt_id(); let excerpt = self.excerpt(excerpt_id)?; Some(( - excerpt.buffer.clone(), + excerpt.buffer_id, excerpt .buffer .symbols_containing(anchor.text_anchor, theme) diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 7b54b3df9a..aec0bc533e 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -106,18 +106,21 @@ pub fn build_workspace( app_state: &Arc, cx: &mut ViewContext, ) -> Workspace { - cx.subscribe(&cx.handle(), |_, _, event, cx| { - let workspace::Event::PaneAdded(pane) = event; - pane.update(cx, |pane, cx| { - pane.toolbar().update(cx, |toolbar, cx| { - let breadcrumbs = cx.add_view(|_| Breadcrumbs::new()); - toolbar.add_item(breadcrumbs, cx); - let buffer_search_bar = cx.add_view(|cx| BufferSearchBar::new(cx)); - toolbar.add_item(buffer_search_bar, cx); - let project_search_bar = cx.add_view(|_| ProjectSearchBar::new()); - toolbar.add_item(project_search_bar, cx); - }) - }); + cx.subscribe(&cx.handle(), { + let project = project.clone(); + move |_, _, event, cx| { + let workspace::Event::PaneAdded(pane) = event; + pane.update(cx, |pane, cx| { + pane.toolbar().update(cx, |toolbar, cx| { + let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(project.clone())); + toolbar.add_item(breadcrumbs, cx); + let buffer_search_bar = cx.add_view(|cx| BufferSearchBar::new(cx)); + toolbar.add_item(buffer_search_bar, cx); + let project_search_bar = cx.add_view(|_| ProjectSearchBar::new()); + toolbar.add_item(project_search_bar, cx); + }) + }); + } }) .detach(); From d0a17f8c2cda6ffc8eeee68460a650c83a8e76e5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sat, 2 Apr 2022 16:16:47 +0200 Subject: [PATCH 32/68] Update toolbar and automatically unfollow when navigating back and forth --- crates/workspace/src/pane.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 33df9fd4c7..8dfe0f49a2 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -207,13 +207,16 @@ impl Pane { let prev_active_index = mem::replace(&mut pane.active_item_index, index); pane.focus_active_item(cx); + pane.update_toolbar(cx); + cx.emit(Event::ActivateItem { local: true }); + cx.notify(); + let mut navigated = prev_active_index != pane.active_item_index; if let Some(data) = entry.data { navigated |= pane.active_item()?.navigate(data, cx); } if navigated { - cx.notify(); break None; } } From b0b54365c79e7431a735c8132a93647df3fcf57a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sat, 2 Apr 2022 16:19:15 +0200 Subject: [PATCH 33/68] Re-render breadcrumbs when buffer has been reparsed --- crates/breadcrumbs/src/breadcrumbs.rs | 3 ++- crates/editor/src/editor.rs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/breadcrumbs/src/breadcrumbs.rs b/crates/breadcrumbs/src/breadcrumbs.rs index 0f8ac9274e..59c8b08b68 100644 --- a/crates/breadcrumbs/src/breadcrumbs.rs +++ b/crates/breadcrumbs/src/breadcrumbs.rs @@ -110,7 +110,8 @@ impl ToolbarItemView for Breadcrumbs { .push(cx.subscribe(&editor, |_, _, event, cx| match event { editor::Event::BufferEdited | editor::Event::TitleChanged - | editor::Event::Saved => cx.notify(), + | editor::Event::Saved + | editor::Event::Reparsed => cx.notify(), editor::Event::SelectionsChanged { local } if *local => cx.notify(), _ => {} })); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 1135c9b260..8a35e4b3d2 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5860,6 +5860,7 @@ impl Editor { self.refresh_code_actions(cx); cx.emit(Event::BufferEdited); } + language::Event::Reparsed => cx.emit(Event::Reparsed), language::Event::Dirtied => cx.emit(Event::Dirtied), language::Event::Saved => cx.emit(Event::Saved), language::Event::FileHandleChanged => cx.emit(Event::TitleChanged), @@ -5987,6 +5988,7 @@ pub enum Event { Activate, BufferEdited, Edited, + Reparsed, Blurred, Dirtied, Saved, From 80b599c4ef3ba126a508527df64cd51cfa80171f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sun, 3 Apr 2022 12:43:33 +0200 Subject: [PATCH 34/68] Prompt to save untitled buffers when closing them while they are dirty --- crates/workspace/src/pane.rs | 196 +++++++++++++++++++++++++---------- 1 file changed, 140 insertions(+), 56 deletions(-) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 33df9fd4c7..afafe480c0 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -12,7 +12,7 @@ use gpui::{ View, ViewContext, ViewHandle, WeakViewHandle, }; use project::{Project, ProjectEntryId, ProjectPath}; -use std::{any::Any, cell::RefCell, cmp, mem, rc::Rc}; +use std::{any::Any, cell::RefCell, cmp, mem, path::Path, rc::Rc}; use util::ResultExt; action!(Split, SplitDirection); @@ -443,41 +443,8 @@ impl Pane { }) { let item = this.read_with(&cx, |this, _| this.items[item_to_close_ix].boxed_clone()); - if cx.read(|cx| item.can_save(cx)) { - if cx.read(|cx| item.has_conflict(cx)) { - let mut answer = this.update(&mut cx, |this, cx| { - this.activate_item(item_to_close_ix, true, cx); - cx.prompt( - PromptLevel::Warning, - CONFLICT_MESSAGE, - &["Overwrite", "Discard", "Cancel"], - ) - }); - - match answer.next().await { - Some(0) => { - if cx - .update(|cx| item.save(project.clone(), cx)) - .await - .log_err() - .is_none() - { - break; - } - } - Some(1) => { - if cx - .update(|cx| item.reload(project.clone(), cx)) - .await - .log_err() - .is_none() - { - break; - } - } - _ => break, - } - } else if cx.read(|cx| item.is_dirty(cx)) { + if cx.read(|cx| item.is_dirty(cx)) { + if cx.read(|cx| item.can_save(cx)) { let mut answer = this.update(&mut cx, |this, cx| { this.activate_item(item_to_close_ix, true, cx); cx.prompt( @@ -501,6 +468,76 @@ impl Pane { Some(1) => {} _ => break, } + } else if cx.read(|cx| item.can_save_as(cx)) { + let mut answer = this.update(&mut cx, |this, cx| { + this.activate_item(item_to_close_ix, true, cx); + cx.prompt( + PromptLevel::Warning, + DIRTY_MESSAGE, + &["Save", "Don't Save", "Cancel"], + ) + }); + + match answer.next().await { + Some(0) => { + let start_abs_path = project + .read_with(&cx, |project, cx| { + let worktree = project.visible_worktrees(cx).next()?; + Some(worktree.read(cx).as_local()?.abs_path().to_path_buf()) + }) + .unwrap_or(Path::new("").into()); + + let mut abs_path = + cx.update(|cx| cx.prompt_for_new_path(&start_abs_path)); + if let Some(abs_path) = abs_path.next().await.flatten() { + if cx + .update(|cx| item.save_as(project.clone(), abs_path, cx)) + .await + .log_err() + .is_none() + { + break; + } + } else { + break; + } + } + Some(1) => {} + _ => break, + } + } + } else if cx.read(|cx| item.has_conflict(cx) && item.can_save(cx)) { + let mut answer = this.update(&mut cx, |this, cx| { + this.activate_item(item_to_close_ix, true, cx); + cx.prompt( + PromptLevel::Warning, + CONFLICT_MESSAGE, + &["Overwrite", "Discard", "Cancel"], + ) + }); + + match answer.next().await { + Some(0) => { + if cx + .update(|cx| item.save(project.clone(), cx)) + .await + .log_err() + .is_none() + { + break; + } + } + Some(1) => { + if cx + .update(|cx| item.reload(project.clone(), cx)) + .await + .log_err() + .is_none() + { + break; + } + } + _ => break, } } @@ -532,6 +569,7 @@ impl Pane { } else { this.focus_active_item(cx); this.activate(cx); + cx.emit(Event::ActivateItem { local: true }); } this.update_toolbar(cx); cx.notify(); @@ -832,32 +870,58 @@ mod tests { let params = cx.update(WorkspaceParams::test); let (window_id, workspace) = cx.add_window(|cx| Workspace::new(¶ms, cx)); - let item1 = cx.add_view(window_id, |_| TestItem::new(false, true)); - let item2 = cx.add_view(window_id, |_| TestItem::new(true, true)); - let item3 = cx.add_view(window_id, |_| TestItem::new(false, true)); - let item4 = cx.add_view(window_id, |_| TestItem::new(true, false)); + let item1 = cx.add_view(window_id, |_| { + let mut item = TestItem::new(); + item.has_conflict = true; + item + }); + let item2 = cx.add_view(window_id, |_| { + let mut item = TestItem::new(); + item.is_dirty = true; + item.has_conflict = true; + item + }); + let item3 = cx.add_view(window_id, |_| { + let mut item = TestItem::new(); + item.has_conflict = true; + item + }); + let item4 = cx.add_view(window_id, |_| { + let mut item = TestItem::new(); + item.is_dirty = true; + item + }); + let item5 = cx.add_view(window_id, |_| { + let mut item = TestItem::new(); + item.is_dirty = true; + item.can_save = false; + item + }); let pane = workspace.update(cx, |workspace, cx| { workspace.add_item(Box::new(item1.clone()), cx); + workspace.add_item(Box::new(item2.clone()), cx); workspace.add_item(Box::new(item3.clone()), cx); workspace.add_item(Box::new(item4.clone()), cx); - workspace.add_item(Box::new(item2.clone()), cx); - assert_eq!(workspace.active_item(cx).unwrap().id(), item2.id()); - + workspace.add_item(Box::new(item5.clone()), cx); workspace.active_pane().clone() }); let close_items = pane.update(cx, |pane, cx| { + pane.activate_item(1, true, cx); + assert_eq!(pane.active_item().unwrap().id(), item2.id()); + let item1_id = item1.id(); let item3_id = item3.id(); let item4_id = item4.id(); + let item5_id = item5.id(); pane.close_items(cx, move |id| { - id == item1_id || id == item3_id || id == item4_id + [item1_id, item3_id, item4_id, item5_id].contains(&id) }) }); cx.foreground().run_until_parked(); pane.read_with(cx, |pane, _| { - assert_eq!(pane.items.len(), 4); + assert_eq!(pane.items.len(), 5); assert_eq!(pane.active_item().unwrap().id(), item1.id()); }); @@ -865,8 +929,9 @@ mod tests { cx.foreground().run_until_parked(); pane.read_with(cx, |pane, cx| { assert_eq!(item1.read(cx).save_count, 1); + assert_eq!(item1.read(cx).save_as_count, 0); assert_eq!(item1.read(cx).reload_count, 0); - assert_eq!(pane.items.len(), 3); + assert_eq!(pane.items.len(), 4); assert_eq!(pane.active_item().unwrap().id(), item3.id()); }); @@ -874,35 +939,53 @@ mod tests { cx.foreground().run_until_parked(); pane.read_with(cx, |pane, cx| { assert_eq!(item3.read(cx).save_count, 0); + assert_eq!(item3.read(cx).save_as_count, 0); assert_eq!(item3.read(cx).reload_count, 1); - assert_eq!(pane.items.len(), 2); + assert_eq!(pane.items.len(), 3); assert_eq!(pane.active_item().unwrap().id(), item4.id()); }); cx.simulate_prompt_answer(window_id, 0); - close_items.await; + cx.foreground().run_until_parked(); pane.read_with(cx, |pane, cx| { assert_eq!(item4.read(cx).save_count, 1); + assert_eq!(item4.read(cx).save_as_count, 0); assert_eq!(item4.read(cx).reload_count, 0); + assert_eq!(pane.items.len(), 2); + assert_eq!(pane.active_item().unwrap().id(), item5.id()); + }); + + cx.simulate_prompt_answer(window_id, 0); + cx.foreground().run_until_parked(); + cx.simulate_new_path_selection(|_| Some(Default::default())); + close_items.await; + pane.read_with(cx, |pane, cx| { + assert_eq!(item5.read(cx).save_count, 0); + assert_eq!(item5.read(cx).save_as_count, 1); + assert_eq!(item5.read(cx).reload_count, 0); assert_eq!(pane.items.len(), 1); assert_eq!(pane.active_item().unwrap().id(), item2.id()); }); } struct TestItem { + save_count: usize, + save_as_count: usize, + reload_count: usize, is_dirty: bool, has_conflict: bool, - save_count: usize, - reload_count: usize, + can_save: bool, } impl TestItem { - fn new(is_dirty: bool, has_conflict: bool) -> Self { + fn new() -> Self { Self { save_count: 0, + save_as_count: 0, reload_count: 0, - is_dirty, - has_conflict, + is_dirty: false, + has_conflict: false, + can_save: true, } } } @@ -945,7 +1028,7 @@ mod tests { } fn can_save(&self, _: &AppContext) -> bool { - true + self.can_save } fn save( @@ -958,7 +1041,7 @@ mod tests { } fn can_save_as(&self, _: &AppContext) -> bool { - false + true } fn save_as( @@ -967,7 +1050,8 @@ mod tests { _: std::path::PathBuf, _: &mut ViewContext, ) -> Task> { - unreachable!() + self.save_as_count += 1; + Task::ready(Ok(())) } fn reload( From 089b0e8e0f195d95c04e47fd33f630a568a0bfb1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sun, 3 Apr 2022 13:00:39 +0200 Subject: [PATCH 35/68] Remove duplicate activation logic when removing items from pane --- crates/workspace/src/pane.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index afafe480c0..f8d145ea9a 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -543,15 +543,23 @@ impl Pane { this.update(&mut cx, |this, cx| { if let Some(item_ix) = this.items.iter().position(|i| i.id() == item.id()) { - this.items.remove(item_ix); if item_ix == this.active_item_index { - item.deactivated(cx); + if item_ix + 1 < this.items.len() { + this.activate_next_item(cx); + } else if item_ix > 0 { + this.activate_prev_item(cx); + } } + + let item = this.items.remove(item_ix); + if this.items.is_empty() { + item.deactivated(cx); + cx.emit(Event::Remove); + } + if item_ix < this.active_item_index { this.active_item_index -= 1; } - this.active_item_index = - cmp::min(this.active_item_index, this.items.len().saturating_sub(1)); let mut nav_history = this.nav_history.borrow_mut(); if let Some(path) = item.project_path(cx) { @@ -563,17 +571,7 @@ impl Pane { }); } - this.update(&mut cx, |this, cx| { - if this.items.is_empty() { - cx.emit(Event::Remove); - } else { - this.focus_active_item(cx); - this.activate(cx); - cx.emit(Event::ActivateItem { local: true }); - } - this.update_toolbar(cx); - cx.notify(); - }) + this.update(&mut cx, |_, cx| cx.notify()); }) } From dee416bdbe5abfa381a8e5bca7202abf4a3445a9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 4 Apr 2022 11:13:35 +0200 Subject: [PATCH 36/68] Avoid text insertion when holding down the `fn` key --- crates/gpui/src/platform/mac/event.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/gpui/src/platform/mac/event.rs b/crates/gpui/src/platform/mac/event.rs index 33f9f22e11..7170bd2fd5 100644 --- a/crates/gpui/src/platform/mac/event.rs +++ b/crates/gpui/src/platform/mac/event.rs @@ -30,6 +30,7 @@ impl Event { let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask); let shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask); let cmd = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask); + let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask); let unmodified_chars = CStr::from_ptr( native_event.charactersIgnoringModifiers().UTF8String() as *mut c_char, @@ -80,7 +81,7 @@ impl Event { NSF12FunctionKey => "f12", _ => { - if !cmd && !ctrl { + if !cmd && !ctrl && !function { input = Some( CStr::from_ptr( native_event.characters().UTF8String() as *mut c_char From 328be473e532e232bea2c0f15373a30f09924ea1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 4 Apr 2022 14:14:21 +0200 Subject: [PATCH 37/68] Rename `sub_mode` to `submode` Co-Authored-By: Nathan Sobo --- crates/vim/src/mode.rs | 6 +++--- crates/vim/src/normal/g_prefix.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/vim/src/mode.rs b/crates/vim/src/mode.rs index 2e5dc4ca2c..f00c14e2e8 100644 --- a/crates/vim/src/mode.rs +++ b/crates/vim/src/mode.rs @@ -52,15 +52,15 @@ pub enum NormalState { impl NormalState { pub fn set_context(&self, context: &mut Context) { - let sub_mode = match self { + let submode = match self { Self::GPrefix => Some("g"), _ => None, }; - if let Some(sub_mode) = sub_mode { + if let Some(submode) = submode { context .map - .insert("vim_sub_mode".to_string(), sub_mode.to_string()); + .insert("vim_submode".to_string(), submode.to_string()); } } } diff --git a/crates/vim/src/normal/g_prefix.rs b/crates/vim/src/normal/g_prefix.rs index 82510c0cf9..5b71089245 100644 --- a/crates/vim/src/normal/g_prefix.rs +++ b/crates/vim/src/normal/g_prefix.rs @@ -6,7 +6,7 @@ use crate::{mode::Mode, SwitchMode, VimState}; action!(MoveToStart); pub fn init(cx: &mut MutableAppContext) { - let context = Some("Editor && vim_mode == normal && vim_sub_mode == g"); + let context = Some("Editor && vim_mode == normal && vim_submode == g"); cx.add_bindings(vec![ Binding::new("g", MoveToStart, context), Binding::new("escape", SwitchMode(Mode::normal()), context), From cbf6d827db5df62acd691643e7b80193a2e7a6e1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 4 Apr 2022 15:09:31 +0200 Subject: [PATCH 38/68] v0.24.0 --- Cargo.lock | 2 +- crates/zed/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c64dd0ba7..c4a7112abd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5981,7 +5981,7 @@ checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" [[package]] name = "zed" -version = "0.23.0" +version = "0.24.0" dependencies = [ "anyhow", "async-compression", diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 68d23b44f8..2e1ef780ca 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] description = "The fast, collaborative code editor." edition = "2021" name = "zed" -version = "0.23.0" +version = "0.24.0" [lib] name = "zed" From 2aebb04a8482e842daf018dfec8c7f0edc9fa6a6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Mar 2022 13:08:00 -0600 Subject: [PATCH 39/68] Start on TypeScript-based styling system Co-Authored-By: Nate Butler <1714999+iamnbutler@users.noreply.github.com> --- .gitignore | 1 + styles/app.ts | 632 +++++++++++++++++++++++++++++++++++++++ styles/components.ts | 62 ++++ styles/core.ts | 38 +++ styles/package-lock.json | 28 ++ styles/package.json | 14 + styles/selector-modal.ts | 59 ++++ styles/theme.ts | 121 ++++++++ 8 files changed, 955 insertions(+) create mode 100644 styles/app.ts create mode 100644 styles/components.ts create mode 100644 styles/core.ts create mode 100644 styles/package-lock.json create mode 100644 styles/package.json create mode 100644 styles/selector-modal.ts create mode 100644 styles/theme.ts diff --git a/.gitignore b/.gitignore index e88434ce4e..140053fc2c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /zed.xcworkspace .DS_Store /script/node_modules +/styles/node_modules /crates/server/.env.toml /crates/server/static/styles.css /vendor/bin diff --git a/styles/app.ts b/styles/app.ts new file mode 100644 index 0000000000..a7ae4348be --- /dev/null +++ b/styles/app.ts @@ -0,0 +1,632 @@ +import { selectorModal } from "./selector-modal"; +import Theme from "./theme"; + +export default function app(theme: Theme): Object { + return { + selector: selectorModal(theme), + workspace: { + background: "$surface.500", + leaderBorderOpacity: 0.7, + leader_border_width: 2.0, + active_tab: { + background: "$surface.300", + extends: "$workspace.tab", + text: "$text.primary", + border: { + bottom: false, + }, + }, + left_sidebar: { + extends: "$workspace.sidebar", + border: { + color: "$border.primary", + right: true, + width: 1, + }, + }, + pane_divider: { + color: "$border.primary", + width: 1, + }, + right_sidebar: { + extends: "$workspace.sidebar", + border: { + color: "$border.primary", + left: true, + width: 1, + }, + }, + sidebar: { + width: 30, + active_item: { + extends: "$workspace.sidebar.item", + icon_color: "$text.primary.color", + }, + border: { + color: "$border.primary", + right: true, + width: 1, + }, + item: { + height: "$workspace.tab.height", + icon_color: "$text.muted.color", + icon_size: 18, + }, + resize_handle: { + background: "$border.primary", + padding: { + left: 1, + }, + }, + }, + status_bar: { + cursor_position: "$text.muted", + diagnostic_message: "$text.muted", + height: 24, + item_spacing: 8, + lsp_message: "$text.muted", + padding: { + left: 6, + right: 6, + }, + }, + tab: { + height: 34, + icon_close: "$text.muted.color", + icon_close_active: "$text.primary.color", + icon_conflict: "$status.warn", + icon_dirty: "$status.info", + icon_width: 8, + spacing: 10, + text: "$text.muted", + border: { + bottom: true, + color: "$border.primary", + left: true, + overlay: true, + width: 1, + }, + padding: { + left: 12, + right: 12, + }, + }, + titlebar: { + avatar_width: 18, + height: 32, + share_icon_active_color: "$text.primary.color", + share_icon_color: "$text.muted.color", + title: "$text.primary", + avatar: { + corner_radius: 10, + border: { + color: "#00000088", + width: 1, + }, + }, + avatar_ribbon: { + background: "#ff0000", + height: 3, + width: 12, + }, + border: { + bottom: true, + color: "$border.primary", + width: 1, + }, + hovered_sign_in_prompt: { + color: "$text.secondary.color", + extends: "$workspace.titlebar.sign_in_prompt", + }, + offline_icon: { + color: "$text.muted.color", + width: 16, + padding: { + right: 4, + }, + }, + outdated_warning: { + extends: "$text.muted", + size: 13, + }, + sign_in_prompt: { + extends: "$text.muted", + size: 13, + underline: true, + padding: { + right: 8, + }, + }, + }, + toolbar: { + height: 44, + }, + }, + chat_panel: { + extends: "$panel", + channel_name: { + extends: "$text.primary", + weight: "bold", + }, + channel_name_hash: { + text: "$text.muted", + padding: { + right: 8, + }, + }, + channel_select: { + active_item: { + extends: "$chat_panel.channel_select.item", + name: "$text.primary", + }, + header: { + extends: "$chat_panel.channel_select.active_item", + padding: { + bottom: 4, + left: 0, + }, + }, + hovered_active_item: { + extends: "$chat_panel.channel_select.hovered_item", + name: "$text.primary", + }, + hovered_item: { + background: "$state.hover", + corner_radius: 6, + extends: "$chat_panel.channel_select.item", + }, + item: { + name: "$text.secondary", + padding: 4, + hash: { + extends: "$text.muted", + margin: { + right: 8, + }, + }, + }, + menu: { + background: "$surface.500", + corner_radius: 6, + padding: 4, + border: { + color: "$border.primary", + width: 1, + }, + shadow: { + blur: 16, + color: "$shadow.0", + offset: [0, 2], + }, + }, + }, + hovered_sign_in_prompt: { + color: "$text.secondary.color", + extends: "$chat_panel.sign_in_prompt", + }, + input_editor: { + background: "$surface.300", + corner_radius: 6, + placeholder_text: "$text.muted", + selection: "$selection.host", + text: "$text.primary", + border: { + color: "$border.primary", + width: 1, + }, + padding: { + bottom: 7, + left: 8, + right: 8, + top: 7, + }, + }, + message: { + body: "$text.secondary", + timestamp: "$text.muted", + padding: { + bottom: 6, + }, + sender: { + extends: "$text.primary", + weight: "bold", + margin: { + right: 8, + }, + }, + }, + pending_message: { + extends: "$chat_panel.message", + body: { + color: "$text.muted.color", + }, + sender: { + color: "$text.muted.color", + }, + timestamp: { + color: "$text.muted.color", + }, + }, + sign_in_prompt: { + extends: "$text.primary", + underline: true, + }, + }, + contacts_panel: { + extends: "$panel", + host_row_height: 28, + tree_branch_color: "$surface.100", + tree_branch_width: 1, + host_avatar: { + corner_radius: 10, + width: 18, + }, + host_username: { + extends: "$text.primary", + padding: { + left: 8, + }, + }, + hovered_shared_project: { + background: "$state.hover", + corner_radius: 6, + extends: "$contacts_panel.shared_project", + }, + hovered_unshared_project: { + background: "$state.hover", + corner_radius: 6, + extends: "$contacts_panel.unshared_project", + }, + project: { + guest_avatar_spacing: 4, + height: 24, + guest_avatar: { + corner_radius: 8, + width: 14, + }, + name: { + extends: "$text.secondary", + margin: { + right: 6, + }, + }, + padding: { + left: 8, + }, + }, + shared_project: { + extends: "$contacts_panel.project", + name: { + color: "$text.primary.color", + }, + }, + unshared_project: { + extends: "$contacts_panel.project", + }, + }, + editor: { + active_line_background: "$state.active_line", + background: "$surface.300", + code_actions_indicator: "$text.muted.color", + diff_background_deleted: "$state.deleted_line", + diff_background_inserted: "$state.inserted_line", + document_highlight_read_background: "#99999920", + document_highlight_write_background: "#99999916", + error_color: "$status.bad", + guest_selections: "$selection.guests", + gutter_background: "$surface.300", + gutter_padding_factor: 2.5, + highlighted_line_background: "$state.highlighted_line", + line_number: "$text.muted.color", + line_number_active: "$text.primary.color", + rename_fade: 0.6, + selection: "$selection.host", + text_color: "$text.secondary.color", + unnecessary_code_fade: 0.5, + autocomplete: { + background: "$surface.100", + corner_radius: 6, + padding: 6, + border: { + color: "$border.secondary", + width: 2, + }, + hovered_item: { + background: "$state.hover", + extends: "$editor.autocomplete.item", + }, + item: { + corner_radius: 6, + padding: { + bottom: 2, + left: 6, + right: 6, + top: 2, + }, + }, + margin: { + left: -14, + }, + match_highlight: { + color: "$editor.syntax.keyword.color", + weight: "$editor.syntax.keyword.weight", + }, + selected_item: { + background: "$state.selected", + extends: "$editor.autocomplete.item", + }, + }, + diagnostic_header: { + background: "$editor.background", + icon_width_factor: 1.5, + text_scale_factor: 0.857, + border: { + bottom: true, + color: "$border.secondary", + top: true, + width: 1, + }, + code: { + extends: "$text.muted", + size: 14, + margin: { + left: 10, + }, + }, + message: { + highlight_text: { + extends: "$text.primary", + size: 14, + weight: "bold", + }, + text: { + extends: "$text.secondary", + size: 14, + }, + }, + }, + diagnostic_path_header: { + background: "$state.active_line", + text_scale_factor: 0.857, + filename: { + extends: "$text.primary", + size: 14, + }, + path: { + extends: "$text.muted", + size: 14, + margin: { + left: 12, + }, + }, + }, + error_diagnostic: { + text_scale_factor: 0.857, + header: { + border: { + color: "$border.primary", + top: true, + width: 1, + }, + }, + message: { + highlight_text: { + color: "$status.bad", + extends: "$text.secondary", + size: 14, + weight: "bold", + }, + text: { + color: "$status.bad", + extends: "$text.secondary", + size: 14, + }, + }, + }, + hint_diagnostic: { + extends: "$editor.error_diagnostic", + message: { + highlight_text: { + color: "$status.info", + }, + text: { + color: "$status.info", + }, + }, + }, + information_diagnostic: { + extends: "$editor.error_diagnostic", + message: { + highlight_text: { + color: "$status.info", + }, + text: { + color: "$status.info", + }, + }, + }, + invalid_error_diagnostic: { + extends: "$editor.error_diagnostic", + message: { + highlight_text: { + color: "$text.muted.color", + }, + text: { + color: "$text.muted.color", + }, + }, + }, + invalid_hint_diagnostic: { + extends: "$editor.hint_diagnostic", + message: { + highlight_text: { + color: "$text.muted.color", + }, + text: { + color: "$text.muted.color", + }, + }, + }, + invalid_information_diagnostic: { + extends: "$editor.information_diagnostic", + message: { + highlight_text: { + color: "$text.muted.color", + }, + text: { + color: "$text.muted.color", + }, + }, + }, + invalid_warning_diagnostic: { + extends: "$editor.warning_diagnostic", + message: { + highlight_text: { + color: "$text.muted.color", + }, + text: { + color: "$text.muted.color", + }, + }, + }, + warning_diagnostic: { + extends: "$editor.error_diagnostic", + message: { + highlight_text: { + color: "$status.warn", + }, + text: { + color: "$status.warn", + }, + }, + }, + }, + project_diagnostics: { + background: "$surface.300", + tab_icon_spacing: 4, + tab_icon_width: 13, + tab_summary_spacing: 10, + empty_message: { + extends: "$text.primary", + size: 18, + }, + status_bar_item: { + extends: "$text.muted", + margin: { + right: 10, + }, + }, + }, + project_panel: { + extends: "$panel", + entry: { + height: 22, + icon_color: "$text.muted.color", + icon_size: 8, + icon_spacing: 8, + text: "$text.secondary", + }, + hovered_entry: { + background: "$state.hover", + extends: "$project_panel.entry", + }, + hovered_selected_entry: { + extends: "$project_panel.hovered_entry", + text: { + extends: "$text.primary", + }, + }, + padding: { + top: 6, + }, + selected_entry: { + extends: "$project_panel.entry", + text: { + extends: "$text.primary", + }, + }, + }, + search: { + background: "$surface.300", + match_background: "$state.highlighted_line", + tab_icon_spacing: 4, + tab_icon_width: 14, + active_hovered_option_button: { + background: "$surface.100", + extends: "$search.option_button", + }, + active_option_button: { + background: "$surface.100", + extends: "$search.option_button", + }, + editor: { + background: "$surface.500", + corner_radius: 6, + max_width: 400, + placeholder_text: "$text.muted", + selection: "$selection.host", + text: "$text.primary", + border: { + color: "$border.primary", + width: 1, + }, + margin: { + bottom: 5, + left: 5, + right: 5, + top: 5, + }, + padding: { + bottom: 3, + left: 13, + right: 13, + top: 3, + }, + }, + hovered_option_button: { + background: "$surface.100", + extends: "$search.option_button", + }, + invalid_editor: { + extends: "$search.editor", + border: { + color: "$status.bad", + width: 1, + }, + }, + match_index: { + extends: "$text.secondary", + padding: 6, + }, + option_button: { + background: "$surface.300", + corner_radius: 6, + extends: "$text.secondary", + border: { + color: "$border.primary", + width: 1, + }, + margin: { + left: 1, + right: 1, + }, + padding: { + bottom: 1, + left: 6, + right: 6, + top: 1, + }, + }, + option_button_group: { + padding: { + left: 2, + right: 2, + }, + }, + results_status: { + extends: "$text.primary", + size: 18, + }, + }, + }; +} diff --git a/styles/components.ts b/styles/components.ts new file mode 100644 index 0000000000..226d1d9e37 --- /dev/null +++ b/styles/components.ts @@ -0,0 +1,62 @@ +import chroma from "chroma-js"; +import core, { Color } from "./core"; +import Theme, { BackgroundColor, Weight } from "./theme"; + +export function text( + theme: Theme, + fontFamily: keyof typeof core.fontFamily, + color: keyof Theme["textColor"], + properties?: { size?: keyof typeof core["fontSize"]; weight?: Weight } +) { + const sizeKey = properties.size || fontFamily === "sans" ? "sm" : "md"; + const size = core.fontSize[sizeKey].value; + + return { + family: core.fontFamily[fontFamily], + color: theme.textColor[color].value, + ...properties, + size, + }; +} + +export function border(theme: Theme, color: keyof Theme["borderColor"]) { + return { + color: theme.borderColor[color].value, + width: 1, + }; +} + +export interface Player { + selection: { + cursor: Color; + selection: Color; + }; +} + +export function player( + theme: Theme, + playerNumber: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 +): Player { + return { + selection: { + cursor: theme.player[playerNumber].cursorColor.value, + selection: theme.player[playerNumber].selectionColor.value, + }, + }; +} + +export function backgroundColor( + theme: Theme, + name: keyof Theme["backgroundColor"], + state?: keyof BackgroundColor +): Color { + return theme.backgroundColor[name][state || "base"].value; +} + +export function shadow(theme) { + return { + blur: 16, + color: chroma("black").alpha(theme.shadowAlpha.value).hex(), + offset: [0, 2], + }; +} diff --git a/styles/core.ts b/styles/core.ts new file mode 100644 index 0000000000..6c63b2285e --- /dev/null +++ b/styles/core.ts @@ -0,0 +1,38 @@ +export type Color = string; + +export default { + fontFamily: { + sans: "Zed Sans", + mono: "Zed Mono", + }, + fontSize: { + "3xs": { + value: "8", + type: "fontSizes", + }, + "2xs": { + value: "10", + type: "fontSizes", + }, + xs: { + value: "12", + type: "fontSizes", + }, + sm: { + value: "14", + type: "fontSizes", + }, + md: { + value: "16", + type: "fontSizes", + }, + lg: { + value: "18", + type: "fontSizes", + }, + xl: { + value: "20", + type: "fontSizes", + }, + }, +}; diff --git a/styles/package-lock.json b/styles/package-lock.json new file mode 100644 index 0000000000..3abb465628 --- /dev/null +++ b/styles/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "styles", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "styles", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "chroma-js": "^2.4.2" + } + }, + "node_modules/chroma-js": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", + "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==" + } + }, + "dependencies": { + "chroma-js": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", + "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==" + } + } +} diff --git a/styles/package.json b/styles/package.json new file mode 100644 index 0000000000..92f0546c56 --- /dev/null +++ b/styles/package.json @@ -0,0 +1,14 @@ +{ + "name": "styles", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "chroma-js": "^2.4.2" + } +} diff --git a/styles/selector-modal.ts b/styles/selector-modal.ts new file mode 100644 index 0000000000..f7101c9151 --- /dev/null +++ b/styles/selector-modal.ts @@ -0,0 +1,59 @@ +import { backgroundColor, border, player, shadow, text } from "./components"; +import Theme from "./theme"; + +export function selectorModal(theme: Theme): Object { + const item = { + padding: { + bottom: 4, + left: 16, + right: 16, + top: 4, + }, + cornerRadius: 6, + text: text(theme, "sans", "secondary"), + highlightText: text(theme, "sans", "feature", { weight: "bold" }), + }; + + const activeItem = { + ...item, + background: backgroundColor(theme, 500, "active"), + text: text(theme, "sans", "primary"), + }; + + return { + background: backgroundColor(theme, 500), + cornerRadius: 6, + padding: 8, + item, + activeItem, + border: border(theme, "primary"), + empty: { + text: text(theme, "sans", "muted"), + padding: { + bottom: 4, + left: 16, + right: 16, + top: 8, + }, + }, + inputEditor: { + background: backgroundColor(theme, 300), + corner_radius: 6, + placeholderText: text(theme, "sans", "placeholder"), + selection: player(theme, 1).selection, + text: text(theme, "mono", "primary"), + border: border(theme, "primary"), + padding: { + bottom: 7, + left: 16, + right: 16, + top: 7, + }, + }, + margin: { + bottom: 52, + top: 52, + }, + shadow: shadow(theme), + }; +} diff --git a/styles/theme.ts b/styles/theme.ts new file mode 100644 index 0000000000..5363a8c01c --- /dev/null +++ b/styles/theme.ts @@ -0,0 +1,121 @@ +export type Color = string; +export type Weight = + | "thin" + | "extra_light" + | "light" + | "normal" + | "medium" + | "semibold" + | "bold" + | "extra_bold" + | "black"; + +interface SyntaxHighlightStyle { + color: { value: Color }; + weight: { value: Weight }; +} + +interface Player { + baseColor: { + value: Color; + }; + cursorColor: { + value: Color; + }; + selectionColor: { + value: Color; + }; + borderColor: { + value: Color; + }; +} + +export interface BackgroundColor { + base: { + value: Color; + }; + hover: { + value: Color; + }; + active: { + value: Color; + }; + focused: { + value: Color; + }; +} + +export default interface Theme { + backgroundColor: { + 100: BackgroundColor; + 300: BackgroundColor; + 500: BackgroundColor; + }; + borderColor: { + primary: { + value: Color; + }; + secondary: { + value: Color; + }; + muted: { + value: Color; + }; + focused: { + value: Color; + }; + active: { + value: Color; + }; + }; + textColor: { + primary: { + value: Color; + }; + secondary: { + value: Color; + }; + muted: { + value: Color; + }; + placeholder: { + value: Color; + }; + active: { + value: Color; + }; + feature: { + value: Color; + }; + }; + syntax: { + primary: SyntaxHighlightStyle; + comment: SyntaxHighlightStyle; + punctuation: SyntaxHighlightStyle; + constant: SyntaxHighlightStyle; + keyword: SyntaxHighlightStyle; + function: SyntaxHighlightStyle; + type: SyntaxHighlightStyle; + variant: SyntaxHighlightStyle; + property: SyntaxHighlightStyle; + enum: SyntaxHighlightStyle; + operator: SyntaxHighlightStyle; + string: SyntaxHighlightStyle; + number: SyntaxHighlightStyle; + boolean: SyntaxHighlightStyle; + predictive: SyntaxHighlightStyle; + }; + player: { + 1: Player; + 2: Player; + 3: Player; + 4: Player; + 5: Player; + 6: Player; + 7: Player; + 8: Player; + }; + shadowAlpha: { + value: number; + }; +} From bfce4a61041e7353492cd5f6ca61d235addb142a Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 29 Mar 2022 15:33:03 -0400 Subject: [PATCH 40/68] WIP: Add `rose` color tokens to `core.ts` --- styles/core.ts | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/styles/core.ts b/styles/core.ts index 6c63b2285e..164b6dba00 100644 --- a/styles/core.ts +++ b/styles/core.ts @@ -1,6 +1,51 @@ +import chroma from "chroma-js"; + export type Color = string; +function getColorRamp(colorName, baseColor, steps = 10) { + let hsl = chroma(baseColor).hsl(); + let h = Math.round(hsl[0]); + let lightColor = chroma.hsl(h, 0.88, 0.96).hex(); + let darkColor = chroma.hsl(h, 0.68, 0.32).hex(); + + let ramp = chroma + .scale([lightColor, baseColor, darkColor]) + .domain([0, 0.5, 1]) + .mode("hsl") + .gamma(1) + .correctLightness(true) + .padding([0, 0.15]) + .colors(steps); + + let tokens = {}; + let token = {}; + let colorNumber = 0; + + for (let i = 0; i < steps; i++) { + if (i !== 0) { + colorNumber = i * 100; + } + + token = { + [`${colorName}_${colorNumber}`]: { + value: ramp[i].value, + rootValue: baseColor, + step: i, + type: "color", + }, + }; + + Object.assign(token, tokens); + } + + return tokens; +} + export default { + color: { + rose: getColorRamp("rose", "#F43F5E", 10), + }, + fontFamily: { sans: "Zed Sans", mono: "Zed Mono", From 1f71e742c5834ac08a58e4be014df92d238554c3 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 29 Mar 2022 17:10:46 -0400 Subject: [PATCH 41/68] WIP: Color WIP --- styles/core.color.ts | 93 ++++++++++++++++++++++++++++++++++++++++++++ styles/core.ts | 45 +-------------------- 2 files changed, 95 insertions(+), 43 deletions(-) create mode 100644 styles/core.color.ts diff --git a/styles/core.color.ts b/styles/core.color.ts new file mode 100644 index 0000000000..004e7209a2 --- /dev/null +++ b/styles/core.color.ts @@ -0,0 +1,93 @@ +import chroma from "chroma-js"; + +export type Color = string; + +function returnTokens( + colorName: string, + ramp: Array, // help, have no clue on type here +) { + let tokens = {}; + let token = {}; + let colorNumber = 0; + let increment = 0; + + for (let i = 0; i < ramp.len; i++) { + if (i > 11 ) { + increment = 50; + } else { + increment = 100; + } + + if (i !== 0) { + colorNumber = i * increment; + } + + token = { + [`${colorName}_${colorNumber}`]: { + value: ramp[i].value, + step: i, + type: "color", + }, + }; + + Object.assign(token, tokens); + } + return tokens; +} + +function oneColorRamp( + colorName: string, + baseColor: string, + steps: number = 10 +) { + let hsl = chroma(baseColor).hsl(); + let h = Math.round(hsl[0]); + let lightColor = chroma.hsl(h, 0.88, 0.96).hex(); + let darkColor = chroma.hsl(h, 0.68, 0.32).hex(); + + let ramp = chroma + .scale([lightColor, baseColor, darkColor]) + .domain([0, 0.5, 1]) + .mode("hsl") + .gamma(1) + .correctLightness(true) + .padding([0, 0.15]) + .colors(steps) + .hex(); + + return returnTokens(colorName, ramp); +} + +function colorRamp( + colorName: string, + startColor: string, + endColor: string, + steps: number +) { + let ramp = chroma.scale([startColor, endColor]).mode("hsl").colors(steps).hex(); + + return returnTokens(colorName, ramp); +} + +export default { + color: { + neutral: colorRamp("neutral", "black", "white", 21), // colorName, startColor, endColor, steps + rose: oneColorRamp("rose", "#F43F5EFF"), // colorName, baseColor, steps(optional) + red: oneColorRamp("red", "#EF4444FF"), + orange: oneColorRamp("orange", "#F97316FF"), + amber: oneColorRamp("amber", "#F59E0BFF"), + yellow: oneColorRamp("yellow", "#EAB308FF"), + lime: oneColorRamp("lime", "#84CC16FF"), + green: oneColorRamp("green", "#22C55EFF"), + emerald: oneColorRamp("emerald", "#10B981FF"), + teal: oneColorRamp("teal", "#14B8A6FF"), + cyan: oneColorRamp("cyan", "#06BBD4FF"), + sky: oneColorRamp("sky", "#0EA5E9FF"), + blue: oneColorRamp("blue", "#3B82F6FF"), + indigo: oneColorRamp("indigo", "#6366F1FF"), + violet: oneColorRamp("violet", "#8B5CF6FF"), + purple: oneColorRamp("purple", "#A855F7FF"), + fuschia: oneColorRamp("fuschia", "#D946E4FF"), + pink: oneColorRamp("pink", "#EC4899FF"), + }, +}; diff --git a/styles/core.ts b/styles/core.ts index 164b6dba00..6444ef9a1c 100644 --- a/styles/core.ts +++ b/styles/core.ts @@ -1,50 +1,9 @@ -import chroma from "chroma-js"; +import color from "./core.color"; export type Color = string; -function getColorRamp(colorName, baseColor, steps = 10) { - let hsl = chroma(baseColor).hsl(); - let h = Math.round(hsl[0]); - let lightColor = chroma.hsl(h, 0.88, 0.96).hex(); - let darkColor = chroma.hsl(h, 0.68, 0.32).hex(); - - let ramp = chroma - .scale([lightColor, baseColor, darkColor]) - .domain([0, 0.5, 1]) - .mode("hsl") - .gamma(1) - .correctLightness(true) - .padding([0, 0.15]) - .colors(steps); - - let tokens = {}; - let token = {}; - let colorNumber = 0; - - for (let i = 0; i < steps; i++) { - if (i !== 0) { - colorNumber = i * 100; - } - - token = { - [`${colorName}_${colorNumber}`]: { - value: ramp[i].value, - rootValue: baseColor, - step: i, - type: "color", - }, - }; - - Object.assign(token, tokens); - } - - return tokens; -} - export default { - color: { - rose: getColorRamp("rose", "#F43F5E", 10), - }, + color: color, fontFamily: { sans: "Zed Sans", From 8b33a58076e5a0c2b41a58f2e34d5c9a6ebe5310 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Mar 2022 16:28:19 -0600 Subject: [PATCH 42/68] Express workspace in terms of new components Co-Authored-By: Nate Butler <1714999+iamnbutler@users.noreply.github.com> --- styles/app.ts | 155 +++------------------------------------ styles/components.ts | 23 +++++- styles/core.color.ts | 93 ----------------------- styles/core.ts | 26 +++++-- styles/lib.ts | 44 +++++++++++ styles/package-lock.json | 11 +++ styles/package.json | 1 + styles/selector-modal.ts | 2 +- styles/theme.ts | 46 ++++++++++++ styles/workspace.ts | 133 +++++++++++++++++++++++++++++++++ 10 files changed, 288 insertions(+), 246 deletions(-) delete mode 100644 styles/core.color.ts create mode 100644 styles/lib.ts create mode 100644 styles/workspace.ts diff --git a/styles/app.ts b/styles/app.ts index a7ae4348be..4f40577ae9 100644 --- a/styles/app.ts +++ b/styles/app.ts @@ -1,147 +1,12 @@ -import { selectorModal } from "./selector-modal"; +import { backgroundColor } from "./components"; +import selectorModal from "./selector-modal"; +import workspace from "./workspace"; import Theme from "./theme"; export default function app(theme: Theme): Object { return { selector: selectorModal(theme), - workspace: { - background: "$surface.500", - leaderBorderOpacity: 0.7, - leader_border_width: 2.0, - active_tab: { - background: "$surface.300", - extends: "$workspace.tab", - text: "$text.primary", - border: { - bottom: false, - }, - }, - left_sidebar: { - extends: "$workspace.sidebar", - border: { - color: "$border.primary", - right: true, - width: 1, - }, - }, - pane_divider: { - color: "$border.primary", - width: 1, - }, - right_sidebar: { - extends: "$workspace.sidebar", - border: { - color: "$border.primary", - left: true, - width: 1, - }, - }, - sidebar: { - width: 30, - active_item: { - extends: "$workspace.sidebar.item", - icon_color: "$text.primary.color", - }, - border: { - color: "$border.primary", - right: true, - width: 1, - }, - item: { - height: "$workspace.tab.height", - icon_color: "$text.muted.color", - icon_size: 18, - }, - resize_handle: { - background: "$border.primary", - padding: { - left: 1, - }, - }, - }, - status_bar: { - cursor_position: "$text.muted", - diagnostic_message: "$text.muted", - height: 24, - item_spacing: 8, - lsp_message: "$text.muted", - padding: { - left: 6, - right: 6, - }, - }, - tab: { - height: 34, - icon_close: "$text.muted.color", - icon_close_active: "$text.primary.color", - icon_conflict: "$status.warn", - icon_dirty: "$status.info", - icon_width: 8, - spacing: 10, - text: "$text.muted", - border: { - bottom: true, - color: "$border.primary", - left: true, - overlay: true, - width: 1, - }, - padding: { - left: 12, - right: 12, - }, - }, - titlebar: { - avatar_width: 18, - height: 32, - share_icon_active_color: "$text.primary.color", - share_icon_color: "$text.muted.color", - title: "$text.primary", - avatar: { - corner_radius: 10, - border: { - color: "#00000088", - width: 1, - }, - }, - avatar_ribbon: { - background: "#ff0000", - height: 3, - width: 12, - }, - border: { - bottom: true, - color: "$border.primary", - width: 1, - }, - hovered_sign_in_prompt: { - color: "$text.secondary.color", - extends: "$workspace.titlebar.sign_in_prompt", - }, - offline_icon: { - color: "$text.muted.color", - width: 16, - padding: { - right: 4, - }, - }, - outdated_warning: { - extends: "$text.muted", - size: 13, - }, - sign_in_prompt: { - extends: "$text.muted", - size: 13, - underline: true, - padding: { - right: 8, - }, - }, - }, - toolbar: { - height: 44, - }, - }, + workspace: workspace(theme), chat_panel: { extends: "$panel", channel_name: { @@ -205,7 +70,7 @@ export default function app(theme: Theme): Object { extends: "$chat_panel.sign_in_prompt", }, input_editor: { - background: "$surface.300", + background: backgroundColor(theme, 300), corner_radius: 6, placeholder_text: "$text.muted", selection: "$selection.host", @@ -306,7 +171,7 @@ export default function app(theme: Theme): Object { }, editor: { active_line_background: "$state.active_line", - background: "$surface.300", + background: backgroundColor(theme, 300), code_actions_indicator: "$text.muted.color", diff_background_deleted: "$state.deleted_line", diff_background_inserted: "$state.inserted_line", @@ -314,7 +179,7 @@ export default function app(theme: Theme): Object { document_highlight_write_background: "#99999916", error_color: "$status.bad", guest_selections: "$selection.guests", - gutter_background: "$surface.300", + gutter_background: backgroundColor(theme, 300), gutter_padding_factor: 2.5, highlighted_line_background: "$state.highlighted_line", line_number: "$text.muted.color", @@ -502,7 +367,7 @@ export default function app(theme: Theme): Object { }, }, project_diagnostics: { - background: "$surface.300", + background: backgroundColor(theme, 300), tab_icon_spacing: 4, tab_icon_width: 13, tab_summary_spacing: 10, @@ -547,7 +412,7 @@ export default function app(theme: Theme): Object { }, }, search: { - background: "$surface.300", + background: backgroundColor(theme, 300), match_background: "$state.highlighted_line", tab_icon_spacing: 4, tab_icon_width: 14, @@ -599,7 +464,7 @@ export default function app(theme: Theme): Object { padding: 6, }, option_button: { - background: "$surface.300", + background: backgroundColor(theme, 300), corner_radius: 6, extends: "$text.secondary", border: { diff --git a/styles/components.ts b/styles/components.ts index 226d1d9e37..9cc58046ff 100644 --- a/styles/components.ts +++ b/styles/components.ts @@ -1,5 +1,6 @@ import chroma from "chroma-js"; -import core, { Color } from "./core"; +import core from "./core"; +import { Color } from "./lib"; import Theme, { BackgroundColor, Weight } from "./theme"; export function text( @@ -19,13 +20,31 @@ export function text( }; } -export function border(theme: Theme, color: keyof Theme["borderColor"]) { +export interface BorderOptions { + width?: number; + top?: boolean; + bottom?: boolean; + left?: boolean; + right?: boolean; + overlay?: boolean; +} + +export function border( + theme: Theme, + color: keyof Theme["borderColor"], + options?: BorderOptions +) { return { color: theme.borderColor[color].value, width: 1, + ...options, }; } +export function iconColor(theme: Theme, color: keyof Theme["iconColor"]) { + return theme.iconColor[color].value; +} + export interface Player { selection: { cursor: Color; diff --git a/styles/core.color.ts b/styles/core.color.ts deleted file mode 100644 index 004e7209a2..0000000000 --- a/styles/core.color.ts +++ /dev/null @@ -1,93 +0,0 @@ -import chroma from "chroma-js"; - -export type Color = string; - -function returnTokens( - colorName: string, - ramp: Array, // help, have no clue on type here -) { - let tokens = {}; - let token = {}; - let colorNumber = 0; - let increment = 0; - - for (let i = 0; i < ramp.len; i++) { - if (i > 11 ) { - increment = 50; - } else { - increment = 100; - } - - if (i !== 0) { - colorNumber = i * increment; - } - - token = { - [`${colorName}_${colorNumber}`]: { - value: ramp[i].value, - step: i, - type: "color", - }, - }; - - Object.assign(token, tokens); - } - return tokens; -} - -function oneColorRamp( - colorName: string, - baseColor: string, - steps: number = 10 -) { - let hsl = chroma(baseColor).hsl(); - let h = Math.round(hsl[0]); - let lightColor = chroma.hsl(h, 0.88, 0.96).hex(); - let darkColor = chroma.hsl(h, 0.68, 0.32).hex(); - - let ramp = chroma - .scale([lightColor, baseColor, darkColor]) - .domain([0, 0.5, 1]) - .mode("hsl") - .gamma(1) - .correctLightness(true) - .padding([0, 0.15]) - .colors(steps) - .hex(); - - return returnTokens(colorName, ramp); -} - -function colorRamp( - colorName: string, - startColor: string, - endColor: string, - steps: number -) { - let ramp = chroma.scale([startColor, endColor]).mode("hsl").colors(steps).hex(); - - return returnTokens(colorName, ramp); -} - -export default { - color: { - neutral: colorRamp("neutral", "black", "white", 21), // colorName, startColor, endColor, steps - rose: oneColorRamp("rose", "#F43F5EFF"), // colorName, baseColor, steps(optional) - red: oneColorRamp("red", "#EF4444FF"), - orange: oneColorRamp("orange", "#F97316FF"), - amber: oneColorRamp("amber", "#F59E0BFF"), - yellow: oneColorRamp("yellow", "#EAB308FF"), - lime: oneColorRamp("lime", "#84CC16FF"), - green: oneColorRamp("green", "#22C55EFF"), - emerald: oneColorRamp("emerald", "#10B981FF"), - teal: oneColorRamp("teal", "#14B8A6FF"), - cyan: oneColorRamp("cyan", "#06BBD4FF"), - sky: oneColorRamp("sky", "#0EA5E9FF"), - blue: oneColorRamp("blue", "#3B82F6FF"), - indigo: oneColorRamp("indigo", "#6366F1FF"), - violet: oneColorRamp("violet", "#8B5CF6FF"), - purple: oneColorRamp("purple", "#A855F7FF"), - fuschia: oneColorRamp("fuschia", "#D946E4FF"), - pink: oneColorRamp("pink", "#EC4899FF"), - }, -}; diff --git a/styles/core.ts b/styles/core.ts index 6444ef9a1c..e9e81982e4 100644 --- a/styles/core.ts +++ b/styles/core.ts @@ -1,10 +1,6 @@ -import color from "./core.color"; - -export type Color = string; +import { colorRamp } from "./lib"; export default { - color: color, - fontFamily: { sans: "Zed Sans", mono: "Zed Mono", @@ -39,4 +35,24 @@ export default { type: "fontSizes", }, }, + color: { + neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }), + rose: colorRamp("#F43F5EFF"), + red: colorRamp("#EF4444FF"), + orange: colorRamp("#F97316FF"), + amber: colorRamp("#F59E0BFF"), + yellow: colorRamp("#EAB308FF"), + lime: colorRamp("#84CC16FF"), + green: colorRamp("#22C55EFF"), + emerald: colorRamp("#10B981FF"), + teal: colorRamp("#14B8A6FF"), + cyan: colorRamp("#06BBD4FF"), + sky: colorRamp("#0EA5E9FF"), + blue: colorRamp("#3B82F6FF"), + indigo: colorRamp("#6366F1FF"), + violet: colorRamp("#8B5CF6FF"), + purple: colorRamp("#A855F7FF"), + fuschia: colorRamp("#D946E4FF"), + pink: colorRamp("#EC4899FF"), + }, }; diff --git a/styles/lib.ts b/styles/lib.ts new file mode 100644 index 0000000000..b59f4fa694 --- /dev/null +++ b/styles/lib.ts @@ -0,0 +1,44 @@ +import chroma, { Scale } from "chroma-js"; + +export type Color = string; +export type ColorRampStep = { value: Color; type: "color"; step: number }; +export type ColorRamp = { + [index: number]: ColorRampStep; +}; + +export function colorRamp( + color: Color | [Color, Color], + options?: { steps?: number; increment?: number } +): ColorRamp { + let scale: Scale; + if (Array.isArray(color)) { + const [startColor, endColor] = color; + scale = chroma.scale([startColor, endColor]); + } else { + let hue = Math.round(chroma(color).hsl()[0]); + let startColor = chroma.hsl(hue, 0.88, 0.96); + let endColor = chroma.hsl(hue, 0.68, 0.32); + scale = chroma + .scale([startColor, color, endColor]) + .domain([0, 0.5, 1]) + .mode("hsl") + .gamma(1) + .correctLightness(true) + .padding([0, 0.15]); + } + + const ramp: ColorRamp = {}; + const steps = options?.steps || 10; + const increment = options?.increment || 100; + + scale.colors(steps, "hex").forEach((color, ix) => { + const step = ix * increment; + ramp[step] = { + value: color, + step, + type: "color", + }; + }); + + return ramp; +} diff --git a/styles/package-lock.json b/styles/package-lock.json index 3abb465628..7b8503bf72 100644 --- a/styles/package-lock.json +++ b/styles/package-lock.json @@ -9,9 +9,15 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@types/chroma-js": "^2.1.3", "chroma-js": "^2.4.2" } }, + "node_modules/@types/chroma-js": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz", + "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g==" + }, "node_modules/chroma-js": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", @@ -19,6 +25,11 @@ } }, "dependencies": { + "@types/chroma-js": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz", + "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g==" + }, "chroma-js": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", diff --git a/styles/package.json b/styles/package.json index 92f0546c56..c66da8718b 100644 --- a/styles/package.json +++ b/styles/package.json @@ -9,6 +9,7 @@ "author": "", "license": "ISC", "dependencies": { + "@types/chroma-js": "^2.1.3", "chroma-js": "^2.4.2" } } diff --git a/styles/selector-modal.ts b/styles/selector-modal.ts index f7101c9151..ddba32683a 100644 --- a/styles/selector-modal.ts +++ b/styles/selector-modal.ts @@ -1,7 +1,7 @@ import { backgroundColor, border, player, shadow, text } from "./components"; import Theme from "./theme"; -export function selectorModal(theme: Theme): Object { +export default function selectorModal(theme: Theme): Object { const item = { padding: { bottom: 4, diff --git a/styles/theme.ts b/styles/theme.ts index 5363a8c01c..ddfa6414f4 100644 --- a/styles/theme.ts +++ b/styles/theme.ts @@ -1,3 +1,5 @@ +import { colorRamp } from "./lib"; + export type Color = string; export type Weight = | "thin" @@ -87,6 +89,50 @@ export default interface Theme { feature: { value: Color; }; + ok: { + value: Color; + }; + error: { + value: Color; + }; + warning: { + value: Color; + }; + info: { + value: Color; + }; + }; + iconColor: { + primary: { + value: Color; + }; + secondary: { + value: Color; + }; + muted: { + value: Color; + }; + placeholder: { + value: Color; + }; + active: { + value: Color; + }; + feature: { + value: Color; + }; + ok: { + value: Color; + }; + error: { + value: Color; + }; + warning: { + value: Color; + }; + info: { + value: Color; + }; }; syntax: { primary: SyntaxHighlightStyle; diff --git a/styles/workspace.ts b/styles/workspace.ts new file mode 100644 index 0000000000..5ecb3a378c --- /dev/null +++ b/styles/workspace.ts @@ -0,0 +1,133 @@ +import { backgroundColor, border, iconColor, text } from "./components"; +import Theme from "./theme"; + +export default function workspace(theme: Theme) { + const signInPrompt = { + ...text(theme, "sans", "secondary"), + size: 13, + underline: true, + padding: { + right: 8, + }, + }; + + const tab = { + height: 34, + iconClose: iconColor(theme, "secondary"), + iconCloseActive: iconColor(theme, "active"), + iconConflict: iconColor(theme, "warning"), + iconDirty: iconColor(theme, "info"), + iconWidth: 8, + spacing: 10, + text: text(theme, "mono", "secondary"), + border: border(theme, "primary", { + left: true, + bottom: true, + overlay: true, + }), + padding: { + left: 12, + right: 12, + }, + }; + + const activeTab = { + ...tab, + background: backgroundColor(theme, 300), + text: text(theme, "mono", "primary"), + border: { + ...tab.border, + bottom: false, + }, + }; + + const sidebarItem = { + height: "$workspace.tab.height", + iconColor: "$text.muted.color", + iconSize: 18, + }; + const sidebar = { + width: 30, + border: border(theme, "primary", { right: true }), + item: sidebarItem, + activeItem: { + ...sidebarItem, + iconColor: iconColor(theme, "primary"), + }, + resizeHandle: { + background: border(theme, "primary").color, + padding: { + left: 1, + }, + }, + }; + + return { + background: backgroundColor(theme, 500), + leaderBorderOpacity: 0.7, + leaderBorderWidth: 2.0, + tab, + activeTab, + leftSidebar: { + ...sidebar, + border: border(theme, "primary", { right: true }), + }, + rightSidebar: { + ...sidebar, + border: border(theme, "primary", { left: true }), + }, + paneDivider: { + color: border(theme, "primary").color, + width: 1, + }, + status_bar: { + height: 24, + itemSpacing: 8, + padding: { + left: 6, + right: 6, + }, + cursorPosition: text(theme, "sans", "muted"), + diagnosticMessage: text(theme, "sans", "muted"), + lspMessage: text(theme, "sans", "muted"), + }, + titlebar: { + avatarWidth: 18, + height: 32, + shareIconColor: iconColor(theme, "secondary"), + shareIconActiveColor: iconColor(theme, "active"), + title: text(theme, "sans", "primary"), + avatar: { + cornerRadius: 10, + border: { + color: "#00000088", + width: 1, + }, + }, + avatarRibbon: { + height: 3, + width: 12, + }, + border: border(theme, "primary", { bottom: true }), + signInPrompt, + hoveredSignInPrompt: { + ...signInPrompt, + ...text(theme, "mono", "active"), + }, + offlineIcon: { + color: iconColor(theme, "muted"), + width: 16, + padding: { + right: 4, + }, + }, + outdatedWarning: { + ...text(theme, "sans", "muted"), + size: 13, + }, + }, + toolbar: { + height: 44, + }, + }; +} From cb3c111401b5ed438733826d7cc850ff5f9bfd62 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Mar 2022 17:59:35 -0600 Subject: [PATCH 43/68] Convert editor styles to TypeScript --- styles/app.ts | 201 +------------------------------------------ styles/components.ts | 4 +- styles/editor.ts | 143 ++++++++++++++++++++++++++++++ styles/theme.ts | 65 ++++++++++++++ 4 files changed, 214 insertions(+), 199 deletions(-) create mode 100644 styles/editor.ts diff --git a/styles/app.ts b/styles/app.ts index 4f40577ae9..a421da8f07 100644 --- a/styles/app.ts +++ b/styles/app.ts @@ -1,13 +1,15 @@ import { backgroundColor } from "./components"; import selectorModal from "./selector-modal"; import workspace from "./workspace"; +import editor from "./editor"; import Theme from "./theme"; export default function app(theme: Theme): Object { return { selector: selectorModal(theme), workspace: workspace(theme), - chat_panel: { + editor: editor(theme), + chatPanel: { extends: "$panel", channel_name: { extends: "$text.primary", @@ -169,203 +171,6 @@ export default function app(theme: Theme): Object { extends: "$contacts_panel.project", }, }, - editor: { - active_line_background: "$state.active_line", - background: backgroundColor(theme, 300), - code_actions_indicator: "$text.muted.color", - diff_background_deleted: "$state.deleted_line", - diff_background_inserted: "$state.inserted_line", - document_highlight_read_background: "#99999920", - document_highlight_write_background: "#99999916", - error_color: "$status.bad", - guest_selections: "$selection.guests", - gutter_background: backgroundColor(theme, 300), - gutter_padding_factor: 2.5, - highlighted_line_background: "$state.highlighted_line", - line_number: "$text.muted.color", - line_number_active: "$text.primary.color", - rename_fade: 0.6, - selection: "$selection.host", - text_color: "$text.secondary.color", - unnecessary_code_fade: 0.5, - autocomplete: { - background: "$surface.100", - corner_radius: 6, - padding: 6, - border: { - color: "$border.secondary", - width: 2, - }, - hovered_item: { - background: "$state.hover", - extends: "$editor.autocomplete.item", - }, - item: { - corner_radius: 6, - padding: { - bottom: 2, - left: 6, - right: 6, - top: 2, - }, - }, - margin: { - left: -14, - }, - match_highlight: { - color: "$editor.syntax.keyword.color", - weight: "$editor.syntax.keyword.weight", - }, - selected_item: { - background: "$state.selected", - extends: "$editor.autocomplete.item", - }, - }, - diagnostic_header: { - background: "$editor.background", - icon_width_factor: 1.5, - text_scale_factor: 0.857, - border: { - bottom: true, - color: "$border.secondary", - top: true, - width: 1, - }, - code: { - extends: "$text.muted", - size: 14, - margin: { - left: 10, - }, - }, - message: { - highlight_text: { - extends: "$text.primary", - size: 14, - weight: "bold", - }, - text: { - extends: "$text.secondary", - size: 14, - }, - }, - }, - diagnostic_path_header: { - background: "$state.active_line", - text_scale_factor: 0.857, - filename: { - extends: "$text.primary", - size: 14, - }, - path: { - extends: "$text.muted", - size: 14, - margin: { - left: 12, - }, - }, - }, - error_diagnostic: { - text_scale_factor: 0.857, - header: { - border: { - color: "$border.primary", - top: true, - width: 1, - }, - }, - message: { - highlight_text: { - color: "$status.bad", - extends: "$text.secondary", - size: 14, - weight: "bold", - }, - text: { - color: "$status.bad", - extends: "$text.secondary", - size: 14, - }, - }, - }, - hint_diagnostic: { - extends: "$editor.error_diagnostic", - message: { - highlight_text: { - color: "$status.info", - }, - text: { - color: "$status.info", - }, - }, - }, - information_diagnostic: { - extends: "$editor.error_diagnostic", - message: { - highlight_text: { - color: "$status.info", - }, - text: { - color: "$status.info", - }, - }, - }, - invalid_error_diagnostic: { - extends: "$editor.error_diagnostic", - message: { - highlight_text: { - color: "$text.muted.color", - }, - text: { - color: "$text.muted.color", - }, - }, - }, - invalid_hint_diagnostic: { - extends: "$editor.hint_diagnostic", - message: { - highlight_text: { - color: "$text.muted.color", - }, - text: { - color: "$text.muted.color", - }, - }, - }, - invalid_information_diagnostic: { - extends: "$editor.information_diagnostic", - message: { - highlight_text: { - color: "$text.muted.color", - }, - text: { - color: "$text.muted.color", - }, - }, - }, - invalid_warning_diagnostic: { - extends: "$editor.warning_diagnostic", - message: { - highlight_text: { - color: "$text.muted.color", - }, - text: { - color: "$text.muted.color", - }, - }, - }, - warning_diagnostic: { - extends: "$editor.error_diagnostic", - message: { - highlight_text: { - color: "$status.warn", - }, - text: { - color: "$status.warn", - }, - }, - }, - }, project_diagnostics: { background: backgroundColor(theme, 300), tab_icon_spacing: 4, diff --git a/styles/components.ts b/styles/components.ts index 9cc58046ff..14becaf2af 100644 --- a/styles/components.ts +++ b/styles/components.ts @@ -3,10 +3,12 @@ import core from "./core"; import { Color } from "./lib"; import Theme, { BackgroundColor, Weight } from "./theme"; +export type TextColor = keyof Theme["textColor"]; + export function text( theme: Theme, fontFamily: keyof typeof core.fontFamily, - color: keyof Theme["textColor"], + color: TextColor, properties?: { size?: keyof typeof core["fontSize"]; weight?: Weight } ) { const sizeKey = properties.size || fontFamily === "sans" ? "sm" : "md"; diff --git a/styles/editor.ts b/styles/editor.ts new file mode 100644 index 0000000000..9edfdc4716 --- /dev/null +++ b/styles/editor.ts @@ -0,0 +1,143 @@ +import { + backgroundColor, + border, + iconColor, + player, + text, + TextColor, +} from "./components"; +import Theme from "./theme"; + +export default function editor(theme: Theme) { + const autocompleteItem = { + cornerRadius: 6, + padding: { + bottom: 2, + left: 6, + right: 6, + top: 2, + }, + }; + + function diagnostic(theme: Theme, color: TextColor) { + return { + textScaleFactor: 0.857, + header: { + border: border(theme, "primary", { + top: true, + }), + }, + message: { + text: { + ...text(theme, "sans", color), + size: 14, + }, + highlightText: { + ...text(theme, "sans", color, { weight: "bold" }), + size: 14, + }, + }, + }; + } + + return { + textColor: theme.textColor.secondary.value, + background: backgroundColor(theme, 300), + activeLineBackground: theme.editor.line.active.value, + codeActionsIndicator: iconColor(theme, "secondary"), + diffBackgroundDeleted: backgroundColor(theme, "error"), + diffBackgroundInserted: backgroundColor(theme, "ok"), + documentHighlightReadBackground: theme.editor.highlight.occurrence.value, + documentHighlightWriteBackground: theme.editor.highlight.occurrence.value, + errorColor: theme.textColor.error, + gutterBackground: backgroundColor(theme, 300), + gutterPaddingFactor: 2.5, + highlightedLineBackground: theme.editor.line.highlighted.value, + lineNumber: theme.editor.gutter.primary.value, + lineNumberActive: theme.editor.gutter.active, + renameFade: 0.6, + unnecessaryCodeFade: 0.5, + selection: player(theme, 1).selection, + guestSelections: [ + player(theme, 2).selection, + player(theme, 3).selection, + player(theme, 4).selection, + player(theme, 5).selection, + player(theme, 6).selection, + player(theme, 7).selection, + player(theme, 8).selection, + ], + autocomplete: { + background: backgroundColor(theme, 100), + cornerRadius: 6, + padding: 6, + border: border(theme, "secondary"), + item: autocompleteItem, + hoveredItem: { + ...autocompleteItem, + background: backgroundColor(theme, 100, "hover"), + }, + margin: { + left: -14, + }, + matchHighlight: { + color: theme.syntax.keyword.color.value, + weight: theme.syntax.keyword.weight.value, + }, + selectedItem: { + ...autocompleteItem, + background: backgroundColor(theme, 100, "active"), + }, + }, + diagnosticHeader: { + background: theme.editor.background.value, + iconWidthFactor: 1.5, + textScaleFactor: 0.857, + border: border(theme, "secondary", { + bottom: true, + top: true, + }), + code: { + ...text(theme, "mono", "muted"), + size: 14, + margin: { + left: 10, + }, + }, + message: { + highlightText: { + ...text(theme, "sans", "primary"), + size: 14, + weight: "bold", + }, + text: { + ...text(theme, "sans", "secondary"), + size: 14, + }, + }, + }, + diagnosticPathHeader: { + background: theme.editor.line.active, + textScaleFactor: 0.857, + filename: { + ...text(theme, "mono", "primary"), + size: 14, + }, + path: { + ...text(theme, "mono", "muted"), + size: 14, + margin: { + left: 12, + }, + }, + }, + errorDiagnostic: diagnostic(theme, "error"), + warningDiagnostic: diagnostic(theme, "warning"), + informationDiagnostic: diagnostic(theme, "info"), + hintDiagnostic: diagnostic(theme, "info"), + invalidErrorDiagnostic: diagnostic(theme, "muted"), + invalidHintDiagnostic: diagnostic(theme, "muted"), + invalidInformationDiagnostic: diagnostic(theme, "muted"), + invalidWarningDiagnostic: diagnostic(theme, "muted"), + }; +} diff --git a/styles/theme.ts b/styles/theme.ts index ddfa6414f4..5220c962c9 100644 --- a/styles/theme.ts +++ b/styles/theme.ts @@ -52,6 +52,10 @@ export default interface Theme { 100: BackgroundColor; 300: BackgroundColor; 500: BackgroundColor; + ok: BackgroundColor; + error: BackgroundColor; + warning: BackgroundColor; + info: BackgroundColor; }; borderColor: { primary: { @@ -134,6 +138,66 @@ export default interface Theme { value: Color; }; }; + editor: { + background: { + value: Color; + }; + indent_guide: { + value: Color; + }; + indent_guide_active: { + value: Color; + }; + line: { + active: { + value: Color; + }; + highlighted: { + value: Color; + }; + inserted: { + value: Color; + }; + deleted: { + value: Color; + }; + modified: { + value: Color; + }; + }; + highlight: { + selection: { + value: Color; + }; + occurrence: { + value: Color; + }; + activeOccurrence: { + value: Color; + }; + matchingBracket: { + value: Color; + }; + match: { + value: Color; + }; + activeMatch: { + value: Color; + }; + related: { + value: Color; + }; + }; + gutter: { + primary: { + value: Color; + }; + active: { + value: Color; + }; + }; + }; + syntax: { primary: SyntaxHighlightStyle; comment: SyntaxHighlightStyle; @@ -151,6 +215,7 @@ export default interface Theme { boolean: SyntaxHighlightStyle; predictive: SyntaxHighlightStyle; }; + player: { 1: Player; 2: Player; From 189db6311cdd13f3286652dedb831b33014492ed Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Mar 2022 18:26:47 -0600 Subject: [PATCH 44/68] Convert project panel styles --- styles/app.ts | 180 +++++++++++++++++----------------------- styles/editor.ts | 38 +++------ styles/project-panel.ts | 32 +++++++ styles/theme.ts | 4 +- 4 files changed, 124 insertions(+), 130 deletions(-) create mode 100644 styles/project-panel.ts diff --git a/styles/app.ts b/styles/app.ts index a421da8f07..ae0f0717bb 100644 --- a/styles/app.ts +++ b/styles/app.ts @@ -1,46 +1,67 @@ -import { backgroundColor } from "./components"; +import { backgroundColor, text } from "./components"; import selectorModal from "./selector-modal"; import workspace from "./workspace"; import editor from "./editor"; import Theme from "./theme"; +import projectPanel from "./project-panel"; + +export const panel = { + padding: { top: 12, left: 12, bottom: 12, right: 12 }, +}; export default function app(theme: Theme): Object { return { selector: selectorModal(theme), workspace: workspace(theme), editor: editor(theme), + projectDiagnostics: { + background: backgroundColor(theme, 300), + tabIconSpacing: 4, + tabIconWidth: 13, + tabSummarySpacing: 10, + emptyMessage: { + ...text(theme, "sans", "primary", { size: "lg" }), + }, + statusBarItem: { + ...text(theme, "sans", "muted"), + margin: { + right: 10, + }, + }, + }, + projectPanel: projectPanel(theme), chatPanel: { extends: "$panel", - channel_name: { + channelName: { extends: "$text.primary", weight: "bold", }, - channel_name_hash: { + channelNameHash: { text: "$text.muted", padding: { right: 8, }, }, - channel_select: { - active_item: { - extends: "$chat_panel.channel_select.item", + channelSelect: { + activeItem: { + extends: "$chatPanel.channel_select.item", name: "$text.primary", }, header: { - extends: "$chat_panel.channel_select.active_item", + extends: "$chat_panel.channel_select.activeItem", padding: { bottom: 4, left: 0, }, }, - hovered_active_item: { - extends: "$chat_panel.channel_select.hovered_item", + hoveredActiveItem: { + extends: "$chatPanel.channelSelect.hoveredItem", name: "$text.primary", }, - hovered_item: { + hoveredItem: { background: "$state.hover", - corner_radius: 6, - extends: "$chat_panel.channel_select.item", + cornerRadius: 6, + extends: "$chat_panel.channelSelect.item", }, item: { name: "$text.secondary", @@ -54,7 +75,7 @@ export default function app(theme: Theme): Object { }, menu: { background: "$surface.500", - corner_radius: 6, + cornerRadius: 6, padding: 4, border: { color: "$border.primary", @@ -67,14 +88,14 @@ export default function app(theme: Theme): Object { }, }, }, - hovered_sign_in_prompt: { + hoveredSignInPrompt: { color: "$text.secondary.color", - extends: "$chat_panel.sign_in_prompt", + extends: "$chatPanel.signInPrompt", }, - input_editor: { + inputEditor: { background: backgroundColor(theme, 300), - corner_radius: 6, - placeholder_text: "$text.muted", + cornerRadius: 6, + placeholderText: "$text.muted", selection: "$selection.host", text: "$text.primary", border: { @@ -102,8 +123,8 @@ export default function app(theme: Theme): Object { }, }, }, - pending_message: { - extends: "$chat_panel.message", + pendingMessage: { + extends: "$chatPanel.message", body: { color: "$text.muted.color", }, @@ -114,41 +135,41 @@ export default function app(theme: Theme): Object { color: "$text.muted.color", }, }, - sign_in_prompt: { + signInPrompt: { extends: "$text.primary", underline: true, }, }, - contacts_panel: { + contactsPanel: { extends: "$panel", - host_row_height: 28, - tree_branch_color: "$surface.100", - tree_branch_width: 1, - host_avatar: { - corner_radius: 10, + hostRowHeight: 28, + treeBranchColor: "$surface.100", + treeBranchWidth: 1, + hostAvatar: { + cornerRadius: 10, width: 18, }, - host_username: { + hostUsername: { extends: "$text.primary", padding: { left: 8, }, }, - hovered_shared_project: { + hoveredSharedProject: { background: "$state.hover", - corner_radius: 6, - extends: "$contacts_panel.shared_project", + cornerRadius: 6, + extends: "$contacts_panel.sharedProject", }, - hovered_unshared_project: { + hoveredUnsharedProject: { background: "$state.hover", - corner_radius: 6, - extends: "$contacts_panel.unshared_project", + cornerRadius: 6, + extends: "$contacts_panel.unsharedProject", }, project: { - guest_avatar_spacing: 4, + guestAvatarSpacing: 4, height: 24, - guest_avatar: { - corner_radius: 8, + guestAvatar: { + cornerRadius: 8, width: 14, }, name: { @@ -161,79 +182,34 @@ export default function app(theme: Theme): Object { left: 8, }, }, - shared_project: { - extends: "$contacts_panel.project", + sharedProject: { + extends: "$contactsPanel.project", name: { color: "$text.primary.color", }, }, - unshared_project: { - extends: "$contacts_panel.project", - }, - }, - project_diagnostics: { - background: backgroundColor(theme, 300), - tab_icon_spacing: 4, - tab_icon_width: 13, - tab_summary_spacing: 10, - empty_message: { - extends: "$text.primary", - size: 18, - }, - status_bar_item: { - extends: "$text.muted", - margin: { - right: 10, - }, - }, - }, - project_panel: { - extends: "$panel", - entry: { - height: 22, - icon_color: "$text.muted.color", - icon_size: 8, - icon_spacing: 8, - text: "$text.secondary", - }, - hovered_entry: { - background: "$state.hover", - extends: "$project_panel.entry", - }, - hovered_selected_entry: { - extends: "$project_panel.hovered_entry", - text: { - extends: "$text.primary", - }, - }, - padding: { - top: 6, - }, - selected_entry: { - extends: "$project_panel.entry", - text: { - extends: "$text.primary", - }, + unsharedProject: { + extends: "$contactsPanel.project", }, }, search: { background: backgroundColor(theme, 300), - match_background: "$state.highlighted_line", - tab_icon_spacing: 4, - tab_icon_width: 14, - active_hovered_option_button: { + matchBackground: "$state.highlightedLine", + tabIconSpacing: 4, + tabIconWidth: 14, + activeHoveredOptionButton: { background: "$surface.100", extends: "$search.option_button", }, - active_option_button: { + activeOptionButton: { background: "$surface.100", extends: "$search.option_button", }, editor: { background: "$surface.500", - corner_radius: 6, - max_width: 400, - placeholder_text: "$text.muted", + cornerRadius: 6, + maxWidth: 400, + placeholderText: "$text.muted", selection: "$selection.host", text: "$text.primary", border: { @@ -253,24 +229,24 @@ export default function app(theme: Theme): Object { top: 3, }, }, - hovered_option_button: { + hoveredOptionButton: { background: "$surface.100", - extends: "$search.option_button", + extends: "$search.optionButton", }, - invalid_editor: { + invalidEditor: { extends: "$search.editor", border: { color: "$status.bad", width: 1, }, }, - match_index: { + matchIndex: { extends: "$text.secondary", padding: 6, }, - option_button: { + optionButton: { background: backgroundColor(theme, 300), - corner_radius: 6, + cornerRadius: 6, extends: "$text.secondary", border: { color: "$border.primary", @@ -287,13 +263,13 @@ export default function app(theme: Theme): Object { top: 1, }, }, - option_button_group: { + optionButtonGroup: { padding: { left: 2, right: 2, }, }, - results_status: { + resultsStatus: { extends: "$text.primary", size: 18, }, diff --git a/styles/editor.ts b/styles/editor.ts index 9edfdc4716..ea7012d209 100644 --- a/styles/editor.ts +++ b/styles/editor.ts @@ -28,14 +28,11 @@ export default function editor(theme: Theme) { }), }, message: { - text: { - ...text(theme, "sans", color), - size: 14, - }, - highlightText: { - ...text(theme, "sans", color, { weight: "bold" }), - size: 14, - }, + text: text(theme, "sans", color, { size: "sm" }), + highlightText: text(theme, "sans", color, { + size: "sm", + weight: "bold", + }), }, }; } @@ -75,7 +72,7 @@ export default function editor(theme: Theme) { item: autocompleteItem, hoveredItem: { ...autocompleteItem, - background: backgroundColor(theme, 100, "hover"), + background: backgroundColor(theme, 100, "hovered"), }, margin: { left: -14, @@ -98,34 +95,25 @@ export default function editor(theme: Theme) { top: true, }), code: { - ...text(theme, "mono", "muted"), - size: 14, + ...text(theme, "mono", "muted", { size: "sm" }), margin: { left: 10, }, }, message: { - highlightText: { - ...text(theme, "sans", "primary"), - size: 14, + highlightText: text(theme, "sans", "primary", { + size: "sm", weight: "bold", - }, - text: { - ...text(theme, "sans", "secondary"), - size: 14, - }, + }), + text: text(theme, "sans", "secondary", { size: "sm" }), }, }, diagnosticPathHeader: { background: theme.editor.line.active, textScaleFactor: 0.857, - filename: { - ...text(theme, "mono", "primary"), - size: 14, - }, + filename: text(theme, "mono", "primary", { size: "sm" }), path: { - ...text(theme, "mono", "muted"), - size: 14, + ...text(theme, "mono", "muted", { size: "sm" }), margin: { left: 12, }, diff --git a/styles/project-panel.ts b/styles/project-panel.ts new file mode 100644 index 0000000000..343e11b96b --- /dev/null +++ b/styles/project-panel.ts @@ -0,0 +1,32 @@ +import { panel } from "./app"; +import { backgroundColor, iconColor, text, TextColor } from "./components"; +import Theme from "./theme"; +import { Color } from "./lib"; + +export default function projectPanel(theme: Theme) { + function entry(theme: Theme, textColor: TextColor, background?: Color) { + return { + height: 22, + background, + iconColor: iconColor(theme, "muted"), + iconSize: 8, + iconSpacing: 8, + text: text(theme, "mono", textColor), + }; + } + + return { + ...panel, + entry: entry(theme, "secondary"), + hoveredEntry: entry( + theme, + "secondary", + backgroundColor(theme, 300, "hovered") + ), + selectedEntry: entry(theme, "primary"), + hoveredSelectedEntry: entry(theme, "primary", "hovered"), + padding: { + top: 6, + }, + }; +} diff --git a/styles/theme.ts b/styles/theme.ts index 5220c962c9..27f578f436 100644 --- a/styles/theme.ts +++ b/styles/theme.ts @@ -1,5 +1,3 @@ -import { colorRamp } from "./lib"; - export type Color = string; export type Weight = | "thin" @@ -36,7 +34,7 @@ export interface BackgroundColor { base: { value: Color; }; - hover: { + hovered: { value: Color; }; active: { From 70b15e4c909b8723442b6d6ec1dc61d2aab2803f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 30 Mar 2022 18:45:34 -0600 Subject: [PATCH 45/68] Convert chat panel --- styles/app.ts | 112 +------------------------------------------ styles/chat-panel.ts | 108 +++++++++++++++++++++++++++++++++++++++++ styles/components.ts | 8 +++- 3 files changed, 116 insertions(+), 112 deletions(-) create mode 100644 styles/chat-panel.ts diff --git a/styles/app.ts b/styles/app.ts index ae0f0717bb..5f2993d30a 100644 --- a/styles/app.ts +++ b/styles/app.ts @@ -4,6 +4,7 @@ import workspace from "./workspace"; import editor from "./editor"; import Theme from "./theme"; import projectPanel from "./project-panel"; +import chatPanel from "./chat-panel"; export const panel = { padding: { top: 12, left: 12, bottom: 12, right: 12 }, @@ -30,116 +31,7 @@ export default function app(theme: Theme): Object { }, }, projectPanel: projectPanel(theme), - chatPanel: { - extends: "$panel", - channelName: { - extends: "$text.primary", - weight: "bold", - }, - channelNameHash: { - text: "$text.muted", - padding: { - right: 8, - }, - }, - channelSelect: { - activeItem: { - extends: "$chatPanel.channel_select.item", - name: "$text.primary", - }, - header: { - extends: "$chat_panel.channel_select.activeItem", - padding: { - bottom: 4, - left: 0, - }, - }, - hoveredActiveItem: { - extends: "$chatPanel.channelSelect.hoveredItem", - name: "$text.primary", - }, - hoveredItem: { - background: "$state.hover", - cornerRadius: 6, - extends: "$chat_panel.channelSelect.item", - }, - item: { - name: "$text.secondary", - padding: 4, - hash: { - extends: "$text.muted", - margin: { - right: 8, - }, - }, - }, - menu: { - background: "$surface.500", - cornerRadius: 6, - padding: 4, - border: { - color: "$border.primary", - width: 1, - }, - shadow: { - blur: 16, - color: "$shadow.0", - offset: [0, 2], - }, - }, - }, - hoveredSignInPrompt: { - color: "$text.secondary.color", - extends: "$chatPanel.signInPrompt", - }, - inputEditor: { - background: backgroundColor(theme, 300), - cornerRadius: 6, - placeholderText: "$text.muted", - selection: "$selection.host", - text: "$text.primary", - border: { - color: "$border.primary", - width: 1, - }, - padding: { - bottom: 7, - left: 8, - right: 8, - top: 7, - }, - }, - message: { - body: "$text.secondary", - timestamp: "$text.muted", - padding: { - bottom: 6, - }, - sender: { - extends: "$text.primary", - weight: "bold", - margin: { - right: 8, - }, - }, - }, - pendingMessage: { - extends: "$chatPanel.message", - body: { - color: "$text.muted.color", - }, - sender: { - color: "$text.muted.color", - }, - timestamp: { - color: "$text.muted.color", - }, - }, - signInPrompt: { - extends: "$text.primary", - underline: true, - }, - }, + chatPanel: chatPanel(theme), contactsPanel: { extends: "$panel", hostRowHeight: 28, diff --git a/styles/chat-panel.ts b/styles/chat-panel.ts new file mode 100644 index 0000000000..c6bf0148ea --- /dev/null +++ b/styles/chat-panel.ts @@ -0,0 +1,108 @@ +import { panel } from "./app"; +import { + backgroundColor, + border, + player, + shadow, + text, + TextColor, +} from "./components"; +import Theme from "./theme"; + +export default function chatPanel(theme: Theme) { + function channelSelectItem( + theme: Theme, + textColor: TextColor, + hovered: boolean + ) { + return { + name: text(theme, "sans", textColor), + padding: 4, + hash: { + ...text(theme, "sans", "muted"), + margin: { + right: 8, + }, + }, + background: hovered ? backgroundColor(theme, 300, "hovered") : undefined, + cornerRadius: hovered ? 6 : 0, + }; + } + + const message = { + body: text(theme, "sans", "secondary"), + timestamp: text(theme, "sans", "muted"), + padding: { + bottom: 6, + }, + sender: { + ...text(theme, "sans", "primary", { weight: "bold" }), + margin: { + right: 8, + }, + }, + }; + + return { + ...panel, + channelName: text(theme, "sans", "primary", { weight: "bold" }), + channelNameHash: { + ...text(theme, "sans", "muted"), + padding: { + right: 8, + }, + }, + channelSelect: { + header: { + ...channelSelectItem(theme, "primary", false), + padding: { + bottom: 4, + left: 0, + }, + }, + item: channelSelectItem(theme, "secondary", false), + hoveredItem: channelSelectItem(theme, "secondary", true), + activeItem: channelSelectItem(theme, "primary", false), + hoveredActiveItem: channelSelectItem(theme, "primary", true), + menu: { + background: backgroundColor(theme, 500), + cornerRadius: 6, + padding: 4, + border: border(theme, "primary"), + shadow: shadow(theme), + }, + }, + signInPrompt: text(theme, "sans", "secondary", { underline: true }), + hoveredSignInPrompt: text(theme, "sans", "primary", { underline: true }), + message, + pendingMessage: { + ...message, + body: { + ...message.body, + color: theme.textColor.muted.value, + }, + sender: { + ...message.sender, + color: theme.textColor.muted.value, + }, + timestamp: { + ...message.timestamp, + color: theme.textColor.muted.value, + }, + }, + inputEditor: { + background: backgroundColor(theme, 300), + cornerRadius: 6, + text: text(theme, "mono", "primary"), + placeholderText: text(theme, "mono", "muted"), + selection: player(theme, 1).selection, + border: border(theme, "primary"), + padding: { + bottom: 7, + left: 8, + right: 8, + top: 7, + }, + }, + }; +} diff --git a/styles/components.ts b/styles/components.ts index 14becaf2af..28d883927b 100644 --- a/styles/components.ts +++ b/styles/components.ts @@ -9,7 +9,11 @@ export function text( theme: Theme, fontFamily: keyof typeof core.fontFamily, color: TextColor, - properties?: { size?: keyof typeof core["fontSize"]; weight?: Weight } + properties?: { + size?: keyof typeof core["fontSize"]; + weight?: Weight; + underline?: boolean; + } ) { const sizeKey = properties.size || fontFamily === "sans" ? "sm" : "md"; const size = core.fontSize[sizeKey].value; @@ -74,7 +78,7 @@ export function backgroundColor( return theme.backgroundColor[name][state || "base"].value; } -export function shadow(theme) { +export function shadow(theme: Theme) { return { blur: 16, color: chroma("black").alpha(theme.shadowAlpha.value).hex(), From d88e20477df2cffa2b10b64dc65ce68066fd40f7 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 31 Mar 2022 01:38:18 -0400 Subject: [PATCH 46/68] Update app.ts, editor.ts --- styles/app.ts | 65 +++++++++++++++++++------------------------- styles/components.ts | 4 +++ styles/editor.ts | 4 +-- styles/theme.ts | 12 ++++++++ styles/workspace.ts | 4 +-- 5 files changed, 48 insertions(+), 41 deletions(-) diff --git a/styles/app.ts b/styles/app.ts index 5f2993d30a..11e476baf7 100644 --- a/styles/app.ts +++ b/styles/app.ts @@ -1,10 +1,10 @@ -import { backgroundColor, text } from "./components"; -import selectorModal from "./selector-modal"; -import workspace from "./workspace"; -import editor from "./editor"; -import Theme from "./theme"; -import projectPanel from "./project-panel"; import chatPanel from "./chat-panel"; +import { backgroundColor, border, borderColor, player, text } from "./components"; +import editor from "./editor"; +import projectPanel from "./project-panel"; +import selectorModal from "./selector-modal"; +import Theme from "./theme"; +import workspace from "./workspace"; export const panel = { padding: { top: 12, left: 12, bottom: 12, right: 12 }, @@ -35,27 +35,27 @@ export default function app(theme: Theme): Object { contactsPanel: { extends: "$panel", hostRowHeight: 28, - treeBranchColor: "$surface.100", + treeBranchColor: borderColor(theme, "muted"), treeBranchWidth: 1, hostAvatar: { cornerRadius: 10, width: 18, }, hostUsername: { - extends: "$text.primary", + ...text(theme, "mono", "muted"), padding: { left: 8, }, }, hoveredSharedProject: { - background: "$state.hover", - cornerRadius: 6, extends: "$contacts_panel.sharedProject", + background: theme.editor.line.active.value, + cornerRadius: 6, }, hoveredUnsharedProject: { - background: "$state.hover", - cornerRadius: 6, extends: "$contacts_panel.unsharedProject", + background: theme.editor.line.active.value, + cornerRadius: 6, }, project: { guestAvatarSpacing: 4, @@ -65,7 +65,7 @@ export default function app(theme: Theme): Object { width: 14, }, name: { - extends: "$text.secondary", + extends: text(theme, "mono", "secondary"), margin: { right: 6, }, @@ -77,7 +77,7 @@ export default function app(theme: Theme): Object { sharedProject: { extends: "$contactsPanel.project", name: { - color: "$text.primary.color", + color: text(theme, "mono", "primary"), }, }, unsharedProject: { @@ -86,28 +86,25 @@ export default function app(theme: Theme): Object { }, search: { background: backgroundColor(theme, 300), - matchBackground: "$state.highlightedLine", + matchBackground: theme.editor.highlight.match, tabIconSpacing: 4, tabIconWidth: 14, activeHoveredOptionButton: { - background: "$surface.100", extends: "$search.option_button", + background: backgroundColor(theme, 100), }, activeOptionButton: { - background: "$surface.100", extends: "$search.option_button", + background: backgroundColor(theme, 100), }, editor: { - background: "$surface.500", + background: backgroundColor(theme, 500), cornerRadius: 6, maxWidth: 400, - placeholderText: "$text.muted", - selection: "$selection.host", - text: "$text.primary", - border: { - color: "$border.primary", - width: 1, - }, + placeholderText: text(theme, "mono", "placeholder"), + selection: player(theme, 1).selection, + text: text(theme, "mono", "primary"), + border: border(theme, "primary"), margin: { bottom: 5, left: 5, @@ -122,28 +119,22 @@ export default function app(theme: Theme): Object { }, }, hoveredOptionButton: { - background: "$surface.100", extends: "$search.optionButton", + background: backgroundColor(theme, 100), }, invalidEditor: { extends: "$search.editor", - border: { - color: "$status.bad", - width: 1, - }, + border: border(theme, "error"), }, matchIndex: { - extends: "$text.secondary", + ...text(theme, "mono", "secondary"), padding: 6, }, optionButton: { + ...text(theme, "mono", "secondary"), background: backgroundColor(theme, 300), cornerRadius: 6, - extends: "$text.secondary", - border: { - color: "$border.primary", - width: 1, - }, + border: border(theme, "primary"), margin: { left: 1, right: 1, @@ -162,7 +153,7 @@ export default function app(theme: Theme): Object { }, }, resultsStatus: { - extends: "$text.primary", + ...text(theme, "mono", "primary"), size: 18, }, }, diff --git a/styles/components.ts b/styles/components.ts index 28d883927b..c8b2f87638 100644 --- a/styles/components.ts +++ b/styles/components.ts @@ -47,6 +47,10 @@ export function border( }; } +export function borderColor(theme: Theme, color: keyof Theme["borderColor"]) { + return theme.borderColor[color].value; +} + export function iconColor(theme: Theme, color: keyof Theme["iconColor"]) { return theme.iconColor[color].value; } diff --git a/styles/editor.ts b/styles/editor.ts index ea7012d209..a27464eee2 100644 --- a/styles/editor.ts +++ b/styles/editor.ts @@ -4,7 +4,7 @@ import { iconColor, player, text, - TextColor, + TextColor } from "./components"; import Theme from "./theme"; @@ -89,7 +89,7 @@ export default function editor(theme: Theme) { diagnosticHeader: { background: theme.editor.background.value, iconWidthFactor: 1.5, - textScaleFactor: 0.857, + textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these. border: border(theme, "secondary", { bottom: true, top: true, diff --git a/styles/theme.ts b/styles/theme.ts index 27f578f436..9d297d552d 100644 --- a/styles/theme.ts +++ b/styles/theme.ts @@ -71,6 +71,18 @@ export default interface Theme { active: { value: Color; }; + ok: { + value: Color; + }; + error: { + value: Color; + }; + warning: { + value: Color; + }; + info: { + value: Color; + }; }; textColor: { primary: { diff --git a/styles/workspace.ts b/styles/workspace.ts index 5ecb3a378c..1a50fe9ee1 100644 --- a/styles/workspace.ts +++ b/styles/workspace.ts @@ -42,8 +42,8 @@ export default function workspace(theme: Theme) { }; const sidebarItem = { - height: "$workspace.tab.height", - iconColor: "$text.muted.color", + height: 32, + iconColor: iconColor(theme, "secondary"), iconSize: 18, }; const sidebar = { From c008e65de6cfdae9b1a3f3fc73c53aeef1f790c6 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 31 Mar 2022 11:27:02 -0400 Subject: [PATCH 47/68] Extract `search` from `app` - Also update border to use borderColor( ) --- styles/app.ts | 79 +++---------------------------------------- styles/components.ts | 2 +- styles/search.ts | 80 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 76 deletions(-) create mode 100644 styles/search.ts diff --git a/styles/app.ts b/styles/app.ts index 11e476baf7..a65442db07 100644 --- a/styles/app.ts +++ b/styles/app.ts @@ -1,7 +1,8 @@ import chatPanel from "./chat-panel"; -import { backgroundColor, border, borderColor, player, text } from "./components"; +import { backgroundColor, borderColor, text } from "./components"; import editor from "./editor"; import projectPanel from "./project-panel"; +import search from "./search"; import selectorModal from "./selector-modal"; import Theme from "./theme"; import workspace from "./workspace"; @@ -33,7 +34,7 @@ export default function app(theme: Theme): Object { projectPanel: projectPanel(theme), chatPanel: chatPanel(theme), contactsPanel: { - extends: "$panel", + ...panel, hostRowHeight: 28, treeBranchColor: borderColor(theme, "muted"), treeBranchWidth: 1, @@ -84,78 +85,6 @@ export default function app(theme: Theme): Object { extends: "$contactsPanel.project", }, }, - search: { - background: backgroundColor(theme, 300), - matchBackground: theme.editor.highlight.match, - tabIconSpacing: 4, - tabIconWidth: 14, - activeHoveredOptionButton: { - extends: "$search.option_button", - background: backgroundColor(theme, 100), - }, - activeOptionButton: { - extends: "$search.option_button", - background: backgroundColor(theme, 100), - }, - editor: { - background: backgroundColor(theme, 500), - cornerRadius: 6, - maxWidth: 400, - placeholderText: text(theme, "mono", "placeholder"), - selection: player(theme, 1).selection, - text: text(theme, "mono", "primary"), - border: border(theme, "primary"), - margin: { - bottom: 5, - left: 5, - right: 5, - top: 5, - }, - padding: { - bottom: 3, - left: 13, - right: 13, - top: 3, - }, - }, - hoveredOptionButton: { - extends: "$search.optionButton", - background: backgroundColor(theme, 100), - }, - invalidEditor: { - extends: "$search.editor", - border: border(theme, "error"), - }, - matchIndex: { - ...text(theme, "mono", "secondary"), - padding: 6, - }, - optionButton: { - ...text(theme, "mono", "secondary"), - background: backgroundColor(theme, 300), - cornerRadius: 6, - border: border(theme, "primary"), - margin: { - left: 1, - right: 1, - }, - padding: { - bottom: 1, - left: 6, - right: 6, - top: 1, - }, - }, - optionButtonGroup: { - padding: { - left: 2, - right: 2, - }, - }, - resultsStatus: { - ...text(theme, "mono", "primary"), - size: 18, - }, - }, + search: search(theme), }; } diff --git a/styles/components.ts b/styles/components.ts index c8b2f87638..590c1b5eea 100644 --- a/styles/components.ts +++ b/styles/components.ts @@ -41,7 +41,7 @@ export function border( options?: BorderOptions ) { return { - color: theme.borderColor[color].value, + color: borderColor(theme, color), width: 1, ...options, }; diff --git a/styles/search.ts b/styles/search.ts new file mode 100644 index 0000000000..ced2266ea7 --- /dev/null +++ b/styles/search.ts @@ -0,0 +1,80 @@ +import { backgroundColor, border, player, text } from "./components"; +import Theme from "./theme"; + +export default function search(theme: Theme) { + const optionButton = { + ...text(theme, "mono", "secondary"), + background: backgroundColor(theme, 300), + cornerRadius: 6, + border: border(theme, "primary"), + margin: { + left: 1, + right: 1, + }, + padding: { + bottom: 1, + left: 6, + right: 6, + top: 1, + }, + }; + + return { + background: backgroundColor(theme, 300), + matchBackground: theme.editor.highlight.match, + tabIconSpacing: 4, + tabIconWidth: 14, + activeHoveredOptionButton: { + ...optionButton, + background: backgroundColor(theme, 100), + }, + activeOptionButton: { + ...optionButton, + background: backgroundColor(theme, 100), + }, + editor: { + background: backgroundColor(theme, 500), + cornerRadius: 6, + maxWidth: 400, + placeholderText: text(theme, "mono", "placeholder"), + selection: player(theme, 1).selection, + text: text(theme, "mono", "primary"), + border: border(theme, "primary"), + margin: { + bottom: 5, + left: 5, + right: 5, + top: 5, + }, + padding: { + bottom: 3, + left: 13, + right: 13, + top: 3, + }, + }, + hoveredOptionButton: { + ...optionButton, + background: backgroundColor(theme, 100), + }, + invalidEditor: { + extends: "$search.editor", + border: border(theme, "error"), + }, + matchIndex: { + ...text(theme, "mono", "secondary"), + padding: 6, + }, + optionButton, + optionButtonGroup: { + padding: { + left: 2, + right: 2, + }, + }, + resultsStatus: { + ...text(theme, "mono", "primary"), + size: 18, + }, + }; +} From ae8b610d85aac1d46782113ee1ad38a0650279af Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 31 Mar 2022 19:10:44 -0400 Subject: [PATCH 48/68] WIP: Scaffold tokens in dark.ts, no real values yet. --- styles/dark.ts | 438 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 438 insertions(+) create mode 100644 styles/dark.ts diff --git a/styles/dark.ts b/styles/dark.ts new file mode 100644 index 0000000000..019f50e40c --- /dev/null +++ b/styles/dark.ts @@ -0,0 +1,438 @@ +import Theme from "./theme"; + +export default function dark(): Theme { + return { + backgroundColor: { + 100: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + 300: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + 500: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + ok: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + error: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + warning: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + info: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + }, + borderColor: { + primary: { + value: "#000000", + }, + secondary: { + value: "#000000", + }, + muted: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + active: { + value: "#000000", + }, + ok: { + value: "#000000", + }, + error: { + value: "#000000", + }, + warning: { + value: "#000000", + }, + info: { + value: "#000000", + }, + }, + textColor: { + primary: { + value: "#000000", + }, + secondary: { + value: "#000000", + }, + muted: { + value: "#000000", + }, + placeholder: { + value: "#000000", + }, + active: { + value: "#000000", + }, + feature: { + value: "#000000", + }, + ok: { + value: "#000000", + }, + error: { + value: "#000000", + }, + warning: { + value: "#000000", + }, + info: { + value: "#000000", + }, + }, + iconColor: { + primary: { + value: "#000000", + }, + secondary: { + value: "#000000", + }, + muted: { + value: "#000000", + }, + placeholder: { + value: "#000000", + }, + active: { + value: "#000000", + }, + feature: { + value: "#000000", + }, + ok: { + value: "#000000", + }, + error: { + value: "#000000", + }, + warning: { + value: "#000000", + }, + info: { + value: "#000000", + }, + }, + editor: { + background: { + value: "#000000", + }, + indent_guide: { + value: "#000000", + }, + indent_guide_active: { + value: "#000000", + }, + line: { + active: { + value: "#000000", + }, + highlighted: { + value: "#000000", + }, + inserted: { + value: "#000000", + }, + deleted: { + value: "#000000", + }, + modified: { + value: "#000000", + }, + }, + highlight: { + selection: { + value: "#000000", + }, + occurrence: { + value: "#000000", + }, + activeOccurrence: { + value: "#000000", + }, + matchingBracket: { + value: "#000000", + }, + match: { + value: "#000000", + }, + activeMatch: { + value: "#000000", + }, + related: { + value: "#000000", + }, + }, + gutter: { + primary: { + value: "#000000", + }, + active: { + value: "#000000", + }, + }, + }, + + syntax: { + primary: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + comment: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + punctuation: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + constant: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + keyword: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + function: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + type: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + variant: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + property: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + enum: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + operator: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + string: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + number: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + boolean: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + predictive: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + }, + player: { + 1: { + baseColor: { + value: "#000000", + }, + cursorColor: { + value: "#000000", + }, + selectionColor: { + value: "#000000", + }, + borderColor: { + value: "#000000", + }, + }, + 2: { + baseColor: { + value: "#000000", + }, + cursorColor: { + value: "#000000", + }, + selectionColor: { + value: "#000000", + }, + borderColor: { + value: "#000000", + }, + }, + 3: { + baseColor: { + value: "#000000", + }, + cursorColor: { + value: "#000000", + }, + selectionColor: { + value: "#000000", + }, + borderColor: { + value: "#000000", + }, + }, + 4: { + baseColor: { + value: "#000000", + }, + cursorColor: { + value: "#000000", + }, + selectionColor: { + value: "#000000", + }, + borderColor: { + value: "#000000", + }, + }, + 5: { + baseColor: { + value: "#000000", + }, + cursorColor: { + value: "#000000", + }, + selectionColor: { + value: "#000000", + }, + borderColor: { + value: "#000000", + }, + }, + 6: { + baseColor: { + value: "#000000", + }, + cursorColor: { + value: "#000000", + }, + selectionColor: { + value: "#000000", + }, + borderColor: { + value: "#000000", + }, + }, + 7: { + baseColor: { + value: "#000000", + }, + cursorColor: { + value: "#000000", + }, + selectionColor: { + value: "#000000", + }, + borderColor: { + value: "#000000", + }, + }, + 8: { + baseColor: { + value: "#000000", + }, + cursorColor: { + value: "#000000", + }, + selectionColor: { + value: "#000000", + }, + borderColor: { + value: "#000000", + }, + }, + }, + shadowAlpha: { + value: 0.32, + }, + }; +} \ No newline at end of file From 083c1f7c0ea8fe94a794d31f3a583566fc8db905 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 31 Mar 2022 20:32:47 -0400 Subject: [PATCH 49/68] WIP for keith --- styles/dark.ts | 884 +++++++++++++++++++++++++------------------------ 1 file changed, 451 insertions(+), 433 deletions(-) diff --git a/styles/dark.ts b/styles/dark.ts index 019f50e40c..efd2d3b8a4 100644 --- a/styles/dark.ts +++ b/styles/dark.ts @@ -1,438 +1,456 @@ +import core from "./core"; import Theme from "./theme"; +const backgroundColor = { + 100: { + base: { + value: core.color.neutral[999].value, + }, + hovered: { + value: core.color.neutral[999].value, + }, + active: { + value: core.color.neutral[999].value, + }, + focused: { + value: core.color.neutral[999].value, + }, + }, + 300: { + base: { + value: core.color.neutral[999].value, + }, + hovered: { + value: core.color.neutral[999].value, + }, + active: { + value: core.color.neutral[999].value, + }, + focused: { + value: core.color.neutral[999].value, + }, + }, + 500: { + base: { + value: core.color.neutral[999].value, + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + ok: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + error: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + warning: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, + info: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + }, +}; + +const borderColor = { + primary: { + value: "#000000", + }, + secondary: { + value: "#000000", + }, + muted: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + active: { + value: "#000000", + }, + ok: { + value: "#000000", + }, + error: { + value: "#000000", + }, + warning: { + value: "#000000", + }, + info: { + value: "#000000", + }, +}; + +const textColor = { + primary: { + value: core.color.neutral[150].value, + }, + secondary: { + value: core.color.neutral[350].value, + }, + muted: { + value: core.color.neutral[550].value, + }, + placeholder: { + value: core.color.neutral[750].value, + }, + active: { + value: core.color.neutral[0].value, + }, + feature: { + //TODO: (design) define feature and it's correct value + value: core.color.sky[500].value, + }, + ok: { + value: core.color.green[600].value, + }, + error: { + value: core.color.red[400].value, + }, + warning: { + value: core.color.amber[300].value, + }, + info: { + value: core.color.blue[500].value, + }, +}; + +const iconColor = { + primary: { + value: core.color.neutral[300].value, + }, + secondary: { + value: core.color.neutral[500].value, + }, + muted: { + value: core.color.neutral[600].value, + }, + placeholder: { + value: core.color.neutral[700].value, + }, + active: { + value: core.color.neutral[50].value, + }, + feature: { + //TODO: (design) define feature and it's correct value + value: core.color.sky[500].value, + }, + ok: { + value: core.color.green[600].value, + }, + error: { + value: core.color.red[400].value, + }, + warning: { + value: core.color.amber[300].value, + }, + info: { + value: core.color.blue[500].value, + }, +}; + +const editor = { + background: { + value: backgroundColor[500].base.value, + }, + indent_guide: { + value: core.color.neutral[999].value, + }, + indent_guide_active: { + value: core.color.neutral[999].value, + }, + line: { + active: { + value: core.color.neutral[999].value, + }, + highlighted: { + value: core.color.neutral[999].value, + }, + inserted: { + value: core.color.neutral[999].value, + }, + deleted: { + value: core.color.neutral[999].value, + }, + modified: { + value: core.color.neutral[999].value, + }, + }, + highlight: { + selection: { + value: core.color.neutral[999].value, + }, + occurrence: { + value: core.color.neutral[999].value, + }, + activeOccurrence: { + value: core.color.neutral[999].value, + }, + matchingBracket: { + value: core.color.neutral[999].value, + }, + match: { + value: core.color.neutral[999].value, + }, + activeMatch: { + value: core.color.neutral[999].value, + }, + related: { + value: core.color.neutral[999].value, + }, + }, + gutter: { + primary: { + value: core.color.neutral[999].value, + }, + active: { + value: core.color.neutral[999].value, + }, + }, +}; + +const syntax = { + primary: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + comment: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + punctuation: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + constant: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + keyword: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + function: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + type: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + variant: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + property: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + enum: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + operator: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + string: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + number: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + boolean: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + predictive: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, +}; + +const player = { + 1: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, + }, + 2: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, + }, + 3: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, + }, + 4: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, + }, + 5: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, + }, + 6: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, + }, + 7: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, + }, + 8: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, + }, +}; + +const shadowAlpha = { + value: 0.32, +}; + export default function dark(): Theme { return { - backgroundColor: { - 100: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - 300: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - 500: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - ok: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - error: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - warning: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - info: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - }, - borderColor: { - primary: { - value: "#000000", - }, - secondary: { - value: "#000000", - }, - muted: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - active: { - value: "#000000", - }, - ok: { - value: "#000000", - }, - error: { - value: "#000000", - }, - warning: { - value: "#000000", - }, - info: { - value: "#000000", - }, - }, - textColor: { - primary: { - value: "#000000", - }, - secondary: { - value: "#000000", - }, - muted: { - value: "#000000", - }, - placeholder: { - value: "#000000", - }, - active: { - value: "#000000", - }, - feature: { - value: "#000000", - }, - ok: { - value: "#000000", - }, - error: { - value: "#000000", - }, - warning: { - value: "#000000", - }, - info: { - value: "#000000", - }, - }, - iconColor: { - primary: { - value: "#000000", - }, - secondary: { - value: "#000000", - }, - muted: { - value: "#000000", - }, - placeholder: { - value: "#000000", - }, - active: { - value: "#000000", - }, - feature: { - value: "#000000", - }, - ok: { - value: "#000000", - }, - error: { - value: "#000000", - }, - warning: { - value: "#000000", - }, - info: { - value: "#000000", - }, - }, - editor: { - background: { - value: "#000000", - }, - indent_guide: { - value: "#000000", - }, - indent_guide_active: { - value: "#000000", - }, - line: { - active: { - value: "#000000", - }, - highlighted: { - value: "#000000", - }, - inserted: { - value: "#000000", - }, - deleted: { - value: "#000000", - }, - modified: { - value: "#000000", - }, - }, - highlight: { - selection: { - value: "#000000", - }, - occurrence: { - value: "#000000", - }, - activeOccurrence: { - value: "#000000", - }, - matchingBracket: { - value: "#000000", - }, - match: { - value: "#000000", - }, - activeMatch: { - value: "#000000", - }, - related: { - value: "#000000", - }, - }, - gutter: { - primary: { - value: "#000000", - }, - active: { - value: "#000000", - }, - }, - }, - - syntax: { - primary: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - comment: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - punctuation: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - constant: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - keyword: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - function: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - type: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - variant: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - property: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - enum: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - operator: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - string: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - number: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - boolean: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - predictive: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - }, - player: { - 1: { - baseColor: { - value: "#000000", - }, - cursorColor: { - value: "#000000", - }, - selectionColor: { - value: "#000000", - }, - borderColor: { - value: "#000000", - }, - }, - 2: { - baseColor: { - value: "#000000", - }, - cursorColor: { - value: "#000000", - }, - selectionColor: { - value: "#000000", - }, - borderColor: { - value: "#000000", - }, - }, - 3: { - baseColor: { - value: "#000000", - }, - cursorColor: { - value: "#000000", - }, - selectionColor: { - value: "#000000", - }, - borderColor: { - value: "#000000", - }, - }, - 4: { - baseColor: { - value: "#000000", - }, - cursorColor: { - value: "#000000", - }, - selectionColor: { - value: "#000000", - }, - borderColor: { - value: "#000000", - }, - }, - 5: { - baseColor: { - value: "#000000", - }, - cursorColor: { - value: "#000000", - }, - selectionColor: { - value: "#000000", - }, - borderColor: { - value: "#000000", - }, - }, - 6: { - baseColor: { - value: "#000000", - }, - cursorColor: { - value: "#000000", - }, - selectionColor: { - value: "#000000", - }, - borderColor: { - value: "#000000", - }, - }, - 7: { - baseColor: { - value: "#000000", - }, - cursorColor: { - value: "#000000", - }, - selectionColor: { - value: "#000000", - }, - borderColor: { - value: "#000000", - }, - }, - 8: { - baseColor: { - value: "#000000", - }, - cursorColor: { - value: "#000000", - }, - selectionColor: { - value: "#000000", - }, - borderColor: { - value: "#000000", - }, - }, - }, - shadowAlpha: { - value: 0.32, - }, + backgroundColor, + borderColor, + textColor, + iconColor, + editor, + syntax, + player, + shadowAlpha, }; -} \ No newline at end of file +} From 210eb2f6b141cfdbf7bb47a0cc74a25a7925a2ad Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Thu, 31 Mar 2022 17:51:25 -0700 Subject: [PATCH 50/68] wip --- message.txt | 1672 ++++++++++++++++++++++++++++++++++++++++++++++++ styles/dark.ts | 814 +++++++++++------------ 2 files changed, 2080 insertions(+), 406 deletions(-) create mode 100644 message.txt diff --git a/message.txt b/message.txt new file mode 100644 index 0000000000..f086360d37 --- /dev/null +++ b/message.txt @@ -0,0 +1,1672 @@ +{ + "core": { + "color": { + "neutral": { + "0": { + "value": "#FFFFFF", + "type": "color" + }, + "50": { + "value": "#F8F8F8", + "type": "color" + }, + "100": { + "value": "#F0F0F0", + "type": "color" + }, + "150": { + "value": "#E1E1E1", + "type": "color" + }, + "200": { + "value": "#D2D2D2", + "type": "color" + }, + "250": { + "value": "#C3C3C3", + "type": "color" + }, + "300": { + "value": "#B4B4B4", + "type": "color" + }, + "350": { + "value": "#A5A5A5", + "type": "color" + }, + "400": { + "value": "#969696", + "type": "color" + }, + "450": { + "value": "#878787", + "type": "color" + }, + "500": { + "value": "#787878", + "type": "color" + }, + "550": { + "value": "#696969", + "type": "color" + }, + "600": { + "value": "#5A5A5A", + "type": "color" + }, + "650": { + "value": "#4B4B4B", + "type": "color" + }, + "700": { + "value": "#3C3C3C", + "type": "color" + }, + "750": { + "value": "#262626", + "type": "color" + }, + "800": { + "value": "#1E1E1E", + "type": "color" + }, + "850": { + "value": "#0F0F0F", + "type": "color" + }, + "900": { + "value": "#000000", + "type": "color" + } + }, + "steel": { + "0": { + "value": "#F8FAFC", + "type": "color" + }, + "100": { + "value": "#F1F5F9", + "type": "color" + }, + "200": { + "value": "#E2E8F0", + "type": "color" + }, + "300": { + "value": "#CBD5E1", + "type": "color" + }, + "400": { + "value": "#94A3BA", + "type": "color" + }, + "500": { + "value": "#64748B", + "type": "color" + }, + "600": { + "value": "#475569", + "type": "color" + }, + "700": { + "value": "#334155", + "type": "color" + }, + "800": { + "value": "#1E293B", + "type": "color" + }, + "900": { + "value": "#0F172A", + "type": "color" + } + }, + "gray": { + "0": { + "value": "#FAFAFA", + "type": "color" + }, + "100": { + "value": "#F4F4F5", + "type": "color" + }, + "200": { + "value": "#E4E4E7", + "type": "color" + }, + "300": { + "value": "#D4D4D8", + "type": "color" + }, + "400": { + "value": "#A1A1AA", + "type": "color" + }, + "500": { + "value": "#71717A", + "type": "color" + }, + "600": { + "value": "#52525B", + "type": "color" + }, + "700": { + "value": "#3F3F46", + "type": "color" + }, + "800": { + "value": "#27272A", + "type": "color" + }, + "900": { + "value": "#18181B", + "type": "color" + } + }, + "rose": { + "0": { + "value": "#FFF1F2", + "type": "color" + }, + "100": { + "value": "#FFE4E6", + "type": "color" + }, + "200": { + "value": "#FECDD3", + "type": "color" + }, + "300": { + "value": "#FDA4AF", + "type": "color" + }, + "400": { + "value": "#FB7185", + "type": "color" + }, + "500": { + "value": "#F43F5E", + "type": "color" + }, + "600": { + "value": "#E11D48", + "type": "color" + }, + "700": { + "value": "#BE123C", + "type": "color" + }, + "800": { + "value": "#9F1239", + "type": "color" + }, + "900": { + "value": "#881337", + "type": "color" + } + }, + "red": { + "0": { + "value": "#FEF2F2", + "type": "color" + }, + "100": { + "value": "#FEE2E2", + "type": "color" + }, + "200": { + "value": "#FECACA", + "type": "color" + }, + "300": { + "value": "#FCA5A5", + "type": "color" + }, + "400": { + "value": "#F87171", + "type": "color" + }, + "500": { + "value": "#EF4444", + "type": "color" + }, + "600": { + "value": "#DC2626", + "type": "color" + }, + "700": { + "value": "#B91C1C", + "type": "color" + }, + "800": { + "value": "#991B1B", + "type": "color" + }, + "900": { + "value": "#7F1D1D", + "type": "color" + } + }, + "orange": { + "0": { + "value": "#FFF7ED", + "type": "color" + }, + "100": { + "value": "#FFEDD5", + "type": "color" + }, + "200": { + "value": "#FED7AA", + "type": "color" + }, + "300": { + "value": "#FDBA74", + "type": "color" + }, + "400": { + "value": "#FB923C", + "type": "color" + }, + "500": { + "value": "#F97316", + "type": "color" + }, + "600": { + "value": "#EA580C", + "type": "color" + }, + "700": { + "value": "#C2410C", + "type": "color" + }, + "800": { + "value": "#9A3412", + "type": "color" + }, + "900": { + "value": "#7C2D12", + "type": "color" + } + }, + "amber": { + "0": { + "value": "#FFFBEB", + "type": "color" + }, + "100": { + "value": "#FEF3C7", + "type": "color" + }, + "200": { + "value": "#FDE68A", + "type": "color" + }, + "300": { + "value": "#FCD34D", + "type": "color" + }, + "400": { + "value": "#FBBF24", + "type": "color" + }, + "500": { + "value": "#F59E0B", + "type": "color" + }, + "600": { + "value": "#D97706", + "type": "color" + }, + "700": { + "value": "#B45309", + "type": "color" + }, + "800": { + "value": "#92400E", + "type": "color" + }, + "900": { + "value": "#78350F", + "type": "color" + } + }, + "yellow": { + "0": { + "value": "#FEFCE8", + "type": "color" + }, + "100": { + "value": "#FEF9C3", + "type": "color" + }, + "200": { + "value": "#FEF08A", + "type": "color" + }, + "300": { + "value": "#FDE047", + "type": "color" + }, + "400": { + "value": "#FACC15", + "type": "color" + }, + "500": { + "value": "#EAB308", + "type": "color" + }, + "600": { + "value": "#CA8A04", + "type": "color" + }, + "700": { + "value": "#A16207", + "type": "color" + }, + "800": { + "value": "#854D0E", + "type": "color" + }, + "900": { + "value": "#713F12", + "type": "color" + } + }, + "lime": { + "0": { + "value": "#F7FEE7", + "type": "color" + }, + "100": { + "value": "#ECFCCB", + "type": "color" + }, + "200": { + "value": "#D9F99D", + "type": "color" + }, + "300": { + "value": "#BEF264", + "type": "color" + }, + "400": { + "value": "#A3E635", + "type": "color" + }, + "500": { + "value": "#84CC16", + "type": "color" + }, + "600": { + "value": "#65A30D", + "type": "color" + }, + "700": { + "value": "#4D7C0F", + "type": "color" + }, + "800": { + "value": "#3F6212", + "type": "color" + }, + "900": { + "value": "#365314", + "type": "color" + } + }, + "green": { + "0": { + "value": "#F0FDF4", + "type": "color" + }, + "100": { + "value": "#DCFCE7", + "type": "color" + }, + "200": { + "value": "#BBF7D0", + "type": "color" + }, + "300": { + "value": "#86EFAC", + "type": "color" + }, + "400": { + "value": "#4ADE80", + "type": "color" + }, + "500": { + "value": "#22C55E", + "type": "color" + }, + "600": { + "value": "#16A34A", + "type": "color" + }, + "700": { + "value": "#15803D", + "type": "color" + }, + "800": { + "value": "#166534", + "type": "color" + }, + "900": { + "value": "#14532D", + "type": "color" + } + }, + "emerald": { + "0": { + "value": "#ECFDF5", + "type": "color" + }, + "100": { + "value": "#D1FAE5", + "type": "color" + }, + "200": { + "value": "#A7F3D0", + "type": "color" + }, + "300": { + "value": "#6EE7B7", + "type": "color" + }, + "400": { + "value": "#34D399", + "type": "color" + }, + "500": { + "value": "#10B981", + "type": "color" + }, + "600": { + "value": "#059669", + "type": "color" + }, + "700": { + "value": "#047857", + "type": "color" + }, + "800": { + "value": "#065F46", + "type": "color" + }, + "900": { + "value": "#064E3B", + "type": "color" + } + }, + "teal": { + "0": { + "value": "#F0FDFA", + "type": "color" + }, + "100": { + "value": "#CCFBF1", + "type": "color" + }, + "200": { + "value": "#99F6E4", + "type": "color" + }, + "300": { + "value": "#5EEAD4", + "type": "color" + }, + "400": { + "value": "#2DD4BF", + "type": "color" + }, + "500": { + "value": "#14B8A6", + "type": "color" + }, + "600": { + "value": "#0D9488", + "type": "color" + }, + "700": { + "value": "#0F766E", + "type": "color" + }, + "800": { + "value": "#115E59", + "type": "color" + }, + "900": { + "value": "#134E4A", + "type": "color" + } + }, + "cyan": { + "0": { + "value": "#ECFEFF", + "type": "color" + }, + "100": { + "value": "#CFFAFE", + "type": "color" + }, + "200": { + "value": "#A5F3FC", + "type": "color" + }, + "300": { + "value": "#67E8F9", + "type": "color" + }, + "400": { + "value": "#22D3EE", + "type": "color" + }, + "500": { + "value": "#06BBD4", + "type": "color" + }, + "600": { + "value": "#0891B2", + "type": "color" + }, + "700": { + "value": "#0E7490", + "type": "color" + }, + "800": { + "value": "#155E75", + "type": "color" + }, + "900": { + "value": "#164E63", + "type": "color" + } + }, + "sky": { + "0": { + "value": "#F0F9FF", + "type": "color" + }, + "100": { + "value": "#E0F2FE", + "type": "color" + }, + "200": { + "value": "#BAE6FD", + "type": "color" + }, + "300": { + "value": "#7DD3FC", + "type": "color" + }, + "400": { + "value": "#38BDF8", + "type": "color" + }, + "500": { + "value": "#0EA5E9", + "type": "color" + }, + "600": { + "value": "#0284C7", + "type": "color" + }, + "700": { + "value": "#0369A1", + "type": "color" + }, + "800": { + "value": "#075985", + "type": "color" + }, + "900": { + "value": "#0C4A6E", + "type": "color" + } + }, + "blue": { + "0": { + "value": "#EFF6FF", + "type": "color" + }, + "100": { + "value": "#DBEAFE", + "type": "color" + }, + "200": { + "value": "#BFDBFE", + "type": "color" + }, + "300": { + "value": "#93C5FD", + "type": "color" + }, + "400": { + "value": "#60A5FA", + "type": "color" + }, + "500": { + "value": "#3B82F6", + "type": "color" + }, + "600": { + "value": "#2563EB", + "type": "color" + }, + "700": { + "value": "#1D4ED8", + "type": "color" + }, + "800": { + "value": "#1E40A4", + "type": "color" + }, + "900": { + "value": "#1E3A8A", + "type": "color" + } + }, + "indigo": { + "0": { + "value": "#EEF2FF", + "type": "color" + }, + "100": { + "value": "#E0E7FF", + "type": "color" + }, + "200": { + "value": "#C7D2FE", + "type": "color" + }, + "300": { + "value": "#A5B4FC", + "type": "color" + }, + "400": { + "value": "#818CF8", + "type": "color" + }, + "500": { + "value": "#6366F1", + "type": "color" + }, + "600": { + "value": "#4F46E5", + "type": "color" + }, + "700": { + "value": "#4338CA", + "type": "color" + }, + "800": { + "value": "#3730A3", + "type": "color" + }, + "900": { + "value": "#312E81", + "type": "color" + } + }, + "violet": { + "0": { + "value": "#F5F3FF", + "type": "color" + }, + "100": { + "value": "#EDE9FE", + "type": "color" + }, + "200": { + "value": "#DDD6FE", + "type": "color" + }, + "300": { + "value": "#C4B5FD", + "type": "color" + }, + "400": { + "value": "#A78BFA", + "type": "color" + }, + "500": { + "value": "#8B5CF6", + "type": "color" + }, + "600": { + "value": "#7C3AED", + "type": "color" + }, + "700": { + "value": "#6D28D9", + "type": "color" + }, + "800": { + "value": "#5B21B6", + "type": "color" + }, + "900": { + "value": "#4C1D95", + "type": "color" + } + }, + "purple": { + "0": { + "value": "#FAF5FF", + "type": "color" + }, + "100": { + "value": "#F3E8FF", + "type": "color" + }, + "200": { + "value": "#E9D5FF", + "type": "color" + }, + "300": { + "value": "#D8B4FE", + "type": "color" + }, + "400": { + "value": "#C084FC", + "type": "color" + }, + "500": { + "value": "#A855F7", + "type": "color" + }, + "600": { + "value": "#9333EA", + "type": "color" + }, + "700": { + "value": "#7E22CE", + "type": "color" + }, + "800": { + "value": "#6B21A8", + "type": "color" + }, + "900": { + "value": "#581C87", + "type": "color" + } + }, + "fuschia": { + "0": { + "value": "#FDF4FF", + "type": "color" + }, + "100": { + "value": "#FAE8FF", + "type": "color" + }, + "200": { + "value": "#F5D0FE", + "type": "color" + }, + "300": { + "value": "#F0ABFC", + "type": "color" + }, + "400": { + "value": "#E879F9", + "type": "color" + }, + "500": { + "value": "#D946E4", + "type": "color" + }, + "600": { + "value": "#C026D3", + "type": "color" + }, + "700": { + "value": "#A21CAF", + "type": "color" + }, + "800": { + "value": "#86198F", + "type": "color" + }, + "900": { + "value": "#701A75", + "type": "color" + } + }, + "pink": { + "0": { + "value": "#FDF2F8", + "type": "color" + }, + "100": { + "value": "#FCE7F3", + "type": "color" + }, + "200": { + "value": "#FBCFE8", + "type": "color" + }, + "300": { + "value": "#F988D4", + "type": "color" + }, + "400": { + "value": "#F472B6", + "type": "color" + }, + "500": { + "value": "#EC4899", + "type": "color" + }, + "600": { + "value": "#DB2777", + "type": "color" + }, + "700": { + "value": "#BE185D", + "type": "color" + }, + "800": { + "value": "#9D174D", + "type": "color" + }, + "900": { + "value": "#831843", + "type": "color" + } + } + }, + "font-weight": { + "normal": { + "100": { + "value": "Thin", + "type": "fontWeights" + }, + "200": { + "value": "Light", + "type": "fontWeights" + }, + "400": { + "value": "Regular", + "type": "fontWeights" + }, + "500": { + "value": "Semibold", + "type": "fontWeights" + }, + "600": { + "value": "Bold", + "type": "fontWeights" + }, + "800": { + "value": "Heavy", + "type": "fontWeights" + } + }, + "normal-bold": { + "100": { + "value": "Thin", + "type": "fontWeights" + }, + "200": { + "value": "Light", + "type": "fontWeights" + }, + "400": { + "value": "Regular", + "type": "fontWeights" + }, + "500": { + "value": "Semibold", + "type": "fontWeights" + }, + "600": { + "value": "Bold", + "type": "fontWeights" + }, + "800": { + "value": "Heavy", + "type": "fontWeights" + } + }, + "italic": { + "100": { + "value": "Thin Italic", + "type": "fontWeights" + }, + "200": { + "value": "Light", + "type": "fontWeights" + }, + "400": { + "value": "Regular", + "type": "fontWeights" + }, + "500": { + "value": "Semibold", + "type": "fontWeights" + }, + "600": { + "value": "Bold", + "type": "fontWeights" + }, + "800": { + "value": "Heavy", + "type": "fontWeights" + } + }, + "italic-bold": { + "100": { + "value": "Thin Italic", + "type": "fontWeights" + }, + "200": { + "value": "Light", + "type": "fontWeights" + }, + "400": { + "value": "Regular", + "type": "fontWeights" + }, + "500": { + "value": "Semibold", + "type": "fontWeights" + }, + "600": { + "value": "Bold", + "type": "fontWeights" + }, + "800": { + "value": "Heavy", + "type": "fontWeights" + } + } + }, + "font-family": { + "zed-mono": { + "value": "Zed Mono", + "type": "fontFamilies" + }, + "zed-sans": { + "value": "Zed Sans", + "type": "fontFamilies" + } + }, + "font-size": { + "3xs": { + "value": "8", + "type": "fontSizes" + }, + "2xs": { + "value": "10", + "type": "fontSizes" + }, + "xs": { + "value": "12", + "type": "fontSizes" + }, + "sm": { + "value": "14", + "type": "fontSizes" + }, + "base": { + "value": "16", + "type": "fontSizes" + }, + "lg": { + "value": "18", + "type": "fontSizes" + }, + "xl": { + "value": "20", + "type": "fontSizes" + } + }, + "leading": { + "xs": { + "value": "16", + "type": "lineHeights" + }, + "sm": { + "value": "20", + "type": "lineHeights" + }, + "base": { + "value": "24", + "type": "lineHeights" + }, + "lg": { + "value": "26", + "type": "lineHeights" + }, + "xl": { + "value": "28", + "type": "lineHeights" + }, + "2xl": { + "value": "30", + "type": "lineHeights" + } + }, + "text-decoration": { + "none": { + "value": "none", + "type": "textDecoration" + } + }, + "ui-text": { + "normal": { + "base": { + "value": { + "fontFamily": "{font-family.zed-sans}", + "fontWeight": "$font-weight.normal.400", + "lineHeight": "{leading.sm}", + "fontSize": "{font-size.sm}", + "letterSpacing": "{letter-spacing.base}", + "paragraphSpacing": "{paragraph-spacing.default}", + "textCase": "{text-case.default}", + "decoration": "{text-decoration.none}", + "textDecoration": "{text-decoration.none}" + }, + "type": "typography", + "bold": { + "value": { + "fontFamily": "$text.family.zed-sans", + "fontWeight": "$text.weight.bold", + "lineHeight": "$text.leading.base", + "fontSize": "$text.size.xs", + "letterSpacing": "$text.tracking.default", + "paragraphSpacing": "$text.paragraphSpacing.0", + "textCase": "$text.case.default", + "decoration": "$text.decoration.none", + "textDecoration": "$text.decoration.none" + }, + "type": "typography" + } + }, + "sm": { + "value": { + "fontFamily": "{font-family.zed-sans}", + "fontWeight": "$font-weight.normal.400", + "lineHeight": "{leading.xs}", + "fontSize": "{font-size.xs}", + "letterSpacing": "{letter-spacing.base}", + "paragraphSpacing": "{paragraph-spacing.default}", + "textCase": "{text-case.default}", + "decoration": "{text-decoration.none}", + "textDecoration": "{text-decoration.none}" + }, + "type": "typography", + "bold": { + "value": { + "fontFamily": "$text.family.zed-sans", + "fontWeight": "$text.weight.bold", + "lineHeight": "$text.leading.base", + "fontSize": "$text.size.xs", + "letterSpacing": "$text.tracking.default", + "paragraphSpacing": "$text.paragraphSpacing.0", + "textCase": "$text.case.default", + "decoration": "$text.decoration.none", + "textDecoration": "$text.decoration.none" + }, + "type": "typography" + } + } + }, + "bold": { + "base": { + "value": { + "fontFamily": "{font-family.zed-sans}", + "fontWeight": "$font-weight.normal.600", + "lineHeight": "{leading.base}", + "fontSize": "{font-size.sm}", + "letterSpacing": "{letter-spacing.sm}", + "paragraphSpacing": "{paragraph-spacing.default}", + "textCase": "{text-case.default}", + "decoration": "{text-decoration.none}", + "textDecoration": "{text-decoration.none}" + }, + "type": "typography" + }, + "sm": { + "value": { + "fontFamily": "{font-family.zed-sans}", + "fontWeight": "$font-weight.normal.600", + "lineHeight": "{leading.xs}", + "fontSize": "{font-size.xs}", + "letterSpacing": "{letter-spacing.base}", + "paragraphSpacing": "{paragraph-spacing.default}", + "textCase": "{text-case.default}", + "decoration": "{text-decoration.none}", + "textDecoration": "{text-decoration.none}" + }, + "type": "typography" + } + } + }, + "buffer-text": { + "normal": { + "xs": { + "value": { + "fontFamily": "{font-family.zed-mono}", + "fontWeight": "$font-weight.normal.400", + "lineHeight": "{leading.xs}", + "fontSize": "{font-size.xs}", + "letterSpacing": "{letter-spacing.base}", + "paragraphSpacing": "{paragraph-spacing.default}", + "textCase": "{text-case.default}", + "decoration": "{text-decoration.none}", + "textDecoration": "{text-decoration.none}" + }, + "type": "typography" + }, + "sm": { + "value": { + "fontFamily": "{font-family.zed-mono}", + "fontWeight": "$font-weight.normal.400", + "lineHeight": "{leading.sm}", + "fontSize": "{font-size.sm}", + "letterSpacing": "{letter-spacing.base}", + "paragraphSpacing": "{paragraph-spacing.default}", + "textCase": "{text-case.default}", + "decoration": "{text-decoration.none}", + "textDecoration": "{text-decoration.none}" + }, + "type": "typography" + }, + "base": { + "value": { + "fontFamily": "{font-family.zed-mono}", + "fontWeight": "$font-weight.normal.400", + "lineHeight": "{leading.lg}", + "fontSize": "{font-size.base}", + "letterSpacing": "{letter-spacing.base}", + "paragraphSpacing": "{paragraph-spacing.default}", + "textCase": "{text-case.default}", + "decoration": "{text-decoration.none}", + "textDecoration": "$text.decoration.default" + }, + "type": "typography" + }, + "lg": { + "value": { + "fontFamily": "{font-family.zed-mono}", + "fontWeight": "$font-weight.normal.400", + "lineHeight": "{leading.lg}", + "fontSize": "{font-size.lg}", + "letterSpacing": "{letter-spacing.base}", + "paragraphSpacing": "{paragraph-spacing.default}", + "textCase": "{text-case.default}", + "decoration": "{text-decoration.none}", + "textDecoration": "$text.decoration.default" + }, + "type": "typography" + } + } + }, + "letter-spacing": { + "tight": { + "value": "-0.05", + "type": "letterSpacing" + }, + "base": { + "value": "0%", + "type": "letterSpacing" + }, + "wide": { + "value": "0.05", + "type": "letterSpacing" + } + }, + "paragraph-spacing": { + "default": { + "value": "0", + "type": "paragraphSpacing" + } + }, + "text-case": { + "default": { + "value": "none", + "type": "textCase" + }, + "lowercase": { + "value": "lowercase", + "type": "textCase" + }, + "uppercase": { + "value": "uppercase", + "type": "textCase" + } + }, + "space": { + "s-0": { + "value": "0", + "type": "spacing" + }, + "s-4": { + "value": "{var.base}", + "type": "spacing" + }, + "s-8": { + "value": "{var.base} * 2", + "type": "spacing" + }, + "s-12": { + "value": "{var.base} * 3", + "type": "spacing" + }, + "s-16": { + "value": "{var.base} * 4", + "type": "spacing" + } + }, + "internal": { + "mac-os": { + "red": { + "value": "#FF5E57", + "type": "color" + }, + "yellow": { + "value": "#FFBB2E", + "type": "color" + }, + "green": { + "value": "#38C149", + "type": "color" + } + } + }, + "border-radius": { + "xs": { + "value": "2", + "type": "borderRadius" + }, + "sm": { + "value": "4", + "type": "borderRadius" + }, + "base": { + "value": "6", + "type": "borderRadius" + }, + "lg": { + "value": "8", + "type": "borderRadius" + }, + "xl": { + "value": "10", + "type": "borderRadius" + } + }, + "border-width": { + "base": { + "value": "1", + "type": "borderWidth" + } + }, + "elevation": { + "300": { + "value": { + "x": "0", + "y": "4", + "blur": "12", + "spread": "0", + "color": "rgba({color.neutral.900}, {shadow.base})", + "type": "dropShadow" + }, + "type": "boxShadow" + } + }, + "var": { + "base": { + "value": "4", + "type": "other" + } + } + }, + "dark": { + "text-color": { + "primary": { + "value": "{color.neutral.150}", + "type": "color" + }, + "secondary": { + "value": "{color.neutral.350}", + "type": "color" + }, + "muted": { + "value": "{color.neutral.550}", + "type": "color" + }, + "minimal": { + "value": "{color.neutral.750}", + "type": "color" + }, + "active": { + "value": "{color.neutral.0}", + "type": "color" + }, + "disabled": { + "value": "{color.neutral.650}", + "type": "color" + }, + "positive": { + "value": "{color.green.600}", + "type": "color" + }, + "negative": { + "value": "{color.red.400}", + "type": "color" + }, + "warning": { + "value": "{color.amber.300}", + "type": "color" + }, + "info": { + "value": "{color.blue.500}", + "type": "color" + } + }, + "icon-color": { + "primary": { + "value": "{text.secondary}", + "type": "color" + }, + "secondary": { + "value": "{text.muted}", + "type": "color" + }, + "active": { + "value": "{text.active}", + "type": "color" + }, + "disabled": { + "value": "{text.disabled}", + "type": "color" + }, + "positive": { + "value": "{color.green.600}", + "type": "color" + }, + "negative": { + "value": "{color.red.400}", + "type": "color" + }, + "warning": { + "value": "{color.amber.300}", + "type": "color" + }, + "info": { + "value": "{color.blue.500}", + "type": "color" + } + }, + "icon-size": { + "default": { + "value": "16", + "type": "size" + } + }, + "background-color": { + "100": { + "value": "{color.neutral.750}", + "type": "color", + "description": "The app background. Used for title-bar, other daylight." + }, + "300": { + "value": "{color.neutral.800}", + "type": "color", + "description": "The primary surface layer. Used for tabs, panels, pop-overs, etc." + }, + "500": { + "value": "{color.neutral.900}", + "type": "color", + "description": "Used for the buffer background and active buffer tabs." + }, + "active": { + "value": "rgba({icon.active}}, 0.1)", + "type": "color" + }, + "focused": { + "value": "// wip", + "type": "color" + }, + "disabled": { + "value": "// wip", + "type": "color" + }, + "positive": { + "value": "{color.green.600}", + "type": "color" + }, + "negative": { + "value": "{color.red.400}", + "type": "color" + }, + "warning": { + "value": "{color.amber.300}", + "type": "color" + }, + "info": { + "value": "{color.blue.500}", + "type": "color" + } + }, + "border-color": { + "default": { + "value": "{color.neutral.850}", + "type": "color" + }, + "secondary": { + "value": "{color.neutral.700}", + "type": "color" + }, + "minimal": { + "value": "{color.neutral.750}", + "type": "color" + }, + "active": { + "value": "{color.neutral.500}", + "type": "color" + }, + "focused": { + "value": "{color.neutral.100}", + "type": "color" + } + }, + "editor": { + "background-color": { + "value": "{surface.500}", + "type": "color" + }, + "indent-guide": { + "value": "{icon.disabled}", + "type": "color" + }, + "indent-guide-active": { + "value": "{icon.secondary}", + "type": "color" + }, + "highlight": { + "active-line": { + "value": "rgba({color.neutral.0}, 0.08)", + "type": "color" + }, + "selection": { + "value": "{player.selection.one}", + "type": "color" + }, + "folded-line": { + "value": "rgba({surface.500}, 0.03)", + "type": "color" + }, + "occurrence": { + "value": "rgba({text.active}, 0.15)", + "type": "color" + }, + "matching-bracket": { + "value": "rgba({color.indigo.500}, 0.8)", + "type": "color" + }, + "match": { + "value": "rgba({color.blue.500},0.5)", + "type": "color" + }, + "active-match": { + "value": "rgba({color.blue.500},0.8)", + "type": "color" + } + }, + "gutter": { + "primary": { + "value": "{text.muted}", + "type": "color" + }, + "active": { + "value": "{text.active}", + "type": "color" + } + }, + "syntax": { + "primary": { + "value": "{text.primary}", + "type": "color" + }, + "comment": { + "value": "{color.lime.200}", + "type": "color" + }, + "punctuation": { + "value": "{text.secondary}", + "type": "color" + }, + "constant": { + "value": "{syntax.primary}", + "type": "color" + }, + "keyword": { + "value": "{color.sky.400}", + "type": "color" + }, + "function": { + "value": "{color.yellow.200}", + "type": "color" + }, + "type": { + "value": "{color.teal.300}", + "type": "color" + }, + "variant": { + "value": "{syntax.type}", + "type": "color" + }, + "property": { + "value": "{color.sky.300}", + "type": "color" + }, + "enum": { + "value": "{syntax.operator}", + "type": "color" + }, + "operator": { + "value": "{syntax.keyword}", + "type": "color" + }, + "string": { + "value": "{color.orange.300}", + "type": "color" + }, + "number": { + "value": "{syntax.primary}", + "type": "color" + }, + "boolean": { + "value": "{syntax.number}", + "type": "color" + }, + "predictive": { + "value": "{text.muted}", + "type": "color" + } + } + }, + "player": { + "color": { + "1": { + "value": "{color.blue.600}", + "type": "color" + }, + "2": { + "value": "{color.indigo.500}", + "type": "color" + }, + "3": { + "value": "{color.green.500}", + "type": "color" + }, + "4": { + "value": "{color.orange.500}", + "type": "color" + }, + "5": { + "value": "{color.purple.500}", + "type": "color" + }, + "6": { + "value": "{color.teal.400}", + "type": "color" + }, + "7": { + "value": "{color.pink.400}", + "type": "color" + }, + "8": { + "value": "{color.yellow.400}", + "type": "color" + } + }, + "selection": { + "1": { + "value": "rgba({color.blue.600},0.1)", + "type": "color" + }, + "2": { + "value": "rgba({color.indigo.500}, 0.1)", + "type": "color" + }, + "3": { + "value": "rgba({color.green.500}, 0.1)", + "type": "color" + }, + "4": { + "value": "rgba({color.orange.500}, 0.15)", + "type": "color" + }, + "5": { + "value": "rgba({color.purple.500}, 0.1)", + "type": "color" + }, + "6": { + "value": "rgba({color.teal.400}, 0.1)", + "type": "color" + }, + "7": { + "value": "rgba({color.pink.400}, 0.1)", + "type": "color" + }, + "8": { + "value": "rgba({color.yellow.400}, 0.15)", + "type": "color" + } + } + }, + "shadow": { + "base": { + "value": "0.36", + "type": "opacity" + } + } + } +} \ No newline at end of file diff --git a/styles/dark.ts b/styles/dark.ts index efd2d3b8a4..bfcac3db81 100644 --- a/styles/dark.ts +++ b/styles/dark.ts @@ -2,455 +2,457 @@ import core from "./core"; import Theme from "./theme"; const backgroundColor = { - 100: { - base: { - value: core.color.neutral[999].value, + 100: { + base: { + value: core.color.neutral[999].value, + }, + hovered: { + value: core.color.neutral[999].value, + }, + active: { + value: core.color.neutral[999].value, + }, + focused: { + value: core.color.neutral[999].value, + }, }, - hovered: { - value: core.color.neutral[999].value, + 300: { + base: { + value: core.color.neutral[999].value, + }, + hovered: { + value: core.color.neutral[999].value, + }, + active: { + value: core.color.neutral[999].value, + }, + focused: { + value: core.color.neutral[999].value, + }, }, - active: { - value: core.color.neutral[999].value, + 500: { + base: { + value: core.color.neutral[999].value, + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, }, - focused: { - value: core.color.neutral[999].value, + ok: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, }, - }, - 300: { - base: { - value: core.color.neutral[999].value, + error: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, }, - hovered: { - value: core.color.neutral[999].value, + warning: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, }, - active: { - value: core.color.neutral[999].value, + info: { + base: { + value: "#000000", + }, + hovered: { + value: "#000000", + }, + active: { + value: "#000000", + }, + focused: { + value: "#000000", + }, }, - focused: { - value: core.color.neutral[999].value, - }, - }, - 500: { - base: { - value: core.color.neutral[999].value, - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - ok: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - error: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - warning: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, - info: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - }, }; const borderColor = { - primary: { - value: "#000000", - }, - secondary: { - value: "#000000", - }, - muted: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - active: { - value: "#000000", - }, - ok: { - value: "#000000", - }, - error: { - value: "#000000", - }, - warning: { - value: "#000000", - }, - info: { - value: "#000000", - }, + primary: { + value: "#000000", + }, + secondary: { + value: "#000000", + }, + muted: { + value: "#000000", + }, + focused: { + value: "#000000", + }, + active: { + value: "#000000", + }, + ok: { + value: "#000000", + }, + error: { + value: "#000000", + }, + warning: { + value: "#000000", + }, + info: { + value: "#000000", + }, }; const textColor = { - primary: { - value: core.color.neutral[150].value, - }, - secondary: { - value: core.color.neutral[350].value, - }, - muted: { - value: core.color.neutral[550].value, - }, - placeholder: { - value: core.color.neutral[750].value, - }, - active: { - value: core.color.neutral[0].value, - }, - feature: { - //TODO: (design) define feature and it's correct value - value: core.color.sky[500].value, - }, - ok: { - value: core.color.green[600].value, - }, - error: { - value: core.color.red[400].value, - }, - warning: { - value: core.color.amber[300].value, - }, - info: { - value: core.color.blue[500].value, - }, + primary: { + value: core.color.neutral[150].value, + }, + secondary: { + value: core.color.neutral[350].value, + }, + muted: { + value: core.color.neutral[550].value, + }, + placeholder: { + value: core.color.neutral[750].value, + }, + active: { + value: core.color.neutral[0].value, + }, + feature: { + //TODO: (design) define feature and it's correct value + value: core.color.sky[500].value, + }, + ok: { + value: core.color.green[600].value, + }, + error: { + value: core.color.red[400].value, + }, + warning: { + value: core.color.amber[300].value, + }, + info: { + value: core.color.blue[500].value, + }, }; const iconColor = { - primary: { - value: core.color.neutral[300].value, - }, - secondary: { - value: core.color.neutral[500].value, - }, - muted: { - value: core.color.neutral[600].value, - }, - placeholder: { - value: core.color.neutral[700].value, - }, - active: { - value: core.color.neutral[50].value, - }, - feature: { - //TODO: (design) define feature and it's correct value - value: core.color.sky[500].value, - }, - ok: { - value: core.color.green[600].value, - }, - error: { - value: core.color.red[400].value, - }, - warning: { - value: core.color.amber[300].value, - }, - info: { - value: core.color.blue[500].value, - }, + primary: { + value: core.color.neutral[300].value, + }, + secondary: { + value: core.color.neutral[500].value, + }, + muted: { + value: core.color.neutral[600].value, + }, + placeholder: { + value: core.color.neutral[700].value, + }, + active: { + value: core.color.neutral[50].value, + }, + feature: { + //TODO: (design) define feature and it's correct value + value: core.color.sky[500].value, + }, + ok: { + value: core.color.green[600].value, + }, + error: { + value: core.color.red[400].value, + }, + warning: { + value: core.color.amber[300].value, + }, + info: { + value: core.color.blue[500].value, + }, }; const editor = { - background: { - value: backgroundColor[500].base.value, - }, - indent_guide: { - value: core.color.neutral[999].value, - }, - indent_guide_active: { - value: core.color.neutral[999].value, - }, - line: { - active: { - value: core.color.neutral[999].value, + background: { + value: backgroundColor[500].base.value, }, - highlighted: { - value: core.color.neutral[999].value, + indent_guide: { + value: core.color.neutral[999].value, }, - inserted: { - value: core.color.neutral[999].value, + indent_guide_active: { + value: core.color.neutral[999].value, }, - deleted: { - value: core.color.neutral[999].value, + line: { + active: { + value: core.color.neutral[999].value, + }, + highlighted: { + value: core.color.neutral[999].value, + }, + inserted: { + value: core.color.neutral[999].value, + }, + deleted: { + value: core.color.neutral[999].value, + }, + modified: { + value: core.color.neutral[999].value, + }, }, - modified: { - value: core.color.neutral[999].value, + highlight: { + selection: { + value: core.color.neutral[999].value, + }, + occurrence: { + value: core.color.neutral[999].value, + }, + activeOccurrence: { + value: core.color.neutral[999].value, + }, + matchingBracket: { + value: core.color.neutral[999].value, + }, + match: { + value: core.color.neutral[999].value, + }, + activeMatch: { + value: core.color.neutral[999].value, + }, + related: { + value: core.color.neutral[999].value, + }, }, - }, - highlight: { - selection: { - value: core.color.neutral[999].value, + gutter: { + primary: { + value: core.color.neutral[999].value, + }, + active: { + value: core.color.neutral[999].value, + }, }, - occurrence: { - value: core.color.neutral[999].value, - }, - activeOccurrence: { - value: core.color.neutral[999].value, - }, - matchingBracket: { - value: core.color.neutral[999].value, - }, - match: { - value: core.color.neutral[999].value, - }, - activeMatch: { - value: core.color.neutral[999].value, - }, - related: { - value: core.color.neutral[999].value, - }, - }, - gutter: { - primary: { - value: core.color.neutral[999].value, - }, - active: { - value: core.color.neutral[999].value, - }, - }, }; const syntax = { - primary: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - comment: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - punctuation: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - constant: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - keyword: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - function: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - type: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - variant: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - property: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - enum: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - operator: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - string: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - number: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - boolean: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, - predictive: { - color: { value: "000000" }, - weight: { value: "normal" }, - }, + primary: { + color: { + value: core.color.neutral[150] + }, + weight: { value: "normal" }, + }, + comment: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + punctuation: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + constant: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + keyword: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + function: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + type: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + variant: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + property: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + enum: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + operator: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + string: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + number: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + boolean: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, + predictive: { + color: { value: "000000" }, + weight: { value: "normal" }, + }, }; const player = { - 1: { - baseColor: { - value: core.color.neutral[999].value, + 1: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, }, - cursorColor: { - value: core.color.neutral[999].value, + 2: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, }, - selectionColor: { - value: core.color.neutral[999].value, + 3: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, }, - borderColor: { - value: core.color.neutral[999].value, + 4: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, }, - }, - 2: { - baseColor: { - value: core.color.neutral[999].value, + 5: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, }, - cursorColor: { - value: core.color.neutral[999].value, + 6: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, }, - selectionColor: { - value: core.color.neutral[999].value, + 7: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, }, - borderColor: { - value: core.color.neutral[999].value, + 8: { + baseColor: { + value: core.color.neutral[999].value, + }, + cursorColor: { + value: core.color.neutral[999].value, + }, + selectionColor: { + value: core.color.neutral[999].value, + }, + borderColor: { + value: core.color.neutral[999].value, + }, }, - }, - 3: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, - }, - 4: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, - }, - 5: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, - }, - 6: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, - }, - 7: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, - }, - 8: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, - }, }; const shadowAlpha = { - value: 0.32, + value: 0.32, }; export default function dark(): Theme { - return { - backgroundColor, - borderColor, - textColor, - iconColor, - editor, - syntax, - player, - shadowAlpha, - }; + return { + backgroundColor, + borderColor, + textColor, + iconColor, + editor, + syntax, + player, + shadowAlpha, + }; } From f11e0aeda936b60ff42578e82a4a6cca43eb5813 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Thu, 31 Mar 2022 19:05:21 -0700 Subject: [PATCH 51/68] wip --- styles/core.ts | 102 +++++------ styles/dark.ts | 462 +++++++++++++----------------------------------- styles/theme.ts | 354 ++++++++++++++----------------------- 3 files changed, 305 insertions(+), 613 deletions(-) diff --git a/styles/core.ts b/styles/core.ts index e9e81982e4..49e376b4eb 100644 --- a/styles/core.ts +++ b/styles/core.ts @@ -1,58 +1,58 @@ import { colorRamp } from "./lib"; export default { - fontFamily: { - sans: "Zed Sans", - mono: "Zed Mono", - }, - fontSize: { - "3xs": { - value: "8", - type: "fontSizes", + fontFamily: { + sans: "Zed Sans", + mono: "Zed Mono", }, - "2xs": { - value: "10", - type: "fontSizes", + fontSize: { + "3xs": { + value: "8", + type: "fontSizes", + }, + "2xs": { + value: "10", + type: "fontSizes", + }, + xs: { + value: "12", + type: "fontSizes", + }, + sm: { + value: "14", + type: "fontSizes", + }, + md: { + value: "16", + type: "fontSizes", + }, + lg: { + value: "18", + type: "fontSizes", + }, + xl: { + value: "20", + type: "fontSizes", + }, }, - xs: { - value: "12", - type: "fontSizes", + color: { + neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }), + rose: colorRamp("#F43F5EFF"), + red: colorRamp("#EF4444FF"), + orange: colorRamp("#F97316FF"), + amber: colorRamp("#F59E0BFF"), + yellow: colorRamp("#EAB308FF"), + lime: colorRamp("#84CC16FF"), + green: colorRamp("#22C55EFF"), + emerald: colorRamp("#10B981FF"), + teal: colorRamp("#14B8A6FF"), + cyan: colorRamp("#06BBD4FF"), + sky: colorRamp("#0EA5E9FF"), + blue: colorRamp("#3B82F6FF"), + indigo: colorRamp("#6366F1FF"), + violet: colorRamp("#8B5CF6FF"), + purple: colorRamp("#A855F7FF"), + fuschia: colorRamp("#D946E4FF"), + pink: colorRamp("#EC4899FF"), }, - sm: { - value: "14", - type: "fontSizes", - }, - md: { - value: "16", - type: "fontSizes", - }, - lg: { - value: "18", - type: "fontSizes", - }, - xl: { - value: "20", - type: "fontSizes", - }, - }, - color: { - neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }), - rose: colorRamp("#F43F5EFF"), - red: colorRamp("#EF4444FF"), - orange: colorRamp("#F97316FF"), - amber: colorRamp("#F59E0BFF"), - yellow: colorRamp("#EAB308FF"), - lime: colorRamp("#84CC16FF"), - green: colorRamp("#22C55EFF"), - emerald: colorRamp("#10B981FF"), - teal: colorRamp("#14B8A6FF"), - cyan: colorRamp("#06BBD4FF"), - sky: colorRamp("#0EA5E9FF"), - blue: colorRamp("#3B82F6FF"), - indigo: colorRamp("#6366F1FF"), - violet: colorRamp("#8B5CF6FF"), - purple: colorRamp("#A855F7FF"), - fuschia: colorRamp("#D946E4FF"), - pink: colorRamp("#EC4899FF"), - }, }; diff --git a/styles/dark.ts b/styles/dark.ts index bfcac3db81..5b60bd0316 100644 --- a/styles/dark.ts +++ b/styles/dark.ts @@ -1,442 +1,230 @@ import core from "./core"; import Theme from "./theme"; +const { color } = core; + const backgroundColor = { 100: { - base: { - value: core.color.neutral[999].value, - }, - hovered: { - value: core.color.neutral[999].value, - }, - active: { - value: core.color.neutral[999].value, - }, - focused: { - value: core.color.neutral[999].value, - }, + base: color.neutral[750], + hovered: color.neutral[750], + active: color.neutral[750], + focused: color.neutral[750], }, 300: { - base: { - value: core.color.neutral[999].value, - }, - hovered: { - value: core.color.neutral[999].value, - }, - active: { - value: core.color.neutral[999].value, - }, - focused: { - value: core.color.neutral[999].value, - }, + base: color.neutral[800], + hovered: color.neutral[800], + active: color.neutral[800], + focused: color.neutral[800], }, 500: { - base: { - value: core.color.neutral[999].value, - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, + base: color.neutral[900], + hovered: color.neutral[900], + active: color.neutral[900], + focused: color.neutral[900], }, ok: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, + base: color.green[600], + hovered: color.green[600], + active: color.green[600], + focused: color.green[600], }, error: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, + base: color.red[400], + hovered: color.red[400], + active: color.red[400], + focused: color.red[400], }, warning: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, + base: color.amber[300], + hovered: color.amber[300], + active: color.amber[300], + focused: color.amber[300], }, info: { - base: { - value: "#000000", - }, - hovered: { - value: "#000000", - }, - active: { - value: "#000000", - }, - focused: { - value: "#000000", - }, + base: color.blue[500], + hovered: color.blue[500], + active: color.blue[500], + focused: color.blue[500], }, }; const borderColor = { - primary: { - value: "#000000", - }, - secondary: { - value: "#000000", - }, - muted: { - value: "#000000", - }, - focused: { - value: "#000000", - }, - active: { - value: "#000000", - }, - ok: { - value: "#000000", - }, - error: { - value: "#000000", - }, - warning: { - value: "#000000", - }, - info: { - value: "#000000", - }, + primary: color.neutral[850], + secondary: color.neutral[700], + muted: color.neutral[750], + focused: color.neutral[100], + active: color.neutral[500], + ok: color.neutral[999], + error: color.neutral[999], + warning: color.neutral[999], + info: color.neutral[999], }; const textColor = { - primary: { - value: core.color.neutral[150].value, - }, - secondary: { - value: core.color.neutral[350].value, - }, - muted: { - value: core.color.neutral[550].value, - }, - placeholder: { - value: core.color.neutral[750].value, - }, - active: { - value: core.color.neutral[0].value, - }, - feature: { - //TODO: (design) define feature and it's correct value - value: core.color.sky[500].value, - }, - ok: { - value: core.color.green[600].value, - }, - error: { - value: core.color.red[400].value, - }, - warning: { - value: core.color.amber[300].value, - }, - info: { - value: core.color.blue[500].value, - }, + primary: color.neutral[150], + secondary: color.neutral[350], + muted: color.neutral[550], + placeholder: color.neutral[750], + active: color.neutral[0], + //TODO: (design) define feature and it's correct value + feature: color.sky[500], + ok: color.green[600], + error: color.red[400], + warning: color.amber[300], + info: color.blue[500], }; const iconColor = { - primary: { - value: core.color.neutral[300].value, - }, - secondary: { - value: core.color.neutral[500].value, - }, - muted: { - value: core.color.neutral[600].value, - }, - placeholder: { - value: core.color.neutral[700].value, - }, - active: { - value: core.color.neutral[50].value, - }, - feature: { - //TODO: (design) define feature and it's correct value - value: core.color.sky[500].value, - }, - ok: { - value: core.color.green[600].value, - }, - error: { - value: core.color.red[400].value, - }, - warning: { - value: core.color.amber[300].value, - }, - info: { - value: core.color.blue[500].value, - }, + primary: color.neutral[300], + secondary: color.neutral[500], + muted: color.neutral[600], + placeholder: color.neutral[700], + active: color.neutral[50], + //TODO: (design) define feature and it's correct value + feature: color.sky[500], + ok: color.green[600], + error: color.red[400], + warning: color.amber[300], + info: color.blue[500], }; const editor = { - background: { - value: backgroundColor[500].base.value, - }, - indent_guide: { - value: core.color.neutral[999].value, - }, - indent_guide_active: { - value: core.color.neutral[999].value, - }, + background: backgroundColor[500].base, + indent_guide: color.neutral[999], + indent_guide_active: color.neutral[999], line: { - active: { - value: core.color.neutral[999].value, - }, - highlighted: { - value: core.color.neutral[999].value, - }, - inserted: { - value: core.color.neutral[999].value, - }, - deleted: { - value: core.color.neutral[999].value, - }, - modified: { - value: core.color.neutral[999].value, - }, + active: color.neutral[999], + highlighted: color.neutral[999], + inserted: color.neutral[999], + deleted: color.neutral[999], + modified: color.neutral[999], }, highlight: { - selection: { - value: core.color.neutral[999].value, - }, - occurrence: { - value: core.color.neutral[999].value, - }, - activeOccurrence: { - value: core.color.neutral[999].value, - }, - matchingBracket: { - value: core.color.neutral[999].value, - }, - match: { - value: core.color.neutral[999].value, - }, - activeMatch: { - value: core.color.neutral[999].value, - }, - related: { - value: core.color.neutral[999].value, - }, + selection: color.neutral[999], + occurrence: color.neutral[999], + activeOccurrence: color.neutral[999], + matchingBracket: color.neutral[999], + match: color.neutral[999], + activeMatch: color.neutral[999], + related: color.neutral[999], }, gutter: { - primary: { - value: core.color.neutral[999].value, - }, - active: { - value: core.color.neutral[999].value, - }, + primary: color.neutral[999], + active: color.neutral[999], }, }; const syntax = { primary: { - color: { - value: core.color.neutral[150] - }, + color: textColor.primary, weight: { value: "normal" }, }, comment: { - color: { value: "000000" }, + color: color.lime[200], weight: { value: "normal" }, }, punctuation: { - color: { value: "000000" }, + color: textColor.primary, weight: { value: "normal" }, }, constant: { - color: { value: "000000" }, + color: color.neutral[150], weight: { value: "normal" }, }, keyword: { - color: { value: "000000" }, + color: color.sky[400], weight: { value: "normal" }, }, function: { - color: { value: "000000" }, + color: color.yellow[200], weight: { value: "normal" }, }, type: { - color: { value: "000000" }, + color: color.teal[300], weight: { value: "normal" }, }, variant: { - color: { value: "000000" }, + color: color.teal[300], weight: { value: "normal" }, }, property: { - color: { value: "000000" }, + color: color.sky[300], weight: { value: "normal" }, }, enum: { - color: { value: "000000" }, + color: color.sky[400], weight: { value: "normal" }, }, operator: { - color: { value: "000000" }, + color: color.sky[400], weight: { value: "normal" }, }, string: { - color: { value: "000000" }, + color: color.orange[300], weight: { value: "normal" }, }, number: { - color: { value: "000000" }, + color: color.neutral[150], weight: { value: "normal" }, }, boolean: { - color: { value: "000000" }, + color: color.neutral[150], weight: { value: "normal" }, }, predictive: { - color: { value: "000000" }, + color: textColor.muted, weight: { value: "normal" }, }, }; const player = { 1: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, + baseColor: color.blue[600], + cursorColor: color.blue[600], + selectionColor: color.blue[600], + borderColor: color.blue[600], }, 2: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, + baseColor: color.indigo[500], + cursorColor: color.indigo[500], + selectionColor: color.indigo[500], + borderColor: color.indigo[500], }, 3: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, + baseColor: color.green[500], + cursorColor: color.green[500], + selectionColor: color.green[500], + borderColor: color.green[500], }, 4: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, + baseColor: color.orange[500], + cursorColor: color.orange[500], + selectionColor: color.orange[500], + borderColor: color.orange[500], }, 5: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, + baseColor: color.purple[500], + cursorColor: color.purple[500], + selectionColor: color.purple[500], + borderColor: color.purple[500], }, 6: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, + baseColor: color.teal[400], + cursorColor: color.teal[400], + selectionColor: color.teal[400], + borderColor: color.teal[400], }, 7: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, + baseColor: color.pink[400], + cursorColor: color.pink[400], + selectionColor: color.pink[400], + borderColor: color.pink[400], }, 8: { - baseColor: { - value: core.color.neutral[999].value, - }, - cursorColor: { - value: core.color.neutral[999].value, - }, - selectionColor: { - value: core.color.neutral[999].value, - }, - borderColor: { - value: core.color.neutral[999].value, - }, + baseColor: color.yellow[400], + cursorColor: color.yellow[400], + selectionColor: color.yellow[400], + borderColor: color.yellow[400], }, }; diff --git a/styles/theme.ts b/styles/theme.ts index 9d297d552d..9d70ea0227 100644 --- a/styles/theme.ts +++ b/styles/theme.ts @@ -1,242 +1,146 @@ -export type Color = string; -export type Weight = - | "thin" - | "extra_light" - | "light" - | "normal" - | "medium" - | "semibold" - | "bold" - | "extra_bold" - | "black"; - -interface SyntaxHighlightStyle { - color: { value: Color }; - weight: { value: Weight }; +export interface NumberToken { + value: number, + type: "number" } -interface Player { - baseColor: { +export type Color = string; +export interface ColorToken { value: Color; - }; - cursorColor: { - value: Color; - }; - selectionColor: { - value: Color; - }; - borderColor: { - value: Color; - }; + type: "color"; + step?: number +} +export type Weight = + | "thin" + | "extra_light" + | "light" + | "normal" + | "medium" + | "semibold" + | "bold" + | "extra_bold" + | "black"; +export interface WeightToken { + value: Weight, + type: "fontWeight" +} + +export interface SyntaxHighlightStyle { + color: ColorToken; + weight: WeightToken; +} + +export interface Player { + baseColor: ColorToken; + cursorColor: ColorToken; + selectionColor: ColorToken; + borderColor: ColorToken; } export interface BackgroundColor { - base: { - value: Color; - }; - hovered: { - value: Color; - }; - active: { - value: Color; - }; - focused: { - value: Color; - }; + base: ColorToken; + hovered: ColorToken; + active: ColorToken; + focused: ColorToken; } export default interface Theme { - backgroundColor: { - 100: BackgroundColor; - 300: BackgroundColor; - 500: BackgroundColor; - ok: BackgroundColor; - error: BackgroundColor; - warning: BackgroundColor; - info: BackgroundColor; - }; - borderColor: { - primary: { - value: Color; + backgroundColor: { + 100: BackgroundColor; + 300: BackgroundColor; + 500: BackgroundColor; + ok: BackgroundColor; + error: BackgroundColor; + warning: BackgroundColor; + info: BackgroundColor; }; - secondary: { - value: Color; + borderColor: { + primary: ColorToken; + secondary: ColorToken; + muted: ColorToken; + focused: ColorToken; + active: ColorToken; + ok: ColorToken; + error: ColorToken; + warning: ColorToken; + info: ColorToken; }; - muted: { - value: Color; + textColor: { + primary: ColorToken; + secondary: ColorToken; + muted: ColorToken; + placeholder: ColorToken; + active: ColorToken; + feature: ColorToken; + ok: ColorToken; + error: ColorToken; + warning: ColorToken; + info: ColorToken; }; - focused: { - value: Color; + iconColor: { + primary: ColorToken; + secondary: ColorToken; + muted: ColorToken; + placeholder: ColorToken; + active: ColorToken; + feature: ColorToken; + ok: ColorToken; + error: ColorToken; + warning: ColorToken; + info: ColorToken; }; - active: { - value: Color; + editor: { + background: ColorToken; + indent_guide: ColorToken; + indent_guide_active: ColorToken; + line: { + active: ColorToken; + highlighted: ColorToken; + inserted: ColorToken; + deleted: ColorToken; + modified: ColorToken; + }; + highlight: { + selection: ColorToken; + occurrence: ColorToken; + activeOccurrence: ColorToken; + matchingBracket: ColorToken; + match: ColorToken; + activeMatch: ColorToken; + related: ColorToken; + }; + gutter: { + primary: ColorToken; + active: ColorToken; + }; }; - ok: { - value: Color; - }; - error: { - value: Color; - }; - warning: { - value: Color; - }; - info: { - value: Color; - }; - }; - textColor: { - primary: { - value: Color; - }; - secondary: { - value: Color; - }; - muted: { - value: Color; - }; - placeholder: { - value: Color; - }; - active: { - value: Color; - }; - feature: { - value: Color; - }; - ok: { - value: Color; - }; - error: { - value: Color; - }; - warning: { - value: Color; - }; - info: { - value: Color; - }; - }; - iconColor: { - primary: { - value: Color; - }; - secondary: { - value: Color; - }; - muted: { - value: Color; - }; - placeholder: { - value: Color; - }; - active: { - value: Color; - }; - feature: { - value: Color; - }; - ok: { - value: Color; - }; - error: { - value: Color; - }; - warning: { - value: Color; - }; - info: { - value: Color; - }; - }; - editor: { - background: { - value: Color; - }; - indent_guide: { - value: Color; - }; - indent_guide_active: { - value: Color; - }; - line: { - active: { - value: Color; - }; - highlighted: { - value: Color; - }; - inserted: { - value: Color; - }; - deleted: { - value: Color; - }; - modified: { - value: Color; - }; - }; - highlight: { - selection: { - value: Color; - }; - occurrence: { - value: Color; - }; - activeOccurrence: { - value: Color; - }; - matchingBracket: { - value: Color; - }; - match: { - value: Color; - }; - activeMatch: { - value: Color; - }; - related: { - value: Color; - }; - }; - gutter: { - primary: { - value: Color; - }; - active: { - value: Color; - }; - }; - }; - syntax: { - primary: SyntaxHighlightStyle; - comment: SyntaxHighlightStyle; - punctuation: SyntaxHighlightStyle; - constant: SyntaxHighlightStyle; - keyword: SyntaxHighlightStyle; - function: SyntaxHighlightStyle; - type: SyntaxHighlightStyle; - variant: SyntaxHighlightStyle; - property: SyntaxHighlightStyle; - enum: SyntaxHighlightStyle; - operator: SyntaxHighlightStyle; - string: SyntaxHighlightStyle; - number: SyntaxHighlightStyle; - boolean: SyntaxHighlightStyle; - predictive: SyntaxHighlightStyle; - }; + syntax: { + primary: SyntaxHighlightStyle; + comment: SyntaxHighlightStyle; + punctuation: SyntaxHighlightStyle; + constant: SyntaxHighlightStyle; + keyword: SyntaxHighlightStyle; + function: SyntaxHighlightStyle; + type: SyntaxHighlightStyle; + variant: SyntaxHighlightStyle; + property: SyntaxHighlightStyle; + enum: SyntaxHighlightStyle; + operator: SyntaxHighlightStyle; + string: SyntaxHighlightStyle; + number: SyntaxHighlightStyle; + boolean: SyntaxHighlightStyle; + predictive: SyntaxHighlightStyle; + }; - player: { - 1: Player; - 2: Player; - 3: Player; - 4: Player; - 5: Player; - 6: Player; - 7: Player; - 8: Player; - }; - shadowAlpha: { - value: number; - }; + player: { + 1: Player; + 2: Player; + 3: Player; + 4: Player; + 5: Player; + 6: Player; + 7: Player; + 8: Player; + }; + shadowAlpha: NumberToken; } From bfeb6abb4bedfbb414841b41a72cd435b11b8379 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Thu, 31 Mar 2022 20:27:25 -0700 Subject: [PATCH 52/68] Finish dark.ts initial port and restructure files to get ready for build script Build script currently fails to type check. Not sure whats going on. Will fix in the morning. Co-authored-by: Nate Butler --- styles/.gitignore | 1 + styles/buildStyleTree.ts | 11 + styles/{ => styleTree}/app.ts | 0 .../{chat-panel.ts => styleTree/chatPanel.ts} | 0 styles/{ => styleTree}/components.ts | 6 +- styles/{ => styleTree}/editor.ts | 0 .../projectPanel.ts} | 4 +- styles/{ => styleTree}/search.ts | 0 .../selectorModal.ts} | 0 styles/{ => styleTree}/workspace.ts | 0 styles/{ => themes}/dark.ts | 213 +++++++-------- styles/themes/light.ts | 251 ++++++++++++++++++ styles/{ => themes}/theme.ts | 36 +-- styles/{ => tokens}/core.ts | 2 +- styles/{lib.ts => utils/color.ts} | 0 15 files changed, 396 insertions(+), 128 deletions(-) create mode 100644 styles/.gitignore create mode 100644 styles/buildStyleTree.ts rename styles/{ => styleTree}/app.ts (100%) rename styles/{chat-panel.ts => styleTree/chatPanel.ts} (100%) rename styles/{ => styleTree}/components.ts (92%) rename styles/{ => styleTree}/editor.ts (100%) rename styles/{project-panel.ts => styleTree/projectPanel.ts} (90%) rename styles/{ => styleTree}/search.ts (100%) rename styles/{selector-modal.ts => styleTree/selectorModal.ts} (100%) rename styles/{ => styleTree}/workspace.ts (100%) rename styles/{ => themes}/dark.ts (71%) create mode 100644 styles/themes/light.ts rename styles/{ => themes}/theme.ts (82%) rename styles/{ => tokens}/core.ts (97%) rename styles/{lib.ts => utils/color.ts} (100%) diff --git a/styles/.gitignore b/styles/.gitignore new file mode 100644 index 0000000000..c2658d7d1b --- /dev/null +++ b/styles/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/styles/buildStyleTree.ts b/styles/buildStyleTree.ts new file mode 100644 index 0000000000..6fa1c1576d --- /dev/null +++ b/styles/buildStyleTree.ts @@ -0,0 +1,11 @@ +import dark from "./themes/dark"; +import light from "./themes/light"; +import app from "./styleTree/app"; + +for (let theme of [dark, light]) { + let styleTree = app(theme); + + let styleTreeJson = JSON.stringify(styleTree); + console.log(styleTreeJson); + // TODO: Write style tree json to zed crate assets folder +} \ No newline at end of file diff --git a/styles/app.ts b/styles/styleTree/app.ts similarity index 100% rename from styles/app.ts rename to styles/styleTree/app.ts diff --git a/styles/chat-panel.ts b/styles/styleTree/chatPanel.ts similarity index 100% rename from styles/chat-panel.ts rename to styles/styleTree/chatPanel.ts diff --git a/styles/components.ts b/styles/styleTree/components.ts similarity index 92% rename from styles/components.ts rename to styles/styleTree/components.ts index 590c1b5eea..b54956facc 100644 --- a/styles/components.ts +++ b/styles/styleTree/components.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js"; -import core from "./core"; -import { Color } from "./lib"; -import Theme, { BackgroundColor, Weight } from "./theme"; +import core from "../tokens/core"; +import { Color } from "../utils/color"; +import Theme, { BackgroundColor, Weight } from "../themes/theme"; export type TextColor = keyof Theme["textColor"]; diff --git a/styles/editor.ts b/styles/styleTree/editor.ts similarity index 100% rename from styles/editor.ts rename to styles/styleTree/editor.ts diff --git a/styles/project-panel.ts b/styles/styleTree/projectPanel.ts similarity index 90% rename from styles/project-panel.ts rename to styles/styleTree/projectPanel.ts index 343e11b96b..3b5fba8853 100644 --- a/styles/project-panel.ts +++ b/styles/styleTree/projectPanel.ts @@ -1,7 +1,7 @@ import { panel } from "./app"; import { backgroundColor, iconColor, text, TextColor } from "./components"; -import Theme from "./theme"; -import { Color } from "./lib"; +import Theme from "../themes/theme"; +import { Color } from "../utils/color"; export default function projectPanel(theme: Theme) { function entry(theme: Theme, textColor: TextColor, background?: Color) { diff --git a/styles/search.ts b/styles/styleTree/search.ts similarity index 100% rename from styles/search.ts rename to styles/styleTree/search.ts diff --git a/styles/selector-modal.ts b/styles/styleTree/selectorModal.ts similarity index 100% rename from styles/selector-modal.ts rename to styles/styleTree/selectorModal.ts diff --git a/styles/workspace.ts b/styles/styleTree/workspace.ts similarity index 100% rename from styles/workspace.ts rename to styles/styleTree/workspace.ts diff --git a/styles/dark.ts b/styles/themes/dark.ts similarity index 71% rename from styles/dark.ts rename to styles/themes/dark.ts index 5b60bd0316..098677a1e9 100644 --- a/styles/dark.ts +++ b/styles/themes/dark.ts @@ -1,5 +1,5 @@ -import core from "./core"; -import Theme from "./theme"; +import core from "../tokens/core"; +import Theme, { NumberToken, Syntax } from "./theme"; const { color } = core; @@ -88,95 +88,6 @@ const iconColor = { info: color.blue[500], }; -const editor = { - background: backgroundColor[500].base, - indent_guide: color.neutral[999], - indent_guide_active: color.neutral[999], - line: { - active: color.neutral[999], - highlighted: color.neutral[999], - inserted: color.neutral[999], - deleted: color.neutral[999], - modified: color.neutral[999], - }, - highlight: { - selection: color.neutral[999], - occurrence: color.neutral[999], - activeOccurrence: color.neutral[999], - matchingBracket: color.neutral[999], - match: color.neutral[999], - activeMatch: color.neutral[999], - related: color.neutral[999], - }, - gutter: { - primary: color.neutral[999], - active: color.neutral[999], - }, -}; - -const syntax = { - primary: { - color: textColor.primary, - weight: { value: "normal" }, - }, - comment: { - color: color.lime[200], - weight: { value: "normal" }, - }, - punctuation: { - color: textColor.primary, - weight: { value: "normal" }, - }, - constant: { - color: color.neutral[150], - weight: { value: "normal" }, - }, - keyword: { - color: color.sky[400], - weight: { value: "normal" }, - }, - function: { - color: color.yellow[200], - weight: { value: "normal" }, - }, - type: { - color: color.teal[300], - weight: { value: "normal" }, - }, - variant: { - color: color.teal[300], - weight: { value: "normal" }, - }, - property: { - color: color.sky[300], - weight: { value: "normal" }, - }, - enum: { - color: color.sky[400], - weight: { value: "normal" }, - }, - operator: { - color: color.sky[400], - weight: { value: "normal" }, - }, - string: { - color: color.orange[300], - weight: { value: "normal" }, - }, - number: { - color: color.neutral[150], - weight: { value: "normal" }, - }, - boolean: { - color: color.neutral[150], - weight: { value: "normal" }, - }, - predictive: { - color: textColor.muted, - weight: { value: "normal" }, - }, -}; - const player = { 1: { baseColor: color.blue[600], @@ -228,19 +139,111 @@ const player = { }, }; -const shadowAlpha = { - value: 0.32, +// TODO: Fixup +const editor = { + background: backgroundColor[500].base, + indent_guide: borderColor.muted, + indent_guide_active: borderColor.secondary, + line: { + active: color.neutral[0], + highlighted: color.neutral[0], + inserted: backgroundColor.ok.active, + deleted: backgroundColor.error.active, + modified: backgroundColor.info.active, + }, + highlight: { + selection: player[1].selectionColor, + occurrence: backgroundColor[500].active, + activeOccurrence: color.neutral[0], + matchingBracket: color.neutral[0], + match: color.neutral[0], + activeMatch: color.neutral[0], + related: color.neutral[0], + }, + gutter: { + primary: color.neutral[0], + active: color.neutral[0], + }, }; -export default function dark(): Theme { - return { - backgroundColor, - borderColor, - textColor, - iconColor, - editor, - syntax, - player, - shadowAlpha, - }; -} +const syntax: Syntax = { + primary: { + color: textColor.primary, + weight: { value: "normal", type: "fontWeight" }, + }, + comment: { + color: color.lime[200], + weight: { value: "normal", type: "fontWeight" }, + }, + punctuation: { + color: textColor.primary, + weight: { value: "normal", type: "fontWeight" }, + }, + constant: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + keyword: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + function: { + color: color.yellow[200], + weight: { value: "normal", type: "fontWeight" }, + }, + type: { + color: color.teal[300], + weight: { value: "normal", type: "fontWeight" }, + }, + variant: { + color: color.teal[300], + weight: { value: "normal", type: "fontWeight" }, + }, + property: { + color: color.sky[300], + weight: { value: "normal", type: "fontWeight" }, + }, + enum: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + operator: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + string: { + color: color.orange[300], + weight: { value: "normal", type: "fontWeight" }, + }, + number: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + boolean: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + predictive: { + color: textColor.muted, + weight: { value: "normal", type: "fontWeight" }, + }, +}; + +const shadowAlpha: NumberToken = { + value: 0.32, + type: "number" +}; + +const theme: Theme = { + name: "dark", + backgroundColor, + borderColor, + textColor, + iconColor, + editor, + syntax, + player, + shadowAlpha, +}; + +export default theme; \ No newline at end of file diff --git a/styles/themes/light.ts b/styles/themes/light.ts new file mode 100644 index 0000000000..20760427f2 --- /dev/null +++ b/styles/themes/light.ts @@ -0,0 +1,251 @@ +import core from "../tokens/core"; +import Theme, { NumberToken, Syntax } from "./theme"; + +const { color } = core; + +// TODO: Replace with light values + +const backgroundColor = { + 100: { + base: color.neutral[750], + hovered: color.neutral[750], + active: color.neutral[750], + focused: color.neutral[750], + }, + 300: { + base: color.neutral[800], + hovered: color.neutral[800], + active: color.neutral[800], + focused: color.neutral[800], + }, + 500: { + base: color.neutral[900], + hovered: color.neutral[900], + active: color.neutral[900], + focused: color.neutral[900], + }, + ok: { + base: color.green[600], + hovered: color.green[600], + active: color.green[600], + focused: color.green[600], + }, + error: { + base: color.red[400], + hovered: color.red[400], + active: color.red[400], + focused: color.red[400], + }, + warning: { + base: color.amber[300], + hovered: color.amber[300], + active: color.amber[300], + focused: color.amber[300], + }, + info: { + base: color.blue[500], + hovered: color.blue[500], + active: color.blue[500], + focused: color.blue[500], + }, +}; + +const borderColor = { + primary: color.neutral[850], + secondary: color.neutral[700], + muted: color.neutral[750], + focused: color.neutral[100], + active: color.neutral[500], + ok: color.neutral[999], + error: color.neutral[999], + warning: color.neutral[999], + info: color.neutral[999], +}; + +const textColor = { + primary: color.neutral[150], + secondary: color.neutral[350], + muted: color.neutral[550], + placeholder: color.neutral[750], + active: color.neutral[0], + //TODO: (design) define feature and it's correct value + feature: color.sky[500], + ok: color.green[600], + error: color.red[400], + warning: color.amber[300], + info: color.blue[500], +}; + +const iconColor = { + primary: color.neutral[300], + secondary: color.neutral[500], + muted: color.neutral[600], + placeholder: color.neutral[700], + active: color.neutral[50], + //TODO: (design) define feature and it's correct value + feature: color.sky[500], + ok: color.green[600], + error: color.red[400], + warning: color.amber[300], + info: color.blue[500], +}; + +const player = { + 1: { + baseColor: color.blue[600], + cursorColor: color.blue[600], + selectionColor: color.blue[600], + borderColor: color.blue[600], + }, + 2: { + baseColor: color.indigo[500], + cursorColor: color.indigo[500], + selectionColor: color.indigo[500], + borderColor: color.indigo[500], + }, + 3: { + baseColor: color.green[500], + cursorColor: color.green[500], + selectionColor: color.green[500], + borderColor: color.green[500], + }, + 4: { + baseColor: color.orange[500], + cursorColor: color.orange[500], + selectionColor: color.orange[500], + borderColor: color.orange[500], + }, + 5: { + baseColor: color.purple[500], + cursorColor: color.purple[500], + selectionColor: color.purple[500], + borderColor: color.purple[500], + }, + 6: { + baseColor: color.teal[400], + cursorColor: color.teal[400], + selectionColor: color.teal[400], + borderColor: color.teal[400], + }, + 7: { + baseColor: color.pink[400], + cursorColor: color.pink[400], + selectionColor: color.pink[400], + borderColor: color.pink[400], + }, + 8: { + baseColor: color.yellow[400], + cursorColor: color.yellow[400], + selectionColor: color.yellow[400], + borderColor: color.yellow[400], + }, +}; + +// TODO: Fixup +const editor = { + background: backgroundColor[500].base, + indent_guide: borderColor.muted, + indent_guide_active: borderColor.secondary, + line: { + active: color.neutral[0], + highlighted: color.neutral[0], + inserted: backgroundColor.ok.active, + deleted: backgroundColor.error.active, + modified: backgroundColor.info.active, + }, + highlight: { + selection: player[1].selectionColor, + occurrence: backgroundColor[500].active, + activeOccurrence: color.neutral[0], + matchingBracket: color.neutral[0], + match: color.neutral[0], + activeMatch: color.neutral[0], + related: color.neutral[0], + }, + gutter: { + primary: color.neutral[0], + active: color.neutral[0], + }, +}; + +const syntax: Syntax = { + primary: { + color: textColor.primary, + weight: { value: "normal", type: "fontWeight" }, + }, + comment: { + color: color.lime[200], + weight: { value: "normal", type: "fontWeight" }, + }, + punctuation: { + color: textColor.primary, + weight: { value: "normal", type: "fontWeight" }, + }, + constant: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + keyword: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + function: { + color: color.yellow[200], + weight: { value: "normal", type: "fontWeight" }, + }, + type: { + color: color.teal[300], + weight: { value: "normal", type: "fontWeight" }, + }, + variant: { + color: color.teal[300], + weight: { value: "normal", type: "fontWeight" }, + }, + property: { + color: color.sky[300], + weight: { value: "normal", type: "fontWeight" }, + }, + enum: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + operator: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + string: { + color: color.orange[300], + weight: { value: "normal", type: "fontWeight" }, + }, + number: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + boolean: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + predictive: { + color: textColor.muted, + weight: { value: "normal", type: "fontWeight" }, + }, +}; + +const shadowAlpha: NumberToken = { + value: 0.32, + type: "number" +}; + +const theme: Theme = { + name: "light", + backgroundColor, + borderColor, + textColor, + iconColor, + editor, + syntax, + player, + shadowAlpha, +}; + +export default theme; diff --git a/styles/theme.ts b/styles/themes/theme.ts similarity index 82% rename from styles/theme.ts rename to styles/themes/theme.ts index 9d70ea0227..e319f510c7 100644 --- a/styles/theme.ts +++ b/styles/themes/theme.ts @@ -43,6 +43,24 @@ export interface BackgroundColor { focused: ColorToken; } +export interface Syntax { + primary: SyntaxHighlightStyle; + comment: SyntaxHighlightStyle; + punctuation: SyntaxHighlightStyle; + constant: SyntaxHighlightStyle; + keyword: SyntaxHighlightStyle; + function: SyntaxHighlightStyle; + type: SyntaxHighlightStyle; + variant: SyntaxHighlightStyle; + property: SyntaxHighlightStyle; + enum: SyntaxHighlightStyle; + operator: SyntaxHighlightStyle; + string: SyntaxHighlightStyle; + number: SyntaxHighlightStyle; + boolean: SyntaxHighlightStyle; + predictive: SyntaxHighlightStyle; +}; + export default interface Theme { backgroundColor: { 100: BackgroundColor; @@ -114,23 +132,7 @@ export default interface Theme { }; }; - syntax: { - primary: SyntaxHighlightStyle; - comment: SyntaxHighlightStyle; - punctuation: SyntaxHighlightStyle; - constant: SyntaxHighlightStyle; - keyword: SyntaxHighlightStyle; - function: SyntaxHighlightStyle; - type: SyntaxHighlightStyle; - variant: SyntaxHighlightStyle; - property: SyntaxHighlightStyle; - enum: SyntaxHighlightStyle; - operator: SyntaxHighlightStyle; - string: SyntaxHighlightStyle; - number: SyntaxHighlightStyle; - boolean: SyntaxHighlightStyle; - predictive: SyntaxHighlightStyle; - }; + syntax: Syntax, player: { 1: Player; diff --git a/styles/core.ts b/styles/tokens/core.ts similarity index 97% rename from styles/core.ts rename to styles/tokens/core.ts index 49e376b4eb..38bfe82e28 100644 --- a/styles/core.ts +++ b/styles/tokens/core.ts @@ -1,4 +1,4 @@ -import { colorRamp } from "./lib"; +import { colorRamp } from "../utils/color"; export default { fontFamily: { diff --git a/styles/lib.ts b/styles/utils/color.ts similarity index 100% rename from styles/lib.ts rename to styles/utils/color.ts From 43a7cadf5bf2c3c7cad3c3fd9a04e153728ff452 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 31 Mar 2022 23:42:45 -0400 Subject: [PATCH 53/68] Type `name` --- styles/themes/theme.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/styles/themes/theme.ts b/styles/themes/theme.ts index e319f510c7..a776045989 100644 --- a/styles/themes/theme.ts +++ b/styles/themes/theme.ts @@ -62,6 +62,7 @@ export interface Syntax { }; export default interface Theme { + name: string; backgroundColor: { 100: BackgroundColor; 300: BackgroundColor; From 211c473d32c0e09f8855d2d504cb1a356d3e58a1 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 31 Mar 2022 23:43:01 -0400 Subject: [PATCH 54/68] Update renamed/moved imports --- styles/styleTree/app.ts | 8 ++++---- styles/styleTree/chatPanel.ts | 4 ++-- styles/styleTree/components.ts | 2 +- styles/styleTree/editor.ts | 2 +- styles/styleTree/search.ts | 2 +- styles/styleTree/selectorModal.ts | 2 +- styles/styleTree/workspace.ts | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/styles/styleTree/app.ts b/styles/styleTree/app.ts index a65442db07..c7edfdc270 100644 --- a/styles/styleTree/app.ts +++ b/styles/styleTree/app.ts @@ -1,10 +1,10 @@ -import chatPanel from "./chat-panel"; +import Theme from "../themes/theme"; +import chatPanel from "./chatPanel"; import { backgroundColor, borderColor, text } from "./components"; import editor from "./editor"; -import projectPanel from "./project-panel"; +import projectPanel from "./projectPanel"; import search from "./search"; -import selectorModal from "./selector-modal"; -import Theme from "./theme"; +import selectorModal from "./selectorModal"; import workspace from "./workspace"; export const panel = { diff --git a/styles/styleTree/chatPanel.ts b/styles/styleTree/chatPanel.ts index c6bf0148ea..ea9a8ffe22 100644 --- a/styles/styleTree/chatPanel.ts +++ b/styles/styleTree/chatPanel.ts @@ -1,3 +1,4 @@ +import Theme from "../themes/theme"; import { panel } from "./app"; import { backgroundColor, @@ -5,9 +6,8 @@ import { player, shadow, text, - TextColor, + TextColor } from "./components"; -import Theme from "./theme"; export default function chatPanel(theme: Theme) { function channelSelectItem( diff --git a/styles/styleTree/components.ts b/styles/styleTree/components.ts index b54956facc..8038cdcd3b 100644 --- a/styles/styleTree/components.ts +++ b/styles/styleTree/components.ts @@ -1,7 +1,7 @@ import chroma from "chroma-js"; +import Theme, { BackgroundColor, Weight } from "../themes/theme"; import core from "../tokens/core"; import { Color } from "../utils/color"; -import Theme, { BackgroundColor, Weight } from "../themes/theme"; export type TextColor = keyof Theme["textColor"]; diff --git a/styles/styleTree/editor.ts b/styles/styleTree/editor.ts index a27464eee2..5d800881e2 100644 --- a/styles/styleTree/editor.ts +++ b/styles/styleTree/editor.ts @@ -1,3 +1,4 @@ +import Theme from "../themes/theme"; import { backgroundColor, border, @@ -6,7 +7,6 @@ import { text, TextColor } from "./components"; -import Theme from "./theme"; export default function editor(theme: Theme) { const autocompleteItem = { diff --git a/styles/styleTree/search.ts b/styles/styleTree/search.ts index ced2266ea7..fd2fd25681 100644 --- a/styles/styleTree/search.ts +++ b/styles/styleTree/search.ts @@ -1,5 +1,5 @@ +import Theme from "../themes/theme"; import { backgroundColor, border, player, text } from "./components"; -import Theme from "./theme"; export default function search(theme: Theme) { const optionButton = { diff --git a/styles/styleTree/selectorModal.ts b/styles/styleTree/selectorModal.ts index ddba32683a..fdebe712fa 100644 --- a/styles/styleTree/selectorModal.ts +++ b/styles/styleTree/selectorModal.ts @@ -1,5 +1,5 @@ +import Theme from "../themes/theme"; import { backgroundColor, border, player, shadow, text } from "./components"; -import Theme from "./theme"; export default function selectorModal(theme: Theme): Object { const item = { diff --git a/styles/styleTree/workspace.ts b/styles/styleTree/workspace.ts index 1a50fe9ee1..e8232442b6 100644 --- a/styles/styleTree/workspace.ts +++ b/styles/styleTree/workspace.ts @@ -1,5 +1,5 @@ +import Theme from "../themes/theme"; import { backgroundColor, border, iconColor, text } from "./components"; -import Theme from "./theme"; export default function workspace(theme: Theme) { const signInPrompt = { From 70a783c8d103461d720c332f78054168486ab99b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 1 Apr 2022 08:25:58 -0600 Subject: [PATCH 55/68] Fix TS compile error --- styles/styleTree/components.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/styleTree/components.ts b/styles/styleTree/components.ts index 8038cdcd3b..55a64cb1ec 100644 --- a/styles/styleTree/components.ts +++ b/styles/styleTree/components.ts @@ -15,7 +15,7 @@ export function text( underline?: boolean; } ) { - const sizeKey = properties.size || fontFamily === "sans" ? "sm" : "md"; + const sizeKey = properties?.size || fontFamily === "sans" ? "sm" : "md"; const size = core.fontSize[sizeKey].value; return { From d2a070c345d338a46d968d61a6ee0115629f9698 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 1 Apr 2022 09:45:11 -0600 Subject: [PATCH 56/68] Write theme JSON files from buildThemes script Co-Authored-By: Nate Butler <1714999+iamnbutler@users.noreply.github.com> --- script/build-themes | 7 + styles/buildStyleTree.ts | 11 - styles/buildThemes.ts | 17 ++ styles/package-lock.json | 279 ++++++++++++++++++++- styles/package.json | 7 +- styles/themes/dark.ts | 432 ++++++++++++++++----------------- styles/themes/light.ts | 430 ++++++++++++++++---------------- styles/tsconfig.json | 12 + styles/utils/decamelizeTree.ts | 21 ++ 9 files changed, 771 insertions(+), 445 deletions(-) create mode 100755 script/build-themes delete mode 100644 styles/buildStyleTree.ts create mode 100644 styles/buildThemes.ts create mode 100644 styles/tsconfig.json create mode 100644 styles/utils/decamelizeTree.ts diff --git a/script/build-themes b/script/build-themes new file mode 100755 index 0000000000..aef3a4250c --- /dev/null +++ b/script/build-themes @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +cd styles +npm install +npm run build diff --git a/styles/buildStyleTree.ts b/styles/buildStyleTree.ts deleted file mode 100644 index 6fa1c1576d..0000000000 --- a/styles/buildStyleTree.ts +++ /dev/null @@ -1,11 +0,0 @@ -import dark from "./themes/dark"; -import light from "./themes/light"; -import app from "./styleTree/app"; - -for (let theme of [dark, light]) { - let styleTree = app(theme); - - let styleTreeJson = JSON.stringify(styleTree); - console.log(styleTreeJson); - // TODO: Write style tree json to zed crate assets folder -} \ No newline at end of file diff --git a/styles/buildThemes.ts b/styles/buildThemes.ts new file mode 100644 index 0000000000..ced82e9866 --- /dev/null +++ b/styles/buildThemes.ts @@ -0,0 +1,17 @@ +import * as fs from "fs"; +import * as path from "path"; +import dark from "./themes/dark"; +import light from "./themes/light"; +import app from "./styleTree/app"; +import decamelizeTree from "./utils/decamelizeTree"; + +const themes = [dark, light]; +for (let theme of themes) { + let styleTree = decamelizeTree(app(theme)); + let styleTreeJSON = JSON.stringify(styleTree, null, 2); + let outPath = path.resolve( + `${__dirname}/../crates/zed/assets/themes/${theme.name}.json` + ); + fs.writeFileSync(outPath, styleTreeJSON); + console.log(`Generated ${outPath}`); +} diff --git a/styles/package-lock.json b/styles/package-lock.json index 7b8503bf72..582f1c8496 100644 --- a/styles/package-lock.json +++ b/styles/package-lock.json @@ -10,30 +10,307 @@ "license": "ISC", "dependencies": { "@types/chroma-js": "^2.1.3", - "chroma-js": "^2.4.2" + "@types/node": "^17.0.23", + "case-anything": "^2.1.10", + "chroma-js": "^2.4.2", + "ts-node": "^10.7.0" } }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" + }, "node_modules/@types/chroma-js": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz", "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g==" }, + "node_modules/@types/node": { + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/case-anything": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz", + "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ==", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/chroma-js": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "node_modules/ts-node": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", + "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", + "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } } }, "dependencies": { + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==" + }, + "@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==" + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==" + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==" + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" + }, "@types/chroma-js": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz", "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g==" }, + "@types/node": { + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "case-anything": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz", + "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ==" + }, "chroma-js": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==" + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "ts-node": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", + "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "requires": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", + "yn": "3.1.1" + } + }, + "typescript": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "peer": true + }, + "v8-compile-cache-lib": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", + "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" } } } diff --git a/styles/package.json b/styles/package.json index c66da8718b..c270bba0e1 100644 --- a/styles/package.json +++ b/styles/package.json @@ -4,12 +4,15 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "build": "ts-node buildThemes.ts" }, "author": "", "license": "ISC", "dependencies": { "@types/chroma-js": "^2.1.3", - "chroma-js": "^2.4.2" + "@types/node": "^17.0.23", + "case-anything": "^2.1.10", + "chroma-js": "^2.4.2", + "ts-node": "^10.7.0" } } diff --git a/styles/themes/dark.ts b/styles/themes/dark.ts index 098677a1e9..42f80cf4c6 100644 --- a/styles/themes/dark.ts +++ b/styles/themes/dark.ts @@ -4,246 +4,246 @@ import Theme, { NumberToken, Syntax } from "./theme"; const { color } = core; const backgroundColor = { - 100: { - base: color.neutral[750], - hovered: color.neutral[750], - active: color.neutral[750], - focused: color.neutral[750], - }, - 300: { - base: color.neutral[800], - hovered: color.neutral[800], - active: color.neutral[800], - focused: color.neutral[800], - }, - 500: { - base: color.neutral[900], - hovered: color.neutral[900], - active: color.neutral[900], - focused: color.neutral[900], - }, - ok: { - base: color.green[600], - hovered: color.green[600], - active: color.green[600], - focused: color.green[600], - }, - error: { - base: color.red[400], - hovered: color.red[400], - active: color.red[400], - focused: color.red[400], - }, - warning: { - base: color.amber[300], - hovered: color.amber[300], - active: color.amber[300], - focused: color.amber[300], - }, - info: { - base: color.blue[500], - hovered: color.blue[500], - active: color.blue[500], - focused: color.blue[500], - }, + 100: { + base: color.neutral[750], + hovered: color.neutral[750], + active: color.neutral[750], + focused: color.neutral[750], + }, + 300: { + base: color.neutral[800], + hovered: color.neutral[800], + active: color.neutral[800], + focused: color.neutral[800], + }, + 500: { + base: color.neutral[900], + hovered: color.neutral[900], + active: color.neutral[900], + focused: color.neutral[900], + }, + ok: { + base: color.green[600], + hovered: color.green[600], + active: color.green[600], + focused: color.green[600], + }, + error: { + base: color.red[400], + hovered: color.red[400], + active: color.red[400], + focused: color.red[400], + }, + warning: { + base: color.amber[300], + hovered: color.amber[300], + active: color.amber[300], + focused: color.amber[300], + }, + info: { + base: color.blue[500], + hovered: color.blue[500], + active: color.blue[500], + focused: color.blue[500], + }, }; const borderColor = { - primary: color.neutral[850], - secondary: color.neutral[700], - muted: color.neutral[750], - focused: color.neutral[100], - active: color.neutral[500], - ok: color.neutral[999], - error: color.neutral[999], - warning: color.neutral[999], - info: color.neutral[999], + primary: color.neutral[850], + secondary: color.neutral[700], + muted: color.neutral[750], + focused: color.neutral[100], + active: color.neutral[500], + ok: color.neutral[1000], + error: color.neutral[1000], + warning: color.neutral[1000], + info: color.neutral[1000], }; const textColor = { - primary: color.neutral[150], - secondary: color.neutral[350], - muted: color.neutral[550], - placeholder: color.neutral[750], - active: color.neutral[0], - //TODO: (design) define feature and it's correct value - feature: color.sky[500], - ok: color.green[600], - error: color.red[400], - warning: color.amber[300], - info: color.blue[500], + primary: color.neutral[150], + secondary: color.neutral[350], + muted: color.neutral[550], + placeholder: color.neutral[750], + active: color.neutral[0], + //TODO: (design) define feature and it's correct value + feature: color.sky[500], + ok: color.green[600], + error: color.red[400], + warning: color.amber[300], + info: color.blue[500], }; const iconColor = { - primary: color.neutral[300], - secondary: color.neutral[500], - muted: color.neutral[600], - placeholder: color.neutral[700], - active: color.neutral[50], - //TODO: (design) define feature and it's correct value - feature: color.sky[500], - ok: color.green[600], - error: color.red[400], - warning: color.amber[300], - info: color.blue[500], + primary: color.neutral[300], + secondary: color.neutral[500], + muted: color.neutral[600], + placeholder: color.neutral[700], + active: color.neutral[50], + //TODO: (design) define feature and it's correct value + feature: color.sky[500], + ok: color.green[600], + error: color.red[400], + warning: color.amber[300], + info: color.blue[500], }; const player = { - 1: { - baseColor: color.blue[600], - cursorColor: color.blue[600], - selectionColor: color.blue[600], - borderColor: color.blue[600], - }, - 2: { - baseColor: color.indigo[500], - cursorColor: color.indigo[500], - selectionColor: color.indigo[500], - borderColor: color.indigo[500], - }, - 3: { - baseColor: color.green[500], - cursorColor: color.green[500], - selectionColor: color.green[500], - borderColor: color.green[500], - }, - 4: { - baseColor: color.orange[500], - cursorColor: color.orange[500], - selectionColor: color.orange[500], - borderColor: color.orange[500], - }, - 5: { - baseColor: color.purple[500], - cursorColor: color.purple[500], - selectionColor: color.purple[500], - borderColor: color.purple[500], - }, - 6: { - baseColor: color.teal[400], - cursorColor: color.teal[400], - selectionColor: color.teal[400], - borderColor: color.teal[400], - }, - 7: { - baseColor: color.pink[400], - cursorColor: color.pink[400], - selectionColor: color.pink[400], - borderColor: color.pink[400], - }, - 8: { - baseColor: color.yellow[400], - cursorColor: color.yellow[400], - selectionColor: color.yellow[400], - borderColor: color.yellow[400], - }, + 1: { + baseColor: color.blue[600], + cursorColor: color.blue[600], + selectionColor: color.blue[600], + borderColor: color.blue[600], + }, + 2: { + baseColor: color.indigo[500], + cursorColor: color.indigo[500], + selectionColor: color.indigo[500], + borderColor: color.indigo[500], + }, + 3: { + baseColor: color.green[500], + cursorColor: color.green[500], + selectionColor: color.green[500], + borderColor: color.green[500], + }, + 4: { + baseColor: color.orange[500], + cursorColor: color.orange[500], + selectionColor: color.orange[500], + borderColor: color.orange[500], + }, + 5: { + baseColor: color.purple[500], + cursorColor: color.purple[500], + selectionColor: color.purple[500], + borderColor: color.purple[500], + }, + 6: { + baseColor: color.teal[400], + cursorColor: color.teal[400], + selectionColor: color.teal[400], + borderColor: color.teal[400], + }, + 7: { + baseColor: color.pink[400], + cursorColor: color.pink[400], + selectionColor: color.pink[400], + borderColor: color.pink[400], + }, + 8: { + baseColor: color.yellow[400], + cursorColor: color.yellow[400], + selectionColor: color.yellow[400], + borderColor: color.yellow[400], + }, }; // TODO: Fixup const editor = { - background: backgroundColor[500].base, - indent_guide: borderColor.muted, - indent_guide_active: borderColor.secondary, - line: { - active: color.neutral[0], - highlighted: color.neutral[0], - inserted: backgroundColor.ok.active, - deleted: backgroundColor.error.active, - modified: backgroundColor.info.active, - }, - highlight: { - selection: player[1].selectionColor, - occurrence: backgroundColor[500].active, - activeOccurrence: color.neutral[0], - matchingBracket: color.neutral[0], - match: color.neutral[0], - activeMatch: color.neutral[0], - related: color.neutral[0], - }, - gutter: { - primary: color.neutral[0], - active: color.neutral[0], - }, + background: backgroundColor[500].base, + indent_guide: borderColor.muted, + indent_guide_active: borderColor.secondary, + line: { + active: color.neutral[0], + highlighted: color.neutral[0], + inserted: backgroundColor.ok.active, + deleted: backgroundColor.error.active, + modified: backgroundColor.info.active, + }, + highlight: { + selection: player[1].selectionColor, + occurrence: backgroundColor[500].active, + activeOccurrence: color.neutral[0], + matchingBracket: color.neutral[0], + match: color.neutral[0], + activeMatch: color.neutral[0], + related: color.neutral[0], + }, + gutter: { + primary: color.neutral[0], + active: color.neutral[0], + }, }; const syntax: Syntax = { - primary: { - color: textColor.primary, - weight: { value: "normal", type: "fontWeight" }, - }, - comment: { - color: color.lime[200], - weight: { value: "normal", type: "fontWeight" }, - }, - punctuation: { - color: textColor.primary, - weight: { value: "normal", type: "fontWeight" }, - }, - constant: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - keyword: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - function: { - color: color.yellow[200], - weight: { value: "normal", type: "fontWeight" }, - }, - type: { - color: color.teal[300], - weight: { value: "normal", type: "fontWeight" }, - }, - variant: { - color: color.teal[300], - weight: { value: "normal", type: "fontWeight" }, - }, - property: { - color: color.sky[300], - weight: { value: "normal", type: "fontWeight" }, - }, - enum: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - operator: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - string: { - color: color.orange[300], - weight: { value: "normal", type: "fontWeight" }, - }, - number: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - boolean: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - predictive: { - color: textColor.muted, - weight: { value: "normal", type: "fontWeight" }, - }, + primary: { + color: textColor.primary, + weight: { value: "normal", type: "fontWeight" }, + }, + comment: { + color: color.lime[200], + weight: { value: "normal", type: "fontWeight" }, + }, + punctuation: { + color: textColor.primary, + weight: { value: "normal", type: "fontWeight" }, + }, + constant: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + keyword: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + function: { + color: color.yellow[200], + weight: { value: "normal", type: "fontWeight" }, + }, + type: { + color: color.teal[300], + weight: { value: "normal", type: "fontWeight" }, + }, + variant: { + color: color.teal[300], + weight: { value: "normal", type: "fontWeight" }, + }, + property: { + color: color.sky[300], + weight: { value: "normal", type: "fontWeight" }, + }, + enum: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + operator: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + string: { + color: color.orange[300], + weight: { value: "normal", type: "fontWeight" }, + }, + number: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + boolean: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + predictive: { + color: textColor.muted, + weight: { value: "normal", type: "fontWeight" }, + }, }; const shadowAlpha: NumberToken = { - value: 0.32, - type: "number" + value: 0.32, + type: "number", }; const theme: Theme = { - name: "dark", - backgroundColor, - borderColor, - textColor, - iconColor, - editor, - syntax, - player, - shadowAlpha, + name: "dark", + backgroundColor, + borderColor, + textColor, + iconColor, + editor, + syntax, + player, + shadowAlpha, }; -export default theme; \ No newline at end of file +export default theme; diff --git a/styles/themes/light.ts b/styles/themes/light.ts index 20760427f2..7a9bf1b552 100644 --- a/styles/themes/light.ts +++ b/styles/themes/light.ts @@ -6,246 +6,246 @@ const { color } = core; // TODO: Replace with light values const backgroundColor = { - 100: { - base: color.neutral[750], - hovered: color.neutral[750], - active: color.neutral[750], - focused: color.neutral[750], - }, - 300: { - base: color.neutral[800], - hovered: color.neutral[800], - active: color.neutral[800], - focused: color.neutral[800], - }, - 500: { - base: color.neutral[900], - hovered: color.neutral[900], - active: color.neutral[900], - focused: color.neutral[900], - }, - ok: { - base: color.green[600], - hovered: color.green[600], - active: color.green[600], - focused: color.green[600], - }, - error: { - base: color.red[400], - hovered: color.red[400], - active: color.red[400], - focused: color.red[400], - }, - warning: { - base: color.amber[300], - hovered: color.amber[300], - active: color.amber[300], - focused: color.amber[300], - }, - info: { - base: color.blue[500], - hovered: color.blue[500], - active: color.blue[500], - focused: color.blue[500], - }, + 100: { + base: color.neutral[750], + hovered: color.neutral[750], + active: color.neutral[750], + focused: color.neutral[750], + }, + 300: { + base: color.neutral[800], + hovered: color.neutral[800], + active: color.neutral[800], + focused: color.neutral[800], + }, + 500: { + base: color.neutral[900], + hovered: color.neutral[900], + active: color.neutral[900], + focused: color.neutral[900], + }, + ok: { + base: color.green[600], + hovered: color.green[600], + active: color.green[600], + focused: color.green[600], + }, + error: { + base: color.red[400], + hovered: color.red[400], + active: color.red[400], + focused: color.red[400], + }, + warning: { + base: color.amber[300], + hovered: color.amber[300], + active: color.amber[300], + focused: color.amber[300], + }, + info: { + base: color.blue[500], + hovered: color.blue[500], + active: color.blue[500], + focused: color.blue[500], + }, }; const borderColor = { - primary: color.neutral[850], - secondary: color.neutral[700], - muted: color.neutral[750], - focused: color.neutral[100], - active: color.neutral[500], - ok: color.neutral[999], - error: color.neutral[999], - warning: color.neutral[999], - info: color.neutral[999], + primary: color.neutral[850], + secondary: color.neutral[700], + muted: color.neutral[750], + focused: color.neutral[100], + active: color.neutral[500], + ok: color.neutral[1000], + error: color.neutral[1000], + warning: color.neutral[1000], + info: color.neutral[1000], }; const textColor = { - primary: color.neutral[150], - secondary: color.neutral[350], - muted: color.neutral[550], - placeholder: color.neutral[750], - active: color.neutral[0], - //TODO: (design) define feature and it's correct value - feature: color.sky[500], - ok: color.green[600], - error: color.red[400], - warning: color.amber[300], - info: color.blue[500], + primary: color.neutral[150], + secondary: color.neutral[350], + muted: color.neutral[550], + placeholder: color.neutral[750], + active: color.neutral[0], + //TODO: (design) define feature and it's correct value + feature: color.sky[500], + ok: color.green[600], + error: color.red[400], + warning: color.amber[300], + info: color.blue[500], }; const iconColor = { - primary: color.neutral[300], - secondary: color.neutral[500], - muted: color.neutral[600], - placeholder: color.neutral[700], - active: color.neutral[50], - //TODO: (design) define feature and it's correct value - feature: color.sky[500], - ok: color.green[600], - error: color.red[400], - warning: color.amber[300], - info: color.blue[500], + primary: color.neutral[300], + secondary: color.neutral[500], + muted: color.neutral[600], + placeholder: color.neutral[700], + active: color.neutral[50], + //TODO: (design) define feature and it's correct value + feature: color.sky[500], + ok: color.green[600], + error: color.red[400], + warning: color.amber[300], + info: color.blue[500], }; const player = { - 1: { - baseColor: color.blue[600], - cursorColor: color.blue[600], - selectionColor: color.blue[600], - borderColor: color.blue[600], - }, - 2: { - baseColor: color.indigo[500], - cursorColor: color.indigo[500], - selectionColor: color.indigo[500], - borderColor: color.indigo[500], - }, - 3: { - baseColor: color.green[500], - cursorColor: color.green[500], - selectionColor: color.green[500], - borderColor: color.green[500], - }, - 4: { - baseColor: color.orange[500], - cursorColor: color.orange[500], - selectionColor: color.orange[500], - borderColor: color.orange[500], - }, - 5: { - baseColor: color.purple[500], - cursorColor: color.purple[500], - selectionColor: color.purple[500], - borderColor: color.purple[500], - }, - 6: { - baseColor: color.teal[400], - cursorColor: color.teal[400], - selectionColor: color.teal[400], - borderColor: color.teal[400], - }, - 7: { - baseColor: color.pink[400], - cursorColor: color.pink[400], - selectionColor: color.pink[400], - borderColor: color.pink[400], - }, - 8: { - baseColor: color.yellow[400], - cursorColor: color.yellow[400], - selectionColor: color.yellow[400], - borderColor: color.yellow[400], - }, + 1: { + baseColor: color.blue[600], + cursorColor: color.blue[600], + selectionColor: color.blue[600], + borderColor: color.blue[600], + }, + 2: { + baseColor: color.indigo[500], + cursorColor: color.indigo[500], + selectionColor: color.indigo[500], + borderColor: color.indigo[500], + }, + 3: { + baseColor: color.green[500], + cursorColor: color.green[500], + selectionColor: color.green[500], + borderColor: color.green[500], + }, + 4: { + baseColor: color.orange[500], + cursorColor: color.orange[500], + selectionColor: color.orange[500], + borderColor: color.orange[500], + }, + 5: { + baseColor: color.purple[500], + cursorColor: color.purple[500], + selectionColor: color.purple[500], + borderColor: color.purple[500], + }, + 6: { + baseColor: color.teal[400], + cursorColor: color.teal[400], + selectionColor: color.teal[400], + borderColor: color.teal[400], + }, + 7: { + baseColor: color.pink[400], + cursorColor: color.pink[400], + selectionColor: color.pink[400], + borderColor: color.pink[400], + }, + 8: { + baseColor: color.yellow[400], + cursorColor: color.yellow[400], + selectionColor: color.yellow[400], + borderColor: color.yellow[400], + }, }; // TODO: Fixup const editor = { - background: backgroundColor[500].base, - indent_guide: borderColor.muted, - indent_guide_active: borderColor.secondary, - line: { - active: color.neutral[0], - highlighted: color.neutral[0], - inserted: backgroundColor.ok.active, - deleted: backgroundColor.error.active, - modified: backgroundColor.info.active, - }, - highlight: { - selection: player[1].selectionColor, - occurrence: backgroundColor[500].active, - activeOccurrence: color.neutral[0], - matchingBracket: color.neutral[0], - match: color.neutral[0], - activeMatch: color.neutral[0], - related: color.neutral[0], - }, - gutter: { - primary: color.neutral[0], - active: color.neutral[0], - }, + background: backgroundColor[500].base, + indent_guide: borderColor.muted, + indent_guide_active: borderColor.secondary, + line: { + active: color.neutral[0], + highlighted: color.neutral[0], + inserted: backgroundColor.ok.active, + deleted: backgroundColor.error.active, + modified: backgroundColor.info.active, + }, + highlight: { + selection: player[1].selectionColor, + occurrence: backgroundColor[500].active, + activeOccurrence: color.neutral[0], + matchingBracket: color.neutral[0], + match: color.neutral[0], + activeMatch: color.neutral[0], + related: color.neutral[0], + }, + gutter: { + primary: color.neutral[0], + active: color.neutral[0], + }, }; const syntax: Syntax = { - primary: { - color: textColor.primary, - weight: { value: "normal", type: "fontWeight" }, - }, - comment: { - color: color.lime[200], - weight: { value: "normal", type: "fontWeight" }, - }, - punctuation: { - color: textColor.primary, - weight: { value: "normal", type: "fontWeight" }, - }, - constant: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - keyword: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - function: { - color: color.yellow[200], - weight: { value: "normal", type: "fontWeight" }, - }, - type: { - color: color.teal[300], - weight: { value: "normal", type: "fontWeight" }, - }, - variant: { - color: color.teal[300], - weight: { value: "normal", type: "fontWeight" }, - }, - property: { - color: color.sky[300], - weight: { value: "normal", type: "fontWeight" }, - }, - enum: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - operator: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - string: { - color: color.orange[300], - weight: { value: "normal", type: "fontWeight" }, - }, - number: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - boolean: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - predictive: { - color: textColor.muted, - weight: { value: "normal", type: "fontWeight" }, - }, + primary: { + color: textColor.primary, + weight: { value: "normal", type: "fontWeight" }, + }, + comment: { + color: color.lime[200], + weight: { value: "normal", type: "fontWeight" }, + }, + punctuation: { + color: textColor.primary, + weight: { value: "normal", type: "fontWeight" }, + }, + constant: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + keyword: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + function: { + color: color.yellow[200], + weight: { value: "normal", type: "fontWeight" }, + }, + type: { + color: color.teal[300], + weight: { value: "normal", type: "fontWeight" }, + }, + variant: { + color: color.teal[300], + weight: { value: "normal", type: "fontWeight" }, + }, + property: { + color: color.sky[300], + weight: { value: "normal", type: "fontWeight" }, + }, + enum: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + operator: { + color: color.sky[400], + weight: { value: "normal", type: "fontWeight" }, + }, + string: { + color: color.orange[300], + weight: { value: "normal", type: "fontWeight" }, + }, + number: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + boolean: { + color: color.neutral[150], + weight: { value: "normal", type: "fontWeight" }, + }, + predictive: { + color: textColor.muted, + weight: { value: "normal", type: "fontWeight" }, + }, }; const shadowAlpha: NumberToken = { - value: 0.32, - type: "number" + value: 0.32, + type: "number", }; const theme: Theme = { - name: "light", - backgroundColor, - borderColor, - textColor, - iconColor, - editor, - syntax, - player, - shadowAlpha, + name: "light", + backgroundColor, + borderColor, + textColor, + iconColor, + editor, + syntax, + player, + shadowAlpha, }; export default theme; diff --git a/styles/tsconfig.json b/styles/tsconfig.json new file mode 100644 index 0000000000..3dfbcc715e --- /dev/null +++ b/styles/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2015", + "module": "commonjs", + "esModuleInterop": true, + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true + }, + "exclude": ["node_modules"] + } \ No newline at end of file diff --git a/styles/utils/decamelizeTree.ts b/styles/utils/decamelizeTree.ts new file mode 100644 index 0000000000..d606902082 --- /dev/null +++ b/styles/utils/decamelizeTree.ts @@ -0,0 +1,21 @@ +import { snakeCase } from "case-anything"; + +export default function decamelizeTree(object: { [key: string]: any }) { + const snakeObject: { [key: string]: any } = {}; + for (const key in object) { + snakeObject[snakeCase(key)] = decamelizeValue(object[key]); + } + return snakeObject; +} + +function decamelizeValue(value: any): any { + if (typeof value === "object") { + if (Array.isArray(value)) { + return value.map(decamelizeValue); + } else { + return decamelizeTree(value); + } + } else { + return value; + } +} From 371ea7c5529aa670e9b5aded82b2762be6073a38 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 1 Apr 2022 09:56:50 -0600 Subject: [PATCH 57/68] Update style tree based on changes to _base.toml from main Co-Authored-By: Nate Butler <1714999+iamnbutler@users.noreply.github.com> --- styles/styleTree/search.ts | 15 ++++++--------- styles/styleTree/workspace.ts | 10 +++++++++- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/styles/styleTree/search.ts b/styles/styleTree/search.ts index fd2fd25681..7ba04cd688 100644 --- a/styles/styleTree/search.ts +++ b/styles/styleTree/search.ts @@ -20,7 +20,6 @@ export default function search(theme: Theme) { }; return { - background: backgroundColor(theme, 300), matchBackground: theme.editor.highlight.match, tabIconSpacing: 4, tabIconWidth: 14, @@ -35,22 +34,20 @@ export default function search(theme: Theme) { editor: { background: backgroundColor(theme, 500), cornerRadius: 6, - maxWidth: 400, + minWidth: 200, + maxWidth: 500, placeholderText: text(theme, "mono", "placeholder"), selection: player(theme, 1).selection, text: text(theme, "mono", "primary"), border: border(theme, "primary"), margin: { - bottom: 5, - left: 5, right: 5, - top: 5, }, padding: { - bottom: 3, - left: 13, - right: 13, top: 3, + bottom: 3, + left: 14, + right: 14, }, }, hoveredOptionButton: { @@ -62,7 +59,7 @@ export default function search(theme: Theme) { border: border(theme, "error"), }, matchIndex: { - ...text(theme, "mono", "secondary"), + ...text(theme, "mono", "muted"), padding: 6, }, optionButton, diff --git a/styles/styleTree/workspace.ts b/styles/styleTree/workspace.ts index e8232442b6..148db08918 100644 --- a/styles/styleTree/workspace.ts +++ b/styles/styleTree/workspace.ts @@ -127,7 +127,15 @@ export default function workspace(theme: Theme) { }, }, toolbar: { - height: 44, + height: 34, + background: backgroundColor(theme, 300), + border: border(theme, "primary", { bottom: true }), + itemSpacing: 8, + padding: { left: 16, right: 8, top: 4, bottom: 4 }, + }, + breadcrumbs: { + ...text(theme, "mono", "secondary"), + padding: { left: 6 }, }, }; } From 391aed3d66c194e5c66781fdec736c577a0c347e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 1 Apr 2022 11:45:08 -0600 Subject: [PATCH 58/68] Start loading new theme JSON format instead of TOML Replaced remaining extends with javascript object extension. Moved tokens/core.ts to tokens.ts and massaged the types to make it more obvious when types don't match up. Co-authored-by: Nathan Sobo --- crates/theme/src/resolution.rs | 497 ----------- crates/theme/src/theme.rs | 3 +- crates/theme/src/theme_registry.rs | 234 +---- crates/zed/assets/themes/_base.toml | 411 --------- crates/zed/assets/themes/black.toml | 67 -- crates/zed/assets/themes/dark.json | 1245 +++++++++++++++++++++++++++ crates/zed/assets/themes/dark.toml | 67 -- crates/zed/assets/themes/light.json | 1245 +++++++++++++++++++++++++++ crates/zed/assets/themes/light.toml | 67 -- crates/zed/src/zed.rs | 3 +- styles/buildThemes.ts | 14 +- styles/styleTree/app.ts | 106 +-- styles/styleTree/components.ts | 14 +- styles/styleTree/contactsPanel.ts | 61 ++ styles/styleTree/editor.ts | 245 +++--- styles/styleTree/projectPanel.ts | 6 +- styles/styleTree/search.ts | 44 +- styles/styleTree/workspace.ts | 5 + styles/themes/dark.ts | 462 +++++----- styles/themes/light.ts | 298 ++++--- styles/themes/theme.ts | 37 +- styles/tokens.ts | 102 +++ styles/tokens/core.ts | 58 -- 23 files changed, 3283 insertions(+), 2008 deletions(-) delete mode 100644 crates/theme/src/resolution.rs delete mode 100644 crates/zed/assets/themes/_base.toml delete mode 100644 crates/zed/assets/themes/black.toml create mode 100644 crates/zed/assets/themes/dark.json delete mode 100644 crates/zed/assets/themes/dark.toml create mode 100644 crates/zed/assets/themes/light.json delete mode 100644 crates/zed/assets/themes/light.toml create mode 100644 styles/styleTree/contactsPanel.ts create mode 100644 styles/tokens.ts delete mode 100644 styles/tokens/core.ts diff --git a/crates/theme/src/resolution.rs b/crates/theme/src/resolution.rs deleted file mode 100644 index acebf72b86..0000000000 --- a/crates/theme/src/resolution.rs +++ /dev/null @@ -1,497 +0,0 @@ -use anyhow::{anyhow, Result}; -use indexmap::IndexMap; -use serde_json::Value; -use std::{ - cell::RefCell, - mem, - rc::{Rc, Weak}, -}; - -pub fn resolve_references(value: Value) -> Result { - let tree = Tree::from_json(value)?; - tree.resolve()?; - tree.to_json() -} - -#[derive(Clone)] -enum Node { - Reference { - path: String, - parent: Option>>, - }, - Object { - base: Option, - children: IndexMap, - resolved: bool, - parent: Option>>, - }, - Array { - children: Vec, - resolved: bool, - parent: Option>>, - }, - String { - value: String, - parent: Option>>, - }, - Number { - value: serde_json::Number, - parent: Option>>, - }, - Bool { - value: bool, - parent: Option>>, - }, - Null { - parent: Option>>, - }, -} - -#[derive(Clone)] -struct Tree(Rc>); - -impl Tree { - pub fn new(node: Node) -> Self { - Self(Rc::new(RefCell::new(node))) - } - - fn from_json(value: Value) -> Result { - match value { - Value::String(value) => { - if let Some(path) = value.strip_prefix("$") { - Ok(Self::new(Node::Reference { - path: path.to_string(), - parent: None, - })) - } else { - Ok(Self::new(Node::String { - value, - parent: None, - })) - } - } - Value::Number(value) => Ok(Self::new(Node::Number { - value, - parent: None, - })), - Value::Bool(value) => Ok(Self::new(Node::Bool { - value, - parent: None, - })), - Value::Null => Ok(Self::new(Node::Null { parent: None })), - Value::Object(object) => { - let tree = Self::new(Node::Object { - base: Default::default(), - children: Default::default(), - resolved: false, - parent: None, - }); - let mut children = IndexMap::new(); - let mut resolved = true; - let mut base = None; - for (key, value) in object.into_iter() { - let value = if key == "extends" { - if value.is_string() { - if let Value::String(value) = value { - base = value.strip_prefix("$").map(str::to_string); - resolved = false; - Self::new(Node::String { - value, - parent: None, - }) - } else { - unreachable!() - } - } else { - Tree::from_json(value)? - } - } else { - Tree::from_json(value)? - }; - value - .0 - .borrow_mut() - .set_parent(Some(Rc::downgrade(&tree.0))); - resolved &= value.is_resolved(); - children.insert(key.clone(), value); - } - - *tree.0.borrow_mut() = Node::Object { - base, - children, - resolved, - parent: None, - }; - Ok(tree) - } - Value::Array(elements) => { - let tree = Self::new(Node::Array { - children: Default::default(), - resolved: false, - parent: None, - }); - - let mut children = Vec::new(); - let mut resolved = true; - for element in elements { - let child = Tree::from_json(element)?; - child - .0 - .borrow_mut() - .set_parent(Some(Rc::downgrade(&tree.0))); - resolved &= child.is_resolved(); - children.push(child); - } - - *tree.0.borrow_mut() = Node::Array { - children, - resolved, - parent: None, - }; - Ok(tree) - } - } - } - - fn to_json(&self) -> Result { - match &*self.0.borrow() { - Node::Reference { .. } => Err(anyhow!("unresolved tree")), - Node::String { value, .. } => Ok(Value::String(value.clone())), - Node::Number { value, .. } => Ok(Value::Number(value.clone())), - Node::Bool { value, .. } => Ok(Value::Bool(*value)), - Node::Null { .. } => Ok(Value::Null), - Node::Object { children, .. } => { - let mut json_children = serde_json::Map::new(); - for (key, value) in children { - json_children.insert(key.clone(), value.to_json()?); - } - Ok(Value::Object(json_children)) - } - Node::Array { children, .. } => { - let mut json_children = Vec::new(); - for child in children { - json_children.push(child.to_json()?); - } - Ok(Value::Array(json_children)) - } - } - } - - fn parent(&self) -> Option { - match &*self.0.borrow() { - Node::Reference { parent, .. } - | Node::Object { parent, .. } - | Node::Array { parent, .. } - | Node::String { parent, .. } - | Node::Number { parent, .. } - | Node::Bool { parent, .. } - | Node::Null { parent } => parent.as_ref().and_then(|p| p.upgrade()).map(Tree), - } - } - - fn get(&self, path: &str) -> Result> { - let mut tree = self.clone(); - for component in path.split('.') { - let node = tree.0.borrow(); - match &*node { - Node::Object { children, .. } => { - if let Some(subtree) = children.get(component).cloned() { - drop(node); - tree = subtree; - } else { - return Err(anyhow!( - "key \"{}\" does not exist in path \"{}\"", - component, - path - )); - } - } - Node::Reference { .. } => return Ok(None), - Node::Array { .. } - | Node::String { .. } - | Node::Number { .. } - | Node::Bool { .. } - | Node::Null { .. } => { - return Err(anyhow!( - "key \"{}\" in path \"{}\" is not an object", - component, - path - )) - } - } - } - - Ok(Some(tree)) - } - - fn is_resolved(&self) -> bool { - match &*self.0.borrow() { - Node::Reference { .. } => false, - Node::Object { resolved, .. } | Node::Array { resolved, .. } => *resolved, - Node::String { .. } | Node::Number { .. } | Node::Bool { .. } | Node::Null { .. } => { - true - } - } - } - - fn update_resolved(&self) { - match &mut *self.0.borrow_mut() { - Node::Object { - resolved, - base, - children, - .. - } => { - *resolved = base.is_none() && children.values().all(|c| c.is_resolved()); - } - Node::Array { - resolved, children, .. - } => { - *resolved = children.iter().all(|c| c.is_resolved()); - } - _ => {} - } - } - - pub fn resolve(&self) -> Result<()> { - let mut unresolved = vec![self.clone()]; - let mut made_progress = true; - - while made_progress && !unresolved.is_empty() { - made_progress = false; - for mut tree in mem::take(&mut unresolved) { - made_progress |= tree.resolve_subtree(self, &mut unresolved)?; - if tree.is_resolved() { - while let Some(parent) = tree.parent() { - parent.update_resolved(); - if !parent.is_resolved() { - break; - } - tree = parent; - } - } - } - } - - if unresolved.is_empty() { - Ok(()) - } else { - Err(anyhow!("tree contains cycles")) - } - } - - fn resolve_subtree(&self, root: &Tree, unresolved: &mut Vec) -> Result { - let node = self.0.borrow(); - match &*node { - Node::Reference { path, parent } => { - if let Some(subtree) = root.get(&path)? { - if subtree.is_resolved() { - let parent = parent.clone(); - drop(node); - let mut new_node = subtree.0.borrow().clone(); - new_node.set_parent(parent); - *self.0.borrow_mut() = new_node; - Ok(true) - } else { - unresolved.push(self.clone()); - Ok(false) - } - } else { - unresolved.push(self.clone()); - Ok(false) - } - } - Node::Object { - base, - children, - resolved, - .. - } => { - if *resolved { - Ok(false) - } else { - let mut made_progress = false; - let mut children_resolved = true; - for child in children.values() { - made_progress |= child.resolve_subtree(root, unresolved)?; - children_resolved &= child.is_resolved(); - } - - if children_resolved { - let mut has_base = false; - let mut resolved_base = None; - if let Some(base) = base { - has_base = true; - if let Some(base) = root.get(base)? { - if base.is_resolved() { - resolved_base = Some(base); - } - } - } - - drop(node); - - if let Some(base) = resolved_base.as_ref() { - self.extend_from(&base); - made_progress = true; - } - - if let Node::Object { resolved, base, .. } = &mut *self.0.borrow_mut() { - if has_base { - if resolved_base.is_some() { - base.take(); - *resolved = true; - } else { - unresolved.push(self.clone()); - } - } else { - *resolved = true; - } - } - } else if base.is_some() { - unresolved.push(self.clone()); - } - - Ok(made_progress) - } - } - Node::Array { - children, resolved, .. - } => { - if *resolved { - Ok(false) - } else { - let mut made_progress = false; - let mut children_resolved = true; - for child in children.iter() { - made_progress |= child.resolve_subtree(root, unresolved)?; - children_resolved &= child.is_resolved(); - } - - if children_resolved { - drop(node); - - if let Node::Array { resolved, .. } = &mut *self.0.borrow_mut() { - *resolved = true; - } - } - - Ok(made_progress) - } - } - Node::String { .. } | Node::Number { .. } | Node::Bool { .. } | Node::Null { .. } => { - Ok(false) - } - } - } - - fn extend_from(&self, base: &Tree) { - if Rc::ptr_eq(&self.0, &base.0) { - return; - } - - if let ( - Node::Object { children, .. }, - Node::Object { - children: base_children, - .. - }, - ) = (&mut *self.0.borrow_mut(), &*base.0.borrow()) - { - for (key, base_value) in base_children { - if let Some(value) = children.get(key) { - value.extend_from(base_value); - } else { - let base_value = base_value.clone(); - base_value - .0 - .borrow_mut() - .set_parent(Some(Rc::downgrade(&self.0))); - children.insert(key.clone(), base_value); - } - } - } - } -} - -impl Node { - fn set_parent(&mut self, new_parent: Option>>) { - match self { - Node::Reference { parent, .. } - | Node::Object { parent, .. } - | Node::Array { parent, .. } - | Node::String { parent, .. } - | Node::Number { parent, .. } - | Node::Bool { parent, .. } - | Node::Null { parent } => *parent = new_parent, - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_references() { - let json = serde_json::json!({ - "a": { - "extends": "$g", - "x": "$b.d" - }, - "b": { - "c": "$a", - "d": "$e.f" - }, - "e": { - "extends": "$a", - "f": "1" - }, - "g": { - "h": 2 - } - }); - - assert_eq!( - resolve_references(json).unwrap(), - serde_json::json!({ - "a": { - "extends": "$g", - "x": "1", - "h": 2 - }, - "b": { - "c": { - "extends": "$g", - "x": "1", - "h": 2 - }, - "d": "1" - }, - "e": { - "extends": "$a", - "f": "1", - "x": "1", - "h": 2 - }, - "g": { - "h": 2 - } - }) - ) - } - - #[test] - fn test_cycles() { - let json = serde_json::json!({ - "a": { - "b": "$c.d" - }, - "c": { - "d": "$a.b", - }, - }); - - assert!(resolve_references(json).is_err()); - } -} diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 8fa15a9235..b3c239b4b9 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -1,4 +1,3 @@ -mod resolution; mod theme_registry; use gpui::{ @@ -12,7 +11,7 @@ use std::{collections::HashMap, sync::Arc}; pub use theme_registry::*; -pub const DEFAULT_THEME_NAME: &'static str = "black"; +pub const DEFAULT_THEME_NAME: &'static str = "dark"; #[derive(Deserialize, Default)] pub struct Theme { diff --git a/crates/theme/src/theme_registry.rs b/crates/theme/src/theme_registry.rs index c3910dc4d2..219828b650 100644 --- a/crates/theme/src/theme_registry.rs +++ b/crates/theme/src/theme_registry.rs @@ -1,8 +1,8 @@ -use crate::{resolution::resolve_references, Theme}; +use crate::Theme; use anyhow::{Context, Result}; use gpui::{fonts, AssetSource, FontCache}; use parking_lot::Mutex; -use serde_json::{Map, Value}; +use serde_json::Value; use std::{collections::HashMap, sync::Arc}; pub struct ThemeRegistry { @@ -25,12 +25,8 @@ impl ThemeRegistry { pub fn list(&self) -> impl Iterator { self.assets.list("themes/").into_iter().filter_map(|path| { let filename = path.strip_prefix("themes/")?; - let theme_name = filename.strip_suffix(".toml")?; - if theme_name.starts_with('_') { - None - } else { - Some(theme_name.to_string()) - } + let theme_name = filename.strip_suffix(".json")?; + Some(theme_name.to_string()) }) } @@ -44,9 +40,14 @@ impl ThemeRegistry { return Ok(theme.clone()); } - let theme_data = self.load(name, true)?; + let asset_path = format!("themes/{}.json", name); + let theme_json = self + .assets + .load(&asset_path) + .with_context(|| format!("failed to load theme file {}", asset_path))?; + let mut theme: Theme = fonts::with_font_cache(self.font_cache.clone(), || { - serde_path_to_error::deserialize(theme_data.as_ref()) + serde_path_to_error::deserialize(&mut serde_json::Deserializer::from_slice(&theme_json)) })?; theme.name = name.into(); @@ -54,217 +55,4 @@ impl ThemeRegistry { self.themes.lock().insert(name.to_string(), theme.clone()); Ok(theme) } - - fn load(&self, name: &str, evaluate_references: bool) -> Result> { - if let Some(data) = self.theme_data.lock().get(name) { - return Ok(data.clone()); - } - - let asset_path = format!("themes/{}.toml", name); - let source_code = self - .assets - .load(&asset_path) - .with_context(|| format!("failed to load theme file {}", asset_path))?; - - let mut theme_data: Map = toml::from_slice(source_code.as_ref()) - .with_context(|| format!("failed to parse {}.toml", name))?; - - // If this theme extends another base theme, deeply merge it into the base theme's data - if let Some(base_name) = theme_data - .get("extends") - .and_then(|name| name.as_str()) - .map(str::to_string) - { - let base_theme_data = self - .load(&base_name, false) - .with_context(|| format!("failed to load base theme {}", base_name))? - .as_ref() - .clone(); - if let Value::Object(mut base_theme_object) = base_theme_data { - deep_merge_json(&mut base_theme_object, theme_data); - theme_data = base_theme_object; - } - } - - let mut theme_data = Value::Object(theme_data); - - // Find all of the key path references in the object, and then sort them according - // to their dependencies. - if evaluate_references { - theme_data = resolve_references(theme_data)?; - } - - let result = Arc::new(theme_data); - self.theme_data - .lock() - .insert(name.to_string(), result.clone()); - - Ok(result) - } -} - -fn deep_merge_json(base: &mut Map, extension: Map) { - for (key, extension_value) in extension { - if let Value::Object(extension_object) = extension_value { - if let Some(base_object) = base.get_mut(&key).and_then(|value| value.as_object_mut()) { - deep_merge_json(base_object, extension_object); - } else { - base.insert(key, Value::Object(extension_object)); - } - } else { - base.insert(key, extension_value); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use anyhow::anyhow; - use gpui::MutableAppContext; - - #[gpui::test] - fn test_theme_extension(cx: &mut MutableAppContext) { - let assets = TestAssets(&[ - ( - "themes/_base.toml", - r##" - [ui.active_tab] - extends = "$ui.tab" - border.color = "#666666" - text = "$text_colors.bright" - - [ui.tab] - extends = "$ui.element" - text = "$text_colors.dull" - - [ui.element] - background = "#111111" - border = {width = 2.0, color = "#00000000"} - - [editor] - background = "#222222" - default_text = "$text_colors.regular" - "##, - ), - ( - "themes/light.toml", - r##" - extends = "_base" - - [text_colors] - bright = "#ffffff" - regular = "#eeeeee" - dull = "#dddddd" - - [editor] - background = "#232323" - "##, - ), - ]); - - let registry = ThemeRegistry::new(assets, cx.font_cache().clone()); - let theme_data = registry.load("light", true).unwrap(); - - assert_eq!( - theme_data.as_ref(), - &serde_json::json!({ - "ui": { - "active_tab": { - "background": "#111111", - "border": { - "width": 2.0, - "color": "#666666" - }, - "extends": "$ui.tab", - "text": "#ffffff" - }, - "tab": { - "background": "#111111", - "border": { - "width": 2.0, - "color": "#00000000" - }, - "extends": "$ui.element", - "text": "#dddddd" - }, - "element": { - "background": "#111111", - "border": { - "width": 2.0, - "color": "#00000000" - } - } - }, - "editor": { - "background": "#232323", - "default_text": "#eeeeee" - }, - "extends": "_base", - "text_colors": { - "bright": "#ffffff", - "regular": "#eeeeee", - "dull": "#dddddd" - } - }) - ); - } - - #[gpui::test] - fn test_nested_extension(cx: &mut MutableAppContext) { - let assets = TestAssets(&[( - "themes/theme.toml", - r##" - [a] - text = { extends = "$text.0" } - - [b] - extends = "$a" - text = { extends = "$text.1" } - - [text] - 0 = { color = "red" } - 1 = { color = "blue" } - "##, - )]); - - let registry = ThemeRegistry::new(assets, cx.font_cache().clone()); - let theme_data = registry.load("theme", true).unwrap(); - assert_eq!( - theme_data - .get("b") - .unwrap() - .get("text") - .unwrap() - .get("color") - .unwrap(), - "blue" - ); - } - - struct TestAssets(&'static [(&'static str, &'static str)]); - - impl AssetSource for TestAssets { - fn load(&self, path: &str) -> Result> { - if let Some(row) = self.0.iter().find(|e| e.0 == path) { - Ok(row.1.as_bytes().into()) - } else { - Err(anyhow!("no such path {}", path)) - } - } - - fn list(&self, prefix: &str) -> Vec> { - self.0 - .iter() - .copied() - .filter_map(|(path, _)| { - if path.starts_with(prefix) { - Some(path.into()) - } else { - None - } - }) - .collect() - } - } } diff --git a/crates/zed/assets/themes/_base.toml b/crates/zed/assets/themes/_base.toml deleted file mode 100644 index 7f235cbf48..0000000000 --- a/crates/zed/assets/themes/_base.toml +++ /dev/null @@ -1,411 +0,0 @@ -[text] -base = { family = "Zed Sans", size = 14 } - -[workspace] -background = "$surface.0" -pane_divider = { width = 1, color = "$border.0" } -leader_border_opacity = 0.7 -leader_border_width = 2.0 - -[workspace.titlebar] -height = 32 -border = { width = 1, bottom = true, color = "$border.0" } -title = "$text.0" -avatar_width = 18 -avatar = { corner_radius = 10, border = { width = 1, color = "#00000088" } } -avatar_ribbon = { background = "#ff0000", height = 3, width = 12 } -outdated_warning = { extends = "$text.2", size = 13 } -share_icon_color = "$text.2.color" -share_icon_active_color = "$text.0.color" - -[workspace.titlebar.sign_in_prompt] -extends = "$text.2" -size = 13 -underline = true -padding = { right = 8 } - -[workspace.titlebar.hovered_sign_in_prompt] -extends = "$workspace.titlebar.sign_in_prompt" -color = "$text.1.color" - -[workspace.titlebar.offline_icon] -padding = { right = 4 } -width = 16 -color = "$text.2.color" - -[workspace.tab] -height = 34 -text = "$text.2" -padding = { left = 12, right = 12 } -icon_width = 8 -spacing = 10 -icon_close = "$text.2.color" -icon_close_active = "$text.0.color" -icon_dirty = "$status.info" -icon_conflict = "$status.warn" -border = { left = true, bottom = true, width = 1, color = "$border.0", overlay = true } - -[workspace.active_tab] -extends = "$workspace.tab" -border.bottom = false -background = "$surface.1" -text = "$text.0" - -[workspace.sidebar] -width = 30 -border = { right = true, width = 1, color = "$border.0" } - -[workspace.sidebar.resize_handle] -padding = { left = 1 } -background = "$border.0" - -[workspace.sidebar.item] -icon_color = "$text.2.color" -icon_size = 18 -height = "$workspace.tab.height" - -[workspace.sidebar.active_item] -extends = "$workspace.sidebar.item" -icon_color = "$text.0.color" - -[workspace.left_sidebar] -extends = "$workspace.sidebar" -border = { width = 1, color = "$border.0", right = true } - -[workspace.right_sidebar] -extends = "$workspace.sidebar" -border = { width = 1, color = "$border.0", left = true } - -[workspace.status_bar] -padding = { left = 6, right = 6 } -height = 24 -item_spacing = 8 -cursor_position = "$text.2" -diagnostic_message = "$text.2" -lsp_message = "$text.2" - -[workspace.toolbar] -background = "$surface.1" -border = { color = "$border.0", width = 1, left = false, right = false, bottom = true, top = false } -height = 34 -item_spacing = 8 -padding = { left = 16, right = 8, top = 4, bottom = 4 } - -[breadcrumbs] -extends = "$text.1" -padding = { left = 6 } - -[panel] -padding = { top = 12, left = 12, bottom = 12, right = 12 } - -[chat_panel] -extends = "$panel" -channel_name = { extends = "$text.0", weight = "bold" } -channel_name_hash = { text = "$text.2", padding.right = 8 } - -[chat_panel.message] -body = "$text.1" -sender = { extends = "$text.0", weight = "bold", margin.right = 8 } -timestamp = "$text.2" -padding.bottom = 6 - -[chat_panel.pending_message] -extends = "$chat_panel.message" -body = { color = "$text.3.color" } -sender = { color = "$text.3.color" } -timestamp = { color = "$text.3.color" } - -[chat_panel.channel_select.item] -padding = 4 -name = "$text.1" -hash = { extends = "$text.2", margin.right = 8 } - -[chat_panel.channel_select.hovered_item] -extends = "$chat_panel.channel_select.item" -background = "$state.hover" -corner_radius = 6 - -[chat_panel.channel_select.active_item] -extends = "$chat_panel.channel_select.item" -name = "$text.0" - -[chat_panel.channel_select.hovered_active_item] -extends = "$chat_panel.channel_select.hovered_item" -name = "$text.0" - -[chat_panel.channel_select.header] -extends = "$chat_panel.channel_select.active_item" -padding.bottom = 4 -padding.left = 0 - -[chat_panel.channel_select.menu] -padding = 4 -corner_radius = 6 -border = { color = "$border.0", width = 1 } -background = "$surface.0" -shadow = { offset = [0, 2], blur = 16, color = "$shadow.0" } - -[chat_panel.input_editor] -background = "$surface.1" -corner_radius = 6 -padding = { left = 8, right = 8, top = 7, bottom = 7 } -text = "$text.0" -placeholder_text = "$text.2" -selection = "$selection.host" -border = { width = 1, color = "$border.0" } - -[chat_panel.sign_in_prompt] -extends = "$text.0" -underline = true - -[chat_panel.hovered_sign_in_prompt] -extends = "$chat_panel.sign_in_prompt" -color = "$text.1.color" - -[contacts_panel] -extends = "$panel" -host_row_height = 28 -host_avatar = { corner_radius = 10, width = 18 } -host_username = { extends = "$text.0", padding.left = 8 } -tree_branch_width = 1 -tree_branch_color = "$surface.2" - -[contacts_panel.project] -height = 24 -padding = { left = 8 } -guest_avatar = { corner_radius = 8, width = 14 } -guest_avatar_spacing = 4 - -[contacts_panel.project.name] -extends = "$text.1" -margin = { right = 6 } - -[contacts_panel.unshared_project] -extends = "$contacts_panel.project" - -[contacts_panel.hovered_unshared_project] -extends = "$contacts_panel.unshared_project" -background = "$state.hover" -corner_radius = 6 - -[contacts_panel.shared_project] -extends = "$contacts_panel.project" -name.color = "$text.0.color" - -[contacts_panel.hovered_shared_project] -extends = "$contacts_panel.shared_project" -background = "$state.hover" -corner_radius = 6 - -[project_panel] -extends = "$panel" -padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2 - -[project_panel.entry] -text = "$text.1" -height = 22 -icon_color = "$text.3.color" -icon_size = 8 -icon_spacing = 8 - -[project_panel.hovered_entry] -extends = "$project_panel.entry" -background = "$state.hover" - -[project_panel.selected_entry] -extends = "$project_panel.entry" -text = { extends = "$text.0" } - -[project_panel.hovered_selected_entry] -extends = "$project_panel.hovered_entry" -text = { extends = "$text.0" } - -[selector] -background = "$surface.0" -padding = 8 -margin = { top = 52, bottom = 52 } -corner_radius = 6 -shadow = { offset = [0, 2], blur = 16, color = "$shadow.0" } -border = { width = 1, color = "$border.0" } - -[selector.input_editor] -background = "$surface.1" -corner_radius = 6 -padding = { left = 16, right = 16, top = 7, bottom = 7 } -text = "$text.0" -placeholder_text = "$text.2" -selection = "$selection.host" -border = { width = 1, color = "$border.0" } - -[selector.empty] -text = "$text.2" -padding = { left = 16, right = 16, top = 8, bottom = 4 } - -[selector.item] -text = "$text.1" -highlight_text = { extends = "$text.base", color = "$editor.syntax.keyword.color", weight = "$editor.syntax.keyword.weight" } -padding = { left = 16, right = 16, top = 4, bottom = 4 } -corner_radius = 6 - -[selector.active_item] -extends = "$selector.item" -background = "$state.hover" -text = "$text.0" - -[editor] -text_color = "$text.1.color" -background = "$surface.1" -gutter_background = "$surface.1" -gutter_padding_factor = 2.5 -active_line_background = "$state.active_line" -highlighted_line_background = "$state.highlighted_line" -rename_fade = 0.6 -unnecessary_code_fade = 0.5 -document_highlight_read_background = "#99999920" -document_highlight_write_background = "#99999916" -diff_background_deleted = "$state.deleted_line" -diff_background_inserted = "$state.inserted_line" -line_number = "$text.2.color" -line_number_active = "$text.0.color" -selection = "$selection.host" -guest_selections = "$selection.guests" -error_color = "$status.bad" -code_actions_indicator = "$text.3.color" - -[editor.diagnostic_path_header] -background = "$state.active_line" -filename = { extends = "$text.0", size = 14 } -path = { extends = "$text.2", size = 14, margin.left = 12 } -text_scale_factor = 0.857 - -[editor.diagnostic_header] -background = "$editor.background" -border = { width = 1, top = true, bottom = true, color = "$border.1" } -code = { extends = "$text.2", size = 14, margin.left = 10 } -icon_width_factor = 1.5 -text_scale_factor = 0.857 - -[editor.diagnostic_header.message] -text = { extends = "$text.1", size = 14 } -highlight_text = { extends = "$text.0", size = 14, weight = "bold" } - -[editor.error_diagnostic] -header.border = { width = 1, top = true, color = "$border.0" } -text_scale_factor = 0.857 - -[editor.error_diagnostic.message] -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" -message.text.color = "$status.warn" -message.highlight_text.color = "$status.warn" - -[editor.information_diagnostic] -extends = "$editor.error_diagnostic" -message.text.color = "$status.info" -message.highlight_text.color = "$status.info" - -[editor.hint_diagnostic] -extends = "$editor.error_diagnostic" -message.text.color = "$status.info" -message.highlight_text.color = "$status.info" - -[editor.invalid_error_diagnostic] -extends = "$editor.error_diagnostic" -message.text.color = "$text.3.color" -message.highlight_text.color = "$text.3.color" - -[editor.invalid_warning_diagnostic] -extends = "$editor.warning_diagnostic" -message.text.color = "$text.3.color" -message.highlight_text.color = "$text.3.color" - -[editor.invalid_information_diagnostic] -extends = "$editor.information_diagnostic" -message.text.color = "$text.3.color" -message.highlight_text.color = "$text.3.color" - -[editor.invalid_hint_diagnostic] -extends = "$editor.hint_diagnostic" -message.text.color = "$text.3.color" -message.highlight_text.color = "$text.3.color" - -[editor.autocomplete] -background = "$surface.2" -border = { width = 2, color = "$border.1" } -corner_radius = 6 -padding = 6 -match_highlight = { color = "$editor.syntax.keyword.color", weight = "$editor.syntax.keyword.weight" } -margin.left = -14 - -[editor.autocomplete.item] -padding = { left = 6, right = 6, top = 2, bottom = 2 } -corner_radius = 6 - -[editor.autocomplete.selected_item] -extends = "$editor.autocomplete.item" -background = "$state.selected" - -[editor.autocomplete.hovered_item] -extends = "$editor.autocomplete.item" -background = "$state.hover" - -[project_diagnostics] -background = "$surface.1" -empty_message = { extends = "$text.0", size = 18 } -status_bar_item = { extends = "$text.2", margin.right = 10 } -tab_icon_width = 13 -tab_icon_spacing = 4 -tab_summary_spacing = 10 - -[search] -match_background = "$state.highlighted_line" -results_status = { extends = "$text.0", size = 18 } -tab_icon_width = 14 -tab_icon_spacing = 4 - -[search.option_button] -extends = "$text.1" -padding = { left = 6, right = 6, top = 1, bottom = 1 } -corner_radius = 6 -background = "$surface.1" -border = { width = 1, color = "$border.0" } -margin.left = 1 -margin.right = 1 - -[search.option_button_group] -padding = { left = 2, right = 2 } - -[search.active_option_button] -extends = "$search.option_button" -background = "$surface.2" - -[search.hovered_option_button] -extends = "$search.option_button" -background = "$surface.2" - -[search.active_hovered_option_button] -extends = "$search.option_button" -background = "$surface.2" - -[search.match_index] -extends = "$text.2" -padding = 6 - -[search.editor] -min_width = 200 -max_width = 500 -background = "$surface.0" -corner_radius = 6 -padding = { left = 14, right = 14, top = 3, bottom = 3 } -margin = { right = 5 } -text = "$text.0" -placeholder_text = "$text.2" -selection = "$selection.host" -border = { width = 1, color = "$border.0" } - -[search.invalid_editor] -extends = "$search.editor" -border = { width = 1, color = "$status.bad" } diff --git a/crates/zed/assets/themes/black.toml b/crates/zed/assets/themes/black.toml deleted file mode 100644 index 34de16627e..0000000000 --- a/crates/zed/assets/themes/black.toml +++ /dev/null @@ -1,67 +0,0 @@ -extends = "_base" - -[surface] -0 = "#222222" -1 = "#0f0b0c" -2 = "#131415" - -[border] -0 = "#000000B2" -1 = "#FFFFFF20" - -[text] -0 = { extends = "$text.base", color = "#ffffff" } -1 = { extends = "$text.base", color = "#b3b3b3" } -2 = { extends = "$text.base", color = "#7b7d80" } -3 = { extends = "$text.base", color = "#66686A" } - -[shadow] -0 = "#00000052" - -[selection] -host = { selection = "#3B57BC55", cursor = "$text.0.color" } -guests = [ - { selection = "#FDF35133", cursor = "#FDF351" }, - { selection = "#4EACAD33", cursor = "#4EACAD" }, - { selection = "#D0453B33", cursor = "#D0453B" }, - { selection = "#3B874B33", cursor = "#3B874B" }, - { selection = "#BD7CB433", cursor = "#BD7CB4" }, - { selection = "#EE823133", cursor = "#EE8231" }, - { selection = "#5A2B9233", cursor = "#5A2B92" }, -] - -[status] -good = "#4fac63" -info = "#3c5dd4" -warn = "#faca50" -bad = "#b7372e" - -[state] -active_line = "#161313" -highlighted_line = "#faca5033" -deleted_line = "#dd000036" -inserted_line = "#00dd0036" -hover = "#00000033" -selected = "#00000088" - -[editor.syntax] -keyword = { color = "#0086c0", weight = "bold" } -function = "#dcdcaa" -string = "#cb8f77" -type = "#4ec9b0" -number = "#b5cea8" -comment = "#6a9955" -property = "#4e94ce" -variant = "#4fc1ff" -constant = "#9cdcfe" -title = { color = "#9cdcfe", weight = "bold" } -emphasis = "#4ec9b0" -"emphasis.strong" = { color = "#4ec9b0", weight = "bold" } -link_uri = { color = "#6a9955", underline = true } -link_text = { color = "#cb8f77", italic = true } -list_marker = "#4e94ce" - -[workspace.disconnected_overlay] -extends = "$text.base" -color = "#ffffff" -background = "#000000aa" diff --git a/crates/zed/assets/themes/dark.json b/crates/zed/assets/themes/dark.json new file mode 100644 index 0000000000..65bf78b140 --- /dev/null +++ b/crates/zed/assets/themes/dark.json @@ -0,0 +1,1245 @@ +{ + "selector": { + "background": "#e6e6e6", + "corner_radius": 6, + "padding": 8, + "item": { + "padding": { + "bottom": 4, + "left": 16, + "right": 16, + "top": 4 + }, + "corner_radius": 6, + "text": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#2db4f3", + "weight": "bold", + "size": 14 + } + }, + "active_item": { + "padding": { + "bottom": 4, + "left": 16, + "right": 16, + "top": 4 + }, + "corner_radius": 6, + "text": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#2db4f3", + "weight": "bold", + "size": 14 + }, + "background": "#e6e6e6" + }, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "empty": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "padding": { + "bottom": 4, + "left": 16, + "right": 16, + "top": 8 + } + }, + "input_editor": { + "background": "#cccccc", + "corner_radius": 6, + "placeholder_text": { + "family": "Zed Sans", + "color": "#bfbfbf", + "size": 14 + }, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "padding": { + "bottom": 7, + "left": 16, + "right": 16, + "top": 7 + } + }, + "margin": { + "bottom": 52, + "top": 52 + }, + "shadow": { + "blur": 16, + "color": "#00000052", + "offset": [ + 0, + 2 + ] + } + }, + "workspace": { + "background": "#e6e6e6", + "leader_border_opacity": 0.7, + "leader_border_width": 2, + "tab": { + "height": 34, + "icon_close": "#808080", + "icon_close_active": "#0d0d0d", + "icon_conflict": "#f8c570", + "icon_dirty": "#6099f7", + "icon_width": 8, + "spacing": 10, + "text": { + "family": "Zed Mono", + "color": "#595959", + "size": 16 + }, + "border": { + "color": "#d9d9d9", + "width": 1, + "left": true, + "bottom": true, + "overlay": true + }, + "padding": { + "left": 12, + "right": 12 + } + }, + "active_tab": { + "height": 34, + "icon_close": "#808080", + "icon_close_active": "#0d0d0d", + "icon_conflict": "#f8c570", + "icon_dirty": "#6099f7", + "icon_width": 8, + "spacing": 10, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "border": { + "color": "#d9d9d9", + "width": 1, + "left": true, + "bottom": false, + "overlay": true + }, + "padding": { + "left": 12, + "right": 12 + }, + "background": "#cccccc" + }, + "left_sidebar": { + "width": 30, + "border": { + "color": "#d9d9d9", + "width": 1, + "right": true + }, + "item": { + "height": 32, + "icon_color": "#808080", + "icon_size": 18 + }, + "active_item": { + "height": 32, + "icon_color": "#4d4d4d", + "icon_size": 18 + }, + "resize_handle": { + "background": "#d9d9d9", + "padding": { + "left": 1 + } + } + }, + "right_sidebar": { + "width": 30, + "border": { + "color": "#d9d9d9", + "width": 1, + "left": true + }, + "item": { + "height": 32, + "icon_color": "#808080", + "icon_size": 18 + }, + "active_item": { + "height": 32, + "icon_color": "#4d4d4d", + "icon_size": 18 + }, + "resize_handle": { + "background": "#d9d9d9", + "padding": { + "left": 1 + } + } + }, + "pane_divider": { + "color": "#d9d9d9", + "width": 1 + }, + "status_bar": { + "height": 24, + "item_spacing": 8, + "padding": { + "left": 6, + "right": 6 + }, + "cursor_position": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "diagnostic_message": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "lsp_message": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + } + }, + "titlebar": { + "avatar_width": 18, + "height": 32, + "share_icon_color": "#808080", + "share_icon_active_color": "#0d0d0d", + "title": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "avatar": { + "corner_radius": 10, + "border": { + "color": "#00000088", + "width": 1 + } + }, + "avatar_ribbon": { + "height": 3, + "width": 12 + }, + "border": { + "color": "#d9d9d9", + "width": 1, + "bottom": true + }, + "sign_in_prompt": { + "family": "Zed Sans", + "color": "#595959", + "size": 13, + "underline": true, + "padding": { + "right": 8 + } + }, + "hovered_sign_in_prompt": { + "family": "Zed Mono", + "color": "#000000", + "size": 16, + "underline": true, + "padding": { + "right": 8 + } + }, + "offline_icon": { + "color": "#999999", + "width": 16, + "padding": { + "right": 4 + } + }, + "outdated_warning": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 13 + } + }, + "toolbar": { + "height": 34, + "background": "#cccccc", + "border": { + "color": "#d9d9d9", + "width": 1, + "bottom": true + }, + "item_spacing": 8, + "padding": { + "left": 16, + "right": 8, + "top": 4, + "bottom": 4 + } + }, + "breadcrumbs": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "padding": { + "left": 6 + } + }, + "disconnected_overlay": { + "family": "Zed Sans", + "color": "#ffffff", + "size": 14, + "background": "#000000aa" + } + }, + "editor": { + "text_color": "#595959", + "background": "#cccccc", + "active_line_background": "#000000", + "code_actions_indicator": "#808080", + "diff_background_deleted": "#f78c8c", + "diff_background_inserted": "#22c55e", + "document_highlight_read_background": "#e6e6e6", + "document_highlight_write_background": "#e6e6e6", + "error_color": "#f78c8c", + "gutter_background": "#cccccc", + "gutter_padding_factor": 2.5, + "highlighted_line_background": "#000000", + "line_number": "#000000", + "line_number_active": "#000000", + "rename_fade": 0.6, + "unnecessary_code_fade": 0.5, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "guest_selections": [ + { + "cursor": "#777af4", + "selection": "#777af4" + }, + { + "cursor": "#23d464", + "selection": "#23d464" + }, + { + "cursor": "#f98a3d", + "selection": "#f98a3d" + }, + { + "cursor": "#b671f8", + "selection": "#b671f8" + }, + { + "cursor": "#16ddc7", + "selection": "#16ddc7" + }, + { + "cursor": "#f58ac0", + "selection": "#f58ac0" + }, + { + "cursor": "#f6bc09", + "selection": "#f6bc09" + } + ], + "autocomplete": { + "background": "#bfbfbf", + "corner_radius": 6, + "padding": 6, + "border": { + "color": "#b3b3b3", + "width": 1 + }, + "item": { + "corner_radius": 6, + "padding": { + "bottom": 2, + "left": 6, + "right": 6, + "top": 2 + } + }, + "hovered_item": { + "corner_radius": 6, + "padding": { + "bottom": 2, + "left": 6, + "right": 6, + "top": 2 + }, + "background": "#bfbfbf" + }, + "margin": { + "left": -14 + }, + "match_highlight": { + "color": "#59c3f5", + "weight": "normal" + }, + "selected_item": { + "corner_radius": 6, + "padding": { + "bottom": 2, + "left": 6, + "right": 6, + "top": 2 + }, + "background": "#bfbfbf" + } + }, + "diagnostic_header": { + "background": "#e6e6e6", + "icon_width_factor": 1.5, + "text_scale_factor": 0.857, + "border": { + "color": "#b3b3b3", + "width": 1, + "bottom": true, + "top": true + }, + "code": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 14, + "margin": { + "left": 10 + } + }, + "message": { + "highlight_text": { + "family": "Zed Sans", + "color": "#262626", + "size": 14, + "weight": "bold" + }, + "text": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + } + } + }, + "diagnostic_path_header": { + "background": "#000000", + "text_scale_factor": 0.857, + "filename": { + "family": "Zed Mono", + "color": "#262626", + "size": 14 + }, + "path": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 14, + "margin": { + "left": 12 + } + } + }, + "error_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#f78c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#f78c8c", + "size": 14, + "weight": "bold" + } + } + }, + "warning_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#f8c570", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#f8c570", + "size": 14, + "weight": "bold" + } + } + }, + "information_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#6099f7", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#6099f7", + "size": 14, + "weight": "bold" + } + } + }, + "hint_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#6099f7", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#6099f7", + "size": 14, + "weight": "bold" + } + } + }, + "invalid_error_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "weight": "bold" + } + } + }, + "invalid_hint_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "weight": "bold" + } + } + }, + "invalid_information_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "weight": "bold" + } + } + }, + "invalid_warning_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "weight": "bold" + } + } + }, + "syntax": {} + }, + "project_diagnostics": { + "background": "#cccccc", + "tab_icon_spacing": 4, + "tab_icon_width": 13, + "tab_summary_spacing": 10, + "empty_message": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "status_bar_item": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 10 + } + } + }, + "project_panel": { + "padding": { + "top": 6 + }, + "entry": { + "height": 22, + "icon_color": "#999999", + "icon_size": 8, + "icon_spacing": 8, + "text": { + "family": "Zed Mono", + "color": "#595959", + "size": 16 + } + }, + "hovered_entry": { + "height": 22, + "background": "#cccccc", + "icon_color": "#999999", + "icon_size": 8, + "icon_spacing": 8, + "text": { + "family": "Zed Mono", + "color": "#595959", + "size": 16 + } + }, + "selected_entry": { + "height": 22, + "icon_color": "#999999", + "icon_size": 8, + "icon_spacing": 8, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + } + }, + "hovered_selected_entry": { + "height": 22, + "background": "#cccccc", + "icon_color": "#999999", + "icon_size": 8, + "icon_spacing": 8, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + } + } + }, + "chat_panel": { + "padding": { + "top": 12, + "left": 12, + "bottom": 12, + "right": 12 + }, + "channel_name": { + "family": "Zed Sans", + "color": "#262626", + "weight": "bold", + "size": 14 + }, + "channel_name_hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "padding": { + "right": 8 + } + }, + "channel_select": { + "header": { + "name": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "padding": { + "bottom": 4, + "left": 0 + }, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "corner_radius": 0 + }, + "item": { + "name": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + }, + "padding": 4, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "corner_radius": 0 + }, + "hovered_item": { + "name": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + }, + "padding": 4, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "background": "#cccccc", + "corner_radius": 6 + }, + "active_item": { + "name": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "padding": 4, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "corner_radius": 0 + }, + "hovered_active_item": { + "name": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "padding": 4, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "background": "#cccccc", + "corner_radius": 6 + }, + "menu": { + "background": "#e6e6e6", + "corner_radius": 6, + "padding": 4, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "shadow": { + "blur": 16, + "color": "#00000052", + "offset": [ + 0, + 2 + ] + } + } + }, + "sign_in_prompt": { + "family": "Zed Sans", + "color": "#595959", + "underline": true, + "size": 14 + }, + "hovered_sign_in_prompt": { + "family": "Zed Sans", + "color": "#262626", + "underline": true, + "size": 14 + }, + "message": { + "body": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + }, + "timestamp": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "padding": { + "bottom": 6 + }, + "sender": { + "family": "Zed Sans", + "color": "#262626", + "weight": "bold", + "size": 14, + "margin": { + "right": 8 + } + } + }, + "pending_message": { + "body": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "timestamp": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "padding": { + "bottom": 6 + }, + "sender": { + "family": "Zed Sans", + "color": "#8c8c8c", + "weight": "bold", + "size": 14, + "margin": { + "right": 8 + } + } + }, + "input_editor": { + "background": "#cccccc", + "corner_radius": 6, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "placeholder_text": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 16 + }, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "padding": { + "bottom": 7, + "left": 8, + "right": 8, + "top": 7 + } + } + }, + "contacts_panel": { + "padding": { + "top": 12, + "left": 12, + "bottom": 12, + "right": 12 + }, + "host_row_height": 28, + "tree_branch_color": "#bfbfbf", + "tree_branch_width": 1, + "host_avatar": { + "corner_radius": 10, + "width": 18 + }, + "host_username": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 16, + "padding": { + "left": 8 + } + }, + "project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + } + }, + "shared_project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#262626", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + } + }, + "hovered_shared_project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#262626", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + }, + "background": "#000000", + "corner_radius": 6 + }, + "unshared_project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + } + }, + "hovered_unshared_project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + }, + "background": "#000000", + "corner_radius": 6 + } + }, + "search": { + "match_background": "#000000", + "tab_icon_spacing": 4, + "tab_icon_width": 14, + "active_hovered_option_button": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "background": "#bfbfbf", + "corner_radius": 6, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "left": 1, + "right": 1 + }, + "padding": { + "bottom": 1, + "left": 6, + "right": 6, + "top": 1 + } + }, + "active_option_button": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "background": "#bfbfbf", + "corner_radius": 6, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "left": 1, + "right": 1 + }, + "padding": { + "bottom": 1, + "left": 6, + "right": 6, + "top": 1 + } + }, + "editor": { + "background": "#e6e6e6", + "corner_radius": 6, + "min_width": 200, + "max_width": 500, + "placeholder_text": { + "family": "Zed Mono", + "color": "#bfbfbf", + "size": 16 + }, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "right": 5 + }, + "padding": { + "top": 3, + "bottom": 3, + "left": 14, + "right": 14 + } + }, + "hovered_option_button": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "background": "#bfbfbf", + "corner_radius": 6, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "left": 1, + "right": 1 + }, + "padding": { + "bottom": 1, + "left": 6, + "right": 6, + "top": 1 + } + }, + "invalid_editor": { + "background": "#e6e6e6", + "corner_radius": 6, + "min_width": 200, + "max_width": 500, + "placeholder_text": { + "family": "Zed Mono", + "color": "#bfbfbf", + "size": 16 + }, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "border": { + "color": "#ffffff", + "width": 1 + }, + "margin": { + "right": 5 + }, + "padding": { + "top": 3, + "bottom": 3, + "left": 14, + "right": 14 + } + }, + "match_index": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 16, + "padding": 6 + }, + "option_button": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "background": "#cccccc", + "corner_radius": 6, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "left": 1, + "right": 1 + }, + "padding": { + "bottom": 1, + "left": 6, + "right": 6, + "top": 1 + } + }, + "option_button_group": { + "padding": { + "left": 2, + "right": 2 + } + }, + "results_status": { + "family": "Zed Mono", + "color": "#262626", + "size": 18 + } + }, + "breadcrumbs": { + "family": "Zed Sans", + "color": "#262626", + "size": 14, + "padding": { + "left": 6 + } + } +} \ No newline at end of file diff --git a/crates/zed/assets/themes/dark.toml b/crates/zed/assets/themes/dark.toml deleted file mode 100644 index fa673ac446..0000000000 --- a/crates/zed/assets/themes/dark.toml +++ /dev/null @@ -1,67 +0,0 @@ -extends = "_base" - -[surface] -0 = "#283340" -1 = "#1C2733" -2 = "#1C2733" - -[border] -0 = "#1B222B" -1 = "#FFFFFF20" - -[text] -0 = { extends = "$text.base", color = "#FFFFFF" } -1 = { extends = "$text.base", color = "#CDD1E2" } -2 = { extends = "$text.base", color = "#9BA8BE" } -3 = { extends = "$text.base", color = "#6E7483" } - -[shadow] -0 = "#00000052" - -[selection] -host = { selection = "#3B57BC55", cursor = "$text.0.color" } -guests = [ - { selection = "#FDF35133", cursor = "#FDF351" }, - { selection = "#4EACAD33", cursor = "#4EACAD" }, - { selection = "#D0453B33", cursor = "#D0453B" }, - { selection = "#3B874B33", cursor = "#3B874B" }, - { selection = "#BD7CB433", cursor = "#BD7CB4" }, - { selection = "#EE823133", cursor = "#EE8231" }, - { selection = "#5A2B9233", cursor = "#5A2B92" }, -] - -[status] -good = "#4fac63" -info = "#3c5dd4" -warn = "#faca50" -bad = "#b7372e" - -[state] -active_line = "#00000022" -highlighted_line = "#faca5033" -deleted_line = "#dd000036" -inserted_line = "#00dd0036" -hover = "#00000033" -selected = "#00000088" - -[editor.syntax] -keyword = { color = "#0086c0", weight = "bold" } -function = "#dcdcaa" -string = "#cb8f77" -type = "#4ec9b0" -number = "#b5cea8" -comment = "#6a9955" -property = "#4e94ce" -variant = "#4fc1ff" -constant = "#9cdcfe" -title = { color = "#9cdcfe", weight = "bold" } -emphasis = "#4ec9b0" -"emphasis.strong" = { color = "#4ec9b0", weight = "bold" } -link_uri = { color = "#6a9955", underline = true } -link_text = { color = "#cb8f77", italic = true } -list_marker = "#4e94ce" - -[workspace.disconnected_overlay] -extends = "$text.base" -color = "#ffffff" -background = "#000000aa" diff --git a/crates/zed/assets/themes/light.json b/crates/zed/assets/themes/light.json new file mode 100644 index 0000000000..65bf78b140 --- /dev/null +++ b/crates/zed/assets/themes/light.json @@ -0,0 +1,1245 @@ +{ + "selector": { + "background": "#e6e6e6", + "corner_radius": 6, + "padding": 8, + "item": { + "padding": { + "bottom": 4, + "left": 16, + "right": 16, + "top": 4 + }, + "corner_radius": 6, + "text": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#2db4f3", + "weight": "bold", + "size": 14 + } + }, + "active_item": { + "padding": { + "bottom": 4, + "left": 16, + "right": 16, + "top": 4 + }, + "corner_radius": 6, + "text": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#2db4f3", + "weight": "bold", + "size": 14 + }, + "background": "#e6e6e6" + }, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "empty": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "padding": { + "bottom": 4, + "left": 16, + "right": 16, + "top": 8 + } + }, + "input_editor": { + "background": "#cccccc", + "corner_radius": 6, + "placeholder_text": { + "family": "Zed Sans", + "color": "#bfbfbf", + "size": 14 + }, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "padding": { + "bottom": 7, + "left": 16, + "right": 16, + "top": 7 + } + }, + "margin": { + "bottom": 52, + "top": 52 + }, + "shadow": { + "blur": 16, + "color": "#00000052", + "offset": [ + 0, + 2 + ] + } + }, + "workspace": { + "background": "#e6e6e6", + "leader_border_opacity": 0.7, + "leader_border_width": 2, + "tab": { + "height": 34, + "icon_close": "#808080", + "icon_close_active": "#0d0d0d", + "icon_conflict": "#f8c570", + "icon_dirty": "#6099f7", + "icon_width": 8, + "spacing": 10, + "text": { + "family": "Zed Mono", + "color": "#595959", + "size": 16 + }, + "border": { + "color": "#d9d9d9", + "width": 1, + "left": true, + "bottom": true, + "overlay": true + }, + "padding": { + "left": 12, + "right": 12 + } + }, + "active_tab": { + "height": 34, + "icon_close": "#808080", + "icon_close_active": "#0d0d0d", + "icon_conflict": "#f8c570", + "icon_dirty": "#6099f7", + "icon_width": 8, + "spacing": 10, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "border": { + "color": "#d9d9d9", + "width": 1, + "left": true, + "bottom": false, + "overlay": true + }, + "padding": { + "left": 12, + "right": 12 + }, + "background": "#cccccc" + }, + "left_sidebar": { + "width": 30, + "border": { + "color": "#d9d9d9", + "width": 1, + "right": true + }, + "item": { + "height": 32, + "icon_color": "#808080", + "icon_size": 18 + }, + "active_item": { + "height": 32, + "icon_color": "#4d4d4d", + "icon_size": 18 + }, + "resize_handle": { + "background": "#d9d9d9", + "padding": { + "left": 1 + } + } + }, + "right_sidebar": { + "width": 30, + "border": { + "color": "#d9d9d9", + "width": 1, + "left": true + }, + "item": { + "height": 32, + "icon_color": "#808080", + "icon_size": 18 + }, + "active_item": { + "height": 32, + "icon_color": "#4d4d4d", + "icon_size": 18 + }, + "resize_handle": { + "background": "#d9d9d9", + "padding": { + "left": 1 + } + } + }, + "pane_divider": { + "color": "#d9d9d9", + "width": 1 + }, + "status_bar": { + "height": 24, + "item_spacing": 8, + "padding": { + "left": 6, + "right": 6 + }, + "cursor_position": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "diagnostic_message": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "lsp_message": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + } + }, + "titlebar": { + "avatar_width": 18, + "height": 32, + "share_icon_color": "#808080", + "share_icon_active_color": "#0d0d0d", + "title": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "avatar": { + "corner_radius": 10, + "border": { + "color": "#00000088", + "width": 1 + } + }, + "avatar_ribbon": { + "height": 3, + "width": 12 + }, + "border": { + "color": "#d9d9d9", + "width": 1, + "bottom": true + }, + "sign_in_prompt": { + "family": "Zed Sans", + "color": "#595959", + "size": 13, + "underline": true, + "padding": { + "right": 8 + } + }, + "hovered_sign_in_prompt": { + "family": "Zed Mono", + "color": "#000000", + "size": 16, + "underline": true, + "padding": { + "right": 8 + } + }, + "offline_icon": { + "color": "#999999", + "width": 16, + "padding": { + "right": 4 + } + }, + "outdated_warning": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 13 + } + }, + "toolbar": { + "height": 34, + "background": "#cccccc", + "border": { + "color": "#d9d9d9", + "width": 1, + "bottom": true + }, + "item_spacing": 8, + "padding": { + "left": 16, + "right": 8, + "top": 4, + "bottom": 4 + } + }, + "breadcrumbs": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "padding": { + "left": 6 + } + }, + "disconnected_overlay": { + "family": "Zed Sans", + "color": "#ffffff", + "size": 14, + "background": "#000000aa" + } + }, + "editor": { + "text_color": "#595959", + "background": "#cccccc", + "active_line_background": "#000000", + "code_actions_indicator": "#808080", + "diff_background_deleted": "#f78c8c", + "diff_background_inserted": "#22c55e", + "document_highlight_read_background": "#e6e6e6", + "document_highlight_write_background": "#e6e6e6", + "error_color": "#f78c8c", + "gutter_background": "#cccccc", + "gutter_padding_factor": 2.5, + "highlighted_line_background": "#000000", + "line_number": "#000000", + "line_number_active": "#000000", + "rename_fade": 0.6, + "unnecessary_code_fade": 0.5, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "guest_selections": [ + { + "cursor": "#777af4", + "selection": "#777af4" + }, + { + "cursor": "#23d464", + "selection": "#23d464" + }, + { + "cursor": "#f98a3d", + "selection": "#f98a3d" + }, + { + "cursor": "#b671f8", + "selection": "#b671f8" + }, + { + "cursor": "#16ddc7", + "selection": "#16ddc7" + }, + { + "cursor": "#f58ac0", + "selection": "#f58ac0" + }, + { + "cursor": "#f6bc09", + "selection": "#f6bc09" + } + ], + "autocomplete": { + "background": "#bfbfbf", + "corner_radius": 6, + "padding": 6, + "border": { + "color": "#b3b3b3", + "width": 1 + }, + "item": { + "corner_radius": 6, + "padding": { + "bottom": 2, + "left": 6, + "right": 6, + "top": 2 + } + }, + "hovered_item": { + "corner_radius": 6, + "padding": { + "bottom": 2, + "left": 6, + "right": 6, + "top": 2 + }, + "background": "#bfbfbf" + }, + "margin": { + "left": -14 + }, + "match_highlight": { + "color": "#59c3f5", + "weight": "normal" + }, + "selected_item": { + "corner_radius": 6, + "padding": { + "bottom": 2, + "left": 6, + "right": 6, + "top": 2 + }, + "background": "#bfbfbf" + } + }, + "diagnostic_header": { + "background": "#e6e6e6", + "icon_width_factor": 1.5, + "text_scale_factor": 0.857, + "border": { + "color": "#b3b3b3", + "width": 1, + "bottom": true, + "top": true + }, + "code": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 14, + "margin": { + "left": 10 + } + }, + "message": { + "highlight_text": { + "family": "Zed Sans", + "color": "#262626", + "size": 14, + "weight": "bold" + }, + "text": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + } + } + }, + "diagnostic_path_header": { + "background": "#000000", + "text_scale_factor": 0.857, + "filename": { + "family": "Zed Mono", + "color": "#262626", + "size": 14 + }, + "path": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 14, + "margin": { + "left": 12 + } + } + }, + "error_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#f78c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#f78c8c", + "size": 14, + "weight": "bold" + } + } + }, + "warning_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#f8c570", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#f8c570", + "size": 14, + "weight": "bold" + } + } + }, + "information_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#6099f7", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#6099f7", + "size": 14, + "weight": "bold" + } + } + }, + "hint_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#6099f7", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#6099f7", + "size": 14, + "weight": "bold" + } + } + }, + "invalid_error_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "weight": "bold" + } + } + }, + "invalid_hint_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "weight": "bold" + } + } + }, + "invalid_information_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "weight": "bold" + } + } + }, + "invalid_warning_diagnostic": { + "text_scale_factor": 0.857, + "header": { + "border": { + "color": "#d9d9d9", + "width": 1, + "top": true + } + }, + "message": { + "text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "highlight_text": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "weight": "bold" + } + } + }, + "syntax": {} + }, + "project_diagnostics": { + "background": "#cccccc", + "tab_icon_spacing": 4, + "tab_icon_width": 13, + "tab_summary_spacing": 10, + "empty_message": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "status_bar_item": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 10 + } + } + }, + "project_panel": { + "padding": { + "top": 6 + }, + "entry": { + "height": 22, + "icon_color": "#999999", + "icon_size": 8, + "icon_spacing": 8, + "text": { + "family": "Zed Mono", + "color": "#595959", + "size": 16 + } + }, + "hovered_entry": { + "height": 22, + "background": "#cccccc", + "icon_color": "#999999", + "icon_size": 8, + "icon_spacing": 8, + "text": { + "family": "Zed Mono", + "color": "#595959", + "size": 16 + } + }, + "selected_entry": { + "height": 22, + "icon_color": "#999999", + "icon_size": 8, + "icon_spacing": 8, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + } + }, + "hovered_selected_entry": { + "height": 22, + "background": "#cccccc", + "icon_color": "#999999", + "icon_size": 8, + "icon_spacing": 8, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + } + } + }, + "chat_panel": { + "padding": { + "top": 12, + "left": 12, + "bottom": 12, + "right": 12 + }, + "channel_name": { + "family": "Zed Sans", + "color": "#262626", + "weight": "bold", + "size": 14 + }, + "channel_name_hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "padding": { + "right": 8 + } + }, + "channel_select": { + "header": { + "name": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "padding": { + "bottom": 4, + "left": 0 + }, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "corner_radius": 0 + }, + "item": { + "name": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + }, + "padding": 4, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "corner_radius": 0 + }, + "hovered_item": { + "name": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + }, + "padding": 4, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "background": "#cccccc", + "corner_radius": 6 + }, + "active_item": { + "name": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "padding": 4, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "corner_radius": 0 + }, + "hovered_active_item": { + "name": { + "family": "Zed Sans", + "color": "#262626", + "size": 14 + }, + "padding": 4, + "hash": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14, + "margin": { + "right": 8 + } + }, + "background": "#cccccc", + "corner_radius": 6 + }, + "menu": { + "background": "#e6e6e6", + "corner_radius": 6, + "padding": 4, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "shadow": { + "blur": 16, + "color": "#00000052", + "offset": [ + 0, + 2 + ] + } + } + }, + "sign_in_prompt": { + "family": "Zed Sans", + "color": "#595959", + "underline": true, + "size": 14 + }, + "hovered_sign_in_prompt": { + "family": "Zed Sans", + "color": "#262626", + "underline": true, + "size": 14 + }, + "message": { + "body": { + "family": "Zed Sans", + "color": "#595959", + "size": 14 + }, + "timestamp": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "padding": { + "bottom": 6 + }, + "sender": { + "family": "Zed Sans", + "color": "#262626", + "weight": "bold", + "size": 14, + "margin": { + "right": 8 + } + } + }, + "pending_message": { + "body": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "timestamp": { + "family": "Zed Sans", + "color": "#8c8c8c", + "size": 14 + }, + "padding": { + "bottom": 6 + }, + "sender": { + "family": "Zed Sans", + "color": "#8c8c8c", + "weight": "bold", + "size": 14, + "margin": { + "right": 8 + } + } + }, + "input_editor": { + "background": "#cccccc", + "corner_radius": 6, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "placeholder_text": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 16 + }, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "padding": { + "bottom": 7, + "left": 8, + "right": 8, + "top": 7 + } + } + }, + "contacts_panel": { + "padding": { + "top": 12, + "left": 12, + "bottom": 12, + "right": 12 + }, + "host_row_height": 28, + "tree_branch_color": "#bfbfbf", + "tree_branch_width": 1, + "host_avatar": { + "corner_radius": 10, + "width": 18 + }, + "host_username": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 16, + "padding": { + "left": 8 + } + }, + "project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + } + }, + "shared_project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#262626", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + } + }, + "hovered_shared_project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#262626", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + }, + "background": "#000000", + "corner_radius": 6 + }, + "unshared_project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + } + }, + "hovered_unshared_project": { + "guest_avatar_spacing": 4, + "height": 24, + "guest_avatar": { + "corner_radius": 8, + "width": 14 + }, + "name": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "margin": { + "right": 6 + } + }, + "padding": { + "left": 8 + }, + "background": "#000000", + "corner_radius": 6 + } + }, + "search": { + "match_background": "#000000", + "tab_icon_spacing": 4, + "tab_icon_width": 14, + "active_hovered_option_button": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "background": "#bfbfbf", + "corner_radius": 6, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "left": 1, + "right": 1 + }, + "padding": { + "bottom": 1, + "left": 6, + "right": 6, + "top": 1 + } + }, + "active_option_button": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "background": "#bfbfbf", + "corner_radius": 6, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "left": 1, + "right": 1 + }, + "padding": { + "bottom": 1, + "left": 6, + "right": 6, + "top": 1 + } + }, + "editor": { + "background": "#e6e6e6", + "corner_radius": 6, + "min_width": 200, + "max_width": 500, + "placeholder_text": { + "family": "Zed Mono", + "color": "#bfbfbf", + "size": 16 + }, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "right": 5 + }, + "padding": { + "top": 3, + "bottom": 3, + "left": 14, + "right": 14 + } + }, + "hovered_option_button": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "background": "#bfbfbf", + "corner_radius": 6, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "left": 1, + "right": 1 + }, + "padding": { + "bottom": 1, + "left": 6, + "right": 6, + "top": 1 + } + }, + "invalid_editor": { + "background": "#e6e6e6", + "corner_radius": 6, + "min_width": 200, + "max_width": 500, + "placeholder_text": { + "family": "Zed Mono", + "color": "#bfbfbf", + "size": 16 + }, + "selection": { + "cursor": "#4287f6", + "selection": "#4287f6" + }, + "text": { + "family": "Zed Mono", + "color": "#262626", + "size": 16 + }, + "border": { + "color": "#ffffff", + "width": 1 + }, + "margin": { + "right": 5 + }, + "padding": { + "top": 3, + "bottom": 3, + "left": 14, + "right": 14 + } + }, + "match_index": { + "family": "Zed Mono", + "color": "#8c8c8c", + "size": 16, + "padding": 6 + }, + "option_button": { + "family": "Zed Mono", + "color": "#595959", + "size": 16, + "background": "#cccccc", + "corner_radius": 6, + "border": { + "color": "#d9d9d9", + "width": 1 + }, + "margin": { + "left": 1, + "right": 1 + }, + "padding": { + "bottom": 1, + "left": 6, + "right": 6, + "top": 1 + } + }, + "option_button_group": { + "padding": { + "left": 2, + "right": 2 + } + }, + "results_status": { + "family": "Zed Mono", + "color": "#262626", + "size": 18 + } + }, + "breadcrumbs": { + "family": "Zed Sans", + "color": "#262626", + "size": 14, + "padding": { + "left": 6 + } + } +} \ No newline at end of file diff --git a/crates/zed/assets/themes/light.toml b/crates/zed/assets/themes/light.toml deleted file mode 100644 index 2884515e09..0000000000 --- a/crates/zed/assets/themes/light.toml +++ /dev/null @@ -1,67 +0,0 @@ -extends = "_base" - -[surface] -0 = "#EAEAEB" -1 = "#FAFAFA" -2 = "#FFFFFF" - -[border] -0 = "#DDDDDC" -1 = "#0000000F" - -[text] -0 = { extends = "$text.base", color = "#000000" } -1 = { extends = "$text.base", color = "#29292B" } -2 = { extends = "$text.base", color = "#7E7E83" } -3 = { extends = "$text.base", color = "#939393" } - -[shadow] -0 = "#0000000D" - -[selection] -host = { selection = "#3B57BC55", cursor = "$text.0.color" } -guests = [ - { selection = "#D0453B33", cursor = "#D0453B" }, - { selection = "#3B874B33", cursor = "#3B874B" }, - { selection = "#BD7CB433", cursor = "#BD7CB4" }, - { selection = "#EE823133", cursor = "#EE8231" }, - { selection = "#5A2B9233", cursor = "#5A2B92" }, - { selection = "#FDF35133", cursor = "#FDF351" }, - { selection = "#4EACAD33", cursor = "#4EACAD" }, -] - -[status] -good = "#4fac63" -info = "#3c5dd4" -warn = "#faca50" -bad = "#b7372e" - -[state] -active_line = "#00000008" -highlighted_line = "#faca5033" -deleted_line = "#dd000036" -inserted_line = "#00dd0036" -hover = "#0000000D" -selected = "#0000001c" - -[editor.syntax] -keyword = { color = "#0000fa", weight = "bold" } -function = "#795e26" -string = "#a82121" -type = "#267f29" -number = "#b5cea8" -comment = "#6a9955" -property = "#4e94ce" -variant = "#4fc1ff" -constant = "#5a9ccc" -title = { color = "#5a9ccc", weight = "bold" } -emphasis = "#267f29" -"emphasis.strong" = { color = "#267f29", weight = "bold" } -link_uri = { color = "#6a9955", underline = true } -link_text = { color = "#a82121", italic = true } -list_marker = "#4e94ce" - -[workspace.disconnected_overlay] -extends = "$text.base" -color = "#ffffff" -background = "#000000cc" diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index aec0bc533e..dd4268fd76 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -988,7 +988,8 @@ mod tests { 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-extended.ttf").unwrap().to_vec().into() + Assets.load("fonts/zed-sans/zed-sans-extended.ttf").unwrap().to_vec().into(), + Assets.load("fonts/zed-mono/zed-mono-extended.ttf").unwrap().to_vec().into(), ]; } diff --git a/styles/buildThemes.ts b/styles/buildThemes.ts index ced82e9866..d67860cee6 100644 --- a/styles/buildThemes.ts +++ b/styles/buildThemes.ts @@ -7,11 +7,11 @@ import decamelizeTree from "./utils/decamelizeTree"; const themes = [dark, light]; for (let theme of themes) { - let styleTree = decamelizeTree(app(theme)); - let styleTreeJSON = JSON.stringify(styleTree, null, 2); - let outPath = path.resolve( - `${__dirname}/../crates/zed/assets/themes/${theme.name}.json` - ); - fs.writeFileSync(outPath, styleTreeJSON); - console.log(`Generated ${outPath}`); + let styleTree = decamelizeTree(app(theme)); + let styleTreeJSON = JSON.stringify(styleTree, null, 2); + let outPath = path.resolve( + `${__dirname}/../crates/zed/assets/themes/${theme.name}.json` + ); + fs.writeFileSync(outPath, styleTreeJSON); + console.log(`Generated ${outPath}`); } diff --git a/styles/styleTree/app.ts b/styles/styleTree/app.ts index c7edfdc270..d26ada4fc9 100644 --- a/styles/styleTree/app.ts +++ b/styles/styleTree/app.ts @@ -1,6 +1,7 @@ import Theme from "../themes/theme"; import chatPanel from "./chatPanel"; import { backgroundColor, borderColor, text } from "./components"; +import contactsPanel from "./contactsPanel"; import editor from "./editor"; import projectPanel from "./projectPanel"; import search from "./search"; @@ -8,83 +9,38 @@ import selectorModal from "./selectorModal"; import workspace from "./workspace"; export const panel = { - padding: { top: 12, left: 12, bottom: 12, right: 12 }, + padding: { top: 12, left: 12, bottom: 12, right: 12 }, }; export default function app(theme: Theme): Object { - return { - selector: selectorModal(theme), - workspace: workspace(theme), - editor: editor(theme), - projectDiagnostics: { - background: backgroundColor(theme, 300), - tabIconSpacing: 4, - tabIconWidth: 13, - tabSummarySpacing: 10, - emptyMessage: { - ...text(theme, "sans", "primary", { size: "lg" }), - }, - statusBarItem: { - ...text(theme, "sans", "muted"), - margin: { - right: 10, + return { + selector: selectorModal(theme), + workspace: workspace(theme), + editor: editor(theme), + projectDiagnostics: { + background: backgroundColor(theme, 300), + tabIconSpacing: 4, + tabIconWidth: 13, + tabSummarySpacing: 10, + emptyMessage: { + ...text(theme, "sans", "primary", { size: "lg" }), + }, + statusBarItem: { + ...text(theme, "sans", "muted"), + margin: { + right: 10, + }, + }, }, - }, - }, - projectPanel: projectPanel(theme), - chatPanel: chatPanel(theme), - contactsPanel: { - ...panel, - hostRowHeight: 28, - treeBranchColor: borderColor(theme, "muted"), - treeBranchWidth: 1, - hostAvatar: { - cornerRadius: 10, - width: 18, - }, - hostUsername: { - ...text(theme, "mono", "muted"), - padding: { - left: 8, - }, - }, - hoveredSharedProject: { - extends: "$contacts_panel.sharedProject", - background: theme.editor.line.active.value, - cornerRadius: 6, - }, - hoveredUnsharedProject: { - extends: "$contacts_panel.unsharedProject", - background: theme.editor.line.active.value, - cornerRadius: 6, - }, - project: { - guestAvatarSpacing: 4, - height: 24, - guestAvatar: { - cornerRadius: 8, - width: 14, - }, - name: { - extends: text(theme, "mono", "secondary"), - margin: { - right: 6, - }, - }, - padding: { - left: 8, - }, - }, - sharedProject: { - extends: "$contactsPanel.project", - name: { - color: text(theme, "mono", "primary"), - }, - }, - unsharedProject: { - extends: "$contactsPanel.project", - }, - }, - search: search(theme), - }; + projectPanel: projectPanel(theme), + chatPanel: chatPanel(theme), + contactsPanel: contactsPanel(theme), + search: search(theme), + breadcrumbs: { + ...text(theme, "sans", "primary"), + padding: { + left: 6, + }, + } + }; } diff --git a/styles/styleTree/components.ts b/styles/styleTree/components.ts index 55a64cb1ec..205fd9b262 100644 --- a/styles/styleTree/components.ts +++ b/styles/styleTree/components.ts @@ -1,25 +1,25 @@ import chroma from "chroma-js"; -import Theme, { BackgroundColor, Weight } from "../themes/theme"; -import core from "../tokens/core"; +import Theme, { BackgroundColor } from "../themes/theme"; +import { fontFamilies, fontSizes, FontWeight } from "../tokens"; import { Color } from "../utils/color"; export type TextColor = keyof Theme["textColor"]; export function text( theme: Theme, - fontFamily: keyof typeof core.fontFamily, + fontFamily: keyof typeof fontFamilies, color: TextColor, properties?: { - size?: keyof typeof core["fontSize"]; - weight?: Weight; + size?: keyof typeof fontSizes; + weight?: FontWeight; underline?: boolean; } ) { const sizeKey = properties?.size || fontFamily === "sans" ? "sm" : "md"; - const size = core.fontSize[sizeKey].value; + const size = fontSizes[sizeKey].value; return { - family: core.fontFamily[fontFamily], + family: fontFamilies[fontFamily].value, color: theme.textColor[color].value, ...properties, size, diff --git a/styles/styleTree/contactsPanel.ts b/styles/styleTree/contactsPanel.ts new file mode 100644 index 0000000000..9b88a35f13 --- /dev/null +++ b/styles/styleTree/contactsPanel.ts @@ -0,0 +1,61 @@ +import Theme from "../themes/theme"; +import { panel } from "./app"; +import { borderColor, text } from "./components"; + +export default function(theme: Theme) { + const project = { + guestAvatarSpacing: 4, + height: 24, + guestAvatar: { + cornerRadius: 8, + width: 14, + }, + name: { + ...text(theme, "mono", "secondary"), + margin: { + right: 6, + }, + }, + padding: { + left: 8, + }, + }; + + const sharedProject = { + ...project, + name: { + ...project.name, + ...text(theme, "mono", "primary"), + }, + }; + + return { + ...panel, + hostRowHeight: 28, + treeBranchColor: borderColor(theme, "muted"), + treeBranchWidth: 1, + hostAvatar: { + cornerRadius: 10, + width: 18, + }, + hostUsername: { + ...text(theme, "mono", "muted"), + padding: { + left: 8, + }, + }, + project, + sharedProject, + hoveredSharedProject: { + ...sharedProject, + background: theme.editor.line.active.value, + cornerRadius: 6, + }, + unsharedProject: project, + hoveredUnsharedProject: { + ...project, + background: theme.editor.line.active.value, + cornerRadius: 6, + }, + } +} \ No newline at end of file diff --git a/styles/styleTree/editor.ts b/styles/styleTree/editor.ts index 5d800881e2..ebc53b4058 100644 --- a/styles/styleTree/editor.ts +++ b/styles/styleTree/editor.ts @@ -1,131 +1,134 @@ import Theme from "../themes/theme"; import { - backgroundColor, - border, - iconColor, - player, - text, - TextColor + backgroundColor, + border, + iconColor, + player, + text, + TextColor, } from "./components"; export default function editor(theme: Theme) { - const autocompleteItem = { - cornerRadius: 6, - padding: { - bottom: 2, - left: 6, - right: 6, - top: 2, - }, - }; - - function diagnostic(theme: Theme, color: TextColor) { - return { - textScaleFactor: 0.857, - header: { - border: border(theme, "primary", { - top: true, - }), - }, - message: { - text: text(theme, "sans", color, { size: "sm" }), - highlightText: text(theme, "sans", color, { - size: "sm", - weight: "bold", - }), - }, + const autocompleteItem = { + cornerRadius: 6, + padding: { + bottom: 2, + left: 6, + right: 6, + top: 2, + }, }; - } - return { - textColor: theme.textColor.secondary.value, - background: backgroundColor(theme, 300), - activeLineBackground: theme.editor.line.active.value, - codeActionsIndicator: iconColor(theme, "secondary"), - diffBackgroundDeleted: backgroundColor(theme, "error"), - diffBackgroundInserted: backgroundColor(theme, "ok"), - documentHighlightReadBackground: theme.editor.highlight.occurrence.value, - documentHighlightWriteBackground: theme.editor.highlight.occurrence.value, - errorColor: theme.textColor.error, - gutterBackground: backgroundColor(theme, 300), - gutterPaddingFactor: 2.5, - highlightedLineBackground: theme.editor.line.highlighted.value, - lineNumber: theme.editor.gutter.primary.value, - lineNumberActive: theme.editor.gutter.active, - renameFade: 0.6, - unnecessaryCodeFade: 0.5, - selection: player(theme, 1).selection, - guestSelections: [ - player(theme, 2).selection, - player(theme, 3).selection, - player(theme, 4).selection, - player(theme, 5).selection, - player(theme, 6).selection, - player(theme, 7).selection, - player(theme, 8).selection, - ], - autocomplete: { - background: backgroundColor(theme, 100), - cornerRadius: 6, - padding: 6, - border: border(theme, "secondary"), - item: autocompleteItem, - hoveredItem: { - ...autocompleteItem, - background: backgroundColor(theme, 100, "hovered"), - }, - margin: { - left: -14, - }, - matchHighlight: { - color: theme.syntax.keyword.color.value, - weight: theme.syntax.keyword.weight.value, - }, - selectedItem: { - ...autocompleteItem, - background: backgroundColor(theme, 100, "active"), - }, - }, - diagnosticHeader: { - background: theme.editor.background.value, - iconWidthFactor: 1.5, - textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these. - border: border(theme, "secondary", { - bottom: true, - top: true, - }), - code: { - ...text(theme, "mono", "muted", { size: "sm" }), - margin: { - left: 10, + function diagnostic(theme: Theme, color: TextColor) { + return { + textScaleFactor: 0.857, + header: { + border: border(theme, "primary", { + top: true, + }), + }, + message: { + text: text(theme, "sans", color, { size: "sm" }), + highlightText: text(theme, "sans", color, { + size: "sm", + weight: "bold", + }), + }, + }; + } + + return { + textColor: theme.textColor.secondary.value, + background: backgroundColor(theme, 300), + activeLineBackground: theme.editor.line.active.value, + codeActionsIndicator: iconColor(theme, "secondary"), + diffBackgroundDeleted: backgroundColor(theme, "error"), + diffBackgroundInserted: backgroundColor(theme, "ok"), + documentHighlightReadBackground: theme.editor.highlight.occurrence.value, + documentHighlightWriteBackground: theme.editor.highlight.occurrence.value, + errorColor: theme.textColor.error.value, + gutterBackground: backgroundColor(theme, 300), + gutterPaddingFactor: 2.5, + highlightedLineBackground: theme.editor.line.highlighted.value, + lineNumber: theme.editor.gutter.primary.value, + lineNumberActive: theme.editor.gutter.active.value, + renameFade: 0.6, + unnecessaryCodeFade: 0.5, + selection: player(theme, 1).selection, + guestSelections: [ + player(theme, 2).selection, + player(theme, 3).selection, + player(theme, 4).selection, + player(theme, 5).selection, + player(theme, 6).selection, + player(theme, 7).selection, + player(theme, 8).selection, + ], + autocomplete: { + background: backgroundColor(theme, 100), + cornerRadius: 6, + padding: 6, + border: border(theme, "secondary"), + item: autocompleteItem, + hoveredItem: { + ...autocompleteItem, + background: backgroundColor(theme, 100, "hovered"), + }, + margin: { + left: -14, + }, + matchHighlight: { + color: theme.syntax.keyword.color.value, + weight: theme.syntax.keyword.weight.value, + }, + selectedItem: { + ...autocompleteItem, + background: backgroundColor(theme, 100, "active"), + }, }, - }, - message: { - highlightText: text(theme, "sans", "primary", { - size: "sm", - weight: "bold", - }), - text: text(theme, "sans", "secondary", { size: "sm" }), - }, - }, - diagnosticPathHeader: { - background: theme.editor.line.active, - textScaleFactor: 0.857, - filename: text(theme, "mono", "primary", { size: "sm" }), - path: { - ...text(theme, "mono", "muted", { size: "sm" }), - margin: { - left: 12, + diagnosticHeader: { + background: theme.editor.background.value, + iconWidthFactor: 1.5, + textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these. + border: border(theme, "secondary", { + bottom: true, + top: true, + }), + code: { + ...text(theme, "mono", "muted", { size: "sm" }), + margin: { + left: 10, + }, + }, + message: { + highlightText: text(theme, "sans", "primary", { + size: "sm", + weight: "bold", + }), + text: text(theme, "sans", "secondary", { size: "sm" }), + }, }, - }, - }, - errorDiagnostic: diagnostic(theme, "error"), - warningDiagnostic: diagnostic(theme, "warning"), - informationDiagnostic: diagnostic(theme, "info"), - hintDiagnostic: diagnostic(theme, "info"), - invalidErrorDiagnostic: diagnostic(theme, "muted"), - invalidHintDiagnostic: diagnostic(theme, "muted"), - invalidInformationDiagnostic: diagnostic(theme, "muted"), - invalidWarningDiagnostic: diagnostic(theme, "muted"), - }; + diagnosticPathHeader: { + background: theme.editor.line.active.value, + textScaleFactor: 0.857, + filename: text(theme, "mono", "primary", { size: "sm" }), + path: { + ...text(theme, "mono", "muted", { size: "sm" }), + margin: { + left: 12, + }, + }, + }, + errorDiagnostic: diagnostic(theme, "error"), + warningDiagnostic: diagnostic(theme, "warning"), + informationDiagnostic: diagnostic(theme, "info"), + hintDiagnostic: diagnostic(theme, "info"), + invalidErrorDiagnostic: diagnostic(theme, "muted"), + invalidHintDiagnostic: diagnostic(theme, "muted"), + invalidInformationDiagnostic: diagnostic(theme, "muted"), + invalidWarningDiagnostic: diagnostic(theme, "muted"), + syntax: { + + } + }; } diff --git a/styles/styleTree/projectPanel.ts b/styles/styleTree/projectPanel.ts index 3b5fba8853..cd6fb49b3a 100644 --- a/styles/styleTree/projectPanel.ts +++ b/styles/styleTree/projectPanel.ts @@ -24,7 +24,11 @@ export default function projectPanel(theme: Theme) { backgroundColor(theme, 300, "hovered") ), selectedEntry: entry(theme, "primary"), - hoveredSelectedEntry: entry(theme, "primary", "hovered"), + hoveredSelectedEntry: entry( + theme, + "primary", + backgroundColor(theme, 300, "hovered") + ), padding: { top: 6, }, diff --git a/styles/styleTree/search.ts b/styles/styleTree/search.ts index 7ba04cd688..42b639f57a 100644 --- a/styles/styleTree/search.ts +++ b/styles/styleTree/search.ts @@ -19,8 +19,28 @@ export default function search(theme: Theme) { }, }; + const editor = { + background: backgroundColor(theme, 500), + cornerRadius: 6, + minWidth: 200, + maxWidth: 500, + placeholderText: text(theme, "mono", "placeholder"), + selection: player(theme, 1).selection, + text: text(theme, "mono", "primary"), + border: border(theme, "primary"), + margin: { + right: 5, + }, + padding: { + top: 3, + bottom: 3, + left: 14, + right: 14, + }, + }; + return { - matchBackground: theme.editor.highlight.match, + matchBackground: theme.editor.highlight.match.value, tabIconSpacing: 4, tabIconWidth: 14, activeHoveredOptionButton: { @@ -31,31 +51,13 @@ export default function search(theme: Theme) { ...optionButton, background: backgroundColor(theme, 100), }, - editor: { - background: backgroundColor(theme, 500), - cornerRadius: 6, - minWidth: 200, - maxWidth: 500, - placeholderText: text(theme, "mono", "placeholder"), - selection: player(theme, 1).selection, - text: text(theme, "mono", "primary"), - border: border(theme, "primary"), - margin: { - right: 5, - }, - padding: { - top: 3, - bottom: 3, - left: 14, - right: 14, - }, - }, + editor, hoveredOptionButton: { ...optionButton, background: backgroundColor(theme, 100), }, invalidEditor: { - extends: "$search.editor", + ...editor, border: border(theme, "error"), }, matchIndex: { diff --git a/styles/styleTree/workspace.ts b/styles/styleTree/workspace.ts index 148db08918..7e71eaad2a 100644 --- a/styles/styleTree/workspace.ts +++ b/styles/styleTree/workspace.ts @@ -137,5 +137,10 @@ export default function workspace(theme: Theme) { ...text(theme, "mono", "secondary"), padding: { left: 6 }, }, + disconnectedOverlay: { + ...text(theme, "sans", "primary"), + color: "#ffffff", + background: "#000000aa", + }, }; } diff --git a/styles/themes/dark.ts b/styles/themes/dark.ts index 42f80cf4c6..2cadf24601 100644 --- a/styles/themes/dark.ts +++ b/styles/themes/dark.ts @@ -1,249 +1,273 @@ -import core from "../tokens/core"; -import Theme, { NumberToken, Syntax } from "./theme"; - -const { color } = core; +import { colors, fontWeights, NumberToken } from "../tokens"; +import Theme, { Syntax } from "./theme"; const backgroundColor = { - 100: { - base: color.neutral[750], - hovered: color.neutral[750], - active: color.neutral[750], - focused: color.neutral[750], - }, - 300: { - base: color.neutral[800], - hovered: color.neutral[800], - active: color.neutral[800], - focused: color.neutral[800], - }, - 500: { - base: color.neutral[900], - hovered: color.neutral[900], - active: color.neutral[900], - focused: color.neutral[900], - }, - ok: { - base: color.green[600], - hovered: color.green[600], - active: color.green[600], - focused: color.green[600], - }, - error: { - base: color.red[400], - hovered: color.red[400], - active: color.red[400], - focused: color.red[400], - }, - warning: { - base: color.amber[300], - hovered: color.amber[300], - active: color.amber[300], - focused: color.amber[300], - }, - info: { - base: color.blue[500], - hovered: color.blue[500], - active: color.blue[500], - focused: color.blue[500], - }, + 100: { + base: colors.neutral[750], + hovered: colors.neutral[750], + active: colors.neutral[750], + focused: colors.neutral[750], + }, + 300: { + base: colors.neutral[800], + hovered: colors.neutral[800], + active: colors.neutral[800], + focused: colors.neutral[800], + }, + 500: { + base: colors.neutral[900], + hovered: colors.neutral[900], + active: colors.neutral[900], + focused: colors.neutral[900], + }, + ok: { + base: colors.green[600], + hovered: colors.green[600], + active: colors.green[600], + focused: colors.green[600], + }, + error: { + base: colors.red[400], + hovered: colors.red[400], + active: colors.red[400], + focused: colors.red[400], + }, + warning: { + base: colors.amber[300], + hovered: colors.amber[300], + active: colors.amber[300], + focused: colors.amber[300], + }, + info: { + base: colors.blue[500], + hovered: colors.blue[500], + active: colors.blue[500], + focused: colors.blue[500], + }, }; const borderColor = { - primary: color.neutral[850], - secondary: color.neutral[700], - muted: color.neutral[750], - focused: color.neutral[100], - active: color.neutral[500], - ok: color.neutral[1000], - error: color.neutral[1000], - warning: color.neutral[1000], - info: color.neutral[1000], + primary: colors.neutral[850], + secondary: colors.neutral[700], + muted: colors.neutral[750], + focused: colors.neutral[100], + active: colors.neutral[500], + ok: colors.neutral[1000], + error: colors.neutral[1000], + warning: colors.neutral[1000], + info: colors.neutral[1000], }; const textColor = { - primary: color.neutral[150], - secondary: color.neutral[350], - muted: color.neutral[550], - placeholder: color.neutral[750], - active: color.neutral[0], - //TODO: (design) define feature and it's correct value - feature: color.sky[500], - ok: color.green[600], - error: color.red[400], - warning: color.amber[300], - info: color.blue[500], + primary: colors.neutral[150], + secondary: colors.neutral[350], + muted: colors.neutral[550], + placeholder: colors.neutral[750], + active: colors.neutral[0], + //TODO: (design) define feature and it's correct value + feature: colors.sky[500], + ok: colors.green[600], + error: colors.red[400], + warning: colors.amber[300], + info: colors.blue[500], }; const iconColor = { - primary: color.neutral[300], - secondary: color.neutral[500], - muted: color.neutral[600], - placeholder: color.neutral[700], - active: color.neutral[50], - //TODO: (design) define feature and it's correct value - feature: color.sky[500], - ok: color.green[600], - error: color.red[400], - warning: color.amber[300], - info: color.blue[500], + primary: colors.neutral[300], + secondary: colors.neutral[500], + muted: colors.neutral[600], + placeholder: colors.neutral[700], + active: colors.neutral[50], + //TODO: (design) define feature and it's correct value + feature: colors.sky[500], + ok: colors.green[600], + error: colors.red[400], + warning: colors.amber[300], + info: colors.blue[500], }; const player = { - 1: { - baseColor: color.blue[600], - cursorColor: color.blue[600], - selectionColor: color.blue[600], - borderColor: color.blue[600], - }, - 2: { - baseColor: color.indigo[500], - cursorColor: color.indigo[500], - selectionColor: color.indigo[500], - borderColor: color.indigo[500], - }, - 3: { - baseColor: color.green[500], - cursorColor: color.green[500], - selectionColor: color.green[500], - borderColor: color.green[500], - }, - 4: { - baseColor: color.orange[500], - cursorColor: color.orange[500], - selectionColor: color.orange[500], - borderColor: color.orange[500], - }, - 5: { - baseColor: color.purple[500], - cursorColor: color.purple[500], - selectionColor: color.purple[500], - borderColor: color.purple[500], - }, - 6: { - baseColor: color.teal[400], - cursorColor: color.teal[400], - selectionColor: color.teal[400], - borderColor: color.teal[400], - }, - 7: { - baseColor: color.pink[400], - cursorColor: color.pink[400], - selectionColor: color.pink[400], - borderColor: color.pink[400], - }, - 8: { - baseColor: color.yellow[400], - cursorColor: color.yellow[400], - selectionColor: color.yellow[400], - borderColor: color.yellow[400], - }, + 1: { + baseColor: colors.blue[600], + cursorColor: colors.blue[600], + selectionColor: colors.blue[600], + borderColor: colors.blue[600], + }, + 2: { + baseColor: colors.indigo[500], + cursorColor: colors.indigo[500], + selectionColor: colors.indigo[500], + borderColor: colors.indigo[500], + }, + 3: { + baseColor: colors.green[500], + cursorColor: colors.green[500], + selectionColor: colors.green[500], + borderColor: colors.green[500], + }, + 4: { + baseColor: colors.orange[500], + cursorColor: colors.orange[500], + selectionColor: colors.orange[500], + borderColor: colors.orange[500], + }, + 5: { + baseColor: colors.purple[500], + cursorColor: colors.purple[500], + selectionColor: colors.purple[500], + borderColor: colors.purple[500], + }, + 6: { + baseColor: colors.teal[400], + cursorColor: colors.teal[400], + selectionColor: colors.teal[400], + borderColor: colors.teal[400], + }, + 7: { + baseColor: colors.pink[400], + cursorColor: colors.pink[400], + selectionColor: colors.pink[400], + borderColor: colors.pink[400], + }, + 8: { + baseColor: colors.yellow[400], + cursorColor: colors.yellow[400], + selectionColor: colors.yellow[400], + borderColor: colors.yellow[400], + }, }; // TODO: Fixup const editor = { - background: backgroundColor[500].base, - indent_guide: borderColor.muted, - indent_guide_active: borderColor.secondary, - line: { - active: color.neutral[0], - highlighted: color.neutral[0], - inserted: backgroundColor.ok.active, - deleted: backgroundColor.error.active, - modified: backgroundColor.info.active, - }, - highlight: { - selection: player[1].selectionColor, - occurrence: backgroundColor[500].active, - activeOccurrence: color.neutral[0], - matchingBracket: color.neutral[0], - match: color.neutral[0], - activeMatch: color.neutral[0], - related: color.neutral[0], - }, - gutter: { - primary: color.neutral[0], - active: color.neutral[0], - }, + background: backgroundColor[500].base, + indent_guide: borderColor.muted, + indent_guide_active: borderColor.secondary, + line: { + active: colors.neutral[0], + highlighted: colors.neutral[0], + inserted: backgroundColor.ok.active, + deleted: backgroundColor.error.active, + modified: backgroundColor.info.active, + }, + highlight: { + selection: player[1].selectionColor, + occurrence: backgroundColor[500].active, + activeOccurrence: colors.neutral[0], + matchingBracket: colors.neutral[0], + match: colors.neutral[0], + activeMatch: colors.neutral[0], + related: colors.neutral[0], + }, + gutter: { + primary: colors.neutral[0], + active: colors.neutral[0], + }, }; const syntax: Syntax = { - primary: { - color: textColor.primary, - weight: { value: "normal", type: "fontWeight" }, - }, - comment: { - color: color.lime[200], - weight: { value: "normal", type: "fontWeight" }, - }, - punctuation: { - color: textColor.primary, - weight: { value: "normal", type: "fontWeight" }, - }, - constant: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - keyword: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - function: { - color: color.yellow[200], - weight: { value: "normal", type: "fontWeight" }, - }, - type: { - color: color.teal[300], - weight: { value: "normal", type: "fontWeight" }, - }, - variant: { - color: color.teal[300], - weight: { value: "normal", type: "fontWeight" }, - }, - property: { - color: color.sky[300], - weight: { value: "normal", type: "fontWeight" }, - }, - enum: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - operator: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, - }, - string: { - color: color.orange[300], - weight: { value: "normal", type: "fontWeight" }, - }, - number: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - boolean: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, - }, - predictive: { - color: textColor.muted, - weight: { value: "normal", type: "fontWeight" }, - }, + primary: { + color: textColor.primary, + weight: fontWeights.normal, + }, + comment: { + color: colors.lime[200], + weight: fontWeights.normal, + }, + punctuation: { + color: textColor.primary, + weight: fontWeights.normal, + }, + constant: { + color: colors.neutral[150], + weight: fontWeights.normal, + }, + keyword: { + color: colors.sky[400], + weight: fontWeights.normal, + }, + function: { + color: colors.yellow[200], + weight: fontWeights.normal, + }, + type: { + color: colors.teal[300], + weight: fontWeights.normal, + }, + variant: { + color: colors.teal[300], + weight: fontWeights.normal, + }, + property: { + color: colors.sky[300], + weight: fontWeights.normal, + }, + enum: { + color: colors.sky[400], + weight: fontWeights.normal, + }, + operator: { + color: colors.sky[400], + weight: fontWeights.normal, + }, + string: { + color: colors.orange[300], + weight: fontWeights.normal, + }, + number: { + color: colors.neutral[150], + weight: fontWeights.normal, + }, + boolean: { + color: colors.neutral[150], + weight: fontWeights.normal, + }, + predictive: { + color: textColor.muted, + weight: fontWeights.normal, + }, + title: { + color: colors.sky[500], + weight: fontWeights.bold, + }, + emphasis: { + color: textColor.active, + weight: fontWeights.normal, + }, + emphasisStrong: { + color: textColor.active, + weight: fontWeights.bold, + }, + linkUrl: { + color: colors.lime[500], + weight: fontWeights.normal, + // TODO: add underline + }, + linkText: { + color: colors.orange[500], + weight: fontWeights.normal, + // TODO: add italic + }, + listMarker: { + color: colors.sky[400], + weight: fontWeights.normal, + } }; const shadowAlpha: NumberToken = { - value: 0.32, - type: "number", + value: 0.32, + type: "number", }; const theme: Theme = { - name: "dark", - backgroundColor, - borderColor, - textColor, - iconColor, - editor, - syntax, - player, - shadowAlpha, + name: "dark", + backgroundColor, + borderColor, + textColor, + iconColor, + editor, + syntax, + player, + shadowAlpha, }; export default theme; diff --git a/styles/themes/light.ts b/styles/themes/light.ts index 7a9bf1b552..acb704de74 100644 --- a/styles/themes/light.ts +++ b/styles/themes/light.ts @@ -1,143 +1,141 @@ -import core from "../tokens/core"; -import Theme, { NumberToken, Syntax } from "./theme"; - -const { color } = core; +import { colors, fontWeights, NumberToken } from "../tokens"; +import Theme, { Syntax } from "./theme"; // TODO: Replace with light values const backgroundColor = { 100: { - base: color.neutral[750], - hovered: color.neutral[750], - active: color.neutral[750], - focused: color.neutral[750], + base: colors.neutral[750], + hovered: colors.neutral[750], + active: colors.neutral[750], + focused: colors.neutral[750], }, 300: { - base: color.neutral[800], - hovered: color.neutral[800], - active: color.neutral[800], - focused: color.neutral[800], + base: colors.neutral[800], + hovered: colors.neutral[800], + active: colors.neutral[800], + focused: colors.neutral[800], }, 500: { - base: color.neutral[900], - hovered: color.neutral[900], - active: color.neutral[900], - focused: color.neutral[900], + base: colors.neutral[900], + hovered: colors.neutral[900], + active: colors.neutral[900], + focused: colors.neutral[900], }, ok: { - base: color.green[600], - hovered: color.green[600], - active: color.green[600], - focused: color.green[600], + base: colors.green[600], + hovered: colors.green[600], + active: colors.green[600], + focused: colors.green[600], }, error: { - base: color.red[400], - hovered: color.red[400], - active: color.red[400], - focused: color.red[400], + base: colors.red[400], + hovered: colors.red[400], + active: colors.red[400], + focused: colors.red[400], }, warning: { - base: color.amber[300], - hovered: color.amber[300], - active: color.amber[300], - focused: color.amber[300], + base: colors.amber[300], + hovered: colors.amber[300], + active: colors.amber[300], + focused: colors.amber[300], }, info: { - base: color.blue[500], - hovered: color.blue[500], - active: color.blue[500], - focused: color.blue[500], + base: colors.blue[500], + hovered: colors.blue[500], + active: colors.blue[500], + focused: colors.blue[500], }, }; const borderColor = { - primary: color.neutral[850], - secondary: color.neutral[700], - muted: color.neutral[750], - focused: color.neutral[100], - active: color.neutral[500], - ok: color.neutral[1000], - error: color.neutral[1000], - warning: color.neutral[1000], - info: color.neutral[1000], + primary: colors.neutral[850], + secondary: colors.neutral[700], + muted: colors.neutral[750], + focused: colors.neutral[100], + active: colors.neutral[500], + ok: colors.neutral[1000], + error: colors.neutral[1000], + warning: colors.neutral[1000], + info: colors.neutral[1000], }; const textColor = { - primary: color.neutral[150], - secondary: color.neutral[350], - muted: color.neutral[550], - placeholder: color.neutral[750], - active: color.neutral[0], + primary: colors.neutral[150], + secondary: colors.neutral[350], + muted: colors.neutral[550], + placeholder: colors.neutral[750], + active: colors.neutral[0], //TODO: (design) define feature and it's correct value - feature: color.sky[500], - ok: color.green[600], - error: color.red[400], - warning: color.amber[300], - info: color.blue[500], + feature: colors.sky[500], + ok: colors.green[600], + error: colors.red[400], + warning: colors.amber[300], + info: colors.blue[500], }; const iconColor = { - primary: color.neutral[300], - secondary: color.neutral[500], - muted: color.neutral[600], - placeholder: color.neutral[700], - active: color.neutral[50], + primary: colors.neutral[300], + secondary: colors.neutral[500], + muted: colors.neutral[600], + placeholder: colors.neutral[700], + active: colors.neutral[50], //TODO: (design) define feature and it's correct value - feature: color.sky[500], - ok: color.green[600], - error: color.red[400], - warning: color.amber[300], - info: color.blue[500], + feature: colors.sky[500], + ok: colors.green[600], + error: colors.red[400], + warning: colors.amber[300], + info: colors.blue[500], }; const player = { 1: { - baseColor: color.blue[600], - cursorColor: color.blue[600], - selectionColor: color.blue[600], - borderColor: color.blue[600], + baseColor: colors.blue[600], + cursorColor: colors.blue[600], + selectionColor: colors.blue[600], + borderColor: colors.blue[600], }, 2: { - baseColor: color.indigo[500], - cursorColor: color.indigo[500], - selectionColor: color.indigo[500], - borderColor: color.indigo[500], + baseColor: colors.indigo[500], + cursorColor: colors.indigo[500], + selectionColor: colors.indigo[500], + borderColor: colors.indigo[500], }, 3: { - baseColor: color.green[500], - cursorColor: color.green[500], - selectionColor: color.green[500], - borderColor: color.green[500], + baseColor: colors.green[500], + cursorColor: colors.green[500], + selectionColor: colors.green[500], + borderColor: colors.green[500], }, 4: { - baseColor: color.orange[500], - cursorColor: color.orange[500], - selectionColor: color.orange[500], - borderColor: color.orange[500], + baseColor: colors.orange[500], + cursorColor: colors.orange[500], + selectionColor: colors.orange[500], + borderColor: colors.orange[500], }, 5: { - baseColor: color.purple[500], - cursorColor: color.purple[500], - selectionColor: color.purple[500], - borderColor: color.purple[500], + baseColor: colors.purple[500], + cursorColor: colors.purple[500], + selectionColor: colors.purple[500], + borderColor: colors.purple[500], }, 6: { - baseColor: color.teal[400], - cursorColor: color.teal[400], - selectionColor: color.teal[400], - borderColor: color.teal[400], + baseColor: colors.teal[400], + cursorColor: colors.teal[400], + selectionColor: colors.teal[400], + borderColor: colors.teal[400], }, 7: { - baseColor: color.pink[400], - cursorColor: color.pink[400], - selectionColor: color.pink[400], - borderColor: color.pink[400], + baseColor: colors.pink[400], + cursorColor: colors.pink[400], + selectionColor: colors.pink[400], + borderColor: colors.pink[400], }, 8: { - baseColor: color.yellow[400], - cursorColor: color.yellow[400], - selectionColor: color.yellow[400], - borderColor: color.yellow[400], + baseColor: colors.yellow[400], + cursorColor: colors.yellow[400], + selectionColor: colors.yellow[400], + borderColor: colors.yellow[400], }, }; @@ -147,88 +145,114 @@ const editor = { indent_guide: borderColor.muted, indent_guide_active: borderColor.secondary, line: { - active: color.neutral[0], - highlighted: color.neutral[0], - inserted: backgroundColor.ok.active, - deleted: backgroundColor.error.active, - modified: backgroundColor.info.active, + active: colors.neutral[0], + highlighted: colors.neutral[0], + inserted: backgroundColor.ok.active, + deleted: backgroundColor.error.active, + modified: backgroundColor.info.active, }, highlight: { - selection: player[1].selectionColor, - occurrence: backgroundColor[500].active, - activeOccurrence: color.neutral[0], - matchingBracket: color.neutral[0], - match: color.neutral[0], - activeMatch: color.neutral[0], - related: color.neutral[0], + selection: player[1].selectionColor, + occurrence: backgroundColor[500].active, + activeOccurrence: colors.neutral[0], + matchingBracket: colors.neutral[0], + match: colors.neutral[0], + activeMatch: colors.neutral[0], + related: colors.neutral[0], }, gutter: { - primary: color.neutral[0], - active: color.neutral[0], + primary: colors.neutral[0], + active: colors.neutral[0], }, }; const syntax: Syntax = { primary: { - color: textColor.primary, - weight: { value: "normal", type: "fontWeight" }, + color: textColor.primary, + weight: fontWeights.normal, }, comment: { - color: color.lime[200], - weight: { value: "normal", type: "fontWeight" }, + color: colors.lime[200], + weight: fontWeights.normal, }, punctuation: { - color: textColor.primary, - weight: { value: "normal", type: "fontWeight" }, + color: textColor.primary, + weight: fontWeights.normal, }, constant: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, + color: colors.neutral[150], + weight: fontWeights.normal, }, keyword: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, + color: colors.sky[400], + weight: fontWeights.normal, }, function: { - color: color.yellow[200], - weight: { value: "normal", type: "fontWeight" }, + color: colors.yellow[200], + weight: fontWeights.normal, }, type: { - color: color.teal[300], - weight: { value: "normal", type: "fontWeight" }, + color: colors.teal[300], + weight: fontWeights.normal, }, variant: { - color: color.teal[300], - weight: { value: "normal", type: "fontWeight" }, + color: colors.teal[300], + weight: fontWeights.normal, }, property: { - color: color.sky[300], - weight: { value: "normal", type: "fontWeight" }, + color: colors.sky[300], + weight: fontWeights.normal, }, enum: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, + color: colors.sky[400], + weight: fontWeights.normal, }, operator: { - color: color.sky[400], - weight: { value: "normal", type: "fontWeight" }, + color: colors.sky[400], + weight: fontWeights.normal, }, string: { - color: color.orange[300], - weight: { value: "normal", type: "fontWeight" }, + color: colors.orange[300], + weight: fontWeights.normal, }, number: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, + color: colors.neutral[150], + weight: fontWeights.normal, }, boolean: { - color: color.neutral[150], - weight: { value: "normal", type: "fontWeight" }, + color: colors.neutral[150], + weight: fontWeights.normal, }, predictive: { - color: textColor.muted, - weight: { value: "normal", type: "fontWeight" }, + color: textColor.muted, + weight: fontWeights.normal, }, + title: { + color: colors.sky[500], + weight: fontWeights.bold, + }, + emphasis: { + color: textColor.active, + weight: fontWeights.normal, + }, + emphasisStrong: { + color: textColor.active, + weight: fontWeights.bold, + }, + linkUrl: { + color: colors.lime[500], + weight: fontWeights.normal, + // TODO: add underline + }, + linkText: { + color: colors.orange[500], + weight: fontWeights.normal, + // TODO: add italic + }, + listMarker: { + color: colors.sky[400], + weight: fontWeights.normal, + } }; const shadowAlpha: NumberToken = { diff --git a/styles/themes/theme.ts b/styles/themes/theme.ts index a776045989..f95d58e494 100644 --- a/styles/themes/theme.ts +++ b/styles/themes/theme.ts @@ -1,32 +1,8 @@ -export interface NumberToken { - value: number, - type: "number" -} - -export type Color = string; -export interface ColorToken { - value: Color; - type: "color"; - step?: number -} -export type Weight = - | "thin" - | "extra_light" - | "light" - | "normal" - | "medium" - | "semibold" - | "bold" - | "extra_bold" - | "black"; -export interface WeightToken { - value: Weight, - type: "fontWeight" -} +import { FontWeightToken, ColorToken, NumberToken } from "../tokens"; export interface SyntaxHighlightStyle { color: ColorToken; - weight: WeightToken; + weight: FontWeightToken; } export interface Player { @@ -43,7 +19,7 @@ export interface BackgroundColor { focused: ColorToken; } -export interface Syntax { +export interface Syntax { primary: SyntaxHighlightStyle; comment: SyntaxHighlightStyle; punctuation: SyntaxHighlightStyle; @@ -59,6 +35,13 @@ export interface Syntax { number: SyntaxHighlightStyle; boolean: SyntaxHighlightStyle; predictive: SyntaxHighlightStyle; + // TODO: Either move the following or rename + title: SyntaxHighlightStyle; + emphasis: SyntaxHighlightStyle; + emphasisStrong: SyntaxHighlightStyle; + linkUrl: SyntaxHighlightStyle; + linkText: SyntaxHighlightStyle; + listMarker: SyntaxHighlightStyle; }; export default interface Theme { diff --git a/styles/tokens.ts b/styles/tokens.ts new file mode 100644 index 0000000000..1e0df5032d --- /dev/null +++ b/styles/tokens.ts @@ -0,0 +1,102 @@ +import { colorRamp } from "./utils/color"; + +interface Token { + value: V, + type: T +} + +export type FontFamily = string; +export type FontFamilyToken = Token; +function fontFamily(value: FontFamily): FontFamilyToken { + return { + value, + type: "fontFamily" + } +} +export const fontFamilies = { + sans: fontFamily("Zed Sans"), + mono: fontFamily("Zed Mono"), +} + +export type FontSize = number; +export type FontSizeToken = Token; +function fontSize(value: FontSize) { + return { + value, + type: "fontSize" + }; +} +export const fontSizes = { + "3xs": fontSize(8), + "2xs": fontSize(10), + xs: fontSize(12), + sm: fontSize(14), + md: fontSize(16), + lg: fontSize(18), + xl: fontSize(20), +}; + +export type FontWeight = + | "thin" + | "extra_light" + | "light" + | "normal" + | "medium" + | "semibold" + | "bold" + | "extra_bold" + | "black"; +export type FontWeightToken = Token; +function fontWeight(value: FontWeight): FontWeightToken { + return { + value, + type: "fontWeight" + }; +} +export const fontWeights = { + "thin": fontWeight("thin"), + "extra_light": fontWeight("extra_light"), + "light": fontWeight("light"), + "normal": fontWeight("normal"), + "medium": fontWeight("medium"), + "semibold": fontWeight("semibold"), + "bold": fontWeight("bold"), + "extra_bold": fontWeight("extra_bold"), + "black": fontWeight("black"), +} + +export type Color = string; +export interface ColorToken { + value: Color, + type: "color", + step?: number, +} +export const colors = { + neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }), + rose: colorRamp("#F43F5EFF"), + red: colorRamp("#EF4444FF"), + orange: colorRamp("#F97316FF"), + amber: colorRamp("#F59E0BFF"), + yellow: colorRamp("#EAB308FF"), + lime: colorRamp("#84CC16FF"), + green: colorRamp("#22C55EFF"), + emerald: colorRamp("#10B981FF"), + teal: colorRamp("#14B8A6FF"), + cyan: colorRamp("#06BBD4FF"), + sky: colorRamp("#0EA5E9FF"), + blue: colorRamp("#3B82F6FF"), + indigo: colorRamp("#6366F1FF"), + violet: colorRamp("#8B5CF6FF"), + purple: colorRamp("#A855F7FF"), + fuschia: colorRamp("#D946E4FF"), + pink: colorRamp("#EC4899FF"), +} + +export type NumberToken = Token; + +export default { + fontFamilies, + fontSizes, + fontWeights, + colors, +}; diff --git a/styles/tokens/core.ts b/styles/tokens/core.ts deleted file mode 100644 index 38bfe82e28..0000000000 --- a/styles/tokens/core.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { colorRamp } from "../utils/color"; - -export default { - fontFamily: { - sans: "Zed Sans", - mono: "Zed Mono", - }, - fontSize: { - "3xs": { - value: "8", - type: "fontSizes", - }, - "2xs": { - value: "10", - type: "fontSizes", - }, - xs: { - value: "12", - type: "fontSizes", - }, - sm: { - value: "14", - type: "fontSizes", - }, - md: { - value: "16", - type: "fontSizes", - }, - lg: { - value: "18", - type: "fontSizes", - }, - xl: { - value: "20", - type: "fontSizes", - }, - }, - color: { - neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }), - rose: colorRamp("#F43F5EFF"), - red: colorRamp("#EF4444FF"), - orange: colorRamp("#F97316FF"), - amber: colorRamp("#F59E0BFF"), - yellow: colorRamp("#EAB308FF"), - lime: colorRamp("#84CC16FF"), - green: colorRamp("#22C55EFF"), - emerald: colorRamp("#10B981FF"), - teal: colorRamp("#14B8A6FF"), - cyan: colorRamp("#06BBD4FF"), - sky: colorRamp("#0EA5E9FF"), - blue: colorRamp("#3B82F6FF"), - indigo: colorRamp("#6366F1FF"), - violet: colorRamp("#8B5CF6FF"), - purple: colorRamp("#A855F7FF"), - fuschia: colorRamp("#D946E4FF"), - pink: colorRamp("#EC4899FF"), - }, -}; From c812adde7f893b932fcd7fc7df401c5a83515ea4 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 1 Apr 2022 22:39:18 -0400 Subject: [PATCH 59/68] Add "npm run watch" command to live reload changes --- styles/nodemon.json | 6 + styles/package-lock.json | 2317 +++++++++++++++++++++++++++++++++++++- styles/package.json | 6 +- 3 files changed, 2306 insertions(+), 23 deletions(-) create mode 100644 styles/nodemon.json diff --git a/styles/nodemon.json b/styles/nodemon.json new file mode 100644 index 0000000000..24022a55ad --- /dev/null +++ b/styles/nodemon.json @@ -0,0 +1,6 @@ +{ + "watch": ["./**/*"], + "ext": "ts", + "ignore": [], + "exec": "ts-node buildThemes.ts" +} \ No newline at end of file diff --git a/styles/package-lock.json b/styles/package-lock.json index 582f1c8496..43c9b19ea1 100644 --- a/styles/package-lock.json +++ b/styles/package-lock.json @@ -12,7 +12,10 @@ "@types/chroma-js": "^2.1.3", "@types/node": "^17.0.23", "case-anything": "^2.1.10", - "chroma-js": "^2.4.2", + "chroma-js": "^2.4.2" + }, + "devDependencies": { + "nodemon": "^2.0.15", "ts-node": "^10.7.0" } }, @@ -20,6 +23,7 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true, "engines": { "node": ">= 12" } @@ -28,6 +32,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, "dependencies": { "@cspotcode/source-map-consumer": "0.8.0" }, @@ -35,25 +40,50 @@ "node": ">=12" } }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==" + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==" + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==" + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true }, "node_modules/@types/chroma-js": { "version": "2.1.3", @@ -65,10 +95,17 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "node_modules/acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -80,14 +117,175 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, "engines": { "node": ">=0.4.0" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/case-anything": { "version": "2.1.10", @@ -100,33 +298,967 @@ "url": "https://github.com/sponsors/mesqueeb" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/chroma-js": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==" }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, "engines": { "node": ">=0.3.1" } }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nodemon": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", + "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5", + "update-notifier": "^5.1.0" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } }, "node_modules/ts-node": { "version": "10.7.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "dev": true, "dependencies": { "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", @@ -165,10 +1297,32 @@ } } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, "node_modules/typescript": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "dev": true, "peer": true, "bin": { "tsc": "bin/tsc", @@ -178,15 +1332,152 @@ "node": ">=4.2.0" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", - "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==" + "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "dev": true + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, "engines": { "node": ">=6" } @@ -196,35 +1487,56 @@ "@cspotcode/source-map-consumer": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==" + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true }, "@cspotcode/source-map-support": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, "requires": { "@cspotcode/source-map-consumer": "0.8.0" } }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, "@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==" + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true }, "@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==" + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true }, "@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==" + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true }, "@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true }, "@types/chroma-js": { "version": "2.1.3", @@ -236,50 +1548,886 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true }, "acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true }, "case-anything": { "version": "2.1.10", "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz", "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ==" }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, "chroma-js": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==" }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "dev": true, + "requires": { + "ini": "2.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } }, "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "nodemon": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", + "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5", + "update-notifier": "^5.1.0" + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + } }, "ts-node": { "version": "10.7.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "dev": true, "requires": { "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", @@ -296,21 +2444,146 @@ "yn": "3.1.1" } }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, "typescript": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "dev": true, "peer": true }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, "v8-compile-cache-lib": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", - "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==" + "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "dev": true + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/styles/package.json b/styles/package.json index c270bba0e1..8576a35d34 100644 --- a/styles/package.json +++ b/styles/package.json @@ -4,7 +4,8 @@ "description": "", "main": "index.js", "scripts": { - "build": "ts-node buildThemes.ts" + "build": "ts-node buildThemes.ts", + "watch": "nodemon" }, "author": "", "license": "ISC", @@ -14,5 +15,8 @@ "case-anything": "^2.1.10", "chroma-js": "^2.4.2", "ts-node": "^10.7.0" + }, + "devDependencies": { + "nodemon": "^2.0.15" } } From 381d50bac62fee058721839a2e983b35445a1ad6 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 1 Apr 2022 23:58:04 -0400 Subject: [PATCH 60/68] WIP --- crates/zed/assets/themes/dark.json | 351 ++++++++++++------------ crates/zed/assets/themes/light.json | 411 ++++++++++++++-------------- styles/buildThemes.ts | 2 +- styles/styleTree/chatPanel.ts | 8 +- styles/styleTree/editor.ts | 14 +- styles/styleTree/projectPanel.ts | 7 +- styles/styleTree/workspace.ts | 29 +- styles/themes/dark.ts | 24 +- styles/themes/light.ts | 288 ++++++++++--------- styles/themes/theme.ts | 2 +- styles/tokens.ts | 2 +- 11 files changed, 576 insertions(+), 562 deletions(-) diff --git a/crates/zed/assets/themes/dark.json b/crates/zed/assets/themes/dark.json index 65bf78b140..fd11fc6c3a 100644 --- a/crates/zed/assets/themes/dark.json +++ b/crates/zed/assets/themes/dark.json @@ -1,6 +1,6 @@ { "selector": { - "background": "#e6e6e6", + "background": "#000000", "corner_radius": 6, "padding": 8, "item": { @@ -13,12 +13,12 @@ "corner_radius": 6, "text": { "family": "Zed Sans", - "color": "#595959", + "color": "#9c9c9c", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#2db4f3", + "color": "#90df17", "weight": "bold", "size": 14 } @@ -33,25 +33,25 @@ "corner_radius": 6, "text": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#2db4f3", + "color": "#90df17", "weight": "bold", "size": 14 }, - "background": "#e6e6e6" + "background": "#000000" }, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "empty": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "padding": { @@ -62,11 +62,11 @@ } }, "input_editor": { - "background": "#cccccc", + "background": "#1c1c1c", "corner_radius": 6, "placeholder_text": { "family": "Zed Sans", - "color": "#bfbfbf", + "color": "#2b2b2b", "size": 14 }, "selection": { @@ -75,11 +75,11 @@ }, "text": { "family": "Zed Mono", - "color": "#262626", + "color": "#d5d5d5", "size": 16 }, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "padding": { @@ -103,24 +103,25 @@ } }, "workspace": { - "background": "#e6e6e6", + "background": "#1c1c1c", "leader_border_opacity": 0.7, "leader_border_width": 2, "tab": { - "height": 34, - "icon_close": "#808080", - "icon_close_active": "#0d0d0d", - "icon_conflict": "#f8c570", - "icon_dirty": "#6099f7", + "height": 32, + "background": "#1c1c1c", + "icon_close": "#717171", + "icon_close_active": "#f1f1f1", + "icon_conflict": "#f7b241", + "icon_dirty": "#4287f6", "icon_width": 8, "spacing": 10, "text": { "family": "Zed Mono", - "color": "#595959", - "size": 16 + "color": "#9c9c9c", + "size": 14 }, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "left": true, "bottom": true, @@ -132,20 +133,21 @@ } }, "active_tab": { - "height": 34, - "icon_close": "#808080", - "icon_close_active": "#0d0d0d", - "icon_conflict": "#f8c570", - "icon_dirty": "#6099f7", + "height": 32, + "background": "#000000", + "icon_close": "#717171", + "icon_close_active": "#f1f1f1", + "icon_conflict": "#f7b241", + "icon_dirty": "#4287f6", "icon_width": 8, "spacing": 10, "text": { "family": "Zed Mono", - "color": "#262626", - "size": 16 + "color": "#ffffff", + "size": 14 }, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "left": true, "bottom": false, @@ -154,28 +156,28 @@ "padding": { "left": 12, "right": 12 - }, - "background": "#cccccc" + } }, "left_sidebar": { "width": 30, + "background": "#1c1c1c", "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "right": true }, "item": { "height": 32, - "icon_color": "#808080", + "icon_color": "#717171", "icon_size": 18 }, "active_item": { "height": 32, - "icon_color": "#4d4d4d", + "icon_color": "#f1f1f1", "icon_size": 18 }, "resize_handle": { - "background": "#d9d9d9", + "background": "#0e0e0e", "padding": { "left": 1 } @@ -183,30 +185,31 @@ }, "right_sidebar": { "width": 30, + "background": "#1c1c1c", "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "left": true }, "item": { "height": 32, - "icon_color": "#808080", + "icon_color": "#717171", "icon_size": 18 }, "active_item": { "height": 32, - "icon_color": "#4d4d4d", + "icon_color": "#f1f1f1", "icon_size": 18 }, "resize_handle": { - "background": "#d9d9d9", + "background": "#0e0e0e", "padding": { "left": 1 } } }, "pane_divider": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "status_bar": { @@ -218,28 +221,29 @@ }, "cursor_position": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "diagnostic_message": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "lsp_message": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 } }, "titlebar": { "avatar_width": 18, "height": 32, - "share_icon_color": "#808080", - "share_icon_active_color": "#0d0d0d", + "background": "#393939", + "share_icon_color": "#717171", + "share_icon_active_color": "#f1f1f1", "title": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "size": 14 }, "avatar": { @@ -254,13 +258,13 @@ "width": 12 }, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "bottom": true }, "sign_in_prompt": { "family": "Zed Sans", - "color": "#595959", + "color": "#9c9c9c", "size": 13, "underline": true, "padding": { @@ -269,15 +273,15 @@ }, "hovered_sign_in_prompt": { "family": "Zed Mono", - "color": "#000000", - "size": 16, + "color": "#ffffff", + "size": 13, "underline": true, "padding": { "right": 8 } }, "offline_icon": { - "color": "#999999", + "color": "#717171", "width": 16, "padding": { "right": 4 @@ -285,15 +289,15 @@ }, "outdated_warning": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#f8c570", "size": 13 } }, "toolbar": { "height": 34, - "background": "#cccccc", + "background": "#000000", "border": { - "color": "#d9d9d9", + "color": "#2b2b2b", "width": 1, "bottom": true }, @@ -307,7 +311,7 @@ }, "breadcrumbs": { "family": "Zed Mono", - "color": "#595959", + "color": "#9c9c9c", "size": 16, "padding": { "left": 6 @@ -321,20 +325,20 @@ } }, "editor": { - "text_color": "#595959", - "background": "#cccccc", - "active_line_background": "#000000", - "code_actions_indicator": "#808080", + "text_color": "#9c9c9c", + "background": "#000000", + "active_line_background": "#ffffff", + "code_actions_indicator": "#717171", "diff_background_deleted": "#f78c8c", "diff_background_inserted": "#22c55e", - "document_highlight_read_background": "#e6e6e6", - "document_highlight_write_background": "#e6e6e6", + "document_highlight_read_background": "#000000", + "document_highlight_write_background": "#000000", "error_color": "#f78c8c", - "gutter_background": "#cccccc", + "gutter_background": "#000000", "gutter_padding_factor": 2.5, - "highlighted_line_background": "#000000", - "line_number": "#000000", - "line_number_active": "#000000", + "highlighted_line_background": "#ffffff", + "line_number": "#ffffff", + "line_number_active": "#ffffff", "rename_fade": 0.6, "unnecessary_code_fade": 0.5, "selection": { @@ -372,11 +376,11 @@ } ], "autocomplete": { - "background": "#bfbfbf", + "background": "#000000", "corner_radius": 6, "padding": 6, "border": { - "color": "#b3b3b3", + "color": "#393939", "width": 1 }, "item": { @@ -396,7 +400,7 @@ "right": 6, "top": 2 }, - "background": "#bfbfbf" + "background": "#000000" }, "margin": { "left": -14 @@ -413,22 +417,22 @@ "right": 6, "top": 2 }, - "background": "#bfbfbf" + "background": "#000000" } }, "diagnostic_header": { - "background": "#e6e6e6", + "background": "#1c1c1c", "icon_width_factor": 1.5, "text_scale_factor": 0.857, "border": { - "color": "#b3b3b3", + "color": "#393939", "width": 1, "bottom": true, "top": true }, "code": { "family": "Zed Mono", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "margin": { "left": 10 @@ -437,28 +441,28 @@ "message": { "highlight_text": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "size": 14, "weight": "bold" }, "text": { "family": "Zed Sans", - "color": "#595959", + "color": "#9c9c9c", "size": 14 } } }, "diagnostic_path_header": { - "background": "#000000", + "background": "#ffffff", "text_scale_factor": 0.857, "filename": { "family": "Zed Mono", - "color": "#262626", + "color": "#d5d5d5", "size": 14 }, "path": { "family": "Zed Mono", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "margin": { "left": 12 @@ -469,7 +473,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "top": true } @@ -492,7 +496,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "top": true } @@ -515,7 +519,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "top": true } @@ -538,7 +542,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "top": true } @@ -561,7 +565,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "top": true } @@ -569,12 +573,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "weight": "bold" } @@ -584,7 +588,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "top": true } @@ -592,12 +596,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "weight": "bold" } @@ -607,7 +611,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "top": true } @@ -615,12 +619,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "weight": "bold" } @@ -630,7 +634,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1, "top": true } @@ -638,12 +642,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "weight": "bold" } @@ -652,18 +656,18 @@ "syntax": {} }, "project_diagnostics": { - "background": "#cccccc", + "background": "#1c1c1c", "tab_icon_spacing": 4, "tab_icon_width": 13, "tab_summary_spacing": 10, "empty_message": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "size": 14 }, "status_bar_item": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "margin": { "right": 10 @@ -672,52 +676,53 @@ }, "project_panel": { "padding": { - "top": 6 + "top": 6, + "left": 12 }, "entry": { "height": 22, - "icon_color": "#999999", + "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#595959", - "size": 16 + "color": "#9c9c9c", + "size": 14 } }, "hovered_entry": { "height": 22, - "background": "#cccccc", - "icon_color": "#999999", + "background": "#1c1c1c", + "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#595959", - "size": 16 + "color": "#9c9c9c", + "size": 14 } }, "selected_entry": { "height": 22, - "icon_color": "#999999", + "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#262626", - "size": 16 + "color": "#d5d5d5", + "size": 14 } }, "hovered_selected_entry": { "height": 22, - "background": "#cccccc", - "icon_color": "#999999", + "background": "#1c1c1c", + "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#262626", - "size": 16 + "color": "#d5d5d5", + "size": 14 } } }, @@ -730,13 +735,13 @@ }, "channel_name": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "weight": "bold", "size": 14 }, "channel_name_hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "padding": { "right": 8 @@ -746,7 +751,7 @@ "header": { "name": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "size": 14 }, "padding": { @@ -755,7 +760,7 @@ }, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "margin": { "right": 8 @@ -766,13 +771,13 @@ "item": { "name": { "family": "Zed Sans", - "color": "#595959", + "color": "#9c9c9c", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "margin": { "right": 8 @@ -783,31 +788,31 @@ "hovered_item": { "name": { "family": "Zed Sans", - "color": "#595959", + "color": "#9c9c9c", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "margin": { "right": 8 } }, - "background": "#cccccc", + "background": "#1c1c1c", "corner_radius": 6 }, "active_item": { "name": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "margin": { "right": 8 @@ -818,27 +823,27 @@ "hovered_active_item": { "name": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14, "margin": { "right": 8 } }, - "background": "#cccccc", + "background": "#1c1c1c", "corner_radius": 6 }, "menu": { - "background": "#e6e6e6", + "background": "#000000", "corner_radius": 6, "padding": 4, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "shadow": { @@ -853,25 +858,25 @@ }, "sign_in_prompt": { "family": "Zed Sans", - "color": "#595959", + "color": "#9c9c9c", "underline": true, "size": 14 }, "hovered_sign_in_prompt": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "underline": true, "size": 14 }, "message": { "body": { "family": "Zed Sans", - "color": "#595959", + "color": "#9c9c9c", "size": 14 }, "timestamp": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "padding": { @@ -879,7 +884,7 @@ }, "sender": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "weight": "bold", "size": 14, "margin": { @@ -890,12 +895,12 @@ "pending_message": { "body": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "timestamp": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "size": 14 }, "padding": { @@ -903,7 +908,7 @@ }, "sender": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#636363", "weight": "bold", "size": 14, "margin": { @@ -912,24 +917,24 @@ } }, "input_editor": { - "background": "#cccccc", + "background": "#000000", "corner_radius": 6, "text": { "family": "Zed Mono", - "color": "#262626", + "color": "#d5d5d5", "size": 16 }, "placeholder_text": { "family": "Zed Mono", - "color": "#8c8c8c", - "size": 16 + "color": "#2b2b2b", + "size": 14 }, "selection": { "cursor": "#4287f6", "selection": "#4287f6" }, "border": { - "color": "#d9d9d9", + "color": "#393939", "width": 1 }, "padding": { @@ -948,7 +953,7 @@ "right": 12 }, "host_row_height": 28, - "tree_branch_color": "#bfbfbf", + "tree_branch_color": "#2b2b2b", "tree_branch_width": 1, "host_avatar": { "corner_radius": 10, @@ -956,7 +961,7 @@ }, "host_username": { "family": "Zed Mono", - "color": "#8c8c8c", + "color": "#636363", "size": 16, "padding": { "left": 8 @@ -971,7 +976,7 @@ }, "name": { "family": "Zed Mono", - "color": "#595959", + "color": "#9c9c9c", "size": 16, "margin": { "right": 6 @@ -990,7 +995,7 @@ }, "name": { "family": "Zed Mono", - "color": "#262626", + "color": "#d5d5d5", "size": 16, "margin": { "right": 6 @@ -1009,7 +1014,7 @@ }, "name": { "family": "Zed Mono", - "color": "#262626", + "color": "#d5d5d5", "size": 16, "margin": { "right": 6 @@ -1018,7 +1023,7 @@ "padding": { "left": 8 }, - "background": "#000000", + "background": "#ffffff", "corner_radius": 6 }, "unshared_project": { @@ -1030,7 +1035,7 @@ }, "name": { "family": "Zed Mono", - "color": "#595959", + "color": "#9c9c9c", "size": 16, "margin": { "right": 6 @@ -1049,7 +1054,7 @@ }, "name": { "family": "Zed Mono", - "color": "#595959", + "color": "#9c9c9c", "size": 16, "margin": { "right": 6 @@ -1058,22 +1063,22 @@ "padding": { "left": 8 }, - "background": "#000000", + "background": "#ffffff", "corner_radius": 6 } }, "search": { - "match_background": "#000000", + "match_background": "#ffffff", "tab_icon_spacing": 4, "tab_icon_width": 14, "active_hovered_option_button": { "family": "Zed Mono", - "color": "#595959", + "color": "#9c9c9c", "size": 16, - "background": "#bfbfbf", + "background": "#393939", "corner_radius": 6, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "margin": { @@ -1089,12 +1094,12 @@ }, "active_option_button": { "family": "Zed Mono", - "color": "#595959", + "color": "#9c9c9c", "size": 16, - "background": "#bfbfbf", + "background": "#393939", "corner_radius": 6, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "margin": { @@ -1109,13 +1114,13 @@ } }, "editor": { - "background": "#e6e6e6", + "background": "#000000", "corner_radius": 6, "min_width": 200, "max_width": 500, "placeholder_text": { "family": "Zed Mono", - "color": "#bfbfbf", + "color": "#2b2b2b", "size": 16 }, "selection": { @@ -1124,11 +1129,11 @@ }, "text": { "family": "Zed Mono", - "color": "#262626", + "color": "#d5d5d5", "size": 16 }, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "margin": { @@ -1143,12 +1148,12 @@ }, "hovered_option_button": { "family": "Zed Mono", - "color": "#595959", + "color": "#9c9c9c", "size": 16, - "background": "#bfbfbf", + "background": "#393939", "corner_radius": 6, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "margin": { @@ -1163,13 +1168,13 @@ } }, "invalid_editor": { - "background": "#e6e6e6", + "background": "#000000", "corner_radius": 6, "min_width": 200, "max_width": 500, "placeholder_text": { "family": "Zed Mono", - "color": "#bfbfbf", + "color": "#2b2b2b", "size": 16 }, "selection": { @@ -1178,11 +1183,11 @@ }, "text": { "family": "Zed Mono", - "color": "#262626", + "color": "#d5d5d5", "size": 16 }, "border": { - "color": "#ffffff", + "color": "#f47171", "width": 1 }, "margin": { @@ -1197,18 +1202,18 @@ }, "match_index": { "family": "Zed Mono", - "color": "#8c8c8c", + "color": "#636363", "size": 16, "padding": 6 }, "option_button": { "family": "Zed Mono", - "color": "#595959", + "color": "#9c9c9c", "size": 16, - "background": "#cccccc", + "background": "#1c1c1c", "corner_radius": 6, "border": { - "color": "#d9d9d9", + "color": "#0e0e0e", "width": 1 }, "margin": { @@ -1230,13 +1235,13 @@ }, "results_status": { "family": "Zed Mono", - "color": "#262626", + "color": "#d5d5d5", "size": 18 } }, "breadcrumbs": { "family": "Zed Sans", - "color": "#262626", + "color": "#d5d5d5", "size": 14, "padding": { "left": 6 diff --git a/crates/zed/assets/themes/light.json b/crates/zed/assets/themes/light.json index 65bf78b140..219f958e87 100644 --- a/crates/zed/assets/themes/light.json +++ b/crates/zed/assets/themes/light.json @@ -1,6 +1,6 @@ { "selector": { - "background": "#e6e6e6", + "background": "#ffffff", "corner_radius": 6, "padding": 8, "item": { @@ -13,12 +13,12 @@ "corner_radius": 6, "text": { "family": "Zed Sans", - "color": "#595959", + "color": "#393939", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#2db4f3", + "color": "#4287f6", "weight": "bold", "size": 14 } @@ -33,25 +33,25 @@ "corner_radius": 6, "text": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#2db4f3", + "color": "#4287f6", "weight": "bold", "size": 14 }, - "background": "#e6e6e6" + "background": "#e3e3e3" }, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "empty": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "padding": { @@ -62,24 +62,24 @@ } }, "input_editor": { - "background": "#cccccc", + "background": "#f1f1f1", "corner_radius": 6, "placeholder_text": { "family": "Zed Sans", - "color": "#bfbfbf", + "color": "#717171", "size": 14 }, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", - "color": "#262626", + "color": "#1c1c1c", "size": 16 }, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "padding": { @@ -95,7 +95,7 @@ }, "shadow": { "blur": 16, - "color": "#00000052", + "color": "#0000001f", "offset": [ 0, 2 @@ -103,24 +103,25 @@ } }, "workspace": { - "background": "#e6e6e6", + "background": "#f1f1f1", "leader_border_opacity": 0.7, "leader_border_width": 2, "tab": { - "height": 34, - "icon_close": "#808080", - "icon_close_active": "#0d0d0d", - "icon_conflict": "#f8c570", - "icon_dirty": "#6099f7", + "height": 32, + "background": "#f1f1f1", + "icon_close": "#717171", + "icon_close_active": "#000000", + "icon_conflict": "#f6bc09", + "icon_dirty": "#4287f6", "icon_width": 8, "spacing": 10, "text": { "family": "Zed Mono", - "color": "#595959", - "size": 16 + "color": "#393939", + "size": 14 }, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "left": true, "bottom": true, @@ -132,20 +133,21 @@ } }, "active_tab": { - "height": 34, - "icon_close": "#808080", - "icon_close_active": "#0d0d0d", - "icon_conflict": "#f8c570", - "icon_dirty": "#6099f7", + "height": 32, + "background": "#ffffff", + "icon_close": "#717171", + "icon_close_active": "#000000", + "icon_conflict": "#f6bc09", + "icon_dirty": "#4287f6", "icon_width": 8, "spacing": 10, "text": { "family": "Zed Mono", - "color": "#262626", - "size": 16 + "color": "#000000", + "size": 14 }, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "left": true, "bottom": false, @@ -154,28 +156,28 @@ "padding": { "left": 12, "right": 12 - }, - "background": "#cccccc" + } }, "left_sidebar": { "width": 30, + "background": "#f1f1f1", "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "right": true }, "item": { "height": 32, - "icon_color": "#808080", + "icon_color": "#717171", "icon_size": 18 }, "active_item": { "height": 32, - "icon_color": "#4d4d4d", + "icon_color": "#000000", "icon_size": 18 }, "resize_handle": { - "background": "#d9d9d9", + "background": "#c6c6c6", "padding": { "left": 1 } @@ -183,30 +185,31 @@ }, "right_sidebar": { "width": 30, + "background": "#f1f1f1", "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "left": true }, "item": { "height": 32, - "icon_color": "#808080", + "icon_color": "#717171", "icon_size": 18 }, "active_item": { "height": 32, - "icon_color": "#4d4d4d", + "icon_color": "#000000", "icon_size": 18 }, "resize_handle": { - "background": "#d9d9d9", + "background": "#c6c6c6", "padding": { "left": 1 } } }, "pane_divider": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "status_bar": { @@ -218,28 +221,29 @@ }, "cursor_position": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "diagnostic_message": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "lsp_message": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 } }, "titlebar": { "avatar_width": 18, "height": 32, - "share_icon_color": "#808080", - "share_icon_active_color": "#0d0d0d", + "background": "#e3e3e3", + "share_icon_color": "#717171", + "share_icon_active_color": "#000000", "title": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "size": 14 }, "avatar": { @@ -254,13 +258,13 @@ "width": 12 }, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "bottom": true }, "sign_in_prompt": { "family": "Zed Sans", - "color": "#595959", + "color": "#393939", "size": 13, "underline": true, "padding": { @@ -270,14 +274,14 @@ "hovered_sign_in_prompt": { "family": "Zed Mono", "color": "#000000", - "size": 16, + "size": 13, "underline": true, "padding": { "right": 8 } }, "offline_icon": { - "color": "#999999", + "color": "#717171", "width": 16, "padding": { "right": 4 @@ -285,15 +289,15 @@ }, "outdated_warning": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#b48d14", "size": 13 } }, "toolbar": { "height": 34, - "background": "#cccccc", + "background": "#ffffff", "border": { - "color": "#d9d9d9", + "color": "#f1f1f1", "width": 1, "bottom": true }, @@ -307,7 +311,7 @@ }, "breadcrumbs": { "family": "Zed Mono", - "color": "#595959", + "color": "#393939", "size": 16, "padding": { "left": 6 @@ -315,68 +319,68 @@ }, "disconnected_overlay": { "family": "Zed Sans", - "color": "#ffffff", + "color": "#000000", "size": 14, "background": "#000000aa" } }, "editor": { - "text_color": "#595959", - "background": "#cccccc", - "active_line_background": "#000000", - "code_actions_indicator": "#808080", - "diff_background_deleted": "#f78c8c", - "diff_background_inserted": "#22c55e", - "document_highlight_read_background": "#e6e6e6", - "document_highlight_write_background": "#e6e6e6", - "error_color": "#f78c8c", - "gutter_background": "#cccccc", + "text_color": "#393939", + "background": "#ffffff", + "active_line_background": "#ffffff", + "code_actions_indicator": "#717171", + "diff_background_deleted": "#fdd4d4", + "diff_background_inserted": "#befad2", + "document_highlight_read_background": "#e3e3e3", + "document_highlight_write_background": "#e3e3e3", + "error_color": "#d11c1c", + "gutter_background": "#ffffff", "gutter_padding_factor": 2.5, - "highlighted_line_background": "#000000", - "line_number": "#000000", - "line_number_active": "#000000", + "highlighted_line_background": "#ffffff", + "line_number": "#ffffff", + "line_number_active": "#ffffff", "rename_fade": 0.6, "unnecessary_code_fade": 0.5, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "guest_selections": [ { "cursor": "#777af4", - "selection": "#777af4" + "selection": "#d4d5fd" }, { "cursor": "#23d464", - "selection": "#23d464" + "selection": "#befad2" }, { "cursor": "#f98a3d", - "selection": "#f98a3d" + "selection": "#fde0cd" }, { "cursor": "#b671f8", - "selection": "#b671f8" + "selection": "#e9d4fd" }, { "cursor": "#16ddc7", - "selection": "#16ddc7" + "selection": "#b4faf2" }, { "cursor": "#f58ac0", - "selection": "#f58ac0" + "selection": "#fcd4e8" }, { "cursor": "#f6bc09", - "selection": "#f6bc09" + "selection": "#fceabc" } ], "autocomplete": { - "background": "#bfbfbf", + "background": "#ffffff", "corner_radius": 6, "padding": 6, "border": { - "color": "#b3b3b3", + "color": "#e3e3e3", "width": 1 }, "item": { @@ -396,7 +400,7 @@ "right": 6, "top": 2 }, - "background": "#bfbfbf" + "background": "#f1f1f1" }, "margin": { "left": -14 @@ -413,22 +417,22 @@ "right": 6, "top": 2 }, - "background": "#bfbfbf" + "background": "#e3e3e3" } }, "diagnostic_header": { - "background": "#e6e6e6", + "background": "#f1f1f1", "icon_width_factor": 1.5, "text_scale_factor": 0.857, "border": { - "color": "#b3b3b3", + "color": "#e3e3e3", "width": 1, "bottom": true, "top": true }, "code": { "family": "Zed Mono", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "margin": { "left": 10 @@ -437,28 +441,28 @@ "message": { "highlight_text": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "size": 14, "weight": "bold" }, "text": { "family": "Zed Sans", - "color": "#595959", + "color": "#393939", "size": 14 } } }, "diagnostic_path_header": { - "background": "#000000", + "background": "#ffffff", "text_scale_factor": 0.857, "filename": { "family": "Zed Mono", - "color": "#262626", + "color": "#1c1c1c", "size": 14 }, "path": { "family": "Zed Mono", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "margin": { "left": 12 @@ -469,7 +473,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "top": true } @@ -477,12 +481,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#f78c8c", + "color": "#d11c1c", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#f78c8c", + "color": "#d11c1c", "size": 14, "weight": "bold" } @@ -492,7 +496,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "top": true } @@ -500,12 +504,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#f8c570", + "color": "#b48d14", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#f8c570", + "color": "#b48d14", "size": 14, "weight": "bold" } @@ -515,7 +519,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "top": true } @@ -523,12 +527,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#1762db", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#1762db", "size": 14, "weight": "bold" } @@ -538,7 +542,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "top": true } @@ -546,12 +550,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#1762db", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#1762db", "size": 14, "weight": "bold" } @@ -561,7 +565,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "top": true } @@ -569,12 +573,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "weight": "bold" } @@ -584,7 +588,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "top": true } @@ -592,12 +596,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "weight": "bold" } @@ -607,7 +611,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "top": true } @@ -615,12 +619,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "weight": "bold" } @@ -630,7 +634,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1, "top": true } @@ -638,12 +642,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "weight": "bold" } @@ -652,18 +656,18 @@ "syntax": {} }, "project_diagnostics": { - "background": "#cccccc", + "background": "#f1f1f1", "tab_icon_spacing": 4, "tab_icon_width": 13, "tab_summary_spacing": 10, "empty_message": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "size": 14 }, "status_bar_item": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "margin": { "right": 10 @@ -672,52 +676,53 @@ }, "project_panel": { "padding": { - "top": 6 + "top": 6, + "left": 12 }, "entry": { "height": 22, - "icon_color": "#999999", + "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#595959", - "size": 16 + "color": "#393939", + "size": 14 } }, "hovered_entry": { "height": 22, - "background": "#cccccc", - "icon_color": "#999999", + "background": "#e3e3e3", + "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#595959", - "size": 16 + "color": "#393939", + "size": 14 } }, "selected_entry": { "height": 22, - "icon_color": "#999999", + "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#262626", - "size": 16 + "color": "#1c1c1c", + "size": 14 } }, "hovered_selected_entry": { "height": 22, - "background": "#cccccc", - "icon_color": "#999999", + "background": "#e3e3e3", + "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#262626", - "size": 16 + "color": "#1c1c1c", + "size": 14 } } }, @@ -730,13 +735,13 @@ }, "channel_name": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "weight": "bold", "size": 14 }, "channel_name_hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "padding": { "right": 8 @@ -746,7 +751,7 @@ "header": { "name": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "size": 14 }, "padding": { @@ -755,7 +760,7 @@ }, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "margin": { "right": 8 @@ -766,13 +771,13 @@ "item": { "name": { "family": "Zed Sans", - "color": "#595959", + "color": "#393939", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "margin": { "right": 8 @@ -783,31 +788,31 @@ "hovered_item": { "name": { "family": "Zed Sans", - "color": "#595959", + "color": "#393939", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "margin": { "right": 8 } }, - "background": "#cccccc", + "background": "#e3e3e3", "corner_radius": 6 }, "active_item": { "name": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "margin": { "right": 8 @@ -818,32 +823,32 @@ "hovered_active_item": { "name": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14, "margin": { "right": 8 } }, - "background": "#cccccc", + "background": "#e3e3e3", "corner_radius": 6 }, "menu": { - "background": "#e6e6e6", + "background": "#ffffff", "corner_radius": 6, "padding": 4, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "shadow": { "blur": 16, - "color": "#00000052", + "color": "#0000001f", "offset": [ 0, 2 @@ -853,25 +858,25 @@ }, "sign_in_prompt": { "family": "Zed Sans", - "color": "#595959", + "color": "#393939", "underline": true, "size": 14 }, "hovered_sign_in_prompt": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "underline": true, "size": 14 }, "message": { "body": { "family": "Zed Sans", - "color": "#595959", + "color": "#393939", "size": 14 }, "timestamp": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "padding": { @@ -879,7 +884,7 @@ }, "sender": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "weight": "bold", "size": 14, "margin": { @@ -890,12 +895,12 @@ "pending_message": { "body": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "timestamp": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "size": 14 }, "padding": { @@ -903,7 +908,7 @@ }, "sender": { "family": "Zed Sans", - "color": "#8c8c8c", + "color": "#555555", "weight": "bold", "size": 14, "margin": { @@ -912,24 +917,24 @@ } }, "input_editor": { - "background": "#cccccc", + "background": "#ffffff", "corner_radius": 6, "text": { "family": "Zed Mono", - "color": "#262626", + "color": "#1c1c1c", "size": 16 }, "placeholder_text": { "family": "Zed Mono", - "color": "#8c8c8c", - "size": 16 + "color": "#717171", + "size": 14 }, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "border": { - "color": "#d9d9d9", + "color": "#e3e3e3", "width": 1 }, "padding": { @@ -948,7 +953,7 @@ "right": 12 }, "host_row_height": 28, - "tree_branch_color": "#bfbfbf", + "tree_branch_color": "#f1f1f1", "tree_branch_width": 1, "host_avatar": { "corner_radius": 10, @@ -956,7 +961,7 @@ }, "host_username": { "family": "Zed Mono", - "color": "#8c8c8c", + "color": "#555555", "size": 16, "padding": { "left": 8 @@ -971,7 +976,7 @@ }, "name": { "family": "Zed Mono", - "color": "#595959", + "color": "#393939", "size": 16, "margin": { "right": 6 @@ -990,7 +995,7 @@ }, "name": { "family": "Zed Mono", - "color": "#262626", + "color": "#1c1c1c", "size": 16, "margin": { "right": 6 @@ -1009,7 +1014,7 @@ }, "name": { "family": "Zed Mono", - "color": "#262626", + "color": "#1c1c1c", "size": 16, "margin": { "right": 6 @@ -1018,7 +1023,7 @@ "padding": { "left": 8 }, - "background": "#000000", + "background": "#ffffff", "corner_radius": 6 }, "unshared_project": { @@ -1030,7 +1035,7 @@ }, "name": { "family": "Zed Mono", - "color": "#595959", + "color": "#393939", "size": 16, "margin": { "right": 6 @@ -1049,7 +1054,7 @@ }, "name": { "family": "Zed Mono", - "color": "#595959", + "color": "#393939", "size": 16, "margin": { "right": 6 @@ -1058,22 +1063,22 @@ "padding": { "left": 8 }, - "background": "#000000", + "background": "#ffffff", "corner_radius": 6 } }, "search": { - "match_background": "#000000", + "match_background": "#ffffff", "tab_icon_spacing": 4, "tab_icon_width": 14, "active_hovered_option_button": { "family": "Zed Mono", - "color": "#595959", + "color": "#393939", "size": 16, - "background": "#bfbfbf", + "background": "#e3e3e3", "corner_radius": 6, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "margin": { @@ -1089,12 +1094,12 @@ }, "active_option_button": { "family": "Zed Mono", - "color": "#595959", + "color": "#393939", "size": 16, - "background": "#bfbfbf", + "background": "#e3e3e3", "corner_radius": 6, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "margin": { @@ -1109,26 +1114,26 @@ } }, "editor": { - "background": "#e6e6e6", + "background": "#ffffff", "corner_radius": 6, "min_width": 200, "max_width": 500, "placeholder_text": { "family": "Zed Mono", - "color": "#bfbfbf", + "color": "#717171", "size": 16 }, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", - "color": "#262626", + "color": "#1c1c1c", "size": 16 }, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "margin": { @@ -1143,12 +1148,12 @@ }, "hovered_option_button": { "family": "Zed Mono", - "color": "#595959", + "color": "#393939", "size": 16, - "background": "#bfbfbf", + "background": "#e3e3e3", "corner_radius": 6, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "margin": { @@ -1163,26 +1168,26 @@ } }, "invalid_editor": { - "background": "#e6e6e6", + "background": "#ffffff", "corner_radius": 6, "min_width": 200, "max_width": 500, "placeholder_text": { "family": "Zed Mono", - "color": "#bfbfbf", + "color": "#717171", "size": 16 }, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", - "color": "#262626", + "color": "#1c1c1c", "size": 16 }, "border": { - "color": "#ffffff", + "color": "#fbbdbd", "width": 1 }, "margin": { @@ -1197,18 +1202,18 @@ }, "match_index": { "family": "Zed Mono", - "color": "#8c8c8c", + "color": "#555555", "size": 16, "padding": 6 }, "option_button": { "family": "Zed Mono", - "color": "#595959", + "color": "#393939", "size": 16, - "background": "#cccccc", + "background": "#f1f1f1", "corner_radius": 6, "border": { - "color": "#d9d9d9", + "color": "#c6c6c6", "width": 1 }, "margin": { @@ -1230,13 +1235,13 @@ }, "results_status": { "family": "Zed Mono", - "color": "#262626", + "color": "#1c1c1c", "size": 18 } }, "breadcrumbs": { "family": "Zed Sans", - "color": "#262626", + "color": "#1c1c1c", "size": 14, "padding": { "left": 6 diff --git a/styles/buildThemes.ts b/styles/buildThemes.ts index d67860cee6..9128eff45d 100644 --- a/styles/buildThemes.ts +++ b/styles/buildThemes.ts @@ -1,8 +1,8 @@ import * as fs from "fs"; import * as path from "path"; +import app from "./styleTree/app"; import dark from "./themes/dark"; import light from "./themes/light"; -import app from "./styleTree/app"; import decamelizeTree from "./utils/decamelizeTree"; const themes = [dark, light]; diff --git a/styles/styleTree/chatPanel.ts b/styles/styleTree/chatPanel.ts index ea9a8ffe22..69b5f3baa0 100644 --- a/styles/styleTree/chatPanel.ts +++ b/styles/styleTree/chatPanel.ts @@ -31,7 +31,7 @@ export default function chatPanel(theme: Theme) { const message = { body: text(theme, "sans", "secondary"), - timestamp: text(theme, "sans", "muted"), + timestamp: text(theme, "sans", "muted", { size: "sm" }), padding: { bottom: 6, }, @@ -91,12 +91,12 @@ export default function chatPanel(theme: Theme) { }, }, inputEditor: { - background: backgroundColor(theme, 300), + background: backgroundColor(theme, 500), cornerRadius: 6, text: text(theme, "mono", "primary"), - placeholderText: text(theme, "mono", "muted"), + placeholderText: text(theme, "mono", "placeholder", { size: "sm" }), selection: player(theme, 1).selection, - border: border(theme, "primary"), + border: border(theme, "secondary"), padding: { bottom: 7, left: 8, diff --git a/styles/styleTree/editor.ts b/styles/styleTree/editor.ts index ebc53b4058..eb379ce520 100644 --- a/styles/styleTree/editor.ts +++ b/styles/styleTree/editor.ts @@ -5,7 +5,7 @@ import { iconColor, player, text, - TextColor, + TextColor } from "./components"; export default function editor(theme: Theme) { @@ -39,7 +39,7 @@ export default function editor(theme: Theme) { return { textColor: theme.textColor.secondary.value, - background: backgroundColor(theme, 300), + background: backgroundColor(theme, 500), activeLineBackground: theme.editor.line.active.value, codeActionsIndicator: iconColor(theme, "secondary"), diffBackgroundDeleted: backgroundColor(theme, "error"), @@ -47,7 +47,7 @@ export default function editor(theme: Theme) { documentHighlightReadBackground: theme.editor.highlight.occurrence.value, documentHighlightWriteBackground: theme.editor.highlight.occurrence.value, errorColor: theme.textColor.error.value, - gutterBackground: backgroundColor(theme, 300), + gutterBackground: backgroundColor(theme, 500), gutterPaddingFactor: 2.5, highlightedLineBackground: theme.editor.line.highlighted.value, lineNumber: theme.editor.gutter.primary.value, @@ -65,14 +65,14 @@ export default function editor(theme: Theme) { player(theme, 8).selection, ], autocomplete: { - background: backgroundColor(theme, 100), + background: backgroundColor(theme, 500), cornerRadius: 6, padding: 6, border: border(theme, "secondary"), item: autocompleteItem, hoveredItem: { ...autocompleteItem, - background: backgroundColor(theme, 100, "hovered"), + background: backgroundColor(theme, 500, "hovered"), }, margin: { left: -14, @@ -83,11 +83,11 @@ export default function editor(theme: Theme) { }, selectedItem: { ...autocompleteItem, - background: backgroundColor(theme, 100, "active"), + background: backgroundColor(theme, 500, "active"), }, }, diagnosticHeader: { - background: theme.editor.background.value, + background: backgroundColor(theme, 300), iconWidthFactor: 1.5, textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these. border: border(theme, "secondary", { diff --git a/styles/styleTree/projectPanel.ts b/styles/styleTree/projectPanel.ts index cd6fb49b3a..e27cd94414 100644 --- a/styles/styleTree/projectPanel.ts +++ b/styles/styleTree/projectPanel.ts @@ -1,7 +1,7 @@ -import { panel } from "./app"; -import { backgroundColor, iconColor, text, TextColor } from "./components"; import Theme from "../themes/theme"; import { Color } from "../utils/color"; +import { panel } from "./app"; +import { backgroundColor, iconColor, text, TextColor } from "./components"; export default function projectPanel(theme: Theme) { function entry(theme: Theme, textColor: TextColor, background?: Color) { @@ -11,7 +11,7 @@ export default function projectPanel(theme: Theme) { iconColor: iconColor(theme, "muted"), iconSize: 8, iconSpacing: 8, - text: text(theme, "mono", textColor), + text: text(theme, "mono", textColor, { size: "sm" }), }; } @@ -31,6 +31,7 @@ export default function projectPanel(theme: Theme) { ), padding: { top: 6, + left: 12, }, }; } diff --git a/styles/styleTree/workspace.ts b/styles/styleTree/workspace.ts index 7e71eaad2a..a734528d74 100644 --- a/styles/styleTree/workspace.ts +++ b/styles/styleTree/workspace.ts @@ -12,14 +12,15 @@ export default function workspace(theme: Theme) { }; const tab = { - height: 34, + height: 32, + background: backgroundColor(theme, 300), iconClose: iconColor(theme, "secondary"), iconCloseActive: iconColor(theme, "active"), iconConflict: iconColor(theme, "warning"), iconDirty: iconColor(theme, "info"), iconWidth: 8, spacing: 10, - text: text(theme, "mono", "secondary"), + text: text(theme, "mono", "secondary", { size: "sm" }), border: border(theme, "primary", { left: true, bottom: true, @@ -33,8 +34,8 @@ export default function workspace(theme: Theme) { const activeTab = { ...tab, - background: backgroundColor(theme, 300), - text: text(theme, "mono", "primary"), + background: backgroundColor(theme, 500), + text: text(theme, "mono", "active", { size: "sm" }), border: { ...tab.border, bottom: false, @@ -48,11 +49,12 @@ export default function workspace(theme: Theme) { }; const sidebar = { width: 30, + background: backgroundColor(theme, 300), border: border(theme, "primary", { right: true }), item: sidebarItem, activeItem: { ...sidebarItem, - iconColor: iconColor(theme, "primary"), + iconColor: iconColor(theme, "active"), }, resizeHandle: { background: border(theme, "primary").color, @@ -63,7 +65,7 @@ export default function workspace(theme: Theme) { }; return { - background: backgroundColor(theme, 500), + background: backgroundColor(theme, 300), leaderBorderOpacity: 0.7, leaderBorderWidth: 2.0, tab, @@ -94,6 +96,7 @@ export default function workspace(theme: Theme) { titlebar: { avatarWidth: 18, height: 32, + background: backgroundColor(theme, 100), shareIconColor: iconColor(theme, "secondary"), shareIconActiveColor: iconColor(theme, "active"), title: text(theme, "sans", "primary"), @@ -107,29 +110,32 @@ export default function workspace(theme: Theme) { avatarRibbon: { height: 3, width: 12, + // TODO: The background for this ideally should be + // set with a token, not hardcoded in rust }, border: border(theme, "primary", { bottom: true }), signInPrompt, hoveredSignInPrompt: { ...signInPrompt, ...text(theme, "mono", "active"), + size: 13, }, offlineIcon: { - color: iconColor(theme, "muted"), + color: iconColor(theme, "secondary"), width: 16, padding: { right: 4, }, }, outdatedWarning: { - ...text(theme, "sans", "muted"), + ...text(theme, "sans", "warning"), size: 13, }, }, toolbar: { height: 34, - background: backgroundColor(theme, 300), - border: border(theme, "primary", { bottom: true }), + background: backgroundColor(theme, 500), + border: border(theme, "muted", { bottom: true }), itemSpacing: 8, padding: { left: 16, right: 8, top: 4, bottom: 4 }, }, @@ -138,8 +144,7 @@ export default function workspace(theme: Theme) { padding: { left: 6 }, }, disconnectedOverlay: { - ...text(theme, "sans", "primary"), - color: "#ffffff", + ...text(theme, "sans", "active"), background: "#000000aa", }, }; diff --git a/styles/themes/dark.ts b/styles/themes/dark.ts index 2cadf24601..f8e0c0fcb6 100644 --- a/styles/themes/dark.ts +++ b/styles/themes/dark.ts @@ -3,10 +3,10 @@ import Theme, { Syntax } from "./theme"; const backgroundColor = { 100: { - base: colors.neutral[750], - hovered: colors.neutral[750], - active: colors.neutral[750], - focused: colors.neutral[750], + base: colors.neutral[700], + hovered: colors.neutral[700], + active: colors.neutral[700], + focused: colors.neutral[700], }, 300: { base: colors.neutral[800], @@ -52,10 +52,10 @@ const borderColor = { muted: colors.neutral[750], focused: colors.neutral[100], active: colors.neutral[500], - ok: colors.neutral[1000], - error: colors.neutral[1000], - warning: colors.neutral[1000], - info: colors.neutral[1000], + ok: colors.green[500], + error: colors.red[500], + warning: colors.amber[500], + info: colors.blue[500], }; const textColor = { @@ -65,7 +65,7 @@ const textColor = { placeholder: colors.neutral[750], active: colors.neutral[0], //TODO: (design) define feature and it's correct value - feature: colors.sky[500], + feature: colors.lime[400], ok: colors.green[600], error: colors.red[400], warning: colors.amber[300], @@ -81,9 +81,9 @@ const iconColor = { //TODO: (design) define feature and it's correct value feature: colors.sky[500], ok: colors.green[600], - error: colors.red[400], - warning: colors.amber[300], - info: colors.blue[500], + error: colors.red[500], + warning: colors.amber[400], + info: colors.blue[600], }; const player = { diff --git a/styles/themes/light.ts b/styles/themes/light.ts index acb704de74..c543c78a30 100644 --- a/styles/themes/light.ts +++ b/styles/themes/light.ts @@ -5,73 +5,72 @@ import Theme, { Syntax } from "./theme"; const backgroundColor = { 100: { - base: colors.neutral[750], - hovered: colors.neutral[750], - active: colors.neutral[750], - focused: colors.neutral[750], + base: colors.neutral[100], + hovered: colors.neutral[150], + active: colors.neutral[200], + focused: colors.neutral[150], }, 300: { - base: colors.neutral[800], - hovered: colors.neutral[800], - active: colors.neutral[800], - focused: colors.neutral[800], + base: colors.neutral[50], + hovered: colors.neutral[100], + active: colors.neutral[150], + focused: colors.neutral[100], }, 500: { - base: colors.neutral[900], - hovered: colors.neutral[900], - active: colors.neutral[900], - focused: colors.neutral[900], + base: colors.neutral[0], + hovered: colors.neutral[50], + active: colors.neutral[100], + focused: colors.neutral[50], }, ok: { - base: colors.green[600], - hovered: colors.green[600], - active: colors.green[600], - focused: colors.green[600], + base: colors.green[100], + hovered: colors.green[100], + active: colors.green[100], + focused: colors.green[100], }, error: { - base: colors.red[400], - hovered: colors.red[400], - active: colors.red[400], - focused: colors.red[400], + base: colors.red[100], + hovered: colors.red[100], + active: colors.red[100], + focused: colors.red[100], }, warning: { - base: colors.amber[300], - hovered: colors.amber[300], - active: colors.amber[300], - focused: colors.amber[300], + base: colors.yellow[100], + hovered: colors.yellow[100], + active: colors.yellow[100], + focused: colors.yellow[100], }, info: { - base: colors.blue[500], - hovered: colors.blue[500], - active: colors.blue[500], - focused: colors.blue[500], + base: colors.blue[100], + hovered: colors.blue[100], + active: colors.blue[100], + focused: colors.blue[100], }, }; const borderColor = { - primary: colors.neutral[850], - secondary: colors.neutral[700], - muted: colors.neutral[750], + primary: colors.neutral[200], + secondary: colors.neutral[100], + muted: colors.neutral[50], focused: colors.neutral[100], - active: colors.neutral[500], - ok: colors.neutral[1000], - error: colors.neutral[1000], - warning: colors.neutral[1000], - info: colors.neutral[1000], + active: colors.neutral[250], + ok: colors.green[200], + error: colors.red[200], + warning: colors.yellow[200], + info: colors.blue[200], }; const textColor = { - primary: colors.neutral[150], - secondary: colors.neutral[350], - muted: colors.neutral[550], - placeholder: colors.neutral[750], - active: colors.neutral[0], - //TODO: (design) define feature and it's correct value - feature: colors.sky[500], - ok: colors.green[600], - error: colors.red[400], - warning: colors.amber[300], - info: colors.blue[500], + primary: colors.neutral[800], + secondary: colors.neutral[700], + muted: colors.neutral[600], + placeholder: colors.neutral[500], + active: colors.neutral[900], + feature: colors.blue[600], + ok: colors.green[800], + error: colors.red[800], + warning: colors.yellow[800], + info: colors.blue[800], }; const iconColor = { @@ -79,63 +78,62 @@ const iconColor = { secondary: colors.neutral[500], muted: colors.neutral[600], placeholder: colors.neutral[700], - active: colors.neutral[50], - //TODO: (design) define feature and it's correct value - feature: colors.sky[500], + active: colors.neutral[900], + feature: colors.sky[600], ok: colors.green[600], - error: colors.red[400], - warning: colors.amber[300], - info: colors.blue[500], + error: colors.red[600], + warning: colors.yellow[400], + info: colors.blue[600], }; const player = { 1: { - baseColor: colors.blue[600], - cursorColor: colors.blue[600], - selectionColor: colors.blue[600], - borderColor: colors.blue[600], + baseColor: colors.blue[600], + cursorColor: colors.blue[500], + selectionColor: colors.blue[100], + borderColor: colors.blue[500], }, 2: { - baseColor: colors.indigo[500], - cursorColor: colors.indigo[500], - selectionColor: colors.indigo[500], - borderColor: colors.indigo[500], + baseColor: colors.indigo[500], + cursorColor: colors.indigo[500], + selectionColor: colors.indigo[100], + borderColor: colors.indigo[500], }, 3: { - baseColor: colors.green[500], - cursorColor: colors.green[500], - selectionColor: colors.green[500], - borderColor: colors.green[500], + baseColor: colors.green[500], + cursorColor: colors.green[500], + selectionColor: colors.green[100], + borderColor: colors.green[500], }, 4: { - baseColor: colors.orange[500], - cursorColor: colors.orange[500], - selectionColor: colors.orange[500], - borderColor: colors.orange[500], + baseColor: colors.orange[500], + cursorColor: colors.orange[500], + selectionColor: colors.orange[100], + borderColor: colors.orange[500], }, 5: { - baseColor: colors.purple[500], - cursorColor: colors.purple[500], - selectionColor: colors.purple[500], - borderColor: colors.purple[500], + baseColor: colors.purple[500], + cursorColor: colors.purple[500], + selectionColor: colors.purple[100], + borderColor: colors.purple[500], }, 6: { - baseColor: colors.teal[400], - cursorColor: colors.teal[400], - selectionColor: colors.teal[400], - borderColor: colors.teal[400], + baseColor: colors.teal[400], + cursorColor: colors.teal[400], + selectionColor: colors.teal[100], + borderColor: colors.teal[400], }, 7: { - baseColor: colors.pink[400], - cursorColor: colors.pink[400], - selectionColor: colors.pink[400], - borderColor: colors.pink[400], + baseColor: colors.pink[400], + cursorColor: colors.pink[400], + selectionColor: colors.pink[100], + borderColor: colors.pink[400], }, 8: { - baseColor: colors.yellow[400], - cursorColor: colors.yellow[400], - selectionColor: colors.yellow[400], - borderColor: colors.yellow[400], + baseColor: colors.yellow[400], + cursorColor: colors.yellow[400], + selectionColor: colors.yellow[100], + borderColor: colors.yellow[400], }, }; @@ -145,118 +143,118 @@ const editor = { indent_guide: borderColor.muted, indent_guide_active: borderColor.secondary, line: { - active: colors.neutral[0], - highlighted: colors.neutral[0], - inserted: backgroundColor.ok.active, - deleted: backgroundColor.error.active, - modified: backgroundColor.info.active, + active: colors.neutral[0], + highlighted: colors.neutral[0], + inserted: backgroundColor.ok.active, + deleted: backgroundColor.error.active, + modified: backgroundColor.info.active, }, highlight: { - selection: player[1].selectionColor, - occurrence: backgroundColor[500].active, - activeOccurrence: colors.neutral[0], - matchingBracket: colors.neutral[0], - match: colors.neutral[0], - activeMatch: colors.neutral[0], - related: colors.neutral[0], + selection: player[1].selectionColor, + occurrence: backgroundColor[500].active, + activeOccurrence: colors.neutral[0], + matchingBracket: colors.neutral[0], + match: colors.neutral[0], + activeMatch: colors.neutral[0], + related: colors.neutral[0], }, gutter: { - primary: colors.neutral[0], - active: colors.neutral[0], + primary: colors.neutral[0], + active: colors.neutral[0], }, }; const syntax: Syntax = { primary: { - color: textColor.primary, - weight: fontWeights.normal, + color: textColor.primary, + weight: fontWeights.normal, }, comment: { - color: colors.lime[200], - weight: fontWeights.normal, + color: colors.lime[200], + weight: fontWeights.normal, }, punctuation: { - color: textColor.primary, - weight: fontWeights.normal, + color: textColor.primary, + weight: fontWeights.normal, }, constant: { - color: colors.neutral[150], - weight: fontWeights.normal, + color: colors.neutral[150], + weight: fontWeights.normal, }, keyword: { - color: colors.sky[400], - weight: fontWeights.normal, + color: colors.sky[400], + weight: fontWeights.normal, }, function: { - color: colors.yellow[200], - weight: fontWeights.normal, + color: colors.yellow[200], + weight: fontWeights.normal, }, type: { - color: colors.teal[300], - weight: fontWeights.normal, + color: colors.teal[300], + weight: fontWeights.normal, }, variant: { - color: colors.teal[300], - weight: fontWeights.normal, + color: colors.teal[300], + weight: fontWeights.normal, }, property: { - color: colors.sky[300], - weight: fontWeights.normal, + color: colors.sky[300], + weight: fontWeights.normal, }, enum: { - color: colors.sky[400], - weight: fontWeights.normal, + color: colors.sky[400], + weight: fontWeights.normal, }, operator: { - color: colors.sky[400], - weight: fontWeights.normal, + color: colors.sky[400], + weight: fontWeights.normal, }, string: { - color: colors.orange[300], - weight: fontWeights.normal, + color: colors.orange[300], + weight: fontWeights.normal, }, number: { - color: colors.neutral[150], - weight: fontWeights.normal, + color: colors.neutral[150], + weight: fontWeights.normal, }, boolean: { - color: colors.neutral[150], - weight: fontWeights.normal, + color: colors.neutral[150], + weight: fontWeights.normal, }, predictive: { - color: textColor.muted, - weight: fontWeights.normal, + color: textColor.muted, + weight: fontWeights.normal, }, title: { - color: colors.sky[500], - weight: fontWeights.bold, + color: colors.sky[500], + weight: fontWeights.bold, }, emphasis: { - color: textColor.active, - weight: fontWeights.normal, + color: textColor.active, + weight: fontWeights.normal, }, emphasisStrong: { - color: textColor.active, - weight: fontWeights.bold, + color: textColor.active, + weight: fontWeights.bold, }, linkUrl: { - color: colors.lime[500], - weight: fontWeights.normal, - // TODO: add underline + color: colors.lime[500], + weight: fontWeights.normal, + // TODO: add underline }, linkText: { - color: colors.orange[500], - weight: fontWeights.normal, - // TODO: add italic + color: colors.orange[500], + weight: fontWeights.normal, + // TODO: add italic }, listMarker: { - color: colors.sky[400], - weight: fontWeights.normal, - } + color: colors.sky[400], + weight: fontWeights.normal, + }, }; const shadowAlpha: NumberToken = { - value: 0.32, + value: 0.12, type: "number", }; diff --git a/styles/themes/theme.ts b/styles/themes/theme.ts index f95d58e494..7f8305c1d5 100644 --- a/styles/themes/theme.ts +++ b/styles/themes/theme.ts @@ -1,4 +1,4 @@ -import { FontWeightToken, ColorToken, NumberToken } from "../tokens"; +import { ColorToken, FontWeightToken, NumberToken } from "../tokens"; export interface SyntaxHighlightStyle { color: ColorToken; diff --git a/styles/tokens.ts b/styles/tokens.ts index 1e0df5032d..63c19a9d64 100644 --- a/styles/tokens.ts +++ b/styles/tokens.ts @@ -72,7 +72,7 @@ export interface ColorToken { step?: number, } export const colors = { - neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }), + neutral: colorRamp(["white", "black"], { steps: 19, increment: 50 }), rose: colorRamp("#F43F5EFF"), red: colorRamp("#EF4444FF"), orange: colorRamp("#F97316FF"), From bfde9dca4e0dc1b50f2eb0927efcc6b7985e9dc3 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 1 Apr 2022 23:59:20 -0400 Subject: [PATCH 61/68] Add greg to .zed.toml --- .zed.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zed.toml b/.zed.toml index 0cbe5c59a5..fae32125f4 100644 --- a/.zed.toml +++ b/.zed.toml @@ -1 +1 @@ -collaborators = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler", "Kethku"] +collaborators = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler", "gibusu", "Kethku"] From c374fd2f548471b587f33ff9d04e21a373cdd1fd Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sat, 2 Apr 2022 01:05:28 -0400 Subject: [PATCH 62/68] WIP --- crates/zed/assets/themes/dark.json | 157 +++++++++--------- crates/zed/assets/themes/light.json | 245 ++++++++++++++-------------- styles/styleTree/app.ts | 3 +- styles/styleTree/editor.ts | 3 +- styles/themes/dark.ts | 56 +++---- styles/themes/light.ts | 38 ++--- styles/utils/color.ts | 4 +- 7 files changed, 252 insertions(+), 254 deletions(-) diff --git a/crates/zed/assets/themes/dark.json b/crates/zed/assets/themes/dark.json index fd11fc6c3a..0abf380cc1 100644 --- a/crates/zed/assets/themes/dark.json +++ b/crates/zed/assets/themes/dark.json @@ -18,7 +18,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#90df17", + "color": "#72ad19", "weight": "bold", "size": 14 } @@ -33,16 +33,16 @@ "corner_radius": 6, "text": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#90df17", + "color": "#72ad19", "weight": "bold", "size": 14 }, - "background": "#000000" + "background": "#1c1c1c" }, "border": { "color": "#0e0e0e", @@ -70,12 +70,12 @@ "size": 14 }, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#195cc8", + "selection": "#307af3" }, "text": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 16 }, "border": { @@ -111,8 +111,8 @@ "background": "#1c1c1c", "icon_close": "#717171", "icon_close_active": "#f1f1f1", - "icon_conflict": "#f7b241", - "icon_dirty": "#4287f6", + "icon_conflict": "#c38214", + "icon_dirty": "#195cc8", "icon_width": 8, "spacing": 10, "text": { @@ -137,8 +137,8 @@ "background": "#000000", "icon_close": "#717171", "icon_close_active": "#f1f1f1", - "icon_conflict": "#f7b241", - "icon_dirty": "#4287f6", + "icon_conflict": "#c38214", + "icon_dirty": "#195cc8", "icon_width": 8, "spacing": 10, "text": { @@ -243,7 +243,7 @@ "share_icon_active_color": "#f1f1f1", "title": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 }, "avatar": { @@ -289,7 +289,7 @@ }, "outdated_warning": { "family": "Zed Sans", - "color": "#f8c570", + "color": "#cc8712", "size": 13 } }, @@ -325,54 +325,54 @@ } }, "editor": { - "text_color": "#9c9c9c", + "text_color": "#e3e3e3", "background": "#000000", - "active_line_background": "#ffffff", + "active_line_background": "#1c1c1c", "code_actions_indicator": "#717171", - "diff_background_deleted": "#f78c8c", - "diff_background_inserted": "#22c55e", - "document_highlight_read_background": "#000000", - "document_highlight_write_background": "#000000", - "error_color": "#f78c8c", + "diff_background_deleted": "#d71c1c", + "diff_background_inserted": "#1ea34f", + "document_highlight_read_background": "#1e22db", + "document_highlight_write_background": "#1e22db", + "error_color": "#d71c1c", "gutter_background": "#000000", "gutter_padding_factor": 2.5, - "highlighted_line_background": "#ffffff", - "line_number": "#ffffff", + "highlighted_line_background": "#0e0e0e", + "line_number": "#636363", "line_number_active": "#ffffff", "rename_fade": 0.6, "unnecessary_code_fade": 0.5, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#195cc8", + "selection": "#307af3" }, "guest_selections": [ { - "cursor": "#777af4", - "selection": "#777af4" + "cursor": "#70a919", + "selection": "#80c517" }, { - "cursor": "#23d464", - "selection": "#23d464" + "cursor": "#1e22db", + "selection": "#5558ee" }, { - "cursor": "#f98a3d", - "selection": "#f98a3d" + "cursor": "#c45c14", + "selection": "#f66e0f" }, { - "cursor": "#b671f8", - "selection": "#b671f8" + "cursor": "#7d19dc", + "selection": "#a048f4" }, { - "cursor": "#16ddc7", - "selection": "#16ddc7" + "cursor": "#17a293", + "selection": "#15b3a2" }, { - "cursor": "#f58ac0", - "selection": "#f58ac0" + "cursor": "#d51e79", + "selection": "#e93d92" }, { - "cursor": "#f6bc09", - "selection": "#f6bc09" + "cursor": "#bc9212", + "selection": "#e0ac0b" } ], "autocomplete": { @@ -400,13 +400,13 @@ "right": 6, "top": 2 }, - "background": "#000000" + "background": "#0e0e0e" }, "margin": { "left": -14 }, "match_highlight": { - "color": "#59c3f5", + "color": "#1588bc", "weight": "normal" }, "selected_item": { @@ -417,7 +417,7 @@ "right": 6, "top": 2 }, - "background": "#000000" + "background": "#1c1c1c" } }, "diagnostic_header": { @@ -441,7 +441,7 @@ "message": { "highlight_text": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14, "weight": "bold" }, @@ -453,11 +453,11 @@ } }, "diagnostic_path_header": { - "background": "#ffffff", + "background": "#1c1c1c", "text_scale_factor": 0.857, "filename": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 }, "path": { @@ -481,12 +481,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#f78c8c", + "color": "#d71c1c", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#f78c8c", + "color": "#d71c1c", "size": 14, "weight": "bold" } @@ -504,12 +504,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#f8c570", + "color": "#cc8712", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#f8c570", + "color": "#cc8712", "size": 14, "weight": "bold" } @@ -527,12 +527,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#185fd0", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#185fd0", "size": 14, "weight": "bold" } @@ -550,12 +550,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#185fd0", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#185fd0", "size": 14, "weight": "bold" } @@ -656,13 +656,12 @@ "syntax": {} }, "project_diagnostics": { - "background": "#1c1c1c", "tab_icon_spacing": 4, "tab_icon_width": 13, "tab_summary_spacing": 10, "empty_message": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 }, "status_bar_item": { @@ -709,7 +708,7 @@ "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 } }, @@ -721,7 +720,7 @@ "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 } } @@ -735,7 +734,7 @@ }, "channel_name": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "weight": "bold", "size": 14 }, @@ -751,7 +750,7 @@ "header": { "name": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 }, "padding": { @@ -806,7 +805,7 @@ "active_item": { "name": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 }, "padding": 4, @@ -823,7 +822,7 @@ "hovered_active_item": { "name": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14 }, "padding": 4, @@ -864,7 +863,7 @@ }, "hovered_sign_in_prompt": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "underline": true, "size": 14 }, @@ -884,7 +883,7 @@ }, "sender": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "weight": "bold", "size": 14, "margin": { @@ -921,7 +920,7 @@ "corner_radius": 6, "text": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 16 }, "placeholder_text": { @@ -930,8 +929,8 @@ "size": 14 }, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#195cc8", + "selection": "#307af3" }, "border": { "color": "#393939", @@ -995,7 +994,7 @@ }, "name": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 16, "margin": { "right": 6 @@ -1014,7 +1013,7 @@ }, "name": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 16, "margin": { "right": 6 @@ -1023,7 +1022,7 @@ "padding": { "left": 8 }, - "background": "#ffffff", + "background": "#1c1c1c", "corner_radius": 6 }, "unshared_project": { @@ -1063,12 +1062,12 @@ "padding": { "left": 8 }, - "background": "#ffffff", + "background": "#1c1c1c", "corner_radius": 6 } }, "search": { - "match_background": "#ffffff", + "match_background": "#70a919", "tab_icon_spacing": 4, "tab_icon_width": 14, "active_hovered_option_button": { @@ -1124,12 +1123,12 @@ "size": 16 }, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#195cc8", + "selection": "#307af3" }, "text": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 16 }, "border": { @@ -1178,16 +1177,16 @@ "size": 16 }, "selection": { - "cursor": "#4287f6", - "selection": "#4287f6" + "cursor": "#195cc8", + "selection": "#307af3" }, "text": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 16 }, "border": { - "color": "#f47171", + "color": "#cd1c1c", "width": 1 }, "margin": { @@ -1235,13 +1234,13 @@ }, "results_status": { "family": "Zed Mono", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 18 } }, "breadcrumbs": { "family": "Zed Sans", - "color": "#d5d5d5", + "color": "#e3e3e3", "size": 14, "padding": { "left": 6 diff --git a/crates/zed/assets/themes/light.json b/crates/zed/assets/themes/light.json index 219f958e87..1024764540 100644 --- a/crates/zed/assets/themes/light.json +++ b/crates/zed/assets/themes/light.json @@ -13,12 +13,12 @@ "corner_radius": 6, "text": { "family": "Zed Sans", - "color": "#393939", + "color": "#555555", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#4287f6", + "color": "#185fd0", "weight": "bold", "size": 14 } @@ -33,12 +33,12 @@ "corner_radius": 6, "text": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#4287f6", + "color": "#185fd0", "weight": "bold", "size": 14 }, @@ -51,7 +51,7 @@ "empty": { "text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "padding": { @@ -66,16 +66,16 @@ "corner_radius": 6, "placeholder_text": { "family": "Zed Sans", - "color": "#717171", + "color": "#aaaaaa", "size": 14 }, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#185fd0", + "selection": "#307af3" }, "text": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 16 }, "border": { @@ -111,13 +111,13 @@ "background": "#f1f1f1", "icon_close": "#717171", "icon_close_active": "#000000", - "icon_conflict": "#f6bc09", - "icon_dirty": "#4287f6", + "icon_conflict": "#bc9212", + "icon_dirty": "#195cc8", "icon_width": 8, "spacing": 10, "text": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 14 }, "border": { @@ -137,8 +137,8 @@ "background": "#ffffff", "icon_close": "#717171", "icon_close_active": "#000000", - "icon_conflict": "#f6bc09", - "icon_dirty": "#4287f6", + "icon_conflict": "#bc9212", + "icon_dirty": "#195cc8", "icon_width": 8, "spacing": 10, "text": { @@ -221,17 +221,17 @@ }, "cursor_position": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "diagnostic_message": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "lsp_message": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 } }, @@ -243,7 +243,7 @@ "share_icon_active_color": "#000000", "title": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 }, "avatar": { @@ -264,7 +264,7 @@ }, "sign_in_prompt": { "family": "Zed Sans", - "color": "#393939", + "color": "#555555", "size": 13, "underline": true, "padding": { @@ -289,7 +289,7 @@ }, "outdated_warning": { "family": "Zed Sans", - "color": "#b48d14", + "color": "#b68e14", "size": 13 } }, @@ -311,7 +311,7 @@ }, "breadcrumbs": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 16, "padding": { "left": 6 @@ -325,54 +325,54 @@ } }, "editor": { - "text_color": "#393939", + "text_color": "#2b2b2b", "background": "#ffffff", - "active_line_background": "#ffffff", + "active_line_background": "#e3e3e3", "code_actions_indicator": "#717171", - "diff_background_deleted": "#fdd4d4", - "diff_background_inserted": "#befad2", + "diff_background_deleted": "#ec3939", + "diff_background_inserted": "#21bf5b", "document_highlight_read_background": "#e3e3e3", "document_highlight_write_background": "#e3e3e3", - "error_color": "#d11c1c", + "error_color": "#cd1c1c", "gutter_background": "#ffffff", "gutter_padding_factor": 2.5, - "highlighted_line_background": "#ffffff", - "line_number": "#ffffff", - "line_number_active": "#ffffff", + "highlighted_line_background": "#e3e3e3", + "line_number": "#808080", + "line_number_active": "#000000", "rename_fade": 0.6, "unnecessary_code_fade": 0.5, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#185fd0", + "selection": "#307af3" }, "guest_selections": [ { - "cursor": "#777af4", - "selection": "#d4d5fd" + "cursor": "#70a919", + "selection": "#80c517" }, { - "cursor": "#23d464", - "selection": "#befad2" + "cursor": "#1e22db", + "selection": "#5558ee" }, { - "cursor": "#f98a3d", - "selection": "#fde0cd" + "cursor": "#c45c14", + "selection": "#f66e0f" }, { - "cursor": "#b671f8", - "selection": "#e9d4fd" + "cursor": "#7d19dc", + "selection": "#a048f4" }, { - "cursor": "#16ddc7", - "selection": "#b4faf2" + "cursor": "#17a293", + "selection": "#15b3a2" }, { - "cursor": "#f58ac0", - "selection": "#fcd4e8" + "cursor": "#d51e79", + "selection": "#e93d92" }, { - "cursor": "#f6bc09", - "selection": "#fceabc" + "cursor": "#bc9212", + "selection": "#e0ac0b" } ], "autocomplete": { @@ -406,7 +406,7 @@ "left": -14 }, "match_highlight": { - "color": "#59c3f5", + "color": "#1588bc", "weight": "normal" }, "selected_item": { @@ -432,7 +432,7 @@ }, "code": { "family": "Zed Mono", - "color": "#555555", + "color": "#808080", "size": 14, "margin": { "left": 10 @@ -441,28 +441,28 @@ "message": { "highlight_text": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14, "weight": "bold" }, "text": { "family": "Zed Sans", - "color": "#393939", + "color": "#555555", "size": 14 } } }, "diagnostic_path_header": { - "background": "#ffffff", + "background": "#e3e3e3", "text_scale_factor": 0.857, "filename": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 }, "path": { "family": "Zed Mono", - "color": "#555555", + "color": "#808080", "size": 14, "margin": { "left": 12 @@ -481,12 +481,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#d11c1c", + "color": "#cd1c1c", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#d11c1c", + "color": "#cd1c1c", "size": 14, "weight": "bold" } @@ -504,12 +504,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#b48d14", + "color": "#b68e14", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#b48d14", + "color": "#b68e14", "size": 14, "weight": "bold" } @@ -527,12 +527,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#1762db", + "color": "#185fd0", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#1762db", + "color": "#185fd0", "size": 14, "weight": "bold" } @@ -550,12 +550,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#1762db", + "color": "#185fd0", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#1762db", + "color": "#185fd0", "size": 14, "weight": "bold" } @@ -573,12 +573,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "weight": "bold" } @@ -596,12 +596,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "weight": "bold" } @@ -619,12 +619,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "weight": "bold" } @@ -642,12 +642,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "weight": "bold" } @@ -656,18 +656,17 @@ "syntax": {} }, "project_diagnostics": { - "background": "#f1f1f1", "tab_icon_spacing": 4, "tab_icon_width": 13, "tab_summary_spacing": 10, "empty_message": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 }, "status_bar_item": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "margin": { "right": 10 @@ -686,7 +685,7 @@ "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 14 } }, @@ -698,7 +697,7 @@ "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 14 } }, @@ -709,7 +708,7 @@ "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 } }, @@ -721,7 +720,7 @@ "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 } } @@ -735,13 +734,13 @@ }, "channel_name": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "weight": "bold", "size": 14 }, "channel_name_hash": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "padding": { "right": 8 @@ -751,7 +750,7 @@ "header": { "name": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 }, "padding": { @@ -760,7 +759,7 @@ }, "hash": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "margin": { "right": 8 @@ -771,13 +770,13 @@ "item": { "name": { "family": "Zed Sans", - "color": "#393939", + "color": "#555555", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "margin": { "right": 8 @@ -788,13 +787,13 @@ "hovered_item": { "name": { "family": "Zed Sans", - "color": "#393939", + "color": "#555555", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "margin": { "right": 8 @@ -806,13 +805,13 @@ "active_item": { "name": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "margin": { "right": 8 @@ -823,13 +822,13 @@ "hovered_active_item": { "name": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14 }, "padding": 4, "hash": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14, "margin": { "right": 8 @@ -858,25 +857,25 @@ }, "sign_in_prompt": { "family": "Zed Sans", - "color": "#393939", + "color": "#555555", "underline": true, "size": 14 }, "hovered_sign_in_prompt": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "underline": true, "size": 14 }, "message": { "body": { "family": "Zed Sans", - "color": "#393939", + "color": "#555555", "size": 14 }, "timestamp": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "padding": { @@ -884,7 +883,7 @@ }, "sender": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "weight": "bold", "size": 14, "margin": { @@ -895,12 +894,12 @@ "pending_message": { "body": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "timestamp": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "size": 14 }, "padding": { @@ -908,7 +907,7 @@ }, "sender": { "family": "Zed Sans", - "color": "#555555", + "color": "#808080", "weight": "bold", "size": 14, "margin": { @@ -921,17 +920,17 @@ "corner_radius": 6, "text": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 16 }, "placeholder_text": { "family": "Zed Mono", - "color": "#717171", + "color": "#aaaaaa", "size": 14 }, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#185fd0", + "selection": "#307af3" }, "border": { "color": "#e3e3e3", @@ -961,7 +960,7 @@ }, "host_username": { "family": "Zed Mono", - "color": "#555555", + "color": "#808080", "size": 16, "padding": { "left": 8 @@ -976,7 +975,7 @@ }, "name": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 16, "margin": { "right": 6 @@ -995,7 +994,7 @@ }, "name": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 16, "margin": { "right": 6 @@ -1014,7 +1013,7 @@ }, "name": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 16, "margin": { "right": 6 @@ -1023,7 +1022,7 @@ "padding": { "left": 8 }, - "background": "#ffffff", + "background": "#e3e3e3", "corner_radius": 6 }, "unshared_project": { @@ -1035,7 +1034,7 @@ }, "name": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 16, "margin": { "right": 6 @@ -1054,7 +1053,7 @@ }, "name": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 16, "margin": { "right": 6 @@ -1063,7 +1062,7 @@ "padding": { "left": 8 }, - "background": "#ffffff", + "background": "#e3e3e3", "corner_radius": 6 } }, @@ -1073,7 +1072,7 @@ "tab_icon_width": 14, "active_hovered_option_button": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 16, "background": "#e3e3e3", "corner_radius": 6, @@ -1094,7 +1093,7 @@ }, "active_option_button": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 16, "background": "#e3e3e3", "corner_radius": 6, @@ -1120,16 +1119,16 @@ "max_width": 500, "placeholder_text": { "family": "Zed Mono", - "color": "#717171", + "color": "#aaaaaa", "size": 16 }, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#185fd0", + "selection": "#307af3" }, "text": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 16 }, "border": { @@ -1148,7 +1147,7 @@ }, "hovered_option_button": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 16, "background": "#e3e3e3", "corner_radius": 6, @@ -1174,20 +1173,20 @@ "max_width": 500, "placeholder_text": { "family": "Zed Mono", - "color": "#717171", + "color": "#aaaaaa", "size": 16 }, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#185fd0", + "selection": "#307af3" }, "text": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 16 }, "border": { - "color": "#fbbdbd", + "color": "#e72727", "width": 1 }, "margin": { @@ -1202,13 +1201,13 @@ }, "match_index": { "family": "Zed Mono", - "color": "#555555", + "color": "#808080", "size": 16, "padding": 6 }, "option_button": { "family": "Zed Mono", - "color": "#393939", + "color": "#555555", "size": 16, "background": "#f1f1f1", "corner_radius": 6, @@ -1235,13 +1234,13 @@ }, "results_status": { "family": "Zed Mono", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 18 } }, "breadcrumbs": { "family": "Zed Sans", - "color": "#1c1c1c", + "color": "#2b2b2b", "size": 14, "padding": { "left": 6 diff --git a/styles/styleTree/app.ts b/styles/styleTree/app.ts index d26ada4fc9..10439b5a00 100644 --- a/styles/styleTree/app.ts +++ b/styles/styleTree/app.ts @@ -1,6 +1,6 @@ import Theme from "../themes/theme"; import chatPanel from "./chatPanel"; -import { backgroundColor, borderColor, text } from "./components"; +import { text } from "./components"; import contactsPanel from "./contactsPanel"; import editor from "./editor"; import projectPanel from "./projectPanel"; @@ -18,7 +18,6 @@ export default function app(theme: Theme): Object { workspace: workspace(theme), editor: editor(theme), projectDiagnostics: { - background: backgroundColor(theme, 300), tabIconSpacing: 4, tabIconWidth: 13, tabSummarySpacing: 10, diff --git a/styles/styleTree/editor.ts b/styles/styleTree/editor.ts index eb379ce520..e760ecec6a 100644 --- a/styles/styleTree/editor.ts +++ b/styles/styleTree/editor.ts @@ -38,7 +38,8 @@ export default function editor(theme: Theme) { } return { - textColor: theme.textColor.secondary.value, + // textColor: theme.syntax.primary.color, + textColor: theme.syntax.primary.color.value, background: backgroundColor(theme, 500), activeLineBackground: theme.editor.line.active.value, codeActionsIndicator: iconColor(theme, "secondary"), diff --git a/styles/themes/dark.ts b/styles/themes/dark.ts index f8e0c0fcb6..fa05576cd2 100644 --- a/styles/themes/dark.ts +++ b/styles/themes/dark.ts @@ -16,9 +16,9 @@ const backgroundColor = { }, 500: { base: colors.neutral[900], - hovered: colors.neutral[900], - active: colors.neutral[900], - focused: colors.neutral[900], + hovered: colors.neutral[850], + active: colors.neutral[800], + focused: colors.neutral[850], }, ok: { base: colors.green[600], @@ -59,7 +59,7 @@ const borderColor = { }; const textColor = { - primary: colors.neutral[150], + primary: colors.neutral[100], secondary: colors.neutral[350], muted: colors.neutral[550], placeholder: colors.neutral[750], @@ -90,49 +90,49 @@ const player = { 1: { baseColor: colors.blue[600], cursorColor: colors.blue[600], - selectionColor: colors.blue[600], + selectionColor: colors.blue[100], borderColor: colors.blue[600], }, 2: { - baseColor: colors.indigo[500], - cursorColor: colors.indigo[500], - selectionColor: colors.indigo[500], - borderColor: colors.indigo[500], + baseColor: colors.lime[500], + cursorColor: colors.lime[500], + selectionColor: colors.lime[100], + borderColor: colors.lime[500], }, 3: { - baseColor: colors.green[500], - cursorColor: colors.green[500], - selectionColor: colors.green[500], - borderColor: colors.green[500], + baseColor: colors.indigo[500], + cursorColor: colors.indigo[500], + selectionColor: colors.indigo[100], + borderColor: colors.indigo[500], }, 4: { baseColor: colors.orange[500], cursorColor: colors.orange[500], - selectionColor: colors.orange[500], + selectionColor: colors.orange[100], borderColor: colors.orange[500], }, 5: { baseColor: colors.purple[500], cursorColor: colors.purple[500], - selectionColor: colors.purple[500], + selectionColor: colors.purple[100], borderColor: colors.purple[500], }, 6: { baseColor: colors.teal[400], cursorColor: colors.teal[400], - selectionColor: colors.teal[400], + selectionColor: colors.teal[100], borderColor: colors.teal[400], }, 7: { baseColor: colors.pink[400], cursorColor: colors.pink[400], - selectionColor: colors.pink[400], + selectionColor: colors.pink[100], borderColor: colors.pink[400], }, 8: { baseColor: colors.yellow[400], cursorColor: colors.yellow[400], - selectionColor: colors.yellow[400], + selectionColor: colors.yellow[100], borderColor: colors.yellow[400], }, }; @@ -143,24 +143,24 @@ const editor = { indent_guide: borderColor.muted, indent_guide_active: borderColor.secondary, line: { - active: colors.neutral[0], - highlighted: colors.neutral[0], + active: backgroundColor[500].active, + highlighted: backgroundColor[500].hovered, inserted: backgroundColor.ok.active, deleted: backgroundColor.error.active, modified: backgroundColor.info.active, }, highlight: { selection: player[1].selectionColor, - occurrence: backgroundColor[500].active, - activeOccurrence: colors.neutral[0], - matchingBracket: colors.neutral[0], - match: colors.neutral[0], - activeMatch: colors.neutral[0], - related: colors.neutral[0], + occurrence: colors.indigo[500], // TODO: Why does indigo[500], indigo[100], and indigo[900] all give me the same color? @kethku + activeOccurrence: colors.indigo[400], // TODO: We don't seem to be using this right now in rust + matchingBracket: backgroundColor[500].active, + match: colors.lime[500], + activeMatch: colors.lime[400], + related: backgroundColor[500].focused, }, gutter: { - primary: colors.neutral[0], - active: colors.neutral[0], + primary: textColor.muted, + active: textColor.active, }, }; diff --git a/styles/themes/light.ts b/styles/themes/light.ts index c543c78a30..ee94e18b19 100644 --- a/styles/themes/light.ts +++ b/styles/themes/light.ts @@ -61,16 +61,16 @@ const borderColor = { }; const textColor = { - primary: colors.neutral[800], - secondary: colors.neutral[700], - muted: colors.neutral[600], - placeholder: colors.neutral[500], + primary: colors.neutral[750], + secondary: colors.neutral[600], + muted: colors.neutral[450], + placeholder: colors.neutral[300], active: colors.neutral[900], - feature: colors.blue[600], - ok: colors.green[800], - error: colors.red[800], - warning: colors.yellow[800], - info: colors.blue[800], + feature: colors.blue[500], + ok: colors.green[500], + error: colors.red[500], + warning: colors.yellow[500], + info: colors.blue[500], }; const iconColor = { @@ -94,17 +94,17 @@ const player = { borderColor: colors.blue[500], }, 2: { + baseColor: colors.lime[500], + cursorColor: colors.lime[500], + selectionColor: colors.lime[100], + borderColor: colors.lime[500], + }, + 3: { baseColor: colors.indigo[500], cursorColor: colors.indigo[500], selectionColor: colors.indigo[100], borderColor: colors.indigo[500], }, - 3: { - baseColor: colors.green[500], - cursorColor: colors.green[500], - selectionColor: colors.green[100], - borderColor: colors.green[500], - }, 4: { baseColor: colors.orange[500], cursorColor: colors.orange[500], @@ -143,8 +143,8 @@ const editor = { indent_guide: borderColor.muted, indent_guide_active: borderColor.secondary, line: { - active: colors.neutral[0], - highlighted: colors.neutral[0], + active: backgroundColor[500].active, + highlighted: backgroundColor[500].active, inserted: backgroundColor.ok.active, deleted: backgroundColor.error.active, modified: backgroundColor.info.active, @@ -159,8 +159,8 @@ const editor = { related: colors.neutral[0], }, gutter: { - primary: colors.neutral[0], - active: colors.neutral[0], + primary: textColor.muted, + active: textColor.active, }, }; diff --git a/styles/utils/color.ts b/styles/utils/color.ts index b59f4fa694..1042899c73 100644 --- a/styles/utils/color.ts +++ b/styles/utils/color.ts @@ -22,8 +22,8 @@ export function colorRamp( .scale([startColor, color, endColor]) .domain([0, 0.5, 1]) .mode("hsl") - .gamma(1) - .correctLightness(true) + .gamma(0.2) + // .correctLightness(true) .padding([0, 0.15]); } From 631d8d034440c3e59410a1e59cf3bf51e0d12a86 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sun, 3 Apr 2022 01:04:34 -0400 Subject: [PATCH 63/68] Refined dark theme styles --- crates/zed/assets/themes/dark.json | 166 ++++++++++++++-------------- crates/zed/assets/themes/light.json | 14 +-- styles/buildThemes.ts | 3 + styles/styleTree/selectorModal.ts | 8 +- styles/styleTree/workspace.ts | 4 +- styles/themes/dark.ts | 38 +++---- styles/tokens.ts | 2 +- styles/utils/color.ts | 2 +- 8 files changed, 120 insertions(+), 117 deletions(-) diff --git a/crates/zed/assets/themes/dark.json b/crates/zed/assets/themes/dark.json index 0abf380cc1..25568bf17c 100644 --- a/crates/zed/assets/themes/dark.json +++ b/crates/zed/assets/themes/dark.json @@ -1,6 +1,6 @@ { "selector": { - "background": "#000000", + "background": "#1c1c1c", "corner_radius": 6, "padding": 8, "item": { @@ -18,7 +18,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#72ad19", + "color": "#1684b6", "weight": "bold", "size": 14 } @@ -33,19 +33,19 @@ "corner_radius": 6, "text": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#72ad19", + "color": "#1684b6", "weight": "bold", "size": 14 }, - "background": "#1c1c1c" + "background": "#2b2b2b" }, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1 }, "empty": { @@ -62,7 +62,7 @@ } }, "input_editor": { - "background": "#1c1c1c", + "background": "#000000", "corner_radius": 6, "placeholder_text": { "family": "Zed Sans", @@ -75,11 +75,11 @@ }, "text": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 16 }, "border": { - "color": "#0e0e0e", + "color": "#151515", "width": 1 }, "padding": { @@ -109,8 +109,8 @@ "tab": { "height": 32, "background": "#1c1c1c", - "icon_close": "#717171", - "icon_close_active": "#f1f1f1", + "icon_close": "#555555", + "icon_close_active": "#ffffff", "icon_conflict": "#c38214", "icon_dirty": "#195cc8", "icon_width": 8, @@ -121,7 +121,7 @@ "size": 14 }, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "left": true, "bottom": true, @@ -135,8 +135,8 @@ "active_tab": { "height": 32, "background": "#000000", - "icon_close": "#717171", - "icon_close_active": "#f1f1f1", + "icon_close": "#555555", + "icon_close_active": "#ffffff", "icon_conflict": "#c38214", "icon_dirty": "#195cc8", "icon_width": 8, @@ -147,7 +147,7 @@ "size": 14 }, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "left": true, "bottom": false, @@ -162,22 +162,22 @@ "width": 30, "background": "#1c1c1c", "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "right": true }, "item": { "height": 32, - "icon_color": "#717171", + "icon_color": "#9c9c9c", "icon_size": 18 }, "active_item": { "height": 32, - "icon_color": "#f1f1f1", + "icon_color": "#ffffff", "icon_size": 18 }, "resize_handle": { - "background": "#0e0e0e", + "background": "#070707", "padding": { "left": 1 } @@ -187,29 +187,29 @@ "width": 30, "background": "#1c1c1c", "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "left": true }, "item": { "height": 32, - "icon_color": "#717171", + "icon_color": "#9c9c9c", "icon_size": 18 }, "active_item": { "height": 32, - "icon_color": "#f1f1f1", + "icon_color": "#ffffff", "icon_size": 18 }, "resize_handle": { - "background": "#0e0e0e", + "background": "#070707", "padding": { "left": 1 } } }, "pane_divider": { - "color": "#0e0e0e", + "color": "#070707", "width": 1 }, "status_bar": { @@ -238,12 +238,12 @@ "titlebar": { "avatar_width": 18, "height": 32, - "background": "#393939", - "share_icon_color": "#717171", - "share_icon_active_color": "#f1f1f1", + "background": "#2b2b2b", + "share_icon_color": "#9c9c9c", + "share_icon_active_color": "#ffffff", "title": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 }, "avatar": { @@ -258,7 +258,7 @@ "width": 12 }, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "bottom": true }, @@ -281,7 +281,7 @@ } }, "offline_icon": { - "color": "#717171", + "color": "#9c9c9c", "width": 16, "padding": { "right": 4 @@ -297,7 +297,7 @@ "height": 34, "background": "#000000", "border": { - "color": "#2b2b2b", + "color": "#070707", "width": 1, "bottom": true }, @@ -325,10 +325,10 @@ } }, "editor": { - "text_color": "#e3e3e3", + "text_color": "#f1f1f1", "background": "#000000", - "active_line_background": "#1c1c1c", - "code_actions_indicator": "#717171", + "active_line_background": "#0e0e0e", + "code_actions_indicator": "#9c9c9c", "diff_background_deleted": "#d71c1c", "diff_background_inserted": "#1ea34f", "document_highlight_read_background": "#1e22db", @@ -336,7 +336,7 @@ "error_color": "#d71c1c", "gutter_background": "#000000", "gutter_padding_factor": 2.5, - "highlighted_line_background": "#0e0e0e", + "highlighted_line_background": "#070707", "line_number": "#636363", "line_number_active": "#ffffff", "rename_fade": 0.6, @@ -380,7 +380,7 @@ "corner_radius": 6, "padding": 6, "border": { - "color": "#393939", + "color": "#151515", "width": 1 }, "item": { @@ -400,7 +400,7 @@ "right": 6, "top": 2 }, - "background": "#0e0e0e" + "background": "#070707" }, "margin": { "left": -14 @@ -417,7 +417,7 @@ "right": 6, "top": 2 }, - "background": "#1c1c1c" + "background": "#0e0e0e" } }, "diagnostic_header": { @@ -425,7 +425,7 @@ "icon_width_factor": 1.5, "text_scale_factor": 0.857, "border": { - "color": "#393939", + "color": "#151515", "width": 1, "bottom": true, "top": true @@ -441,7 +441,7 @@ "message": { "highlight_text": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14, "weight": "bold" }, @@ -453,11 +453,11 @@ } }, "diagnostic_path_header": { - "background": "#1c1c1c", + "background": "#0e0e0e", "text_scale_factor": 0.857, "filename": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 }, "path": { @@ -473,7 +473,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "top": true } @@ -496,7 +496,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "top": true } @@ -519,7 +519,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "top": true } @@ -542,7 +542,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "top": true } @@ -565,7 +565,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "top": true } @@ -588,7 +588,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "top": true } @@ -611,7 +611,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "top": true } @@ -634,7 +634,7 @@ "text_scale_factor": 0.857, "header": { "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1, "top": true } @@ -661,7 +661,7 @@ "tab_summary_spacing": 10, "empty_message": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 }, "status_bar_item": { @@ -691,7 +691,7 @@ }, "hovered_entry": { "height": 22, - "background": "#1c1c1c", + "background": "#232323", "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, @@ -708,19 +708,19 @@ "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 } }, "hovered_selected_entry": { "height": 22, - "background": "#1c1c1c", + "background": "#232323", "icon_color": "#555555", "icon_size": 8, "icon_spacing": 8, "text": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 } } @@ -734,7 +734,7 @@ }, "channel_name": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "weight": "bold", "size": 14 }, @@ -750,7 +750,7 @@ "header": { "name": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 }, "padding": { @@ -799,13 +799,13 @@ "right": 8 } }, - "background": "#1c1c1c", + "background": "#232323", "corner_radius": 6 }, "active_item": { "name": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 }, "padding": 4, @@ -822,7 +822,7 @@ "hovered_active_item": { "name": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14 }, "padding": 4, @@ -834,7 +834,7 @@ "right": 8 } }, - "background": "#1c1c1c", + "background": "#232323", "corner_radius": 6 }, "menu": { @@ -842,7 +842,7 @@ "corner_radius": 6, "padding": 4, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1 }, "shadow": { @@ -863,7 +863,7 @@ }, "hovered_sign_in_prompt": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "underline": true, "size": 14 }, @@ -883,7 +883,7 @@ }, "sender": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "weight": "bold", "size": 14, "margin": { @@ -920,7 +920,7 @@ "corner_radius": 6, "text": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 16 }, "placeholder_text": { @@ -933,7 +933,7 @@ "selection": "#307af3" }, "border": { - "color": "#393939", + "color": "#151515", "width": 1 }, "padding": { @@ -952,7 +952,7 @@ "right": 12 }, "host_row_height": 28, - "tree_branch_color": "#2b2b2b", + "tree_branch_color": "#232323", "tree_branch_width": 1, "host_avatar": { "corner_radius": 10, @@ -994,7 +994,7 @@ }, "name": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 16, "margin": { "right": 6 @@ -1013,7 +1013,7 @@ }, "name": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 16, "margin": { "right": 6 @@ -1022,7 +1022,7 @@ "padding": { "left": 8 }, - "background": "#1c1c1c", + "background": "#0e0e0e", "corner_radius": 6 }, "unshared_project": { @@ -1062,7 +1062,7 @@ "padding": { "left": 8 }, - "background": "#1c1c1c", + "background": "#0e0e0e", "corner_radius": 6 } }, @@ -1074,10 +1074,10 @@ "family": "Zed Mono", "color": "#9c9c9c", "size": 16, - "background": "#393939", + "background": "#2b2b2b", "corner_radius": 6, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1 }, "margin": { @@ -1095,10 +1095,10 @@ "family": "Zed Mono", "color": "#9c9c9c", "size": 16, - "background": "#393939", + "background": "#2b2b2b", "corner_radius": 6, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1 }, "margin": { @@ -1128,11 +1128,11 @@ }, "text": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 16 }, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1 }, "margin": { @@ -1149,10 +1149,10 @@ "family": "Zed Mono", "color": "#9c9c9c", "size": 16, - "background": "#393939", + "background": "#2b2b2b", "corner_radius": 6, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1 }, "margin": { @@ -1182,7 +1182,7 @@ }, "text": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 16 }, "border": { @@ -1212,7 +1212,7 @@ "background": "#1c1c1c", "corner_radius": 6, "border": { - "color": "#0e0e0e", + "color": "#070707", "width": 1 }, "margin": { @@ -1234,13 +1234,13 @@ }, "results_status": { "family": "Zed Mono", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 18 } }, "breadcrumbs": { "family": "Zed Sans", - "color": "#e3e3e3", + "color": "#f1f1f1", "size": 14, "padding": { "left": 6 diff --git a/crates/zed/assets/themes/light.json b/crates/zed/assets/themes/light.json index 1024764540..76fe01501d 100644 --- a/crates/zed/assets/themes/light.json +++ b/crates/zed/assets/themes/light.json @@ -1,6 +1,6 @@ { "selector": { - "background": "#ffffff", + "background": "#f1f1f1", "corner_radius": 6, "padding": 8, "item": { @@ -42,7 +42,7 @@ "weight": "bold", "size": 14 }, - "background": "#e3e3e3" + "background": "#d5d5d5" }, "border": { "color": "#c6c6c6", @@ -62,7 +62,7 @@ } }, "input_editor": { - "background": "#f1f1f1", + "background": "#ffffff", "corner_radius": 6, "placeholder_text": { "family": "Zed Sans", @@ -79,7 +79,7 @@ "size": 16 }, "border": { - "color": "#c6c6c6", + "color": "#e3e3e3", "width": 1 }, "padding": { @@ -109,7 +109,7 @@ "tab": { "height": 32, "background": "#f1f1f1", - "icon_close": "#717171", + "icon_close": "#555555", "icon_close_active": "#000000", "icon_conflict": "#bc9212", "icon_dirty": "#195cc8", @@ -135,7 +135,7 @@ "active_tab": { "height": 32, "background": "#ffffff", - "icon_close": "#717171", + "icon_close": "#555555", "icon_close_active": "#000000", "icon_conflict": "#bc9212", "icon_dirty": "#195cc8", @@ -297,7 +297,7 @@ "height": 34, "background": "#ffffff", "border": { - "color": "#f1f1f1", + "color": "#c6c6c6", "width": 1, "bottom": true }, diff --git a/styles/buildThemes.ts b/styles/buildThemes.ts index 9128eff45d..a1a07ecb2d 100644 --- a/styles/buildThemes.ts +++ b/styles/buildThemes.ts @@ -3,6 +3,7 @@ import * as path from "path"; import app from "./styleTree/app"; import dark from "./themes/dark"; import light from "./themes/light"; +import { colors } from "./tokens"; import decamelizeTree from "./utils/decamelizeTree"; const themes = [dark, light]; @@ -14,4 +15,6 @@ for (let theme of themes) { ); fs.writeFileSync(outPath, styleTreeJSON); console.log(`Generated ${outPath}`); + + console.log(JSON.stringify(colors.indigo, null, 2)); } diff --git a/styles/styleTree/selectorModal.ts b/styles/styleTree/selectorModal.ts index fdebe712fa..47355cff11 100644 --- a/styles/styleTree/selectorModal.ts +++ b/styles/styleTree/selectorModal.ts @@ -16,12 +16,12 @@ export default function selectorModal(theme: Theme): Object { const activeItem = { ...item, - background: backgroundColor(theme, 500, "active"), + background: backgroundColor(theme, 300, "active"), text: text(theme, "sans", "primary"), }; return { - background: backgroundColor(theme, 500), + background: backgroundColor(theme, 300), cornerRadius: 6, padding: 8, item, @@ -37,12 +37,12 @@ export default function selectorModal(theme: Theme): Object { }, }, inputEditor: { - background: backgroundColor(theme, 300), + background: backgroundColor(theme, 500), corner_radius: 6, placeholderText: text(theme, "sans", "placeholder"), selection: player(theme, 1).selection, text: text(theme, "mono", "primary"), - border: border(theme, "primary"), + border: border(theme, "secondary"), padding: { bottom: 7, left: 16, diff --git a/styles/styleTree/workspace.ts b/styles/styleTree/workspace.ts index a734528d74..4349ba0ab6 100644 --- a/styles/styleTree/workspace.ts +++ b/styles/styleTree/workspace.ts @@ -14,7 +14,7 @@ export default function workspace(theme: Theme) { const tab = { height: 32, background: backgroundColor(theme, 300), - iconClose: iconColor(theme, "secondary"), + iconClose: iconColor(theme, "muted"), iconCloseActive: iconColor(theme, "active"), iconConflict: iconColor(theme, "warning"), iconDirty: iconColor(theme, "info"), @@ -135,7 +135,7 @@ export default function workspace(theme: Theme) { toolbar: { height: 34, background: backgroundColor(theme, 500), - border: border(theme, "muted", { bottom: true }), + border: border(theme, "primary", { bottom: true }), itemSpacing: 8, padding: { left: 16, right: 8, top: 4, bottom: 4 }, }, diff --git a/styles/themes/dark.ts b/styles/themes/dark.ts index fa05576cd2..3cb3b653b4 100644 --- a/styles/themes/dark.ts +++ b/styles/themes/dark.ts @@ -3,22 +3,22 @@ import Theme, { Syntax } from "./theme"; const backgroundColor = { 100: { - base: colors.neutral[700], - hovered: colors.neutral[700], + base: colors.neutral[750], + hovered: colors.neutral[725], active: colors.neutral[700], - focused: colors.neutral[700], + focused: colors.neutral[675], }, 300: { base: colors.neutral[800], - hovered: colors.neutral[800], - active: colors.neutral[800], - focused: colors.neutral[800], + hovered: colors.neutral[775], + active: colors.neutral[750], + focused: colors.neutral[725], }, 500: { base: colors.neutral[900], - hovered: colors.neutral[850], - active: colors.neutral[800], - focused: colors.neutral[850], + hovered: colors.neutral[875], + active: colors.neutral[850], + focused: colors.neutral[825], }, ok: { base: colors.green[600], @@ -47,11 +47,11 @@ const backgroundColor = { }; const borderColor = { - primary: colors.neutral[850], - secondary: colors.neutral[700], - muted: colors.neutral[750], - focused: colors.neutral[100], - active: colors.neutral[500], + primary: colors.neutral[875], + secondary: colors.neutral[825], + muted: colors.neutral[775], + focused: colors.neutral[500], + active: colors.neutral[900], ok: colors.green[500], error: colors.red[500], warning: colors.amber[500], @@ -59,13 +59,13 @@ const borderColor = { }; const textColor = { - primary: colors.neutral[100], + primary: colors.neutral[50], secondary: colors.neutral[350], muted: colors.neutral[550], placeholder: colors.neutral[750], active: colors.neutral[0], //TODO: (design) define feature and it's correct value - feature: colors.lime[400], + feature: colors.sky[500], ok: colors.green[600], error: colors.red[400], warning: colors.amber[300], @@ -73,11 +73,11 @@ const textColor = { }; const iconColor = { - primary: colors.neutral[300], - secondary: colors.neutral[500], + primary: colors.neutral[200], + secondary: colors.neutral[350], muted: colors.neutral[600], placeholder: colors.neutral[700], - active: colors.neutral[50], + active: colors.neutral[0], //TODO: (design) define feature and it's correct value feature: colors.sky[500], ok: colors.green[600], diff --git a/styles/tokens.ts b/styles/tokens.ts index 63c19a9d64..aa865ae694 100644 --- a/styles/tokens.ts +++ b/styles/tokens.ts @@ -72,7 +72,7 @@ export interface ColorToken { step?: number, } export const colors = { - neutral: colorRamp(["white", "black"], { steps: 19, increment: 50 }), + neutral: colorRamp(["white", "black"], { steps: 37, increment: 25 }), // (900/25) + 1 rose: colorRamp("#F43F5EFF"), red: colorRamp("#EF4444FF"), orange: colorRamp("#F97316FF"), diff --git a/styles/utils/color.ts b/styles/utils/color.ts index 1042899c73..c7506f696d 100644 --- a/styles/utils/color.ts +++ b/styles/utils/color.ts @@ -8,7 +8,7 @@ export type ColorRamp = { export function colorRamp( color: Color | [Color, Color], - options?: { steps?: number; increment?: number } + options?: { steps?: number; increment?: number; } ): ColorRamp { let scale: Scale; if (Array.isArray(color)) { From e0e9a145905299a9e0819b46c7e942596b9541c2 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sun, 3 Apr 2022 10:50:41 -0400 Subject: [PATCH 64/68] Remove leftover console.log --- styles/buildThemes.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/styles/buildThemes.ts b/styles/buildThemes.ts index a1a07ecb2d..9128eff45d 100644 --- a/styles/buildThemes.ts +++ b/styles/buildThemes.ts @@ -3,7 +3,6 @@ import * as path from "path"; import app from "./styleTree/app"; import dark from "./themes/dark"; import light from "./themes/light"; -import { colors } from "./tokens"; import decamelizeTree from "./utils/decamelizeTree"; const themes = [dark, light]; @@ -15,6 +14,4 @@ for (let theme of themes) { ); fs.writeFileSync(outPath, styleTreeJSON); console.log(`Generated ${outPath}`); - - console.log(JSON.stringify(colors.indigo, null, 2)); } From 37441bf3420ddc24fa4b812abd0402d62fbbe564 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sun, 3 Apr 2022 13:30:59 -0400 Subject: [PATCH 65/68] Add basic support for exporting tokens to Figma Tokens. (#724) * WIP on figma token export * WIP Working export * Tidy up the figma tokens script * Correctly format theme json structure for Figma Tokens * Finish up themeTokens imports --- styles/buildFigmaTokens.ts | 99 ++++ styles/figma/core.json | 1155 ++++++++++++++++++++++++++++++++++++ styles/figma/dark.json | 637 ++++++++++++++++++++ styles/figma/light.json | 637 ++++++++++++++++++++ 4 files changed, 2528 insertions(+) create mode 100644 styles/buildFigmaTokens.ts create mode 100644 styles/figma/core.json create mode 100644 styles/figma/dark.json create mode 100644 styles/figma/light.json diff --git a/styles/buildFigmaTokens.ts b/styles/buildFigmaTokens.ts new file mode 100644 index 0000000000..6b3285e58e --- /dev/null +++ b/styles/buildFigmaTokens.ts @@ -0,0 +1,99 @@ +import * as fs from "fs"; +import * as path from "path"; +import dark from "./themes/dark"; +import light from "./themes/light"; +import Theme from "./themes/theme"; +import { colors, fontFamilies, fontSizes, fontWeights } from "./tokens"; + +// Organize theme tokens +function themeTokens(theme: Theme): Object { + return { + meta: { + themeName: theme.name, + }, + text: theme.textColor, + icon: theme.iconColor, + background: theme.backgroundColor, + border: theme.borderColor, + editor: theme.editor, + syntax: { + primary: { + value: theme.syntax.primary.color.value, + type: "color", + }, + comment: { + value: theme.syntax.comment.color.value, + type: "color", + }, + keyword: { + value: theme.syntax.keyword.color.value, + type: "color", + }, + function: { + value: theme.syntax.function.color.value, + type: "color", + }, + type: { + value: theme.syntax.type.color.value, + type: "color", + }, + variant: { + value: theme.syntax.variant.color.value, + type: "color", + }, + property: { + value: theme.syntax.property.color.value, + type: "color", + }, + enum: { + value: theme.syntax.enum.color.value, + type: "color", + }, + operator: { + value: theme.syntax.operator.color.value, + type: "color", + }, + string: { + value: theme.syntax.string.color.value, + type: "color", + }, + number: { + value: theme.syntax.number.color.value, + type: "color", + }, + boolean: { + value: theme.syntax.boolean.color.value, + type: "color", + }, + }, + player: theme.player, + shadowAlpha: theme.shadowAlpha, + }; +} + +let themes = [themeTokens(dark), themeTokens(light)]; + +// Create {theme}.json +const themePath = path.resolve(`${__dirname}/figma`); +themes.forEach((theme) => { + const tokenJSON = JSON.stringify(theme, null, 2); + //@ts-ignore //TODO: IDK what the hell TS wants me to do here + fs.writeFileSync(`${themePath}/${theme.meta.themeName}.json`, tokenJSON); +}); + +// Organize core tokens +const coreTokens = { + color: { + ...colors, + }, + text: { + family: fontFamilies, + weight: fontWeights, + }, + size: fontSizes, +}; + +// Create core.json +const corePath = path.resolve(`${__dirname}/figma/core.json`); +const coreTokenJSON = JSON.stringify(coreTokens, null, 2); +fs.writeFileSync(corePath, coreTokenJSON); diff --git a/styles/figma/core.json b/styles/figma/core.json new file mode 100644 index 0000000000..77dabe6b4e --- /dev/null +++ b/styles/figma/core.json @@ -0,0 +1,1155 @@ +{ + "color": { + "neutral": { + "0": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "25": { + "value": "#f8f8f8", + "step": 25, + "type": "color" + }, + "50": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "75": { + "value": "#eaeaea", + "step": 75, + "type": "color" + }, + "100": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "125": { + "value": "#dcdcdc", + "step": 125, + "type": "color" + }, + "150": { + "value": "#d5d5d5", + "step": 150, + "type": "color" + }, + "175": { + "value": "#cdcdcd", + "step": 175, + "type": "color" + }, + "200": { + "value": "#c6c6c6", + "step": 200, + "type": "color" + }, + "225": { + "value": "#bfbfbf", + "step": 225, + "type": "color" + }, + "250": { + "value": "#b8b8b8", + "step": 250, + "type": "color" + }, + "275": { + "value": "#b1b1b1", + "step": 275, + "type": "color" + }, + "300": { + "value": "#aaaaaa", + "step": 300, + "type": "color" + }, + "325": { + "value": "#a3a3a3", + "step": 325, + "type": "color" + }, + "350": { + "value": "#9c9c9c", + "step": 350, + "type": "color" + }, + "375": { + "value": "#959595", + "step": 375, + "type": "color" + }, + "400": { + "value": "#8e8e8e", + "step": 400, + "type": "color" + }, + "425": { + "value": "#878787", + "step": 425, + "type": "color" + }, + "450": { + "value": "#808080", + "step": 450, + "type": "color" + }, + "475": { + "value": "#787878", + "step": 475, + "type": "color" + }, + "500": { + "value": "#717171", + "step": 500, + "type": "color" + }, + "525": { + "value": "#6a6a6a", + "step": 525, + "type": "color" + }, + "550": { + "value": "#636363", + "step": 550, + "type": "color" + }, + "575": { + "value": "#5c5c5c", + "step": 575, + "type": "color" + }, + "600": { + "value": "#555555", + "step": 600, + "type": "color" + }, + "625": { + "value": "#4e4e4e", + "step": 625, + "type": "color" + }, + "650": { + "value": "#474747", + "step": 650, + "type": "color" + }, + "675": { + "value": "#404040", + "step": 675, + "type": "color" + }, + "700": { + "value": "#393939", + "step": 700, + "type": "color" + }, + "725": { + "value": "#323232", + "step": 725, + "type": "color" + }, + "750": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "775": { + "value": "#232323", + "step": 775, + "type": "color" + }, + "800": { + "value": "#1c1c1c", + "step": 800, + "type": "color" + }, + "825": { + "value": "#151515", + "step": 825, + "type": "color" + }, + "850": { + "value": "#0e0e0e", + "step": 850, + "type": "color" + }, + "875": { + "value": "#070707", + "step": 875, + "type": "color" + }, + "900": { + "value": "#000000", + "step": 900, + "type": "color" + } + }, + "rose": { + "0": { + "value": "#feecef", + "step": 0, + "type": "color" + }, + "100": { + "value": "#f13455", + "step": 100, + "type": "color" + }, + "200": { + "value": "#eb2245", + "step": 200, + "type": "color" + }, + "300": { + "value": "#e7183b", + "step": 300, + "type": "color" + }, + "400": { + "value": "#da193a", + "step": 400, + "type": "color" + }, + "500": { + "value": "#d01939", + "step": 500, + "type": "color" + }, + "600": { + "value": "#c81a37", + "step": 600, + "type": "color" + }, + "700": { + "value": "#c01a36", + "step": 700, + "type": "color" + }, + "800": { + "value": "#ba1a36", + "step": 800, + "type": "color" + }, + "900": { + "value": "#b41a35", + "step": 900, + "type": "color" + } + }, + "red": { + "0": { + "value": "#feecec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#ec3939", + "step": 100, + "type": "color" + }, + "200": { + "value": "#e72727", + "step": 200, + "type": "color" + }, + "300": { + "value": "#e31c1c", + "step": 300, + "type": "color" + }, + "400": { + "value": "#d71c1c", + "step": 400, + "type": "color" + }, + "500": { + "value": "#cd1c1c", + "step": 500, + "type": "color" + }, + "600": { + "value": "#c51c1c", + "step": 600, + "type": "color" + }, + "700": { + "value": "#be1c1c", + "step": 700, + "type": "color" + }, + "800": { + "value": "#b81c1c", + "step": 800, + "type": "color" + }, + "900": { + "value": "#b21c1c", + "step": 900, + "type": "color" + } + }, + "orange": { + "0": { + "value": "#fef3ec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#f66e0f", + "step": 100, + "type": "color" + }, + "200": { + "value": "#e5660f", + "step": 200, + "type": "color" + }, + "300": { + "value": "#d66211", + "step": 300, + "type": "color" + }, + "400": { + "value": "#cc5f13", + "step": 400, + "type": "color" + }, + "500": { + "value": "#c45c14", + "step": 500, + "type": "color" + }, + "600": { + "value": "#bc5a15", + "step": 600, + "type": "color" + }, + "700": { + "value": "#b65816", + "step": 700, + "type": "color" + }, + "800": { + "value": "#b15617", + "step": 800, + "type": "color" + }, + "900": { + "value": "#ac5517", + "step": 900, + "type": "color" + } + }, + "amber": { + "0": { + "value": "#fef7ec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#eb980d", + "step": 100, + "type": "color" + }, + "200": { + "value": "#d88e10", + "step": 200, + "type": "color" + }, + "300": { + "value": "#cc8712", + "step": 300, + "type": "color" + }, + "400": { + "value": "#c38214", + "step": 400, + "type": "color" + }, + "500": { + "value": "#bb7e15", + "step": 500, + "type": "color" + }, + "600": { + "value": "#b57a16", + "step": 600, + "type": "color" + }, + "700": { + "value": "#b07717", + "step": 700, + "type": "color" + }, + "800": { + "value": "#ab7517", + "step": 800, + "type": "color" + }, + "900": { + "value": "#a77218", + "step": 900, + "type": "color" + } + }, + "yellow": { + "0": { + "value": "#fef9ec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#e0ac0b", + "step": 100, + "type": "color" + }, + "200": { + "value": "#cfa00f", + "step": 200, + "type": "color" + }, + "300": { + "value": "#c49811", + "step": 300, + "type": "color" + }, + "400": { + "value": "#bc9212", + "step": 400, + "type": "color" + }, + "500": { + "value": "#b68e14", + "step": 500, + "type": "color" + }, + "600": { + "value": "#b08a15", + "step": 600, + "type": "color" + }, + "700": { + "value": "#ac8615", + "step": 700, + "type": "color" + }, + "800": { + "value": "#a88316", + "step": 800, + "type": "color" + }, + "900": { + "value": "#a48117", + "step": 900, + "type": "color" + } + }, + "lime": { + "0": { + "value": "#f7feec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#80c517", + "step": 100, + "type": "color" + }, + "200": { + "value": "#7aba18", + "step": 200, + "type": "color" + }, + "300": { + "value": "#76b318", + "step": 300, + "type": "color" + }, + "400": { + "value": "#72ad19", + "step": 400, + "type": "color" + }, + "500": { + "value": "#70a919", + "step": 500, + "type": "color" + }, + "600": { + "value": "#6ea519", + "step": 600, + "type": "color" + }, + "700": { + "value": "#6ca219", + "step": 700, + "type": "color" + }, + "800": { + "value": "#6a9f1a", + "step": 800, + "type": "color" + }, + "900": { + "value": "#699c1a", + "step": 900, + "type": "color" + } + }, + "green": { + "0": { + "value": "#ecfef2", + "step": 0, + "type": "color" + }, + "100": { + "value": "#21bf5b", + "step": 100, + "type": "color" + }, + "200": { + "value": "#20b557", + "step": 200, + "type": "color" + }, + "300": { + "value": "#1faf54", + "step": 300, + "type": "color" + }, + "400": { + "value": "#1faa52", + "step": 400, + "type": "color" + }, + "500": { + "value": "#1ea650", + "step": 500, + "type": "color" + }, + "600": { + "value": "#1ea34f", + "step": 600, + "type": "color" + }, + "700": { + "value": "#1da04d", + "step": 700, + "type": "color" + }, + "800": { + "value": "#1d9d4c", + "step": 800, + "type": "color" + }, + "900": { + "value": "#1d9b4b", + "step": 900, + "type": "color" + } + }, + "emerald": { + "0": { + "value": "#ecfef8", + "step": 0, + "type": "color" + }, + "100": { + "value": "#11b47e", + "step": 100, + "type": "color" + }, + "200": { + "value": "#13ac79", + "step": 200, + "type": "color" + }, + "300": { + "value": "#14a776", + "step": 300, + "type": "color" + }, + "400": { + "value": "#15a374", + "step": 400, + "type": "color" + }, + "500": { + "value": "#16a072", + "step": 500, + "type": "color" + }, + "600": { + "value": "#169d70", + "step": 600, + "type": "color" + }, + "700": { + "value": "#179b6f", + "step": 700, + "type": "color" + }, + "800": { + "value": "#17996e", + "step": 800, + "type": "color" + }, + "900": { + "value": "#18976c", + "step": 900, + "type": "color" + } + }, + "teal": { + "0": { + "value": "#ecfefc", + "step": 0, + "type": "color" + }, + "100": { + "value": "#15b3a2", + "step": 100, + "type": "color" + }, + "200": { + "value": "#16ab9b", + "step": 200, + "type": "color" + }, + "300": { + "value": "#17a696", + "step": 300, + "type": "color" + }, + "400": { + "value": "#17a293", + "step": 400, + "type": "color" + }, + "500": { + "value": "#189f90", + "step": 500, + "type": "color" + }, + "600": { + "value": "#189d8e", + "step": 600, + "type": "color" + }, + "700": { + "value": "#189a8c", + "step": 700, + "type": "color" + }, + "800": { + "value": "#19988a", + "step": 800, + "type": "color" + }, + "900": { + "value": "#199788", + "step": 900, + "type": "color" + } + }, + "cyan": { + "0": { + "value": "#ecfcfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#09b5cc", + "step": 100, + "type": "color" + }, + "200": { + "value": "#0daabf", + "step": 200, + "type": "color" + }, + "300": { + "value": "#0fa3b7", + "step": 300, + "type": "color" + }, + "400": { + "value": "#119eb1", + "step": 400, + "type": "color" + }, + "500": { + "value": "#1299ac", + "step": 500, + "type": "color" + }, + "600": { + "value": "#1396a8", + "step": 600, + "type": "color" + }, + "700": { + "value": "#1493a4", + "step": 700, + "type": "color" + }, + "800": { + "value": "#1590a1", + "step": 800, + "type": "color" + }, + "900": { + "value": "#168e9e", + "step": 900, + "type": "color" + } + }, + "sky": { + "0": { + "value": "#ecf8fe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#109fdf", + "step": 100, + "type": "color" + }, + "200": { + "value": "#1394cf", + "step": 200, + "type": "color" + }, + "300": { + "value": "#148dc4", + "step": 300, + "type": "color" + }, + "400": { + "value": "#1588bc", + "step": 400, + "type": "color" + }, + "500": { + "value": "#1684b6", + "step": 500, + "type": "color" + }, + "600": { + "value": "#1780b0", + "step": 600, + "type": "color" + }, + "700": { + "value": "#177dac", + "step": 700, + "type": "color" + }, + "800": { + "value": "#187ba8", + "step": 800, + "type": "color" + }, + "900": { + "value": "#1878a4", + "step": 900, + "type": "color" + } + }, + "blue": { + "0": { + "value": "#ecf3fe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#307af3", + "step": 100, + "type": "color" + }, + "200": { + "value": "#1f6eed", + "step": 200, + "type": "color" + }, + "300": { + "value": "#1666e7", + "step": 300, + "type": "color" + }, + "400": { + "value": "#1762db", + "step": 400, + "type": "color" + }, + "500": { + "value": "#185fd0", + "step": 500, + "type": "color" + }, + "600": { + "value": "#195cc8", + "step": 600, + "type": "color" + }, + "700": { + "value": "#1959c0", + "step": 700, + "type": "color" + }, + "800": { + "value": "#1957ba", + "step": 800, + "type": "color" + }, + "900": { + "value": "#1a55b4", + "step": 900, + "type": "color" + } + }, + "indigo": { + "0": { + "value": "#ececfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#5558ee", + "step": 100, + "type": "color" + }, + "200": { + "value": "#3d41e9", + "step": 200, + "type": "color" + }, + "300": { + "value": "#2e32e5", + "step": 300, + "type": "color" + }, + "400": { + "value": "#2327e2", + "step": 400, + "type": "color" + }, + "500": { + "value": "#1e22db", + "step": 500, + "type": "color" + }, + "600": { + "value": "#1e22d1", + "step": 600, + "type": "color" + }, + "700": { + "value": "#1e21c9", + "step": 700, + "type": "color" + }, + "800": { + "value": "#1e21c1", + "step": 800, + "type": "color" + }, + "900": { + "value": "#1d20bb", + "step": 900, + "type": "color" + } + }, + "violet": { + "0": { + "value": "#f1ecfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#804ef3", + "step": 100, + "type": "color" + }, + "200": { + "value": "#6e37ee", + "step": 200, + "type": "color" + }, + "300": { + "value": "#6329e9", + "step": 300, + "type": "color" + }, + "400": { + "value": "#5a1ee6", + "step": 400, + "type": "color" + }, + "500": { + "value": "#551bde", + "step": 500, + "type": "color" + }, + "600": { + "value": "#531bd4", + "step": 600, + "type": "color" + }, + "700": { + "value": "#501bcb", + "step": 700, + "type": "color" + }, + "800": { + "value": "#4e1bc3", + "step": 800, + "type": "color" + }, + "900": { + "value": "#4c1bbc", + "step": 900, + "type": "color" + } + }, + "purple": { + "0": { + "value": "#f5ecfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#a048f4", + "step": 100, + "type": "color" + }, + "200": { + "value": "#9332ee", + "step": 200, + "type": "color" + }, + "300": { + "value": "#8a24ea", + "step": 300, + "type": "color" + }, + "400": { + "value": "#831ae7", + "step": 400, + "type": "color" + }, + "500": { + "value": "#7d19dc", + "step": 500, + "type": "color" + }, + "600": { + "value": "#781ad2", + "step": 600, + "type": "color" + }, + "700": { + "value": "#741ac9", + "step": 700, + "type": "color" + }, + "800": { + "value": "#701bc2", + "step": 800, + "type": "color" + }, + "900": { + "value": "#6d1bbb", + "step": 900, + "type": "color" + } + }, + "fuschia": { + "0": { + "value": "#fdecfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#d63be2", + "step": 100, + "type": "color" + }, + "200": { + "value": "#d12ade", + "step": 200, + "type": "color" + }, + "300": { + "value": "#ca23d6", + "step": 300, + "type": "color" + }, + "400": { + "value": "#c122cc", + "step": 400, + "type": "color" + }, + "500": { + "value": "#b921c4", + "step": 500, + "type": "color" + }, + "600": { + "value": "#b320bd", + "step": 600, + "type": "color" + }, + "700": { + "value": "#ad20b7", + "step": 700, + "type": "color" + }, + "800": { + "value": "#a81fb2", + "step": 800, + "type": "color" + }, + "900": { + "value": "#a41ead", + "step": 900, + "type": "color" + } + }, + "pink": { + "0": { + "value": "#feecf5", + "step": 0, + "type": "color" + }, + "100": { + "value": "#e93d92", + "step": 100, + "type": "color" + }, + "200": { + "value": "#e42a87", + "step": 200, + "type": "color" + }, + "300": { + "value": "#e11e7f", + "step": 300, + "type": "color" + }, + "400": { + "value": "#d51e79", + "step": 400, + "type": "color" + }, + "500": { + "value": "#cc1e75", + "step": 500, + "type": "color" + }, + "600": { + "value": "#c41e71", + "step": 600, + "type": "color" + }, + "700": { + "value": "#bd1d6d", + "step": 700, + "type": "color" + }, + "800": { + "value": "#b71d6a", + "step": 800, + "type": "color" + }, + "900": { + "value": "#b21d67", + "step": 900, + "type": "color" + } + } + }, + "text": { + "family": { + "sans": { + "value": "Zed Sans", + "type": "fontFamily" + }, + "mono": { + "value": "Zed Mono", + "type": "fontFamily" + } + }, + "weight": { + "thin": { + "value": "thin", + "type": "fontWeight" + }, + "extra_light": { + "value": "extra_light", + "type": "fontWeight" + }, + "light": { + "value": "light", + "type": "fontWeight" + }, + "normal": { + "value": "normal", + "type": "fontWeight" + }, + "medium": { + "value": "medium", + "type": "fontWeight" + }, + "semibold": { + "value": "semibold", + "type": "fontWeight" + }, + "bold": { + "value": "bold", + "type": "fontWeight" + }, + "extra_bold": { + "value": "extra_bold", + "type": "fontWeight" + }, + "black": { + "value": "black", + "type": "fontWeight" + } + } + }, + "size": { + "3xs": { + "value": 8, + "type": "fontSize" + }, + "2xs": { + "value": 10, + "type": "fontSize" + }, + "xs": { + "value": 12, + "type": "fontSize" + }, + "sm": { + "value": 14, + "type": "fontSize" + }, + "md": { + "value": 16, + "type": "fontSize" + }, + "lg": { + "value": 18, + "type": "fontSize" + }, + "xl": { + "value": 20, + "type": "fontSize" + } + } +} \ No newline at end of file diff --git a/styles/figma/dark.json b/styles/figma/dark.json new file mode 100644 index 0000000000..fadaf7c19e --- /dev/null +++ b/styles/figma/dark.json @@ -0,0 +1,637 @@ +{ + "meta": { + "themeName": "dark" + }, + "text": { + "primary": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "secondary": { + "value": "#9c9c9c", + "step": 350, + "type": "color" + }, + "muted": { + "value": "#636363", + "step": 550, + "type": "color" + }, + "placeholder": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "active": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "feature": { + "value": "#1684b6", + "step": 500, + "type": "color" + }, + "ok": { + "value": "#1ea34f", + "step": 600, + "type": "color" + }, + "error": { + "value": "#d71c1c", + "step": 400, + "type": "color" + }, + "warning": { + "value": "#cc8712", + "step": 300, + "type": "color" + }, + "info": { + "value": "#185fd0", + "step": 500, + "type": "color" + } + }, + "icon": { + "primary": { + "value": "#c6c6c6", + "step": 200, + "type": "color" + }, + "secondary": { + "value": "#9c9c9c", + "step": 350, + "type": "color" + }, + "muted": { + "value": "#555555", + "step": 600, + "type": "color" + }, + "placeholder": { + "value": "#393939", + "step": 700, + "type": "color" + }, + "active": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "feature": { + "value": "#1684b6", + "step": 500, + "type": "color" + }, + "ok": { + "value": "#1ea34f", + "step": 600, + "type": "color" + }, + "error": { + "value": "#cd1c1c", + "step": 500, + "type": "color" + }, + "warning": { + "value": "#c38214", + "step": 400, + "type": "color" + }, + "info": { + "value": "#195cc8", + "step": 600, + "type": "color" + } + }, + "background": { + "100": { + "base": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "hovered": { + "value": "#323232", + "step": 725, + "type": "color" + }, + "active": { + "value": "#393939", + "step": 700, + "type": "color" + }, + "focused": { + "value": "#404040", + "step": 675, + "type": "color" + } + }, + "300": { + "base": { + "value": "#1c1c1c", + "step": 800, + "type": "color" + }, + "hovered": { + "value": "#232323", + "step": 775, + "type": "color" + }, + "active": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "focused": { + "value": "#323232", + "step": 725, + "type": "color" + } + }, + "500": { + "base": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "hovered": { + "value": "#070707", + "step": 875, + "type": "color" + }, + "active": { + "value": "#0e0e0e", + "step": 850, + "type": "color" + }, + "focused": { + "value": "#151515", + "step": 825, + "type": "color" + } + }, + "ok": { + "base": { + "value": "#1ea34f", + "step": 600, + "type": "color" + }, + "hovered": { + "value": "#1ea34f", + "step": 600, + "type": "color" + }, + "active": { + "value": "#1ea34f", + "step": 600, + "type": "color" + }, + "focused": { + "value": "#1ea34f", + "step": 600, + "type": "color" + } + }, + "error": { + "base": { + "value": "#d71c1c", + "step": 400, + "type": "color" + }, + "hovered": { + "value": "#d71c1c", + "step": 400, + "type": "color" + }, + "active": { + "value": "#d71c1c", + "step": 400, + "type": "color" + }, + "focused": { + "value": "#d71c1c", + "step": 400, + "type": "color" + } + }, + "warning": { + "base": { + "value": "#cc8712", + "step": 300, + "type": "color" + }, + "hovered": { + "value": "#cc8712", + "step": 300, + "type": "color" + }, + "active": { + "value": "#cc8712", + "step": 300, + "type": "color" + }, + "focused": { + "value": "#cc8712", + "step": 300, + "type": "color" + } + }, + "info": { + "base": { + "value": "#185fd0", + "step": 500, + "type": "color" + }, + "hovered": { + "value": "#185fd0", + "step": 500, + "type": "color" + }, + "active": { + "value": "#185fd0", + "step": 500, + "type": "color" + }, + "focused": { + "value": "#185fd0", + "step": 500, + "type": "color" + } + } + }, + "border": { + "primary": { + "value": "#070707", + "step": 875, + "type": "color" + }, + "secondary": { + "value": "#151515", + "step": 825, + "type": "color" + }, + "muted": { + "value": "#232323", + "step": 775, + "type": "color" + }, + "focused": { + "value": "#717171", + "step": 500, + "type": "color" + }, + "active": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "ok": { + "value": "#1ea650", + "step": 500, + "type": "color" + }, + "error": { + "value": "#cd1c1c", + "step": 500, + "type": "color" + }, + "warning": { + "value": "#bb7e15", + "step": 500, + "type": "color" + }, + "info": { + "value": "#185fd0", + "step": 500, + "type": "color" + } + }, + "editor": { + "background": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "indent_guide": { + "value": "#232323", + "step": 775, + "type": "color" + }, + "indent_guide_active": { + "value": "#151515", + "step": 825, + "type": "color" + }, + "line": { + "active": { + "value": "#0e0e0e", + "step": 850, + "type": "color" + }, + "highlighted": { + "value": "#070707", + "step": 875, + "type": "color" + }, + "inserted": { + "value": "#1ea34f", + "step": 600, + "type": "color" + }, + "deleted": { + "value": "#d71c1c", + "step": 400, + "type": "color" + }, + "modified": { + "value": "#185fd0", + "step": 500, + "type": "color" + } + }, + "highlight": { + "selection": { + "value": "#307af3", + "step": 100, + "type": "color" + }, + "occurrence": { + "value": "#1e22db", + "step": 500, + "type": "color" + }, + "activeOccurrence": { + "value": "#2327e2", + "step": 400, + "type": "color" + }, + "matchingBracket": { + "value": "#0e0e0e", + "step": 850, + "type": "color" + }, + "match": { + "value": "#70a919", + "step": 500, + "type": "color" + }, + "activeMatch": { + "value": "#72ad19", + "step": 400, + "type": "color" + }, + "related": { + "value": "#151515", + "step": 825, + "type": "color" + } + }, + "gutter": { + "primary": { + "value": "#636363", + "step": 550, + "type": "color" + }, + "active": { + "value": "#ffffff", + "step": 0, + "type": "color" + } + } + }, + "syntax": { + "primary": { + "value": "#f1f1f1", + "type": "color" + }, + "comment": { + "value": "#7aba18", + "type": "color" + }, + "keyword": { + "value": "#1588bc", + "type": "color" + }, + "function": { + "value": "#cfa00f", + "type": "color" + }, + "type": { + "value": "#17a696", + "type": "color" + }, + "variant": { + "value": "#17a696", + "type": "color" + }, + "property": { + "value": "#148dc4", + "type": "color" + }, + "enum": { + "value": "#1588bc", + "type": "color" + }, + "operator": { + "value": "#1588bc", + "type": "color" + }, + "string": { + "value": "#d66211", + "type": "color" + }, + "number": { + "value": "#d5d5d5", + "type": "color" + }, + "boolean": { + "value": "#d5d5d5", + "type": "color" + } + }, + "player": { + "1": { + "baseColor": { + "value": "#195cc8", + "step": 600, + "type": "color" + }, + "cursorColor": { + "value": "#195cc8", + "step": 600, + "type": "color" + }, + "selectionColor": { + "value": "#307af3", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#195cc8", + "step": 600, + "type": "color" + } + }, + "2": { + "baseColor": { + "value": "#70a919", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#70a919", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#80c517", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#70a919", + "step": 500, + "type": "color" + } + }, + "3": { + "baseColor": { + "value": "#1e22db", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#1e22db", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#5558ee", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#1e22db", + "step": 500, + "type": "color" + } + }, + "4": { + "baseColor": { + "value": "#c45c14", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#c45c14", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#f66e0f", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#c45c14", + "step": 500, + "type": "color" + } + }, + "5": { + "baseColor": { + "value": "#7d19dc", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#7d19dc", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#a048f4", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#7d19dc", + "step": 500, + "type": "color" + } + }, + "6": { + "baseColor": { + "value": "#17a293", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#17a293", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#15b3a2", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#17a293", + "step": 400, + "type": "color" + } + }, + "7": { + "baseColor": { + "value": "#d51e79", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#d51e79", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#e93d92", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#d51e79", + "step": 400, + "type": "color" + } + }, + "8": { + "baseColor": { + "value": "#bc9212", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#bc9212", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#e0ac0b", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#bc9212", + "step": 400, + "type": "color" + } + } + }, + "shadowAlpha": { + "value": 0.32, + "type": "number" + } +} \ No newline at end of file diff --git a/styles/figma/light.json b/styles/figma/light.json new file mode 100644 index 0000000000..415ab40933 --- /dev/null +++ b/styles/figma/light.json @@ -0,0 +1,637 @@ +{ + "meta": { + "themeName": "light" + }, + "text": { + "primary": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "secondary": { + "value": "#555555", + "step": 600, + "type": "color" + }, + "muted": { + "value": "#808080", + "step": 450, + "type": "color" + }, + "placeholder": { + "value": "#aaaaaa", + "step": 300, + "type": "color" + }, + "active": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "feature": { + "value": "#185fd0", + "step": 500, + "type": "color" + }, + "ok": { + "value": "#1ea650", + "step": 500, + "type": "color" + }, + "error": { + "value": "#cd1c1c", + "step": 500, + "type": "color" + }, + "warning": { + "value": "#b68e14", + "step": 500, + "type": "color" + }, + "info": { + "value": "#185fd0", + "step": 500, + "type": "color" + } + }, + "icon": { + "primary": { + "value": "#aaaaaa", + "step": 300, + "type": "color" + }, + "secondary": { + "value": "#717171", + "step": 500, + "type": "color" + }, + "muted": { + "value": "#555555", + "step": 600, + "type": "color" + }, + "placeholder": { + "value": "#393939", + "step": 700, + "type": "color" + }, + "active": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "feature": { + "value": "#1780b0", + "step": 600, + "type": "color" + }, + "ok": { + "value": "#1ea34f", + "step": 600, + "type": "color" + }, + "error": { + "value": "#c51c1c", + "step": 600, + "type": "color" + }, + "warning": { + "value": "#bc9212", + "step": 400, + "type": "color" + }, + "info": { + "value": "#195cc8", + "step": 600, + "type": "color" + } + }, + "background": { + "100": { + "base": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#d5d5d5", + "step": 150, + "type": "color" + }, + "active": { + "value": "#c6c6c6", + "step": 200, + "type": "color" + }, + "focused": { + "value": "#d5d5d5", + "step": 150, + "type": "color" + } + }, + "300": { + "base": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "hovered": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "active": { + "value": "#d5d5d5", + "step": 150, + "type": "color" + }, + "focused": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + } + }, + "500": { + "base": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "hovered": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "active": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + } + }, + "ok": { + "base": { + "value": "#21bf5b", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#21bf5b", + "step": 100, + "type": "color" + }, + "active": { + "value": "#21bf5b", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#21bf5b", + "step": 100, + "type": "color" + } + }, + "error": { + "base": { + "value": "#ec3939", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#ec3939", + "step": 100, + "type": "color" + }, + "active": { + "value": "#ec3939", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#ec3939", + "step": 100, + "type": "color" + } + }, + "warning": { + "base": { + "value": "#e0ac0b", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#e0ac0b", + "step": 100, + "type": "color" + }, + "active": { + "value": "#e0ac0b", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#e0ac0b", + "step": 100, + "type": "color" + } + }, + "info": { + "base": { + "value": "#307af3", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#307af3", + "step": 100, + "type": "color" + }, + "active": { + "value": "#307af3", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#307af3", + "step": 100, + "type": "color" + } + } + }, + "border": { + "primary": { + "value": "#c6c6c6", + "step": 200, + "type": "color" + }, + "secondary": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "muted": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "focused": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "active": { + "value": "#b8b8b8", + "step": 250, + "type": "color" + }, + "ok": { + "value": "#20b557", + "step": 200, + "type": "color" + }, + "error": { + "value": "#e72727", + "step": 200, + "type": "color" + }, + "warning": { + "value": "#cfa00f", + "step": 200, + "type": "color" + }, + "info": { + "value": "#1f6eed", + "step": 200, + "type": "color" + } + }, + "editor": { + "background": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "indent_guide": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "indent_guide_active": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "line": { + "active": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "highlighted": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "inserted": { + "value": "#21bf5b", + "step": 100, + "type": "color" + }, + "deleted": { + "value": "#ec3939", + "step": 100, + "type": "color" + }, + "modified": { + "value": "#307af3", + "step": 100, + "type": "color" + } + }, + "highlight": { + "selection": { + "value": "#307af3", + "step": 100, + "type": "color" + }, + "occurrence": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "activeOccurrence": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "matchingBracket": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "match": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "activeMatch": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "related": { + "value": "#ffffff", + "step": 0, + "type": "color" + } + }, + "gutter": { + "primary": { + "value": "#808080", + "step": 450, + "type": "color" + }, + "active": { + "value": "#000000", + "step": 900, + "type": "color" + } + } + }, + "syntax": { + "primary": { + "value": "#2b2b2b", + "type": "color" + }, + "comment": { + "value": "#7aba18", + "type": "color" + }, + "keyword": { + "value": "#1588bc", + "type": "color" + }, + "function": { + "value": "#cfa00f", + "type": "color" + }, + "type": { + "value": "#17a696", + "type": "color" + }, + "variant": { + "value": "#17a696", + "type": "color" + }, + "property": { + "value": "#148dc4", + "type": "color" + }, + "enum": { + "value": "#1588bc", + "type": "color" + }, + "operator": { + "value": "#1588bc", + "type": "color" + }, + "string": { + "value": "#d66211", + "type": "color" + }, + "number": { + "value": "#d5d5d5", + "type": "color" + }, + "boolean": { + "value": "#d5d5d5", + "type": "color" + } + }, + "player": { + "1": { + "baseColor": { + "value": "#195cc8", + "step": 600, + "type": "color" + }, + "cursorColor": { + "value": "#185fd0", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#307af3", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#185fd0", + "step": 500, + "type": "color" + } + }, + "2": { + "baseColor": { + "value": "#70a919", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#70a919", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#80c517", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#70a919", + "step": 500, + "type": "color" + } + }, + "3": { + "baseColor": { + "value": "#1e22db", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#1e22db", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#5558ee", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#1e22db", + "step": 500, + "type": "color" + } + }, + "4": { + "baseColor": { + "value": "#c45c14", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#c45c14", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#f66e0f", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#c45c14", + "step": 500, + "type": "color" + } + }, + "5": { + "baseColor": { + "value": "#7d19dc", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#7d19dc", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#a048f4", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#7d19dc", + "step": 500, + "type": "color" + } + }, + "6": { + "baseColor": { + "value": "#17a293", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#17a293", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#15b3a2", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#17a293", + "step": 400, + "type": "color" + } + }, + "7": { + "baseColor": { + "value": "#d51e79", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#d51e79", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#e93d92", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#d51e79", + "step": 400, + "type": "color" + } + }, + "8": { + "baseColor": { + "value": "#bc9212", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#bc9212", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#e0ac0b", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#bc9212", + "step": 400, + "type": "color" + } + } + }, + "shadowAlpha": { + "value": 0.12, + "type": "number" + } +} \ No newline at end of file From 90df8a31e77c02e81bc55f45ba676a65e4c42f02 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sun, 3 Apr 2022 13:37:47 -0400 Subject: [PATCH 66/68] Fix incorrect ramp preset values in `color.ts` - Regenerate themes and tokens as well --- crates/zed/assets/themes/dark.json | 94 +++++----- crates/zed/assets/themes/light.json | 88 ++++----- styles/figma/core.json | 272 ++++++++++++++-------------- styles/figma/dark.json | 158 ++++++++-------- styles/figma/light.json | 150 +++++++-------- styles/utils/color.ts | 4 +- 6 files changed, 383 insertions(+), 383 deletions(-) diff --git a/crates/zed/assets/themes/dark.json b/crates/zed/assets/themes/dark.json index 25568bf17c..da7fa4650e 100644 --- a/crates/zed/assets/themes/dark.json +++ b/crates/zed/assets/themes/dark.json @@ -18,7 +18,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#1684b6", + "color": "#2db4f3", "weight": "bold", "size": 14 } @@ -38,7 +38,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#1684b6", + "color": "#2db4f3", "weight": "bold", "size": 14 }, @@ -70,8 +70,8 @@ "size": 14 }, "selection": { - "cursor": "#195cc8", - "selection": "#307af3" + "cursor": "#4287f6", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", @@ -111,8 +111,8 @@ "background": "#1c1c1c", "icon_close": "#555555", "icon_close_active": "#ffffff", - "icon_conflict": "#c38214", - "icon_dirty": "#195cc8", + "icon_conflict": "#f7b241", + "icon_dirty": "#4287f6", "icon_width": 8, "spacing": 10, "text": { @@ -137,8 +137,8 @@ "background": "#000000", "icon_close": "#555555", "icon_close_active": "#ffffff", - "icon_conflict": "#c38214", - "icon_dirty": "#195cc8", + "icon_conflict": "#f7b241", + "icon_dirty": "#4287f6", "icon_width": 8, "spacing": 10, "text": { @@ -289,7 +289,7 @@ }, "outdated_warning": { "family": "Zed Sans", - "color": "#cc8712", + "color": "#f8c570", "size": 13 } }, @@ -329,11 +329,11 @@ "background": "#000000", "active_line_background": "#0e0e0e", "code_actions_indicator": "#9c9c9c", - "diff_background_deleted": "#d71c1c", - "diff_background_inserted": "#1ea34f", - "document_highlight_read_background": "#1e22db", - "document_highlight_write_background": "#1e22db", - "error_color": "#d71c1c", + "diff_background_deleted": "#f78c8c", + "diff_background_inserted": "#22c55e", + "document_highlight_read_background": "#777af4", + "document_highlight_write_background": "#777af4", + "error_color": "#f78c8c", "gutter_background": "#000000", "gutter_padding_factor": 2.5, "highlighted_line_background": "#070707", @@ -342,37 +342,37 @@ "rename_fade": 0.6, "unnecessary_code_fade": 0.5, "selection": { - "cursor": "#195cc8", - "selection": "#307af3" + "cursor": "#4287f6", + "selection": "#d0e2fd" }, "guest_selections": [ { - "cursor": "#70a919", - "selection": "#80c517" + "cursor": "#87d116", + "selection": "#dbf9ac" }, { - "cursor": "#1e22db", - "selection": "#5558ee" + "cursor": "#777af4", + "selection": "#d4d5fd" }, { - "cursor": "#c45c14", - "selection": "#f66e0f" + "cursor": "#f98a3d", + "selection": "#fde0cd" }, { - "cursor": "#7d19dc", - "selection": "#a048f4" + "cursor": "#b671f8", + "selection": "#e9d4fd" }, { - "cursor": "#17a293", - "selection": "#15b3a2" + "cursor": "#16ddc7", + "selection": "#b4faf2" }, { - "cursor": "#d51e79", - "selection": "#e93d92" + "cursor": "#f58ac0", + "selection": "#fcd4e8" }, { - "cursor": "#bc9212", - "selection": "#e0ac0b" + "cursor": "#f6bc09", + "selection": "#fceabc" } ], "autocomplete": { @@ -406,7 +406,7 @@ "left": -14 }, "match_highlight": { - "color": "#1588bc", + "color": "#59c3f5", "weight": "normal" }, "selected_item": { @@ -481,12 +481,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#d71c1c", + "color": "#f78c8c", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#d71c1c", + "color": "#f78c8c", "size": 14, "weight": "bold" } @@ -504,12 +504,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#cc8712", + "color": "#f8c570", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#cc8712", + "color": "#f8c570", "size": 14, "weight": "bold" } @@ -527,12 +527,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "size": 14, "weight": "bold" } @@ -550,12 +550,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "size": 14, "weight": "bold" } @@ -929,8 +929,8 @@ "size": 14 }, "selection": { - "cursor": "#195cc8", - "selection": "#307af3" + "cursor": "#4287f6", + "selection": "#d0e2fd" }, "border": { "color": "#151515", @@ -1067,7 +1067,7 @@ } }, "search": { - "match_background": "#70a919", + "match_background": "#87d116", "tab_icon_spacing": 4, "tab_icon_width": 14, "active_hovered_option_button": { @@ -1123,8 +1123,8 @@ "size": 16 }, "selection": { - "cursor": "#195cc8", - "selection": "#307af3" + "cursor": "#4287f6", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", @@ -1177,8 +1177,8 @@ "size": 16 }, "selection": { - "cursor": "#195cc8", - "selection": "#307af3" + "cursor": "#4287f6", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", @@ -1186,7 +1186,7 @@ "size": 16 }, "border": { - "color": "#cd1c1c", + "color": "#f47171", "width": 1 }, "margin": { diff --git a/crates/zed/assets/themes/light.json b/crates/zed/assets/themes/light.json index 76fe01501d..dcff3352f7 100644 --- a/crates/zed/assets/themes/light.json +++ b/crates/zed/assets/themes/light.json @@ -18,7 +18,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "weight": "bold", "size": 14 } @@ -38,7 +38,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "weight": "bold", "size": 14 }, @@ -70,8 +70,8 @@ "size": 14 }, "selection": { - "cursor": "#185fd0", - "selection": "#307af3" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", @@ -111,8 +111,8 @@ "background": "#f1f1f1", "icon_close": "#555555", "icon_close_active": "#000000", - "icon_conflict": "#bc9212", - "icon_dirty": "#195cc8", + "icon_conflict": "#f6bc09", + "icon_dirty": "#4287f6", "icon_width": 8, "spacing": 10, "text": { @@ -137,8 +137,8 @@ "background": "#ffffff", "icon_close": "#555555", "icon_close_active": "#000000", - "icon_conflict": "#bc9212", - "icon_dirty": "#195cc8", + "icon_conflict": "#f6bc09", + "icon_dirty": "#4287f6", "icon_width": 8, "spacing": 10, "text": { @@ -289,7 +289,7 @@ }, "outdated_warning": { "family": "Zed Sans", - "color": "#b68e14", + "color": "#e5af09", "size": 13 } }, @@ -329,11 +329,11 @@ "background": "#ffffff", "active_line_background": "#e3e3e3", "code_actions_indicator": "#717171", - "diff_background_deleted": "#ec3939", - "diff_background_inserted": "#21bf5b", + "diff_background_deleted": "#fdd4d4", + "diff_background_inserted": "#befad2", "document_highlight_read_background": "#e3e3e3", "document_highlight_write_background": "#e3e3e3", - "error_color": "#cd1c1c", + "error_color": "#f47171", "gutter_background": "#ffffff", "gutter_padding_factor": 2.5, "highlighted_line_background": "#e3e3e3", @@ -342,37 +342,37 @@ "rename_fade": 0.6, "unnecessary_code_fade": 0.5, "selection": { - "cursor": "#185fd0", - "selection": "#307af3" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "guest_selections": [ { - "cursor": "#70a919", - "selection": "#80c517" + "cursor": "#87d116", + "selection": "#dbf9ac" }, { - "cursor": "#1e22db", - "selection": "#5558ee" + "cursor": "#777af4", + "selection": "#d4d5fd" }, { - "cursor": "#c45c14", - "selection": "#f66e0f" + "cursor": "#f98a3d", + "selection": "#fde0cd" }, { - "cursor": "#7d19dc", - "selection": "#a048f4" + "cursor": "#b671f8", + "selection": "#e9d4fd" }, { - "cursor": "#17a293", - "selection": "#15b3a2" + "cursor": "#16ddc7", + "selection": "#b4faf2" }, { - "cursor": "#d51e79", - "selection": "#e93d92" + "cursor": "#f58ac0", + "selection": "#fcd4e8" }, { - "cursor": "#bc9212", - "selection": "#e0ac0b" + "cursor": "#f6bc09", + "selection": "#fceabc" } ], "autocomplete": { @@ -406,7 +406,7 @@ "left": -14 }, "match_highlight": { - "color": "#1588bc", + "color": "#59c3f5", "weight": "normal" }, "selected_item": { @@ -481,12 +481,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#cd1c1c", + "color": "#f47171", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#cd1c1c", + "color": "#f47171", "size": 14, "weight": "bold" } @@ -504,12 +504,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#b68e14", + "color": "#e5af09", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#b68e14", + "color": "#e5af09", "size": 14, "weight": "bold" } @@ -527,12 +527,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "size": 14, "weight": "bold" } @@ -550,12 +550,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#185fd0", + "color": "#6099f7", "size": 14, "weight": "bold" } @@ -929,8 +929,8 @@ "size": 14 }, "selection": { - "cursor": "#185fd0", - "selection": "#307af3" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "border": { "color": "#e3e3e3", @@ -1123,8 +1123,8 @@ "size": 16 }, "selection": { - "cursor": "#185fd0", - "selection": "#307af3" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", @@ -1177,8 +1177,8 @@ "size": 16 }, "selection": { - "cursor": "#185fd0", - "selection": "#307af3" + "cursor": "#6099f7", + "selection": "#d0e2fd" }, "text": { "family": "Zed Mono", @@ -1186,7 +1186,7 @@ "size": 16 }, "border": { - "color": "#e72727", + "color": "#fbbdbd", "width": 1 }, "margin": { diff --git a/styles/figma/core.json b/styles/figma/core.json index 77dabe6b4e..b3e13f1c7a 100644 --- a/styles/figma/core.json +++ b/styles/figma/core.json @@ -194,42 +194,42 @@ "type": "color" }, "100": { - "value": "#f13455", + "value": "#fdd5db", "step": 100, "type": "color" }, "200": { - "value": "#eb2245", + "value": "#fbbdc8", "step": 200, "type": "color" }, "300": { - "value": "#e7183b", + "value": "#faa4b3", "step": 300, "type": "color" }, "400": { - "value": "#da193a", + "value": "#f98a9d", "step": 400, "type": "color" }, "500": { - "value": "#d01939", + "value": "#f76e86", "step": 500, "type": "color" }, "600": { - "value": "#c81a37", + "value": "#f54c69", "step": 600, "type": "color" }, "700": { - "value": "#c01a36", + "value": "#ec2548", "step": 700, "type": "color" }, "800": { - "value": "#ba1a36", + "value": "#d21939", "step": 800, "type": "color" }, @@ -246,42 +246,42 @@ "type": "color" }, "100": { - "value": "#ec3939", + "value": "#fdd4d4", "step": 100, "type": "color" }, "200": { - "value": "#e72727", + "value": "#fbbdbd", "step": 200, "type": "color" }, "300": { - "value": "#e31c1c", + "value": "#f9a5a5", "step": 300, "type": "color" }, "400": { - "value": "#d71c1c", + "value": "#f78c8c", "step": 400, "type": "color" }, "500": { - "value": "#cd1c1c", + "value": "#f47171", "step": 500, "type": "color" }, "600": { - "value": "#c51c1c", + "value": "#f15252", "step": 600, "type": "color" }, "700": { - "value": "#be1c1c", + "value": "#e82c2c", "step": 700, "type": "color" }, "800": { - "value": "#b81c1c", + "value": "#d11c1c", "step": 800, "type": "color" }, @@ -298,42 +298,42 @@ "type": "color" }, "100": { - "value": "#f66e0f", + "value": "#fde0cd", "step": 100, "type": "color" }, "200": { - "value": "#e5660f", + "value": "#fbccac", "step": 200, "type": "color" }, "300": { - "value": "#d66211", + "value": "#fab78b", "step": 300, "type": "color" }, "400": { - "value": "#cc5f13", + "value": "#faa266", "step": 400, "type": "color" }, "500": { - "value": "#c45c14", + "value": "#f98a3d", "step": 500, "type": "color" }, "600": { - "value": "#bc5a15", + "value": "#f77113", "step": 600, "type": "color" }, "700": { - "value": "#b65816", + "value": "#e0650f", "step": 700, "type": "color" }, "800": { - "value": "#b15617", + "value": "#c65d14", "step": 800, "type": "color" }, @@ -350,42 +350,42 @@ "type": "color" }, "100": { - "value": "#eb980d", + "value": "#fce7c4", "step": 100, "type": "color" }, "200": { - "value": "#d88e10", + "value": "#fad69d", "step": 200, "type": "color" }, "300": { - "value": "#cc8712", + "value": "#f8c570", "step": 300, "type": "color" }, "400": { - "value": "#c38214", + "value": "#f7b241", "step": 400, "type": "color" }, "500": { - "value": "#bb7e15", + "value": "#f59f0c", "step": 500, "type": "color" }, "600": { - "value": "#b57a16", + "value": "#e1930e", "step": 600, "type": "color" }, "700": { - "value": "#b07717", + "value": "#cd8812", "step": 700, "type": "color" }, "800": { - "value": "#ab7517", + "value": "#ba7d15", "step": 800, "type": "color" }, @@ -402,42 +402,42 @@ "type": "color" }, "100": { - "value": "#e0ac0b", + "value": "#fceabc", "step": 100, "type": "color" }, "200": { - "value": "#cfa00f", + "value": "#fadc89", "step": 200, "type": "color" }, "300": { - "value": "#c49811", + "value": "#f8cc4e", "step": 300, "type": "color" }, "400": { - "value": "#bc9212", + "value": "#f6bc09", "step": 400, "type": "color" }, "500": { - "value": "#b68e14", + "value": "#e5af09", "step": 500, "type": "color" }, "600": { - "value": "#b08a15", + "value": "#d4a30d", "step": 600, "type": "color" }, "700": { - "value": "#ac8615", + "value": "#c49811", "step": 700, "type": "color" }, "800": { - "value": "#a88316", + "value": "#b48d14", "step": 800, "type": "color" }, @@ -454,42 +454,42 @@ "type": "color" }, "100": { - "value": "#80c517", + "value": "#dbf9ac", "step": 100, "type": "color" }, "200": { - "value": "#7aba18", + "value": "#bdf36b", "step": 200, "type": "color" }, "300": { - "value": "#76b318", + "value": "#9feb2b", "step": 300, "type": "color" }, "400": { - "value": "#72ad19", + "value": "#90df17", "step": 400, "type": "color" }, "500": { - "value": "#70a919", + "value": "#87d116", "step": 500, "type": "color" }, "600": { - "value": "#6ea519", + "value": "#7fc417", "step": 600, "type": "color" }, "700": { - "value": "#6ca219", + "value": "#78b618", "step": 700, "type": "color" }, "800": { - "value": "#6a9f1a", + "value": "#70aa19", "step": 800, "type": "color" }, @@ -506,42 +506,42 @@ "type": "color" }, "100": { - "value": "#21bf5b", + "value": "#befad2", "step": 100, "type": "color" }, "200": { - "value": "#20b557", + "value": "#8ff4b2", "step": 200, "type": "color" }, "300": { - "value": "#1faf54", + "value": "#60ec92", "step": 300, "type": "color" }, "400": { - "value": "#1faa52", + "value": "#34e173", "step": 400, "type": "color" }, "500": { - "value": "#1ea650", + "value": "#23d464", "step": 500, "type": "color" }, "600": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" }, "700": { - "value": "#1da04d", + "value": "#20b658", "step": 700, "type": "color" }, "800": { - "value": "#1d9d4c", + "value": "#1ea851", "step": 800, "type": "color" }, @@ -558,42 +558,42 @@ "type": "color" }, "100": { - "value": "#11b47e", + "value": "#b3fbe3", "step": 100, "type": "color" }, "200": { - "value": "#13ac79", + "value": "#72f6ca", "step": 200, "type": "color" }, "300": { - "value": "#14a776", + "value": "#1feda9", "step": 300, "type": "color" }, "400": { - "value": "#15a374", + "value": "#12e09b", "step": 400, "type": "color" }, "500": { - "value": "#16a072", + "value": "#11d091", "step": 500, "type": "color" }, "600": { - "value": "#169d70", + "value": "#11c287", "step": 600, "type": "color" }, "700": { - "value": "#179b6f", + "value": "#11b37e", "step": 700, "type": "color" }, "800": { - "value": "#17996e", + "value": "#15a575", "step": 800, "type": "color" }, @@ -610,42 +610,42 @@ "type": "color" }, "100": { - "value": "#15b3a2", + "value": "#b4faf2", "step": 100, "type": "color" }, "200": { - "value": "#16ab9b", + "value": "#73f4e6", "step": 200, "type": "color" }, "300": { - "value": "#17a696", + "value": "#26ebd5", "step": 300, "type": "color" }, "400": { - "value": "#17a293", + "value": "#16ddc7", "step": 400, "type": "color" }, "500": { - "value": "#189f90", + "value": "#15cfba", "step": 500, "type": "color" }, "600": { - "value": "#189d8e", + "value": "#15c1ae", "step": 600, "type": "color" }, "700": { - "value": "#189a8c", + "value": "#15b2a1", "step": 700, "type": "color" }, "800": { - "value": "#19988a", + "value": "#17a495", "step": 800, "type": "color" }, @@ -662,42 +662,42 @@ "type": "color" }, "100": { - "value": "#09b5cc", + "value": "#bcf5fc", "step": 100, "type": "color" }, "200": { - "value": "#0daabf", + "value": "#86edfa", "step": 200, "type": "color" }, "300": { - "value": "#0fa3b7", + "value": "#41e3f8", "step": 300, "type": "color" }, "400": { - "value": "#119eb1", + "value": "#07d5f1", "step": 400, "type": "color" }, "500": { - "value": "#1299ac", + "value": "#07c7e1", "step": 500, "type": "color" }, "600": { - "value": "#1396a8", + "value": "#07b8d0", "step": 600, "type": "color" }, "700": { - "value": "#1493a4", + "value": "#0daabf", "step": 700, "type": "color" }, "800": { - "value": "#1590a1", + "value": "#119bae", "step": 800, "type": "color" }, @@ -714,42 +714,42 @@ "type": "color" }, "100": { - "value": "#109fdf", + "value": "#caecfc", "step": 100, "type": "color" }, "200": { - "value": "#1394cf", + "value": "#a6defa", "step": 200, "type": "color" }, "300": { - "value": "#148dc4", + "value": "#81d2f8", "step": 300, "type": "color" }, "400": { - "value": "#1588bc", + "value": "#59c3f5", "step": 400, "type": "color" }, "500": { - "value": "#1684b6", + "value": "#2db4f3", "step": 500, "type": "color" }, "600": { - "value": "#1780b0", + "value": "#0ea5e8", "step": 600, "type": "color" }, "700": { - "value": "#177dac", + "value": "#1296d1", "step": 700, "type": "color" }, "800": { - "value": "#187ba8", + "value": "#1686ba", "step": 800, "type": "color" }, @@ -766,42 +766,42 @@ "type": "color" }, "100": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" }, "200": { - "value": "#1f6eed", + "value": "#b4cffb", "step": 200, "type": "color" }, "300": { - "value": "#1666e7", + "value": "#99befa", "step": 300, "type": "color" }, "400": { - "value": "#1762db", + "value": "#7cacf9", "step": 400, "type": "color" }, "500": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" }, "600": { - "value": "#195cc8", + "value": "#4287f6", "step": 600, "type": "color" }, "700": { - "value": "#1959c0", + "value": "#2774f0", "step": 700, "type": "color" }, "800": { - "value": "#1957ba", + "value": "#1762db", "step": 800, "type": "color" }, @@ -818,42 +818,42 @@ "type": "color" }, "100": { - "value": "#5558ee", + "value": "#d4d5fd", "step": 100, "type": "color" }, "200": { - "value": "#3d41e9", + "value": "#bebefb", "step": 200, "type": "color" }, "300": { - "value": "#2e32e5", + "value": "#a7a8f9", "step": 300, "type": "color" }, "400": { - "value": "#2327e2", + "value": "#8f90f6", "step": 400, "type": "color" }, "500": { - "value": "#1e22db", + "value": "#777af4", "step": 500, "type": "color" }, "600": { - "value": "#1e22d1", + "value": "#5f62f0", "step": 600, "type": "color" }, "700": { - "value": "#1e21c9", + "value": "#464aeb", "step": 700, "type": "color" }, "800": { - "value": "#1e21c1", + "value": "#292de4", "step": 800, "type": "color" }, @@ -870,42 +870,42 @@ "type": "color" }, "100": { - "value": "#804ef3", + "value": "#e0d5fd", "step": 100, "type": "color" }, "200": { - "value": "#6e37ee", + "value": "#cfbcfb", "step": 200, "type": "color" }, "300": { - "value": "#6329e9", + "value": "#bda4fa", "step": 300, "type": "color" }, "400": { - "value": "#5a1ee6", + "value": "#ad8cf9", "step": 400, "type": "color" }, "500": { - "value": "#551bde", + "value": "#9b73f7", "step": 500, "type": "color" }, "600": { - "value": "#531bd4", + "value": "#8959f6", "step": 600, "type": "color" }, "700": { - "value": "#501bcb", + "value": "#7540f0", "step": 700, "type": "color" }, "800": { - "value": "#4e1bc3", + "value": "#5e22e7", "step": 800, "type": "color" }, @@ -922,42 +922,42 @@ "type": "color" }, "100": { - "value": "#a048f4", + "value": "#e9d4fd", "step": 100, "type": "color" }, "200": { - "value": "#9332ee", + "value": "#dcbcfc", "step": 200, "type": "color" }, "300": { - "value": "#8a24ea", + "value": "#d0a4fa", "step": 300, "type": "color" }, "400": { - "value": "#831ae7", + "value": "#c38bf9", "step": 400, "type": "color" }, "500": { - "value": "#7d19dc", + "value": "#b671f8", "step": 500, "type": "color" }, "600": { - "value": "#781ad2", + "value": "#a856f7", "step": 600, "type": "color" }, "700": { - "value": "#741ac9", + "value": "#9739f1", "step": 700, "type": "color" }, "800": { - "value": "#701bc2", + "value": "#831ae6", "step": 800, "type": "color" }, @@ -974,42 +974,42 @@ "type": "color" }, "100": { - "value": "#d63be2", + "value": "#fad4fc", "step": 100, "type": "color" }, "200": { - "value": "#d12ade", + "value": "#f6bbfa", "step": 200, "type": "color" }, "300": { - "value": "#ca23d6", + "value": "#f1a2f7", "step": 300, "type": "color" }, "400": { - "value": "#c122cc", + "value": "#ec8af3", "step": 400, "type": "color" }, "500": { - "value": "#b921c4", + "value": "#e56fee", "step": 500, "type": "color" }, "600": { - "value": "#b320bd", + "value": "#dd51e7", "step": 600, "type": "color" }, "700": { - "value": "#ad20b7", + "value": "#d32edf", "step": 700, "type": "color" }, "800": { - "value": "#a81fb2", + "value": "#bc21c8", "step": 800, "type": "color" }, @@ -1026,42 +1026,42 @@ "type": "color" }, "100": { - "value": "#e93d92", + "value": "#fcd4e8", "step": 100, "type": "color" }, "200": { - "value": "#e42a87", + "value": "#fbbcdb", "step": 200, "type": "color" }, "300": { - "value": "#e11e7f", + "value": "#f8a5ce", "step": 300, "type": "color" }, "400": { - "value": "#d51e79", + "value": "#f58ac0", "step": 400, "type": "color" }, "500": { - "value": "#cc1e75", + "value": "#f26fb0", "step": 500, "type": "color" }, "600": { - "value": "#c41e71", + "value": "#ee519e", "step": 600, "type": "color" }, "700": { - "value": "#bd1d6d", + "value": "#e52e89", "step": 700, "type": "color" }, "800": { - "value": "#b71d6a", + "value": "#ce1e76", "step": 800, "type": "color" }, diff --git a/styles/figma/dark.json b/styles/figma/dark.json index fadaf7c19e..568f53b815 100644 --- a/styles/figma/dark.json +++ b/styles/figma/dark.json @@ -29,27 +29,27 @@ "type": "color" }, "feature": { - "value": "#1684b6", + "value": "#2db4f3", "step": 500, "type": "color" }, "ok": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" }, "error": { - "value": "#d71c1c", + "value": "#f78c8c", "step": 400, "type": "color" }, "warning": { - "value": "#cc8712", + "value": "#f8c570", "step": 300, "type": "color" }, "info": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" } @@ -81,27 +81,27 @@ "type": "color" }, "feature": { - "value": "#1684b6", + "value": "#2db4f3", "step": 500, "type": "color" }, "ok": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" }, "error": { - "value": "#cd1c1c", + "value": "#f47171", "step": 500, "type": "color" }, "warning": { - "value": "#c38214", + "value": "#f7b241", "step": 400, "type": "color" }, "info": { - "value": "#195cc8", + "value": "#4287f6", "step": 600, "type": "color" } @@ -175,88 +175,88 @@ }, "ok": { "base": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" }, "hovered": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" }, "active": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" }, "focused": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" } }, "error": { "base": { - "value": "#d71c1c", + "value": "#f78c8c", "step": 400, "type": "color" }, "hovered": { - "value": "#d71c1c", + "value": "#f78c8c", "step": 400, "type": "color" }, "active": { - "value": "#d71c1c", + "value": "#f78c8c", "step": 400, "type": "color" }, "focused": { - "value": "#d71c1c", + "value": "#f78c8c", "step": 400, "type": "color" } }, "warning": { "base": { - "value": "#cc8712", + "value": "#f8c570", "step": 300, "type": "color" }, "hovered": { - "value": "#cc8712", + "value": "#f8c570", "step": 300, "type": "color" }, "active": { - "value": "#cc8712", + "value": "#f8c570", "step": 300, "type": "color" }, "focused": { - "value": "#cc8712", + "value": "#f8c570", "step": 300, "type": "color" } }, "info": { "base": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" }, "hovered": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" }, "active": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" }, "focused": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" } @@ -289,22 +289,22 @@ "type": "color" }, "ok": { - "value": "#1ea650", + "value": "#23d464", "step": 500, "type": "color" }, "error": { - "value": "#cd1c1c", + "value": "#f47171", "step": 500, "type": "color" }, "warning": { - "value": "#bb7e15", + "value": "#f59f0c", "step": 500, "type": "color" }, "info": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" } @@ -337,34 +337,34 @@ "type": "color" }, "inserted": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" }, "deleted": { - "value": "#d71c1c", + "value": "#f78c8c", "step": 400, "type": "color" }, "modified": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" } }, "highlight": { "selection": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" }, "occurrence": { - "value": "#1e22db", + "value": "#777af4", "step": 500, "type": "color" }, "activeOccurrence": { - "value": "#2327e2", + "value": "#8f90f6", "step": 400, "type": "color" }, @@ -374,12 +374,12 @@ "type": "color" }, "match": { - "value": "#70a919", + "value": "#87d116", "step": 500, "type": "color" }, "activeMatch": { - "value": "#72ad19", + "value": "#90df17", "step": 400, "type": "color" }, @@ -408,39 +408,39 @@ "type": "color" }, "comment": { - "value": "#7aba18", + "value": "#bdf36b", "type": "color" }, "keyword": { - "value": "#1588bc", + "value": "#59c3f5", "type": "color" }, "function": { - "value": "#cfa00f", + "value": "#fadc89", "type": "color" }, "type": { - "value": "#17a696", + "value": "#26ebd5", "type": "color" }, "variant": { - "value": "#17a696", + "value": "#26ebd5", "type": "color" }, "property": { - "value": "#148dc4", + "value": "#81d2f8", "type": "color" }, "enum": { - "value": "#1588bc", + "value": "#59c3f5", "type": "color" }, "operator": { - "value": "#1588bc", + "value": "#59c3f5", "type": "color" }, "string": { - "value": "#d66211", + "value": "#fab78b", "type": "color" }, "number": { @@ -455,176 +455,176 @@ "player": { "1": { "baseColor": { - "value": "#195cc8", + "value": "#4287f6", "step": 600, "type": "color" }, "cursorColor": { - "value": "#195cc8", + "value": "#4287f6", "step": 600, "type": "color" }, "selectionColor": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" }, "borderColor": { - "value": "#195cc8", + "value": "#4287f6", "step": 600, "type": "color" } }, "2": { "baseColor": { - "value": "#70a919", + "value": "#87d116", "step": 500, "type": "color" }, "cursorColor": { - "value": "#70a919", + "value": "#87d116", "step": 500, "type": "color" }, "selectionColor": { - "value": "#80c517", + "value": "#dbf9ac", "step": 100, "type": "color" }, "borderColor": { - "value": "#70a919", + "value": "#87d116", "step": 500, "type": "color" } }, "3": { "baseColor": { - "value": "#1e22db", + "value": "#777af4", "step": 500, "type": "color" }, "cursorColor": { - "value": "#1e22db", + "value": "#777af4", "step": 500, "type": "color" }, "selectionColor": { - "value": "#5558ee", + "value": "#d4d5fd", "step": 100, "type": "color" }, "borderColor": { - "value": "#1e22db", + "value": "#777af4", "step": 500, "type": "color" } }, "4": { "baseColor": { - "value": "#c45c14", + "value": "#f98a3d", "step": 500, "type": "color" }, "cursorColor": { - "value": "#c45c14", + "value": "#f98a3d", "step": 500, "type": "color" }, "selectionColor": { - "value": "#f66e0f", + "value": "#fde0cd", "step": 100, "type": "color" }, "borderColor": { - "value": "#c45c14", + "value": "#f98a3d", "step": 500, "type": "color" } }, "5": { "baseColor": { - "value": "#7d19dc", + "value": "#b671f8", "step": 500, "type": "color" }, "cursorColor": { - "value": "#7d19dc", + "value": "#b671f8", "step": 500, "type": "color" }, "selectionColor": { - "value": "#a048f4", + "value": "#e9d4fd", "step": 100, "type": "color" }, "borderColor": { - "value": "#7d19dc", + "value": "#b671f8", "step": 500, "type": "color" } }, "6": { "baseColor": { - "value": "#17a293", + "value": "#16ddc7", "step": 400, "type": "color" }, "cursorColor": { - "value": "#17a293", + "value": "#16ddc7", "step": 400, "type": "color" }, "selectionColor": { - "value": "#15b3a2", + "value": "#b4faf2", "step": 100, "type": "color" }, "borderColor": { - "value": "#17a293", + "value": "#16ddc7", "step": 400, "type": "color" } }, "7": { "baseColor": { - "value": "#d51e79", + "value": "#f58ac0", "step": 400, "type": "color" }, "cursorColor": { - "value": "#d51e79", + "value": "#f58ac0", "step": 400, "type": "color" }, "selectionColor": { - "value": "#e93d92", + "value": "#fcd4e8", "step": 100, "type": "color" }, "borderColor": { - "value": "#d51e79", + "value": "#f58ac0", "step": 400, "type": "color" } }, "8": { "baseColor": { - "value": "#bc9212", + "value": "#f6bc09", "step": 400, "type": "color" }, "cursorColor": { - "value": "#bc9212", + "value": "#f6bc09", "step": 400, "type": "color" }, "selectionColor": { - "value": "#e0ac0b", + "value": "#fceabc", "step": 100, "type": "color" }, "borderColor": { - "value": "#bc9212", + "value": "#f6bc09", "step": 400, "type": "color" } diff --git a/styles/figma/light.json b/styles/figma/light.json index 415ab40933..c8ef9e5dcd 100644 --- a/styles/figma/light.json +++ b/styles/figma/light.json @@ -29,27 +29,27 @@ "type": "color" }, "feature": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" }, "ok": { - "value": "#1ea650", + "value": "#23d464", "step": 500, "type": "color" }, "error": { - "value": "#cd1c1c", + "value": "#f47171", "step": 500, "type": "color" }, "warning": { - "value": "#b68e14", + "value": "#e5af09", "step": 500, "type": "color" }, "info": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" } @@ -81,27 +81,27 @@ "type": "color" }, "feature": { - "value": "#1780b0", + "value": "#0ea5e8", "step": 600, "type": "color" }, "ok": { - "value": "#1ea34f", + "value": "#22c55e", "step": 600, "type": "color" }, "error": { - "value": "#c51c1c", + "value": "#f15252", "step": 600, "type": "color" }, "warning": { - "value": "#bc9212", + "value": "#f6bc09", "step": 400, "type": "color" }, "info": { - "value": "#195cc8", + "value": "#4287f6", "step": 600, "type": "color" } @@ -175,88 +175,88 @@ }, "ok": { "base": { - "value": "#21bf5b", + "value": "#befad2", "step": 100, "type": "color" }, "hovered": { - "value": "#21bf5b", + "value": "#befad2", "step": 100, "type": "color" }, "active": { - "value": "#21bf5b", + "value": "#befad2", "step": 100, "type": "color" }, "focused": { - "value": "#21bf5b", + "value": "#befad2", "step": 100, "type": "color" } }, "error": { "base": { - "value": "#ec3939", + "value": "#fdd4d4", "step": 100, "type": "color" }, "hovered": { - "value": "#ec3939", + "value": "#fdd4d4", "step": 100, "type": "color" }, "active": { - "value": "#ec3939", + "value": "#fdd4d4", "step": 100, "type": "color" }, "focused": { - "value": "#ec3939", + "value": "#fdd4d4", "step": 100, "type": "color" } }, "warning": { "base": { - "value": "#e0ac0b", + "value": "#fceabc", "step": 100, "type": "color" }, "hovered": { - "value": "#e0ac0b", + "value": "#fceabc", "step": 100, "type": "color" }, "active": { - "value": "#e0ac0b", + "value": "#fceabc", "step": 100, "type": "color" }, "focused": { - "value": "#e0ac0b", + "value": "#fceabc", "step": 100, "type": "color" } }, "info": { "base": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" }, "hovered": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" }, "active": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" }, "focused": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" } @@ -289,22 +289,22 @@ "type": "color" }, "ok": { - "value": "#20b557", + "value": "#8ff4b2", "step": 200, "type": "color" }, "error": { - "value": "#e72727", + "value": "#fbbdbd", "step": 200, "type": "color" }, "warning": { - "value": "#cfa00f", + "value": "#fadc89", "step": 200, "type": "color" }, "info": { - "value": "#1f6eed", + "value": "#b4cffb", "step": 200, "type": "color" } @@ -337,24 +337,24 @@ "type": "color" }, "inserted": { - "value": "#21bf5b", + "value": "#befad2", "step": 100, "type": "color" }, "deleted": { - "value": "#ec3939", + "value": "#fdd4d4", "step": 100, "type": "color" }, "modified": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" } }, "highlight": { "selection": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" }, @@ -408,39 +408,39 @@ "type": "color" }, "comment": { - "value": "#7aba18", + "value": "#bdf36b", "type": "color" }, "keyword": { - "value": "#1588bc", + "value": "#59c3f5", "type": "color" }, "function": { - "value": "#cfa00f", + "value": "#fadc89", "type": "color" }, "type": { - "value": "#17a696", + "value": "#26ebd5", "type": "color" }, "variant": { - "value": "#17a696", + "value": "#26ebd5", "type": "color" }, "property": { - "value": "#148dc4", + "value": "#81d2f8", "type": "color" }, "enum": { - "value": "#1588bc", + "value": "#59c3f5", "type": "color" }, "operator": { - "value": "#1588bc", + "value": "#59c3f5", "type": "color" }, "string": { - "value": "#d66211", + "value": "#fab78b", "type": "color" }, "number": { @@ -455,176 +455,176 @@ "player": { "1": { "baseColor": { - "value": "#195cc8", + "value": "#4287f6", "step": 600, "type": "color" }, "cursorColor": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" }, "selectionColor": { - "value": "#307af3", + "value": "#d0e2fd", "step": 100, "type": "color" }, "borderColor": { - "value": "#185fd0", + "value": "#6099f7", "step": 500, "type": "color" } }, "2": { "baseColor": { - "value": "#70a919", + "value": "#87d116", "step": 500, "type": "color" }, "cursorColor": { - "value": "#70a919", + "value": "#87d116", "step": 500, "type": "color" }, "selectionColor": { - "value": "#80c517", + "value": "#dbf9ac", "step": 100, "type": "color" }, "borderColor": { - "value": "#70a919", + "value": "#87d116", "step": 500, "type": "color" } }, "3": { "baseColor": { - "value": "#1e22db", + "value": "#777af4", "step": 500, "type": "color" }, "cursorColor": { - "value": "#1e22db", + "value": "#777af4", "step": 500, "type": "color" }, "selectionColor": { - "value": "#5558ee", + "value": "#d4d5fd", "step": 100, "type": "color" }, "borderColor": { - "value": "#1e22db", + "value": "#777af4", "step": 500, "type": "color" } }, "4": { "baseColor": { - "value": "#c45c14", + "value": "#f98a3d", "step": 500, "type": "color" }, "cursorColor": { - "value": "#c45c14", + "value": "#f98a3d", "step": 500, "type": "color" }, "selectionColor": { - "value": "#f66e0f", + "value": "#fde0cd", "step": 100, "type": "color" }, "borderColor": { - "value": "#c45c14", + "value": "#f98a3d", "step": 500, "type": "color" } }, "5": { "baseColor": { - "value": "#7d19dc", + "value": "#b671f8", "step": 500, "type": "color" }, "cursorColor": { - "value": "#7d19dc", + "value": "#b671f8", "step": 500, "type": "color" }, "selectionColor": { - "value": "#a048f4", + "value": "#e9d4fd", "step": 100, "type": "color" }, "borderColor": { - "value": "#7d19dc", + "value": "#b671f8", "step": 500, "type": "color" } }, "6": { "baseColor": { - "value": "#17a293", + "value": "#16ddc7", "step": 400, "type": "color" }, "cursorColor": { - "value": "#17a293", + "value": "#16ddc7", "step": 400, "type": "color" }, "selectionColor": { - "value": "#15b3a2", + "value": "#b4faf2", "step": 100, "type": "color" }, "borderColor": { - "value": "#17a293", + "value": "#16ddc7", "step": 400, "type": "color" } }, "7": { "baseColor": { - "value": "#d51e79", + "value": "#f58ac0", "step": 400, "type": "color" }, "cursorColor": { - "value": "#d51e79", + "value": "#f58ac0", "step": 400, "type": "color" }, "selectionColor": { - "value": "#e93d92", + "value": "#fcd4e8", "step": 100, "type": "color" }, "borderColor": { - "value": "#d51e79", + "value": "#f58ac0", "step": 400, "type": "color" } }, "8": { "baseColor": { - "value": "#bc9212", + "value": "#f6bc09", "step": 400, "type": "color" }, "cursorColor": { - "value": "#bc9212", + "value": "#f6bc09", "step": 400, "type": "color" }, "selectionColor": { - "value": "#e0ac0b", + "value": "#fceabc", "step": 100, "type": "color" }, "borderColor": { - "value": "#bc9212", + "value": "#f6bc09", "step": 400, "type": "color" } diff --git a/styles/utils/color.ts b/styles/utils/color.ts index c7506f696d..156fc5ba41 100644 --- a/styles/utils/color.ts +++ b/styles/utils/color.ts @@ -22,8 +22,8 @@ export function colorRamp( .scale([startColor, color, endColor]) .domain([0, 0.5, 1]) .mode("hsl") - .gamma(0.2) - // .correctLightness(true) + .gamma(1) + .correctLightness(true) .padding([0, 0.15]); } From a3fc719a526e985d5f5296471751ac94b020f55e Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sun, 3 Apr 2022 15:03:38 -0400 Subject: [PATCH 67/68] Add a combined `tokens.json` for Figma Tokens - Having individual json files for themes and core is useful for copy+pasting while exploring changes - Figma github sync requires a single json file to pull down --- styles/buildFigmaTokens.ts | 42 +- styles/figma/tokens.json | 2431 ++++++++++++++++++++++++++++++++++++ 2 files changed, 2460 insertions(+), 13 deletions(-) create mode 100644 styles/figma/tokens.json diff --git a/styles/buildFigmaTokens.ts b/styles/buildFigmaTokens.ts index 6b3285e58e..bb77046e85 100644 --- a/styles/buildFigmaTokens.ts +++ b/styles/buildFigmaTokens.ts @@ -5,8 +5,13 @@ import light from "./themes/light"; import Theme from "./themes/theme"; import { colors, fontFamilies, fontSizes, fontWeights } from "./tokens"; +let themes = [ + dark, + light +]; + // Organize theme tokens -function themeTokens(theme: Theme): Object { +function themeTokens(theme: Theme) { return { meta: { themeName: theme.name, @@ -71,16 +76,6 @@ function themeTokens(theme: Theme): Object { }; } -let themes = [themeTokens(dark), themeTokens(light)]; - -// Create {theme}.json -const themePath = path.resolve(`${__dirname}/figma`); -themes.forEach((theme) => { - const tokenJSON = JSON.stringify(theme, null, 2); - //@ts-ignore //TODO: IDK what the hell TS wants me to do here - fs.writeFileSync(`${themePath}/${theme.meta.themeName}.json`, tokenJSON); -}); - // Organize core tokens const coreTokens = { color: { @@ -93,7 +88,28 @@ const coreTokens = { size: fontSizes, }; +const combinedTokens = { + core: coreTokens, + dark: themeTokens(dark), + light: themeTokens(light) +} + // Create core.json const corePath = path.resolve(`${__dirname}/figma/core.json`); -const coreTokenJSON = JSON.stringify(coreTokens, null, 2); -fs.writeFileSync(corePath, coreTokenJSON); +const coreJSON = JSON.stringify(coreTokens, null, 2); +fs.writeFileSync(corePath, coreJSON); +console.log(`- Core: core.json created`); + +// Create {theme}.json +const themePath = path.resolve(`${__dirname}/figma`); +themes.forEach((theme) => { + const tokenJSON = JSON.stringify(themeTokens(theme), null, 2); + fs.writeFileSync(`${themePath}/${theme.name}.json`, tokenJSON); + console.log(`- Theme: ${theme.name}.json created`); +}); + +// Create combined tokens.json +const combinedPath = path.resolve(`${__dirname}/figma/tokens.json`); +const combinedJSON = JSON.stringify(combinedTokens, null, 2); +fs.writeFileSync(combinedPath, combinedJSON); +console.log(`- Combined: tokens.json created`); \ No newline at end of file diff --git a/styles/figma/tokens.json b/styles/figma/tokens.json new file mode 100644 index 0000000000..cffc3ed16d --- /dev/null +++ b/styles/figma/tokens.json @@ -0,0 +1,2431 @@ +{ + "core": { + "color": { + "neutral": { + "0": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "25": { + "value": "#f8f8f8", + "step": 25, + "type": "color" + }, + "50": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "75": { + "value": "#eaeaea", + "step": 75, + "type": "color" + }, + "100": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "125": { + "value": "#dcdcdc", + "step": 125, + "type": "color" + }, + "150": { + "value": "#d5d5d5", + "step": 150, + "type": "color" + }, + "175": { + "value": "#cdcdcd", + "step": 175, + "type": "color" + }, + "200": { + "value": "#c6c6c6", + "step": 200, + "type": "color" + }, + "225": { + "value": "#bfbfbf", + "step": 225, + "type": "color" + }, + "250": { + "value": "#b8b8b8", + "step": 250, + "type": "color" + }, + "275": { + "value": "#b1b1b1", + "step": 275, + "type": "color" + }, + "300": { + "value": "#aaaaaa", + "step": 300, + "type": "color" + }, + "325": { + "value": "#a3a3a3", + "step": 325, + "type": "color" + }, + "350": { + "value": "#9c9c9c", + "step": 350, + "type": "color" + }, + "375": { + "value": "#959595", + "step": 375, + "type": "color" + }, + "400": { + "value": "#8e8e8e", + "step": 400, + "type": "color" + }, + "425": { + "value": "#878787", + "step": 425, + "type": "color" + }, + "450": { + "value": "#808080", + "step": 450, + "type": "color" + }, + "475": { + "value": "#787878", + "step": 475, + "type": "color" + }, + "500": { + "value": "#717171", + "step": 500, + "type": "color" + }, + "525": { + "value": "#6a6a6a", + "step": 525, + "type": "color" + }, + "550": { + "value": "#636363", + "step": 550, + "type": "color" + }, + "575": { + "value": "#5c5c5c", + "step": 575, + "type": "color" + }, + "600": { + "value": "#555555", + "step": 600, + "type": "color" + }, + "625": { + "value": "#4e4e4e", + "step": 625, + "type": "color" + }, + "650": { + "value": "#474747", + "step": 650, + "type": "color" + }, + "675": { + "value": "#404040", + "step": 675, + "type": "color" + }, + "700": { + "value": "#393939", + "step": 700, + "type": "color" + }, + "725": { + "value": "#323232", + "step": 725, + "type": "color" + }, + "750": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "775": { + "value": "#232323", + "step": 775, + "type": "color" + }, + "800": { + "value": "#1c1c1c", + "step": 800, + "type": "color" + }, + "825": { + "value": "#151515", + "step": 825, + "type": "color" + }, + "850": { + "value": "#0e0e0e", + "step": 850, + "type": "color" + }, + "875": { + "value": "#070707", + "step": 875, + "type": "color" + }, + "900": { + "value": "#000000", + "step": 900, + "type": "color" + } + }, + "rose": { + "0": { + "value": "#feecef", + "step": 0, + "type": "color" + }, + "100": { + "value": "#fdd5db", + "step": 100, + "type": "color" + }, + "200": { + "value": "#fbbdc8", + "step": 200, + "type": "color" + }, + "300": { + "value": "#faa4b3", + "step": 300, + "type": "color" + }, + "400": { + "value": "#f98a9d", + "step": 400, + "type": "color" + }, + "500": { + "value": "#f76e86", + "step": 500, + "type": "color" + }, + "600": { + "value": "#f54c69", + "step": 600, + "type": "color" + }, + "700": { + "value": "#ec2548", + "step": 700, + "type": "color" + }, + "800": { + "value": "#d21939", + "step": 800, + "type": "color" + }, + "900": { + "value": "#b41a35", + "step": 900, + "type": "color" + } + }, + "red": { + "0": { + "value": "#feecec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#fdd4d4", + "step": 100, + "type": "color" + }, + "200": { + "value": "#fbbdbd", + "step": 200, + "type": "color" + }, + "300": { + "value": "#f9a5a5", + "step": 300, + "type": "color" + }, + "400": { + "value": "#f78c8c", + "step": 400, + "type": "color" + }, + "500": { + "value": "#f47171", + "step": 500, + "type": "color" + }, + "600": { + "value": "#f15252", + "step": 600, + "type": "color" + }, + "700": { + "value": "#e82c2c", + "step": 700, + "type": "color" + }, + "800": { + "value": "#d11c1c", + "step": 800, + "type": "color" + }, + "900": { + "value": "#b21c1c", + "step": 900, + "type": "color" + } + }, + "orange": { + "0": { + "value": "#fef3ec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#fde0cd", + "step": 100, + "type": "color" + }, + "200": { + "value": "#fbccac", + "step": 200, + "type": "color" + }, + "300": { + "value": "#fab78b", + "step": 300, + "type": "color" + }, + "400": { + "value": "#faa266", + "step": 400, + "type": "color" + }, + "500": { + "value": "#f98a3d", + "step": 500, + "type": "color" + }, + "600": { + "value": "#f77113", + "step": 600, + "type": "color" + }, + "700": { + "value": "#e0650f", + "step": 700, + "type": "color" + }, + "800": { + "value": "#c65d14", + "step": 800, + "type": "color" + }, + "900": { + "value": "#ac5517", + "step": 900, + "type": "color" + } + }, + "amber": { + "0": { + "value": "#fef7ec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#fce7c4", + "step": 100, + "type": "color" + }, + "200": { + "value": "#fad69d", + "step": 200, + "type": "color" + }, + "300": { + "value": "#f8c570", + "step": 300, + "type": "color" + }, + "400": { + "value": "#f7b241", + "step": 400, + "type": "color" + }, + "500": { + "value": "#f59f0c", + "step": 500, + "type": "color" + }, + "600": { + "value": "#e1930e", + "step": 600, + "type": "color" + }, + "700": { + "value": "#cd8812", + "step": 700, + "type": "color" + }, + "800": { + "value": "#ba7d15", + "step": 800, + "type": "color" + }, + "900": { + "value": "#a77218", + "step": 900, + "type": "color" + } + }, + "yellow": { + "0": { + "value": "#fef9ec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#fceabc", + "step": 100, + "type": "color" + }, + "200": { + "value": "#fadc89", + "step": 200, + "type": "color" + }, + "300": { + "value": "#f8cc4e", + "step": 300, + "type": "color" + }, + "400": { + "value": "#f6bc09", + "step": 400, + "type": "color" + }, + "500": { + "value": "#e5af09", + "step": 500, + "type": "color" + }, + "600": { + "value": "#d4a30d", + "step": 600, + "type": "color" + }, + "700": { + "value": "#c49811", + "step": 700, + "type": "color" + }, + "800": { + "value": "#b48d14", + "step": 800, + "type": "color" + }, + "900": { + "value": "#a48117", + "step": 900, + "type": "color" + } + }, + "lime": { + "0": { + "value": "#f7feec", + "step": 0, + "type": "color" + }, + "100": { + "value": "#dbf9ac", + "step": 100, + "type": "color" + }, + "200": { + "value": "#bdf36b", + "step": 200, + "type": "color" + }, + "300": { + "value": "#9feb2b", + "step": 300, + "type": "color" + }, + "400": { + "value": "#90df17", + "step": 400, + "type": "color" + }, + "500": { + "value": "#87d116", + "step": 500, + "type": "color" + }, + "600": { + "value": "#7fc417", + "step": 600, + "type": "color" + }, + "700": { + "value": "#78b618", + "step": 700, + "type": "color" + }, + "800": { + "value": "#70aa19", + "step": 800, + "type": "color" + }, + "900": { + "value": "#699c1a", + "step": 900, + "type": "color" + } + }, + "green": { + "0": { + "value": "#ecfef2", + "step": 0, + "type": "color" + }, + "100": { + "value": "#befad2", + "step": 100, + "type": "color" + }, + "200": { + "value": "#8ff4b2", + "step": 200, + "type": "color" + }, + "300": { + "value": "#60ec92", + "step": 300, + "type": "color" + }, + "400": { + "value": "#34e173", + "step": 400, + "type": "color" + }, + "500": { + "value": "#23d464", + "step": 500, + "type": "color" + }, + "600": { + "value": "#22c55e", + "step": 600, + "type": "color" + }, + "700": { + "value": "#20b658", + "step": 700, + "type": "color" + }, + "800": { + "value": "#1ea851", + "step": 800, + "type": "color" + }, + "900": { + "value": "#1d9b4b", + "step": 900, + "type": "color" + } + }, + "emerald": { + "0": { + "value": "#ecfef8", + "step": 0, + "type": "color" + }, + "100": { + "value": "#b3fbe3", + "step": 100, + "type": "color" + }, + "200": { + "value": "#72f6ca", + "step": 200, + "type": "color" + }, + "300": { + "value": "#1feda9", + "step": 300, + "type": "color" + }, + "400": { + "value": "#12e09b", + "step": 400, + "type": "color" + }, + "500": { + "value": "#11d091", + "step": 500, + "type": "color" + }, + "600": { + "value": "#11c287", + "step": 600, + "type": "color" + }, + "700": { + "value": "#11b37e", + "step": 700, + "type": "color" + }, + "800": { + "value": "#15a575", + "step": 800, + "type": "color" + }, + "900": { + "value": "#18976c", + "step": 900, + "type": "color" + } + }, + "teal": { + "0": { + "value": "#ecfefc", + "step": 0, + "type": "color" + }, + "100": { + "value": "#b4faf2", + "step": 100, + "type": "color" + }, + "200": { + "value": "#73f4e6", + "step": 200, + "type": "color" + }, + "300": { + "value": "#26ebd5", + "step": 300, + "type": "color" + }, + "400": { + "value": "#16ddc7", + "step": 400, + "type": "color" + }, + "500": { + "value": "#15cfba", + "step": 500, + "type": "color" + }, + "600": { + "value": "#15c1ae", + "step": 600, + "type": "color" + }, + "700": { + "value": "#15b2a1", + "step": 700, + "type": "color" + }, + "800": { + "value": "#17a495", + "step": 800, + "type": "color" + }, + "900": { + "value": "#199788", + "step": 900, + "type": "color" + } + }, + "cyan": { + "0": { + "value": "#ecfcfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#bcf5fc", + "step": 100, + "type": "color" + }, + "200": { + "value": "#86edfa", + "step": 200, + "type": "color" + }, + "300": { + "value": "#41e3f8", + "step": 300, + "type": "color" + }, + "400": { + "value": "#07d5f1", + "step": 400, + "type": "color" + }, + "500": { + "value": "#07c7e1", + "step": 500, + "type": "color" + }, + "600": { + "value": "#07b8d0", + "step": 600, + "type": "color" + }, + "700": { + "value": "#0daabf", + "step": 700, + "type": "color" + }, + "800": { + "value": "#119bae", + "step": 800, + "type": "color" + }, + "900": { + "value": "#168e9e", + "step": 900, + "type": "color" + } + }, + "sky": { + "0": { + "value": "#ecf8fe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#caecfc", + "step": 100, + "type": "color" + }, + "200": { + "value": "#a6defa", + "step": 200, + "type": "color" + }, + "300": { + "value": "#81d2f8", + "step": 300, + "type": "color" + }, + "400": { + "value": "#59c3f5", + "step": 400, + "type": "color" + }, + "500": { + "value": "#2db4f3", + "step": 500, + "type": "color" + }, + "600": { + "value": "#0ea5e8", + "step": 600, + "type": "color" + }, + "700": { + "value": "#1296d1", + "step": 700, + "type": "color" + }, + "800": { + "value": "#1686ba", + "step": 800, + "type": "color" + }, + "900": { + "value": "#1878a4", + "step": 900, + "type": "color" + } + }, + "blue": { + "0": { + "value": "#ecf3fe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + }, + "200": { + "value": "#b4cffb", + "step": 200, + "type": "color" + }, + "300": { + "value": "#99befa", + "step": 300, + "type": "color" + }, + "400": { + "value": "#7cacf9", + "step": 400, + "type": "color" + }, + "500": { + "value": "#6099f7", + "step": 500, + "type": "color" + }, + "600": { + "value": "#4287f6", + "step": 600, + "type": "color" + }, + "700": { + "value": "#2774f0", + "step": 700, + "type": "color" + }, + "800": { + "value": "#1762db", + "step": 800, + "type": "color" + }, + "900": { + "value": "#1a55b4", + "step": 900, + "type": "color" + } + }, + "indigo": { + "0": { + "value": "#ececfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#d4d5fd", + "step": 100, + "type": "color" + }, + "200": { + "value": "#bebefb", + "step": 200, + "type": "color" + }, + "300": { + "value": "#a7a8f9", + "step": 300, + "type": "color" + }, + "400": { + "value": "#8f90f6", + "step": 400, + "type": "color" + }, + "500": { + "value": "#777af4", + "step": 500, + "type": "color" + }, + "600": { + "value": "#5f62f0", + "step": 600, + "type": "color" + }, + "700": { + "value": "#464aeb", + "step": 700, + "type": "color" + }, + "800": { + "value": "#292de4", + "step": 800, + "type": "color" + }, + "900": { + "value": "#1d20bb", + "step": 900, + "type": "color" + } + }, + "violet": { + "0": { + "value": "#f1ecfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#e0d5fd", + "step": 100, + "type": "color" + }, + "200": { + "value": "#cfbcfb", + "step": 200, + "type": "color" + }, + "300": { + "value": "#bda4fa", + "step": 300, + "type": "color" + }, + "400": { + "value": "#ad8cf9", + "step": 400, + "type": "color" + }, + "500": { + "value": "#9b73f7", + "step": 500, + "type": "color" + }, + "600": { + "value": "#8959f6", + "step": 600, + "type": "color" + }, + "700": { + "value": "#7540f0", + "step": 700, + "type": "color" + }, + "800": { + "value": "#5e22e7", + "step": 800, + "type": "color" + }, + "900": { + "value": "#4c1bbc", + "step": 900, + "type": "color" + } + }, + "purple": { + "0": { + "value": "#f5ecfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#e9d4fd", + "step": 100, + "type": "color" + }, + "200": { + "value": "#dcbcfc", + "step": 200, + "type": "color" + }, + "300": { + "value": "#d0a4fa", + "step": 300, + "type": "color" + }, + "400": { + "value": "#c38bf9", + "step": 400, + "type": "color" + }, + "500": { + "value": "#b671f8", + "step": 500, + "type": "color" + }, + "600": { + "value": "#a856f7", + "step": 600, + "type": "color" + }, + "700": { + "value": "#9739f1", + "step": 700, + "type": "color" + }, + "800": { + "value": "#831ae6", + "step": 800, + "type": "color" + }, + "900": { + "value": "#6d1bbb", + "step": 900, + "type": "color" + } + }, + "fuschia": { + "0": { + "value": "#fdecfe", + "step": 0, + "type": "color" + }, + "100": { + "value": "#fad4fc", + "step": 100, + "type": "color" + }, + "200": { + "value": "#f6bbfa", + "step": 200, + "type": "color" + }, + "300": { + "value": "#f1a2f7", + "step": 300, + "type": "color" + }, + "400": { + "value": "#ec8af3", + "step": 400, + "type": "color" + }, + "500": { + "value": "#e56fee", + "step": 500, + "type": "color" + }, + "600": { + "value": "#dd51e7", + "step": 600, + "type": "color" + }, + "700": { + "value": "#d32edf", + "step": 700, + "type": "color" + }, + "800": { + "value": "#bc21c8", + "step": 800, + "type": "color" + }, + "900": { + "value": "#a41ead", + "step": 900, + "type": "color" + } + }, + "pink": { + "0": { + "value": "#feecf5", + "step": 0, + "type": "color" + }, + "100": { + "value": "#fcd4e8", + "step": 100, + "type": "color" + }, + "200": { + "value": "#fbbcdb", + "step": 200, + "type": "color" + }, + "300": { + "value": "#f8a5ce", + "step": 300, + "type": "color" + }, + "400": { + "value": "#f58ac0", + "step": 400, + "type": "color" + }, + "500": { + "value": "#f26fb0", + "step": 500, + "type": "color" + }, + "600": { + "value": "#ee519e", + "step": 600, + "type": "color" + }, + "700": { + "value": "#e52e89", + "step": 700, + "type": "color" + }, + "800": { + "value": "#ce1e76", + "step": 800, + "type": "color" + }, + "900": { + "value": "#b21d67", + "step": 900, + "type": "color" + } + } + }, + "text": { + "family": { + "sans": { + "value": "Zed Sans", + "type": "fontFamily" + }, + "mono": { + "value": "Zed Mono", + "type": "fontFamily" + } + }, + "weight": { + "thin": { + "value": "thin", + "type": "fontWeight" + }, + "extra_light": { + "value": "extra_light", + "type": "fontWeight" + }, + "light": { + "value": "light", + "type": "fontWeight" + }, + "normal": { + "value": "normal", + "type": "fontWeight" + }, + "medium": { + "value": "medium", + "type": "fontWeight" + }, + "semibold": { + "value": "semibold", + "type": "fontWeight" + }, + "bold": { + "value": "bold", + "type": "fontWeight" + }, + "extra_bold": { + "value": "extra_bold", + "type": "fontWeight" + }, + "black": { + "value": "black", + "type": "fontWeight" + } + } + }, + "size": { + "3xs": { + "value": 8, + "type": "fontSize" + }, + "2xs": { + "value": 10, + "type": "fontSize" + }, + "xs": { + "value": 12, + "type": "fontSize" + }, + "sm": { + "value": 14, + "type": "fontSize" + }, + "md": { + "value": 16, + "type": "fontSize" + }, + "lg": { + "value": 18, + "type": "fontSize" + }, + "xl": { + "value": 20, + "type": "fontSize" + } + } + }, + "dark": { + "meta": { + "themeName": "dark" + }, + "text": { + "primary": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "secondary": { + "value": "#9c9c9c", + "step": 350, + "type": "color" + }, + "muted": { + "value": "#636363", + "step": 550, + "type": "color" + }, + "placeholder": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "active": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "feature": { + "value": "#2db4f3", + "step": 500, + "type": "color" + }, + "ok": { + "value": "#22c55e", + "step": 600, + "type": "color" + }, + "error": { + "value": "#f78c8c", + "step": 400, + "type": "color" + }, + "warning": { + "value": "#f8c570", + "step": 300, + "type": "color" + }, + "info": { + "value": "#6099f7", + "step": 500, + "type": "color" + } + }, + "icon": { + "primary": { + "value": "#c6c6c6", + "step": 200, + "type": "color" + }, + "secondary": { + "value": "#9c9c9c", + "step": 350, + "type": "color" + }, + "muted": { + "value": "#555555", + "step": 600, + "type": "color" + }, + "placeholder": { + "value": "#393939", + "step": 700, + "type": "color" + }, + "active": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "feature": { + "value": "#2db4f3", + "step": 500, + "type": "color" + }, + "ok": { + "value": "#22c55e", + "step": 600, + "type": "color" + }, + "error": { + "value": "#f47171", + "step": 500, + "type": "color" + }, + "warning": { + "value": "#f7b241", + "step": 400, + "type": "color" + }, + "info": { + "value": "#4287f6", + "step": 600, + "type": "color" + } + }, + "background": { + "100": { + "base": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "hovered": { + "value": "#323232", + "step": 725, + "type": "color" + }, + "active": { + "value": "#393939", + "step": 700, + "type": "color" + }, + "focused": { + "value": "#404040", + "step": 675, + "type": "color" + } + }, + "300": { + "base": { + "value": "#1c1c1c", + "step": 800, + "type": "color" + }, + "hovered": { + "value": "#232323", + "step": 775, + "type": "color" + }, + "active": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "focused": { + "value": "#323232", + "step": 725, + "type": "color" + } + }, + "500": { + "base": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "hovered": { + "value": "#070707", + "step": 875, + "type": "color" + }, + "active": { + "value": "#0e0e0e", + "step": 850, + "type": "color" + }, + "focused": { + "value": "#151515", + "step": 825, + "type": "color" + } + }, + "ok": { + "base": { + "value": "#22c55e", + "step": 600, + "type": "color" + }, + "hovered": { + "value": "#22c55e", + "step": 600, + "type": "color" + }, + "active": { + "value": "#22c55e", + "step": 600, + "type": "color" + }, + "focused": { + "value": "#22c55e", + "step": 600, + "type": "color" + } + }, + "error": { + "base": { + "value": "#f78c8c", + "step": 400, + "type": "color" + }, + "hovered": { + "value": "#f78c8c", + "step": 400, + "type": "color" + }, + "active": { + "value": "#f78c8c", + "step": 400, + "type": "color" + }, + "focused": { + "value": "#f78c8c", + "step": 400, + "type": "color" + } + }, + "warning": { + "base": { + "value": "#f8c570", + "step": 300, + "type": "color" + }, + "hovered": { + "value": "#f8c570", + "step": 300, + "type": "color" + }, + "active": { + "value": "#f8c570", + "step": 300, + "type": "color" + }, + "focused": { + "value": "#f8c570", + "step": 300, + "type": "color" + } + }, + "info": { + "base": { + "value": "#6099f7", + "step": 500, + "type": "color" + }, + "hovered": { + "value": "#6099f7", + "step": 500, + "type": "color" + }, + "active": { + "value": "#6099f7", + "step": 500, + "type": "color" + }, + "focused": { + "value": "#6099f7", + "step": 500, + "type": "color" + } + } + }, + "border": { + "primary": { + "value": "#070707", + "step": 875, + "type": "color" + }, + "secondary": { + "value": "#151515", + "step": 825, + "type": "color" + }, + "muted": { + "value": "#232323", + "step": 775, + "type": "color" + }, + "focused": { + "value": "#717171", + "step": 500, + "type": "color" + }, + "active": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "ok": { + "value": "#23d464", + "step": 500, + "type": "color" + }, + "error": { + "value": "#f47171", + "step": 500, + "type": "color" + }, + "warning": { + "value": "#f59f0c", + "step": 500, + "type": "color" + }, + "info": { + "value": "#6099f7", + "step": 500, + "type": "color" + } + }, + "editor": { + "background": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "indent_guide": { + "value": "#232323", + "step": 775, + "type": "color" + }, + "indent_guide_active": { + "value": "#151515", + "step": 825, + "type": "color" + }, + "line": { + "active": { + "value": "#0e0e0e", + "step": 850, + "type": "color" + }, + "highlighted": { + "value": "#070707", + "step": 875, + "type": "color" + }, + "inserted": { + "value": "#22c55e", + "step": 600, + "type": "color" + }, + "deleted": { + "value": "#f78c8c", + "step": 400, + "type": "color" + }, + "modified": { + "value": "#6099f7", + "step": 500, + "type": "color" + } + }, + "highlight": { + "selection": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + }, + "occurrence": { + "value": "#777af4", + "step": 500, + "type": "color" + }, + "activeOccurrence": { + "value": "#8f90f6", + "step": 400, + "type": "color" + }, + "matchingBracket": { + "value": "#0e0e0e", + "step": 850, + "type": "color" + }, + "match": { + "value": "#87d116", + "step": 500, + "type": "color" + }, + "activeMatch": { + "value": "#90df17", + "step": 400, + "type": "color" + }, + "related": { + "value": "#151515", + "step": 825, + "type": "color" + } + }, + "gutter": { + "primary": { + "value": "#636363", + "step": 550, + "type": "color" + }, + "active": { + "value": "#ffffff", + "step": 0, + "type": "color" + } + } + }, + "syntax": { + "primary": { + "value": "#f1f1f1", + "type": "color" + }, + "comment": { + "value": "#bdf36b", + "type": "color" + }, + "keyword": { + "value": "#59c3f5", + "type": "color" + }, + "function": { + "value": "#fadc89", + "type": "color" + }, + "type": { + "value": "#26ebd5", + "type": "color" + }, + "variant": { + "value": "#26ebd5", + "type": "color" + }, + "property": { + "value": "#81d2f8", + "type": "color" + }, + "enum": { + "value": "#59c3f5", + "type": "color" + }, + "operator": { + "value": "#59c3f5", + "type": "color" + }, + "string": { + "value": "#fab78b", + "type": "color" + }, + "number": { + "value": "#d5d5d5", + "type": "color" + }, + "boolean": { + "value": "#d5d5d5", + "type": "color" + } + }, + "player": { + "1": { + "baseColor": { + "value": "#4287f6", + "step": 600, + "type": "color" + }, + "cursorColor": { + "value": "#4287f6", + "step": 600, + "type": "color" + }, + "selectionColor": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#4287f6", + "step": 600, + "type": "color" + } + }, + "2": { + "baseColor": { + "value": "#87d116", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#87d116", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#dbf9ac", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#87d116", + "step": 500, + "type": "color" + } + }, + "3": { + "baseColor": { + "value": "#777af4", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#777af4", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#d4d5fd", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#777af4", + "step": 500, + "type": "color" + } + }, + "4": { + "baseColor": { + "value": "#f98a3d", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#f98a3d", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#fde0cd", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#f98a3d", + "step": 500, + "type": "color" + } + }, + "5": { + "baseColor": { + "value": "#b671f8", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#b671f8", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#e9d4fd", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#b671f8", + "step": 500, + "type": "color" + } + }, + "6": { + "baseColor": { + "value": "#16ddc7", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#16ddc7", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#b4faf2", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#16ddc7", + "step": 400, + "type": "color" + } + }, + "7": { + "baseColor": { + "value": "#f58ac0", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#f58ac0", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#fcd4e8", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#f58ac0", + "step": 400, + "type": "color" + } + }, + "8": { + "baseColor": { + "value": "#f6bc09", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#f6bc09", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#fceabc", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#f6bc09", + "step": 400, + "type": "color" + } + } + }, + "shadowAlpha": { + "value": 0.32, + "type": "number" + } + }, + "light": { + "meta": { + "themeName": "light" + }, + "text": { + "primary": { + "value": "#2b2b2b", + "step": 750, + "type": "color" + }, + "secondary": { + "value": "#555555", + "step": 600, + "type": "color" + }, + "muted": { + "value": "#808080", + "step": 450, + "type": "color" + }, + "placeholder": { + "value": "#aaaaaa", + "step": 300, + "type": "color" + }, + "active": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "feature": { + "value": "#6099f7", + "step": 500, + "type": "color" + }, + "ok": { + "value": "#23d464", + "step": 500, + "type": "color" + }, + "error": { + "value": "#f47171", + "step": 500, + "type": "color" + }, + "warning": { + "value": "#e5af09", + "step": 500, + "type": "color" + }, + "info": { + "value": "#6099f7", + "step": 500, + "type": "color" + } + }, + "icon": { + "primary": { + "value": "#aaaaaa", + "step": 300, + "type": "color" + }, + "secondary": { + "value": "#717171", + "step": 500, + "type": "color" + }, + "muted": { + "value": "#555555", + "step": 600, + "type": "color" + }, + "placeholder": { + "value": "#393939", + "step": 700, + "type": "color" + }, + "active": { + "value": "#000000", + "step": 900, + "type": "color" + }, + "feature": { + "value": "#0ea5e8", + "step": 600, + "type": "color" + }, + "ok": { + "value": "#22c55e", + "step": 600, + "type": "color" + }, + "error": { + "value": "#f15252", + "step": 600, + "type": "color" + }, + "warning": { + "value": "#f6bc09", + "step": 400, + "type": "color" + }, + "info": { + "value": "#4287f6", + "step": 600, + "type": "color" + } + }, + "background": { + "100": { + "base": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#d5d5d5", + "step": 150, + "type": "color" + }, + "active": { + "value": "#c6c6c6", + "step": 200, + "type": "color" + }, + "focused": { + "value": "#d5d5d5", + "step": 150, + "type": "color" + } + }, + "300": { + "base": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "hovered": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "active": { + "value": "#d5d5d5", + "step": 150, + "type": "color" + }, + "focused": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + } + }, + "500": { + "base": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "hovered": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "active": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + } + }, + "ok": { + "base": { + "value": "#befad2", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#befad2", + "step": 100, + "type": "color" + }, + "active": { + "value": "#befad2", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#befad2", + "step": 100, + "type": "color" + } + }, + "error": { + "base": { + "value": "#fdd4d4", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#fdd4d4", + "step": 100, + "type": "color" + }, + "active": { + "value": "#fdd4d4", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#fdd4d4", + "step": 100, + "type": "color" + } + }, + "warning": { + "base": { + "value": "#fceabc", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#fceabc", + "step": 100, + "type": "color" + }, + "active": { + "value": "#fceabc", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#fceabc", + "step": 100, + "type": "color" + } + }, + "info": { + "base": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + }, + "hovered": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + }, + "active": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + }, + "focused": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + } + } + }, + "border": { + "primary": { + "value": "#c6c6c6", + "step": 200, + "type": "color" + }, + "secondary": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "muted": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "focused": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "active": { + "value": "#b8b8b8", + "step": 250, + "type": "color" + }, + "ok": { + "value": "#8ff4b2", + "step": 200, + "type": "color" + }, + "error": { + "value": "#fbbdbd", + "step": 200, + "type": "color" + }, + "warning": { + "value": "#fadc89", + "step": 200, + "type": "color" + }, + "info": { + "value": "#b4cffb", + "step": 200, + "type": "color" + } + }, + "editor": { + "background": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "indent_guide": { + "value": "#f1f1f1", + "step": 50, + "type": "color" + }, + "indent_guide_active": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "line": { + "active": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "highlighted": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "inserted": { + "value": "#befad2", + "step": 100, + "type": "color" + }, + "deleted": { + "value": "#fdd4d4", + "step": 100, + "type": "color" + }, + "modified": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + } + }, + "highlight": { + "selection": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + }, + "occurrence": { + "value": "#e3e3e3", + "step": 100, + "type": "color" + }, + "activeOccurrence": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "matchingBracket": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "match": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "activeMatch": { + "value": "#ffffff", + "step": 0, + "type": "color" + }, + "related": { + "value": "#ffffff", + "step": 0, + "type": "color" + } + }, + "gutter": { + "primary": { + "value": "#808080", + "step": 450, + "type": "color" + }, + "active": { + "value": "#000000", + "step": 900, + "type": "color" + } + } + }, + "syntax": { + "primary": { + "value": "#2b2b2b", + "type": "color" + }, + "comment": { + "value": "#bdf36b", + "type": "color" + }, + "keyword": { + "value": "#59c3f5", + "type": "color" + }, + "function": { + "value": "#fadc89", + "type": "color" + }, + "type": { + "value": "#26ebd5", + "type": "color" + }, + "variant": { + "value": "#26ebd5", + "type": "color" + }, + "property": { + "value": "#81d2f8", + "type": "color" + }, + "enum": { + "value": "#59c3f5", + "type": "color" + }, + "operator": { + "value": "#59c3f5", + "type": "color" + }, + "string": { + "value": "#fab78b", + "type": "color" + }, + "number": { + "value": "#d5d5d5", + "type": "color" + }, + "boolean": { + "value": "#d5d5d5", + "type": "color" + } + }, + "player": { + "1": { + "baseColor": { + "value": "#4287f6", + "step": 600, + "type": "color" + }, + "cursorColor": { + "value": "#6099f7", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#d0e2fd", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#6099f7", + "step": 500, + "type": "color" + } + }, + "2": { + "baseColor": { + "value": "#87d116", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#87d116", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#dbf9ac", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#87d116", + "step": 500, + "type": "color" + } + }, + "3": { + "baseColor": { + "value": "#777af4", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#777af4", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#d4d5fd", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#777af4", + "step": 500, + "type": "color" + } + }, + "4": { + "baseColor": { + "value": "#f98a3d", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#f98a3d", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#fde0cd", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#f98a3d", + "step": 500, + "type": "color" + } + }, + "5": { + "baseColor": { + "value": "#b671f8", + "step": 500, + "type": "color" + }, + "cursorColor": { + "value": "#b671f8", + "step": 500, + "type": "color" + }, + "selectionColor": { + "value": "#e9d4fd", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#b671f8", + "step": 500, + "type": "color" + } + }, + "6": { + "baseColor": { + "value": "#16ddc7", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#16ddc7", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#b4faf2", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#16ddc7", + "step": 400, + "type": "color" + } + }, + "7": { + "baseColor": { + "value": "#f58ac0", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#f58ac0", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#fcd4e8", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#f58ac0", + "step": 400, + "type": "color" + } + }, + "8": { + "baseColor": { + "value": "#f6bc09", + "step": 400, + "type": "color" + }, + "cursorColor": { + "value": "#f6bc09", + "step": 400, + "type": "color" + }, + "selectionColor": { + "value": "#fceabc", + "step": 100, + "type": "color" + }, + "borderColor": { + "value": "#f6bc09", + "step": 400, + "type": "color" + } + } + }, + "shadowAlpha": { + "value": 0.12, + "type": "number" + } + } +} \ No newline at end of file From 3dc99a874330b0a93afa5f41956b9e687e8a967d Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Sun, 3 Apr 2022 21:15:14 -0400 Subject: [PATCH 68/68] Update dark, light themes. --- crates/zed/assets/themes/dark.json | 130 +++++++++++++++---------- crates/zed/assets/themes/light.json | 142 +++++++++++++++++----------- styles/styleTree/editor.ts | 20 +++- styles/styleTree/workspace.ts | 2 +- styles/themes/dark.ts | 52 +++++----- styles/themes/light.ts | 38 ++++---- styles/utils/color.ts | 6 +- 7 files changed, 230 insertions(+), 160 deletions(-) diff --git a/crates/zed/assets/themes/dark.json b/crates/zed/assets/themes/dark.json index da7fa4650e..1334a65727 100644 --- a/crates/zed/assets/themes/dark.json +++ b/crates/zed/assets/themes/dark.json @@ -18,7 +18,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#2db4f3", + "color": "#1096d3", "weight": "bold", "size": 14 } @@ -38,7 +38,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#2db4f3", + "color": "#1096d3", "weight": "bold", "size": 14 }, @@ -70,8 +70,8 @@ "size": 14 }, "selection": { - "cursor": "#4287f6", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#103063" }, "text": { "family": "Zed Mono", @@ -111,8 +111,8 @@ "background": "#1c1c1c", "icon_close": "#555555", "icon_close_active": "#ffffff", - "icon_conflict": "#f7b241", - "icon_dirty": "#4287f6", + "icon_conflict": "#f6a724", + "icon_dirty": "#135acd", "icon_width": 8, "spacing": 10, "text": { @@ -137,8 +137,8 @@ "background": "#000000", "icon_close": "#555555", "icon_close_active": "#ffffff", - "icon_conflict": "#f7b241", - "icon_dirty": "#4287f6", + "icon_conflict": "#f6a724", + "icon_dirty": "#135acd", "icon_width": 8, "spacing": 10, "text": { @@ -289,7 +289,7 @@ }, "outdated_warning": { "family": "Zed Sans", - "color": "#f8c570", + "color": "#f7bb57", "size": 13 } }, @@ -297,7 +297,7 @@ "height": 34, "background": "#000000", "border": { - "color": "#070707", + "color": "#151515", "width": 1, "bottom": true }, @@ -325,54 +325,54 @@ } }, "editor": { - "text_color": "#f1f1f1", + "text_color": "#d5d5d5", "background": "#000000", "active_line_background": "#0e0e0e", "code_actions_indicator": "#9c9c9c", - "diff_background_deleted": "#f78c8c", - "diff_background_inserted": "#22c55e", - "document_highlight_read_background": "#777af4", - "document_highlight_write_background": "#777af4", - "error_color": "#f78c8c", + "diff_background_deleted": "#f15656", + "diff_background_inserted": "#1b9447", + "document_highlight_read_background": "#2b2b2b", + "document_highlight_write_background": "#2b2b2b", + "error_color": "#f15656", "gutter_background": "#000000", - "gutter_padding_factor": 2.5, + "gutter_padding_factor": 3.5, "highlighted_line_background": "#070707", "line_number": "#636363", "line_number_active": "#ffffff", "rename_fade": 0.6, "unnecessary_code_fade": 0.5, "selection": { - "cursor": "#4287f6", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#103063" }, "guest_selections": [ { - "cursor": "#87d116", - "selection": "#dbf9ac" + "cursor": "#79ba16", + "selection": "#38530f" }, { - "cursor": "#777af4", - "selection": "#d4d5fd" + "cursor": "#484bed", + "selection": "#121269" }, { - "cursor": "#f98a3d", - "selection": "#fde0cd" + "cursor": "#ee670a", + "selection": "#5d2f0e" }, { - "cursor": "#b671f8", - "selection": "#e9d4fd" + "cursor": "#993bf3", + "selection": "#3e1169" }, { - "cursor": "#16ddc7", - "selection": "#b4faf2" + "cursor": "#16d6c1", + "selection": "#0e4f48" }, { - "cursor": "#f58ac0", - "selection": "#fcd4e8" + "cursor": "#ef59a3", + "selection": "#fbc6e1" }, { - "cursor": "#f6bc09", - "selection": "#fceabc" + "cursor": "#f7bf17", + "selection": "#fce9b7" } ], "autocomplete": { @@ -406,7 +406,7 @@ "left": -14 }, "match_highlight": { - "color": "#59c3f5", + "color": "#4f8ff7", "weight": "normal" }, "selected_item": { @@ -481,12 +481,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#f78c8c", + "color": "#f15656", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#f78c8c", + "color": "#f15656", "size": 14, "weight": "bold" } @@ -504,12 +504,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#f8c570", + "color": "#f7bb57", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#f8c570", + "color": "#f7bb57", "size": 14, "weight": "bold" } @@ -527,12 +527,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "size": 14, "weight": "bold" } @@ -550,12 +550,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "size": 14, "weight": "bold" } @@ -653,7 +653,35 @@ } } }, - "syntax": {} + "syntax": { + "keyword": "#4f8ff7", + "function": "#f9da82", + "string": "#f99d5f", + "type": "#3eeeda", + "number": "#aeef4b", + "comment": "#aaaaaa", + "property": "#4f8ff7", + "variant": "#53c1f5", + "constant": "#d5d5d5", + "title": { + "color": "#de900c", + "weight": "bold" + }, + "emphasis": "#1096d3", + "emphasis_strong": { + "color": "#1096d3", + "weight": "bold" + }, + "link_uri": { + "color": "#79ba16", + "underline": true + }, + "link_text": { + "color": "#ee670a", + "italic": true + }, + "list_marker": "#20b0f2" + } }, "project_diagnostics": { "tab_icon_spacing": 4, @@ -929,8 +957,8 @@ "size": 14 }, "selection": { - "cursor": "#4287f6", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#103063" }, "border": { "color": "#151515", @@ -1067,7 +1095,7 @@ } }, "search": { - "match_background": "#87d116", + "match_background": "#0a2633", "tab_icon_spacing": 4, "tab_icon_width": 14, "active_hovered_option_button": { @@ -1123,8 +1151,8 @@ "size": 16 }, "selection": { - "cursor": "#4287f6", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#103063" }, "text": { "family": "Zed Mono", @@ -1177,8 +1205,8 @@ "size": 16 }, "selection": { - "cursor": "#4287f6", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#103063" }, "text": { "family": "Zed Mono", @@ -1186,7 +1214,7 @@ "size": 16 }, "border": { - "color": "#f47171", + "color": "#eb2d2d", "width": 1 }, "margin": { diff --git a/crates/zed/assets/themes/light.json b/crates/zed/assets/themes/light.json index dcff3352f7..283b3b10b3 100644 --- a/crates/zed/assets/themes/light.json +++ b/crates/zed/assets/themes/light.json @@ -18,7 +18,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "weight": "bold", "size": 14 } @@ -38,7 +38,7 @@ }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "weight": "bold", "size": 14 }, @@ -70,8 +70,8 @@ "size": 14 }, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#c5dafc" }, "text": { "family": "Zed Mono", @@ -111,8 +111,8 @@ "background": "#f1f1f1", "icon_close": "#555555", "icon_close_active": "#000000", - "icon_conflict": "#f6bc09", - "icon_dirty": "#4287f6", + "icon_conflict": "#f7bf17", + "icon_dirty": "#135acd", "icon_width": 8, "spacing": 10, "text": { @@ -137,8 +137,8 @@ "background": "#ffffff", "icon_close": "#555555", "icon_close_active": "#000000", - "icon_conflict": "#f6bc09", - "icon_dirty": "#4287f6", + "icon_conflict": "#f7bf17", + "icon_dirty": "#135acd", "icon_width": 8, "spacing": 10, "text": { @@ -289,7 +289,7 @@ }, "outdated_warning": { "family": "Zed Sans", - "color": "#e5af09", + "color": "#d3a20b", "size": 13 } }, @@ -297,7 +297,7 @@ "height": 34, "background": "#ffffff", "border": { - "color": "#c6c6c6", + "color": "#e3e3e3", "width": 1, "bottom": true }, @@ -327,52 +327,52 @@ "editor": { "text_color": "#2b2b2b", "background": "#ffffff", - "active_line_background": "#e3e3e3", + "active_line_background": "#f1f1f1", "code_actions_indicator": "#717171", - "diff_background_deleted": "#fdd4d4", - "diff_background_inserted": "#befad2", - "document_highlight_read_background": "#e3e3e3", - "document_highlight_write_background": "#e3e3e3", - "error_color": "#f47171", + "diff_background_deleted": "#fcc6c6", + "diff_background_inserted": "#b7f9ce", + "document_highlight_read_background": "#f1f1f1", + "document_highlight_write_background": "#f1f1f1", + "error_color": "#eb2d2d", "gutter_background": "#ffffff", - "gutter_padding_factor": 2.5, - "highlighted_line_background": "#e3e3e3", - "line_number": "#808080", + "gutter_padding_factor": 3.5, + "highlighted_line_background": "#f1f1f1", + "line_number": "#aaaaaa", "line_number_active": "#000000", "rename_fade": 0.6, "unnecessary_code_fade": 0.5, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#c5dafc" }, "guest_selections": [ { - "cursor": "#87d116", - "selection": "#dbf9ac" + "cursor": "#79ba16", + "selection": "#dffab5" }, { - "cursor": "#777af4", - "selection": "#d4d5fd" + "cursor": "#484bed", + "selection": "#cdcdfc" }, { - "cursor": "#f98a3d", - "selection": "#fde0cd" + "cursor": "#ee670a", + "selection": "#fcd6bd" }, { - "cursor": "#b671f8", - "selection": "#e9d4fd" + "cursor": "#993bf3", + "selection": "#e4cbfc" }, { - "cursor": "#16ddc7", - "selection": "#b4faf2" + "cursor": "#16d6c1", + "selection": "#b1faf2" }, { - "cursor": "#f58ac0", - "selection": "#fcd4e8" + "cursor": "#ef59a3", + "selection": "#fbc6e1" }, { - "cursor": "#f6bc09", - "selection": "#fceabc" + "cursor": "#f7bf17", + "selection": "#fce9b7" } ], "autocomplete": { @@ -400,13 +400,13 @@ "right": 6, "top": 2 }, - "background": "#f1f1f1" + "background": "#f8f8f8" }, "margin": { "left": -14 }, "match_highlight": { - "color": "#59c3f5", + "color": "#103063", "weight": "normal" }, "selected_item": { @@ -417,7 +417,7 @@ "right": 6, "top": 2 }, - "background": "#e3e3e3" + "background": "#f1f1f1" } }, "diagnostic_header": { @@ -453,7 +453,7 @@ } }, "diagnostic_path_header": { - "background": "#e3e3e3", + "background": "#f1f1f1", "text_scale_factor": 0.857, "filename": { "family": "Zed Mono", @@ -481,12 +481,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#f47171", + "color": "#eb2d2d", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#f47171", + "color": "#eb2d2d", "size": 14, "weight": "bold" } @@ -504,12 +504,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#e5af09", + "color": "#d3a20b", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#e5af09", + "color": "#d3a20b", "size": 14, "weight": "bold" } @@ -527,12 +527,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "size": 14, "weight": "bold" } @@ -550,12 +550,12 @@ "message": { "text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "size": 14 }, "highlight_text": { "family": "Zed Sans", - "color": "#6099f7", + "color": "#2472f2", "size": 14, "weight": "bold" } @@ -653,7 +653,35 @@ } } }, - "syntax": {} + "syntax": { + "keyword": "#103063", + "function": "#1b9447", + "string": "#bb550e", + "type": "#138a7d", + "number": "#14a898", + "comment": "#555555", + "property": "#134697", + "variant": "#1179a8", + "constant": "#393939", + "title": { + "color": "#1096d3", + "weight": "bold" + }, + "emphasis": "#2472f2", + "emphasis_strong": { + "color": "#2472f2", + "weight": "bold" + }, + "link_uri": { + "color": "#14a898", + "underline": true + }, + "link_text": { + "color": "#ee670a", + "italic": true + }, + "list_marker": "#20b0f2" + } }, "project_diagnostics": { "tab_icon_spacing": 4, @@ -929,8 +957,8 @@ "size": 14 }, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#c5dafc" }, "border": { "color": "#e3e3e3", @@ -1022,7 +1050,7 @@ "padding": { "left": 8 }, - "background": "#e3e3e3", + "background": "#f1f1f1", "corner_radius": 6 }, "unshared_project": { @@ -1062,7 +1090,7 @@ "padding": { "left": 8 }, - "background": "#e3e3e3", + "background": "#f1f1f1", "corner_radius": 6 } }, @@ -1123,8 +1151,8 @@ "size": 16 }, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#c5dafc" }, "text": { "family": "Zed Mono", @@ -1177,8 +1205,8 @@ "size": 16 }, "selection": { - "cursor": "#6099f7", - "selection": "#d0e2fd" + "cursor": "#2472f2", + "selection": "#c5dafc" }, "text": { "family": "Zed Mono", @@ -1186,7 +1214,7 @@ "size": 16 }, "border": { - "color": "#fbbdbd", + "color": "#f9a0a0", "width": 1 }, "margin": { diff --git a/styles/styleTree/editor.ts b/styles/styleTree/editor.ts index e760ecec6a..23c1e67ac6 100644 --- a/styles/styleTree/editor.ts +++ b/styles/styleTree/editor.ts @@ -49,7 +49,7 @@ export default function editor(theme: Theme) { documentHighlightWriteBackground: theme.editor.highlight.occurrence.value, errorColor: theme.textColor.error.value, gutterBackground: backgroundColor(theme, 500), - gutterPaddingFactor: 2.5, + gutterPaddingFactor: 3.5, highlightedLineBackground: theme.editor.line.highlighted.value, lineNumber: theme.editor.gutter.primary.value, lineNumberActive: theme.editor.gutter.active.value, @@ -129,7 +129,21 @@ export default function editor(theme: Theme) { invalidInformationDiagnostic: diagnostic(theme, "muted"), invalidWarningDiagnostic: diagnostic(theme, "muted"), syntax: { - - } + keyword: theme.syntax.keyword.color.value, + function: theme.syntax.function.color.value, + string: theme.syntax.string.color.value, + type: theme.syntax.type.color.value, + number: theme.syntax.number.color.value, + comment: theme.syntax.comment.color.value, + property: theme.syntax.property.color.value, + variant: theme.syntax.variant.color.value, + constant: theme.syntax.constant.color.value, + title: { color: theme.syntax.title.color.value, weight: "bold" }, + emphasis: theme.textColor.feature.value, + "emphasis.strong": { color: theme.textColor.feature.value, weight: "bold" }, + link_uri: { color: theme.syntax.linkUrl.color.value, underline: true }, + link_text: { color: theme.syntax.linkText.color.value, italic: true }, + list_marker: theme.syntax.listMarker.color.value, + }, }; } diff --git a/styles/styleTree/workspace.ts b/styles/styleTree/workspace.ts index 4349ba0ab6..030f8edc95 100644 --- a/styles/styleTree/workspace.ts +++ b/styles/styleTree/workspace.ts @@ -135,7 +135,7 @@ export default function workspace(theme: Theme) { toolbar: { height: 34, background: backgroundColor(theme, 500), - border: border(theme, "primary", { bottom: true }), + border: border(theme, "secondary", { bottom: true }), itemSpacing: 8, padding: { left: 16, right: 8, top: 4, bottom: 4 }, }, diff --git a/styles/themes/dark.ts b/styles/themes/dark.ts index 3cb3b653b4..3351d3d3fa 100644 --- a/styles/themes/dark.ts +++ b/styles/themes/dark.ts @@ -88,39 +88,39 @@ const iconColor = { const player = { 1: { - baseColor: colors.blue[600], - cursorColor: colors.blue[600], - selectionColor: colors.blue[100], - borderColor: colors.blue[600], + baseColor: colors.blue[500], + cursorColor: colors.blue[500], + selectionColor: colors.blue[800], + borderColor: colors.blue[800], }, 2: { baseColor: colors.lime[500], cursorColor: colors.lime[500], - selectionColor: colors.lime[100], + selectionColor: colors.lime[800], borderColor: colors.lime[500], }, 3: { baseColor: colors.indigo[500], cursorColor: colors.indigo[500], - selectionColor: colors.indigo[100], + selectionColor: colors.indigo[800], borderColor: colors.indigo[500], }, 4: { baseColor: colors.orange[500], cursorColor: colors.orange[500], - selectionColor: colors.orange[100], + selectionColor: colors.orange[800], borderColor: colors.orange[500], }, 5: { baseColor: colors.purple[500], cursorColor: colors.purple[500], - selectionColor: colors.purple[100], + selectionColor: colors.purple[800], borderColor: colors.purple[500], }, 6: { baseColor: colors.teal[400], cursorColor: colors.teal[400], - selectionColor: colors.teal[100], + selectionColor: colors.teal[800], borderColor: colors.teal[400], }, 7: { @@ -151,11 +151,11 @@ const editor = { }, highlight: { selection: player[1].selectionColor, - occurrence: colors.indigo[500], // TODO: Why does indigo[500], indigo[100], and indigo[900] all give me the same color? @kethku - activeOccurrence: colors.indigo[400], // TODO: We don't seem to be using this right now in rust + occurrence: colors.neutral[750], + activeOccurrence: colors.neutral[700], matchingBracket: backgroundColor[500].active, - match: colors.lime[500], - activeMatch: colors.lime[400], + match: colors.sky[900], + activeMatch: colors.sky[800], related: backgroundColor[500].focused, }, gutter: { @@ -166,15 +166,15 @@ const editor = { const syntax: Syntax = { primary: { - color: textColor.primary, + color: colors.neutral[150], weight: fontWeights.normal, }, comment: { - color: colors.lime[200], + color: colors.neutral[300], weight: fontWeights.normal, }, punctuation: { - color: textColor.primary, + color: colors.neutral[200], weight: fontWeights.normal, }, constant: { @@ -182,7 +182,7 @@ const syntax: Syntax = { weight: fontWeights.normal, }, keyword: { - color: colors.sky[400], + color: colors.blue[400], weight: fontWeights.normal, }, function: { @@ -194,19 +194,19 @@ const syntax: Syntax = { weight: fontWeights.normal, }, variant: { - color: colors.teal[300], - weight: fontWeights.normal, - }, - property: { color: colors.sky[300], weight: fontWeights.normal, }, + property: { + color: colors.blue[400], + weight: fontWeights.normal, + }, enum: { - color: colors.sky[400], + color: colors.orange[500], weight: fontWeights.normal, }, operator: { - color: colors.sky[400], + color: colors.orange[500], weight: fontWeights.normal, }, string: { @@ -214,11 +214,11 @@ const syntax: Syntax = { weight: fontWeights.normal, }, number: { - color: colors.neutral[150], + color: colors.lime[300], weight: fontWeights.normal, }, boolean: { - color: colors.neutral[150], + color: colors.lime[300], weight: fontWeights.normal, }, predictive: { @@ -226,7 +226,7 @@ const syntax: Syntax = { weight: fontWeights.normal, }, title: { - color: colors.sky[500], + color: colors.amber[500], weight: fontWeights.bold, }, emphasis: { diff --git a/styles/themes/light.ts b/styles/themes/light.ts index ee94e18b19..649fd719a8 100644 --- a/styles/themes/light.ts +++ b/styles/themes/light.ts @@ -18,9 +18,9 @@ const backgroundColor = { }, 500: { base: colors.neutral[0], - hovered: colors.neutral[50], - active: colors.neutral[100], - focused: colors.neutral[50], + hovered: colors.neutral[25], + active: colors.neutral[50], + focused: colors.neutral[75], }, ok: { base: colors.green[100], @@ -159,66 +159,66 @@ const editor = { related: colors.neutral[0], }, gutter: { - primary: textColor.muted, + primary: colors.neutral[300], active: textColor.active, }, }; const syntax: Syntax = { primary: { - color: textColor.primary, + color: colors.neutral[750], weight: fontWeights.normal, }, comment: { - color: colors.lime[200], + color: colors.neutral[600], weight: fontWeights.normal, }, punctuation: { - color: textColor.primary, + color: colors.neutral[700], weight: fontWeights.normal, }, constant: { - color: colors.neutral[150], + color: colors.neutral[700], weight: fontWeights.normal, }, keyword: { - color: colors.sky[400], + color: colors.blue[800], weight: fontWeights.normal, }, function: { - color: colors.yellow[200], + color: colors.green[600], weight: fontWeights.normal, }, type: { - color: colors.teal[300], + color: colors.teal[600], weight: fontWeights.normal, }, variant: { - color: colors.teal[300], + color: colors.sky[600], weight: fontWeights.normal, }, property: { - color: colors.sky[300], + color: colors.blue[700], weight: fontWeights.normal, }, enum: { - color: colors.sky[400], + color: colors.orange[600], weight: fontWeights.normal, }, operator: { - color: colors.sky[400], + color: colors.orange[600], weight: fontWeights.normal, }, string: { - color: colors.orange[300], + color: colors.orange[600], weight: fontWeights.normal, }, number: { - color: colors.neutral[150], + color: colors.teal[500], weight: fontWeights.normal, }, boolean: { - color: colors.neutral[150], + color: colors.amber[600], weight: fontWeights.normal, }, predictive: { @@ -238,7 +238,7 @@ const syntax: Syntax = { weight: fontWeights.bold, }, linkUrl: { - color: colors.lime[500], + color: colors.teal[500], weight: fontWeights.normal, // TODO: add underline }, diff --git a/styles/utils/color.ts b/styles/utils/color.ts index 156fc5ba41..e69d903a43 100644 --- a/styles/utils/color.ts +++ b/styles/utils/color.ts @@ -17,14 +17,14 @@ export function colorRamp( } else { let hue = Math.round(chroma(color).hsl()[0]); let startColor = chroma.hsl(hue, 0.88, 0.96); - let endColor = chroma.hsl(hue, 0.68, 0.32); + let endColor = chroma.hsl(hue, 0.68, 0.12); scale = chroma .scale([startColor, color, endColor]) .domain([0, 0.5, 1]) .mode("hsl") .gamma(1) - .correctLightness(true) - .padding([0, 0.15]); + // .correctLightness(true) + .padding([0, 0]); } const ramp: ColorRamp = {};