From a6dd070f9216a118b697c6bd607801fdb0288b92 Mon Sep 17 00:00:00 2001 From: Mark Grey Date: Mon, 12 Feb 2024 17:01:46 -0500 Subject: [PATCH 01/40] Implement initial structs from spec --- zellij-utils/src/data.rs | 37 +++++++++++++++++++++++++++++++++ zellij-utils/src/input/theme.rs | 3 ++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index 54c056e359..830b7a2895 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -1134,6 +1134,43 @@ pub struct Style { pub hide_session_name: bool, } +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub struct Styling { + text_unselected: [PaletteColor; 6], + text_selected: [PaletteColor; 6], + ribbon_unselected: [PaletteColor; 6], + ribbon_selected: [PaletteColor; 6], + table_title: [PaletteColor; 6], + table_cell_unselected: [PaletteColor; 6], + table_cell_selected: [PaletteColor; 6], + list_unselected: [PaletteColor; 6], + list_selected: [PaletteColor; 6], + frame_unselected: [PaletteColor; 5], + frame_selected: [PaletteColor; 5], + exit_code_success: [PaletteColor; 5], + exit_code_error: [PaletteColor; 5], +} + +impl Default for Styling { + fn default() -> Self { + Self { + text_unselected: Default::default(), + text_selected: Default::default(), + ribbon_unselected: Default::default(), + ribbon_selected: Default::default(), + table_title: Default::default(), + table_cell_unselected: Default::default(), + table_cell_selected: Default::default(), + list_unselected: Default::default(), + list_selected: Default::default(), + frame_unselected: Default::default(), + frame_selected: Default::default(), + exit_code_success: Default::default(), + exit_code_error: Default::default(), + } + } +} + // FIXME: Poor devs hashtable since HashTable can't derive `Default`... pub type KeybindsVec = Vec<(InputMode, Vec<(KeyWithModifier, Vec)>)>; diff --git a/zellij-utils/src/input/theme.rs b/zellij-utils/src/input/theme.rs index bf0edf232c..eb4c2023dc 100644 --- a/zellij-utils/src/input/theme.rs +++ b/zellij-utils/src/input/theme.rs @@ -7,7 +7,7 @@ use std::{ fmt, }; -use crate::data::Palette; +use crate::data::{Palette, Styling}; #[derive(Debug, Default, Clone, Copy, PartialEq, Deserialize, Serialize)] pub struct UiConfig { @@ -73,6 +73,7 @@ impl Themes { pub struct Theme { #[serde(flatten)] pub palette: Palette, + pub styling: Styling, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] From 2bbe0a522527bfde3e4298630ae30215b3f4924f Mon Sep 17 00:00:00 2001 From: Mark Grey Date: Mon, 12 Feb 2024 17:02:12 -0500 Subject: [PATCH 02/40] kdl configuration unmarshalling --- zellij-client/src/lib.rs | 1 + zellij-utils/assets/prost/api.style.rs | 33 ++++++ zellij-utils/src/data.rs | 61 +++++----- zellij-utils/src/input/config.rs | 145 +++++++++++++++++++++++- zellij-utils/src/kdl/mod.rs | 78 ++++++++++--- zellij-utils/src/plugin_api/event.rs | 2 + zellij-utils/src/plugin_api/style.proto | 19 +++- zellij-utils/src/plugin_api/style.rs | 25 +++- 8 files changed, 312 insertions(+), 52 deletions(-) diff --git a/zellij-client/src/lib.rs b/zellij-client/src/lib.rs index 422e205283..ce2322d02c 100644 --- a/zellij-client/src/lib.rs +++ b/zellij-client/src/lib.rs @@ -215,6 +215,7 @@ pub fn start_client( size: full_screen_ws, style: Style { colors: palette, + styling: palette.into(), rounded_corners: config.ui.pane_frames.rounded_corners, hide_session_name: config.ui.pane_frames.hide_session_name, }, diff --git a/zellij-utils/assets/prost/api.style.rs b/zellij-utils/assets/prost/api.style.rs index cd768c3908..1f99b9709d 100644 --- a/zellij-utils/assets/prost/api.style.rs +++ b/zellij-utils/assets/prost/api.style.rs @@ -1,12 +1,15 @@ #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Style { + #[deprecated] #[prost(message, optional, tag = "1")] pub palette: ::core::option::Option, #[prost(bool, tag = "2")] pub rounded_corners: bool, #[prost(bool, tag = "3")] pub hide_session_name: bool, + #[prost(message, optional, tag = "4")] + pub styling: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -77,6 +80,36 @@ pub struct RgbColorPayload { #[prost(uint32, tag = "3")] pub blue: u32, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Styling { + #[prost(message, repeated, tag = "1")] + pub text_unselected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "2")] + pub text_selected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "3")] + pub ribbon_unselected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "4")] + pub ribbon_selected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "5")] + pub table_title: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "6")] + pub table_cell_unselected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "7")] + pub table_cell_selected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "8")] + pub list_unselected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "9")] + pub list_selected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "10")] + pub frame_unselected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "11")] + pub frame_selected: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "12")] + pub exit_code_success: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "13")] + pub exit_code_error: ::prost::alloc::vec::Vec, +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum ColorType { diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index 830b7a2895..eac08f79cf 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -1130,44 +1130,39 @@ pub struct Palette { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default, Serialize, Deserialize)] pub struct Style { pub colors: Palette, + pub styling: Styling, pub rounded_corners: bool, pub hide_session_name: bool, } -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[derive(Debug, Copy, Default, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] pub struct Styling { - text_unselected: [PaletteColor; 6], - text_selected: [PaletteColor; 6], - ribbon_unselected: [PaletteColor; 6], - ribbon_selected: [PaletteColor; 6], - table_title: [PaletteColor; 6], - table_cell_unselected: [PaletteColor; 6], - table_cell_selected: [PaletteColor; 6], - list_unselected: [PaletteColor; 6], - list_selected: [PaletteColor; 6], - frame_unselected: [PaletteColor; 5], - frame_selected: [PaletteColor; 5], - exit_code_success: [PaletteColor; 5], - exit_code_error: [PaletteColor; 5], -} - -impl Default for Styling { - fn default() -> Self { - Self { - text_unselected: Default::default(), - text_selected: Default::default(), - ribbon_unselected: Default::default(), - ribbon_selected: Default::default(), - table_title: Default::default(), - table_cell_unselected: Default::default(), - table_cell_selected: Default::default(), - list_unselected: Default::default(), - list_selected: Default::default(), - frame_unselected: Default::default(), - frame_selected: Default::default(), - exit_code_success: Default::default(), - exit_code_error: Default::default(), - } + pub text_unselected: [PaletteColor; 6], + pub text_selected: [PaletteColor; 6], + pub ribbon_unselected: [PaletteColor; 6], + pub ribbon_selected: [PaletteColor; 6], + pub table_title: [PaletteColor; 6], + pub table_cell_unselected: [PaletteColor; 6], + pub table_cell_selected: [PaletteColor; 6], + pub list_unselected: [PaletteColor; 6], + pub list_selected: [PaletteColor; 6], + pub frame_unselected: [PaletteColor; 5], + pub frame_selected: [PaletteColor; 5], + pub exit_code_success: [PaletteColor; 5], + pub exit_code_error: [PaletteColor; 5], +} + +impl From for Styling { + fn from(_value: Palette) -> Self { + // TODO: Implement mapping of old colors -> styling + todo!() + } +} + +impl From for Palette { + // TODO: Implement mapping of old colors -> styling + fn from(_value: Styling) -> Self { + todo!() } } diff --git a/zellij-utils/src/input/config.rs b/zellij-utils/src/input/config.rs index 56c6f338af..91f887d8e5 100644 --- a/zellij-utils/src/input/config.rs +++ b/zellij-utils/src/input/config.rs @@ -238,7 +238,7 @@ impl Config { #[cfg(test)] mod config_test { use super::*; - use crate::data::{InputMode, Palette, PaletteColor, PluginTag}; + use crate::data::{InputMode, Palette, PaletteColor, PluginTag, Styling}; use crate::input::layout::{RunPlugin, RunPluginLocation}; use crate::input::options::{Clipboard, OnForceClose}; use crate::input::plugins::{PluginConfig, PluginType}; @@ -463,6 +463,7 @@ mod config_test { white: PaletteColor::Rgb((255, 255, 255)), ..Default::default() }, + styling: Default::default(), }, ); let expected_themes = Themes::from_data(expected_themes); @@ -520,6 +521,7 @@ mod config_test { white: PaletteColor::Rgb((255, 255, 255)), ..Default::default() }, + styling: Default::default(), }, ); expected_themes.insert( @@ -539,6 +541,7 @@ mod config_test { orange: PaletteColor::Rgb((208, 135, 112)), ..Default::default() }, + styling: Default::default(), }, ); let expected_themes = Themes::from_data(expected_themes); @@ -583,12 +586,152 @@ mod config_test { white: PaletteColor::EightBit(255), ..Default::default() }, + styling: Default::default(), }, ); let expected_themes = Themes::from_data(expected_themes); assert_eq!(config.themes, expected_themes, "Theme defined in config"); } + #[test] + fn can_define_style_for_theme_with_hex() { + let config_contents = r##" + themes { + named_theme { + styling { + // base emp1 emp2 emp3 emp4 bg + text_unselected "#DCD7BA" "#DCD7CD" "#DCD8DD" "#DCD899" "#ACD7CD" "#1F1F28" + text_selected "#16161D" "#16161D" "#16161D" "#16161D" "#16161D" "#9CABCA" + ribbon_unselected "#DCD7BA" "#7FB4CA" "#A3D4D5" "#7AA89F" "#DCD819" "#252535" + ribbon_selected "#16161D" "#181820" "#1A1A22" "#2A2A37" "#363646" "#76946A" + table_title "#DCD7BA" "#7FB4CA" "#A3D4D5" "#7AA89F" "#DCD819" "#252535" + table_cell_unselected "#DCD7BA" "#DCD7CD" "#DCD8DD" "#DCD899" "#ACD7CD" "#1F1F28" + table_cell_selected "#16161D" "#181820" "#1A1A22" "#2A2A37" "#363646" "#76946A" + list_unselected "#DCD7BA" "#DCD7CD" "#DCD8DD" "#DCD899" "#ACD7CD" "#1F1F28" + list_selected "#16161D" "#181820" "#1A1A22" "#2A2A37" "#363646" "#76946A" + frame_unselected "#DCD8DD" "#7FB4CA" "#A3D4D5" "#7AA89F" "#DCD819" + frame_selected "#76946A" "#C34043" "#C8C093" "#ACD7CD" "#DCD819" + exit_code_success "#76946A" "#76946A" "#76946A" "#76946A" "#76946A" + exit_code_error "#C34043" "#C34043" "#C34043" "#C34043" "#C34043" + } + } + } + "##; + + let config = Config::from_kdl(config_contents, None).unwrap(); + let mut expected_themes = HashMap::new(); + expected_themes.insert( + "named_theme".into(), + Theme { + styling: Styling { + text_unselected: [ + PaletteColor::Rgb((220, 215, 186)), + PaletteColor::Rgb((220, 215, 205)), + PaletteColor::Rgb((220, 216, 221)), + PaletteColor::Rgb((220, 216, 153)), + PaletteColor::Rgb((172, 215, 205)), + PaletteColor::Rgb((31, 31, 40)), + ], + text_selected: [ + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((156, 171, 202)), + ], + ribbon_unselected: [ + PaletteColor::Rgb((220, 215, 186)), + PaletteColor::Rgb((127, 180, 202)), + PaletteColor::Rgb((163, 212, 213)), + PaletteColor::Rgb((122, 168, 159)), + PaletteColor::Rgb((220, 216, 25)), + PaletteColor::Rgb((37, 37, 53)), + ], + ribbon_selected: [ + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((24, 24, 32)), + PaletteColor::Rgb((26, 26, 34)), + PaletteColor::Rgb((42, 42, 55)), + PaletteColor::Rgb((54, 54, 70)), + PaletteColor::Rgb((118, 148, 106)), + ], + table_title: [ + PaletteColor::Rgb((220, 215, 186)), + PaletteColor::Rgb((127, 180, 202)), + PaletteColor::Rgb((163, 212, 213)), + PaletteColor::Rgb((122, 168, 159)), + PaletteColor::Rgb((220, 216, 25)), + PaletteColor::Rgb((37, 37, 53)), + ], + table_cell_unselected: [ + PaletteColor::Rgb((220, 215, 186)), + PaletteColor::Rgb((220, 215, 205)), + PaletteColor::Rgb((220, 216, 221)), + PaletteColor::Rgb((220, 216, 153)), + PaletteColor::Rgb((172, 215, 205)), + PaletteColor::Rgb((31, 31, 40)), + ], + table_cell_selected: [ + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((24, 24, 32)), + PaletteColor::Rgb((26, 26, 34)), + PaletteColor::Rgb((42, 42, 55)), + PaletteColor::Rgb((54, 54, 70)), + PaletteColor::Rgb((118, 148, 106)), + ], + list_unselected: [ + PaletteColor::Rgb((220, 215, 186)), + PaletteColor::Rgb((220, 215, 205)), + PaletteColor::Rgb((220, 216, 221)), + PaletteColor::Rgb((220, 216, 153)), + PaletteColor::Rgb((172, 215, 205)), + PaletteColor::Rgb((31, 31, 40)), + ], + list_selected: [ + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((22, 22, 29)), + PaletteColor::Rgb((156, 171, 202)), + ], + frame_unselected: [ + PaletteColor::Rgb((220, 216, 221)), + PaletteColor::Rgb((127, 180, 202)), + PaletteColor::Rgb((163, 212, 213)), + PaletteColor::Rgb((122, 168, 159)), + PaletteColor::Rgb((220, 216, 25)), + ], + frame_selected: [ + PaletteColor::Rgb((118, 148, 106)), + PaletteColor::Rgb((195, 64, 67)), + PaletteColor::Rgb((200, 192, 147)), + PaletteColor::Rgb((172, 215, 205)), + PaletteColor::Rgb((220, 216, 125)), + ], + exit_code_success: [ + PaletteColor::Rgb((118, 148, 106)), + PaletteColor::Rgb((118, 148, 106)), + PaletteColor::Rgb((118, 148, 106)), + PaletteColor::Rgb((118, 148, 106)), + PaletteColor::Rgb((118, 148, 106)), + ], + exit_code_error: [ + PaletteColor::Rgb((195, 64, 67)), + PaletteColor::Rgb((195, 64, 67)), + PaletteColor::Rgb((195, 64, 67)), + PaletteColor::Rgb((195, 64, 67)), + PaletteColor::Rgb((195, 64, 67)), + ], + }, + palette: Default::default(), + }, + ); + let expected_themes = Themes::from_data(expected_themes); + assert_eq!(config.themes, expected_themes, "Theme defined in config") + } + #[test] fn can_define_plugin_configuration_in_configfile() { let config_contents = r#" diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index a69b6b0276..9baff92a4e 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -1,7 +1,7 @@ mod kdl_layout_parser; use crate::data::{ Direction, FloatingPaneCoordinates, InputMode, KeyWithModifier, LayoutInfo, Palette, - PaletteColor, PaneInfo, PaneManifest, PermissionType, Resize, SessionInfo, TabInfo, + PaletteColor, PaneInfo, PaneManifest, PermissionType, Resize, SessionInfo, Styling, TabInfo, }; use crate::envs::EnvironmentVariables; use crate::home::{find_default_config_dir, get_layout_dir}; @@ -1981,20 +1981,68 @@ impl Themes { for theme_config in kdl_children_nodes_or_error!(themes_from_kdl, "no themes found") { let theme_name = kdl_name!(theme_config); let theme_colors = kdl_children_or_error!(theme_config, "empty theme"); - let theme = Theme { - palette: Palette { - fg: PaletteColor::try_from(("fg", theme_colors))?, - bg: PaletteColor::try_from(("bg", theme_colors))?, - red: PaletteColor::try_from(("red", theme_colors))?, - green: PaletteColor::try_from(("green", theme_colors))?, - yellow: PaletteColor::try_from(("yellow", theme_colors))?, - blue: PaletteColor::try_from(("blue", theme_colors))?, - magenta: PaletteColor::try_from(("magenta", theme_colors))?, - orange: PaletteColor::try_from(("orange", theme_colors))?, - cyan: PaletteColor::try_from(("cyan", theme_colors))?, - black: PaletteColor::try_from(("black", theme_colors))?, - white: PaletteColor::try_from(("white", theme_colors))?, - ..Default::default() + let styling = kdl_child_with_name!(theme_config, "styling"); + /* + let styling_node = + kdl_child_with_name!(theme_config, "styling").ok_or(ConfigError::new_kdl_error( + "Styling block invalid".into(), + theme_config.span().offset(), + theme_config.span().len(), + ))?; + + let mut colors = BTreeMap::new(); + let color_nodes = kdl_children_nodes_or_error!(theme_config, "Palette is empty").iter(); + for color in color_nodes.filter(|n| n.name().value() != "styling") { + let color_name = kdl_name!(color); + let color = PaletteColor::try_from(color)?; + colors.insert(color_name.to_owned(), color); + } + */ + let theme = match styling { + // Newer theme definition with named styles + Some(style) => { + let s = Styling { + text_unselected: todo!(), + text_selected: todo!(), + ribbon_unselected: todo!(), + ribbon_selected: todo!(), + table_title: todo!(), + table_cell_unselected: todo!(), + table_cell_selected: todo!(), + list_unselected: todo!(), + list_selected: todo!(), + frame_unselected: todo!(), + frame_selected: todo!(), + exit_code_success: todo!(), + exit_code_error: todo!(), + }; + + let t = Theme { + palette: Default::default(), + styling: Default::default(), + }; + t + }, + // Older palette based theme definition + None => { + let palette = Palette { + fg: PaletteColor::try_from(("fg", theme_colors))?, + bg: PaletteColor::try_from(("bg", theme_colors))?, + red: PaletteColor::try_from(("red", theme_colors))?, + green: PaletteColor::try_from(("green", theme_colors))?, + yellow: PaletteColor::try_from(("yellow", theme_colors))?, + blue: PaletteColor::try_from(("blue", theme_colors))?, + magenta: PaletteColor::try_from(("magenta", theme_colors))?, + orange: PaletteColor::try_from(("orange", theme_colors))?, + cyan: PaletteColor::try_from(("cyan", theme_colors))?, + black: PaletteColor::try_from(("black", theme_colors))?, + white: PaletteColor::try_from(("white", theme_colors))?, + ..Default::default() + }; + Theme { + palette, + styling: palette.into(), + } }, }; themes.insert(theme_name.into(), theme); diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs index 1e793e66cf..30814b842e 100644 --- a/zellij-utils/src/plugin_api/event.rs +++ b/zellij-utils/src/plugin_api/event.rs @@ -1115,6 +1115,8 @@ fn serialize_mode_update_event_with_non_default_values() { pink: PaletteColor::EightBit(2), brown: PaletteColor::Rgb((222, 221, 220)), }, + // TODO: replace default + styling: Default::default(), rounded_corners: true, hide_session_name: false, }, diff --git a/zellij-utils/src/plugin_api/style.proto b/zellij-utils/src/plugin_api/style.proto index f4f3b75889..8cc50b192e 100644 --- a/zellij-utils/src/plugin_api/style.proto +++ b/zellij-utils/src/plugin_api/style.proto @@ -3,9 +3,10 @@ syntax = "proto3"; package api.style; message Style { - Palette palette = 1; + Palette palette = 1 [deprecated = true]; bool rounded_corners = 2; bool hide_session_name = 3; + Styling styling = 4; } message Palette { @@ -52,3 +53,19 @@ enum ThemeHue { Dark = 0; Light = 1; } + +message Styling { + repeated Color text_unselected = 1; + repeated Color text_selected = 2; + repeated Color ribbon_unselected = 3; + repeated Color ribbon_selected =4; + repeated Color table_title = 5; + repeated Color table_cell_unselected = 6; + repeated Color table_cell_selected = 7; + repeated Color list_unselected = 8; + repeated Color list_selected = 9; + repeated Color frame_unselected = 10; + repeated Color frame_selected = 11; + repeated Color exit_code_success = 12; + repeated Color exit_code_error = 13; +} diff --git a/zellij-utils/src/plugin_api/style.rs b/zellij-utils/src/plugin_api/style.rs index 1e3ba677f6..795a026948 100644 --- a/zellij-utils/src/plugin_api/style.rs +++ b/zellij-utils/src/plugin_api/style.rs @@ -1,9 +1,9 @@ use super::generated_api::api::style::{ color::Payload as ProtobufColorPayload, Color as ProtobufColor, ColorType as ProtobufColorType, Palette as ProtobufPalette, RgbColorPayload as ProtobufRgbColorPayload, Style as ProtobufStyle, - ThemeHue as ProtobufThemeHue, + Styling as ProtobufStyling, ThemeHue as ProtobufThemeHue, }; -use crate::data::{Palette, PaletteColor, Style, ThemeHue}; +use crate::data::{Palette, PaletteColor, Style, Styling, ThemeHue}; use crate::errors::prelude::*; use std::convert::TryFrom; @@ -16,6 +16,10 @@ impl TryFrom for Style { .palette .ok_or("malformed style payload")? .try_into()?, + styling: protobuf_style + .styling + .ok_or("malformed style payload")? + .try_into()?, rounded_corners: protobuf_style.rounded_corners, hide_session_name: protobuf_style.hide_session_name, }) @@ -29,10 +33,27 @@ impl TryFrom