Merge remote-tracking branch 'origin/main' into editor2-paint
This commit is contained in:
commit
bdf6e8bcc7
204 changed files with 48828 additions and 1648 deletions
18
crates/theme_importer/Cargo.toml
Normal file
18
crates/theme_importer/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "theme_importer"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
convert_case = "0.6.0"
|
||||
gpui = { package = "gpui2", path = "../gpui2" }
|
||||
log.workspace = true
|
||||
rust-embed.workspace = true
|
||||
serde.workspace = true
|
||||
simplelog = "0.9"
|
||||
theme = { package = "theme2", path = "../theme2" }
|
||||
uuid.workspace = true
|
124
crates/theme_importer/README.md
Normal file
124
crates/theme_importer/README.md
Normal file
|
@ -0,0 +1,124 @@
|
|||
# Zed Theme Importer
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
- `cargo run -p theme_importer` - Import the context of `assets/themes/src`
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
As the importer generates rust files, you may need to manually do some cleanup in `registry.rs` and `themes/mod.rs` if you remove themes or delete the `themes` folder in the theme crate.
|
||||
|
||||
---
|
||||
|
||||
## Required Structure
|
||||
|
||||
To import a theme or series of themes 3 things are required:
|
||||
|
||||
- `family.json`: A JSON file containing the theme family metadata and list of theme variants
|
||||
- `{theme_name}.json`: One theme json for each theme variant
|
||||
- `LICENSE`: A license file for the theme family
|
||||
|
||||
### `family.json`
|
||||
|
||||
#### `name`
|
||||
|
||||
The name of the theme family. Avoid special characters.
|
||||
|
||||
This will be used for the theme family directory name (lowercased) and the theme family name in the Zed UI.
|
||||
|
||||
Good:
|
||||
|
||||
- `Rose Pine`
|
||||
- `Synthwave 84`
|
||||
- `Monokai Solarized`
|
||||
|
||||
Bad:
|
||||
|
||||
- `Rosé Pine`
|
||||
- `Synthwave '84`
|
||||
- `Monokai (Solarized)`
|
||||
|
||||
#### `author`
|
||||
|
||||
The author of the theme family. This can be a name or a username.
|
||||
|
||||
This will be used for the theme family author in the Zed UI.
|
||||
|
||||
#### `themes`
|
||||
|
||||
A list of theme variants.
|
||||
|
||||
`appearance` can be either `light` or `dark`. This will impact which default fallback colors are used, and where the theme shows up in the Zed UI.
|
||||
|
||||
### `{theme_name}.json`
|
||||
|
||||
Each theme added to the family must have a corresponding JSON file. This JSON file can be obtained from the VSCode extensions folder (once you have installed it.) This is usually located at `~/.vscode/extensions` (on macOS).
|
||||
|
||||
You can use `open ~/.vscode/extensions` to open the folder in Finder directly.
|
||||
|
||||
Copy that json file into the theme family directory and tidy up the filenames as needed.
|
||||
|
||||
### `LICENSE`
|
||||
|
||||
A LICENSE file is required to import a theme family. Failing to provide a complete text license will cause it to be skipped when the import is run.
|
||||
|
||||
If the theme only provices a license code (e.g. MIT, Apache 2.0, etc.) then put that code into the LICENSE file.
|
||||
|
||||
If no license is provided, either contact the theme creator or don't add the theme.
|
||||
|
||||
---
|
||||
|
||||
### Complete Example:
|
||||
|
||||
An example family with multiple variants:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Ayu",
|
||||
// When both name and username are available
|
||||
// prefer the `username (name)` format
|
||||
"author": "dempfi (Ike Ku)",
|
||||
"themes": [
|
||||
{
|
||||
"name": "Ayu Light",
|
||||
"file_name": "ayu-light.json",
|
||||
"appearance": "light"
|
||||
},
|
||||
{
|
||||
"name": "Ayu Mirage",
|
||||
"file_name": "ayu-mirage.json",
|
||||
"appearance": "dark"
|
||||
},
|
||||
{
|
||||
"name": "Ayu Dark",
|
||||
"file_name": "ayu-dark.json",
|
||||
"appearance": "dark"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
An example single variant family:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Andromeda",
|
||||
"author": "Eliver Lara (EliverLara)",
|
||||
"themes": [
|
||||
{
|
||||
"name": "Andromeda",
|
||||
"file_name": "andromeda.json",
|
||||
"appearance": "dark"
|
||||
},
|
||||
{
|
||||
"name": "Andromeda Bordered",
|
||||
"file_name": "andromeda-bordered.json",
|
||||
"appearance": "dark"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
215
crates/theme_importer/src/main.rs
Normal file
215
crates/theme_importer/src/main.rs
Normal file
|
@ -0,0 +1,215 @@
|
|||
mod theme_printer;
|
||||
mod util;
|
||||
mod vscode;
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use convert_case::{Case, Casing};
|
||||
use gpui::serde_json;
|
||||
use log::LevelFilter;
|
||||
use serde::Deserialize;
|
||||
use simplelog::SimpleLogger;
|
||||
use theme::{default_color_scales, Appearance, ThemeFamily};
|
||||
use vscode::VsCodeThemeConverter;
|
||||
|
||||
use crate::theme_printer::ThemeFamilyPrinter;
|
||||
use crate::vscode::VsCodeTheme;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct FamilyMetadata {
|
||||
pub name: String,
|
||||
pub author: String,
|
||||
pub themes: Vec<ThemeMetadata>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ThemeAppearanceJson {
|
||||
Light,
|
||||
Dark,
|
||||
}
|
||||
|
||||
impl From<ThemeAppearanceJson> for Appearance {
|
||||
fn from(value: ThemeAppearanceJson) -> Self {
|
||||
match value {
|
||||
ThemeAppearanceJson::Light => Self::Light,
|
||||
ThemeAppearanceJson::Dark => Self::Dark,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ThemeMetadata {
|
||||
pub name: String,
|
||||
pub file_name: String,
|
||||
pub appearance: ThemeAppearanceJson,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
const SOURCE_PATH: &str = "assets/themes/src/vscode";
|
||||
const OUT_PATH: &str = "crates/theme2/src/themes";
|
||||
|
||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||
|
||||
println!("Loading themes source...");
|
||||
let vscode_themes_path = PathBuf::from_str(SOURCE_PATH)?;
|
||||
if !vscode_themes_path.exists() {
|
||||
return Err(anyhow!(format!(
|
||||
"Couldn't find {}, make sure it exists",
|
||||
SOURCE_PATH
|
||||
)));
|
||||
}
|
||||
|
||||
let mut theme_families = Vec::new();
|
||||
|
||||
for theme_family_dir in fs::read_dir(&vscode_themes_path)? {
|
||||
let theme_family_dir = theme_family_dir?;
|
||||
|
||||
if !theme_family_dir.file_type()?.is_dir() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let theme_family_slug = theme_family_dir
|
||||
.path()
|
||||
.file_stem()
|
||||
.ok_or(anyhow!("no file stem"))
|
||||
.map(|stem| stem.to_string_lossy().to_string())?;
|
||||
|
||||
let family_metadata_file = File::open(theme_family_dir.path().join("family.json"))
|
||||
.context(format!(
|
||||
"no `family.json` found for '{}'",
|
||||
theme_family_slug
|
||||
))?;
|
||||
|
||||
let license_file_path = theme_family_dir.path().join("LICENSE");
|
||||
|
||||
if !license_file_path.exists() {
|
||||
println!("Skipping theme family '{}' because it does not have a LICENSE file. This theme will only be imported once a LICENSE file is provided.", theme_family_slug);
|
||||
continue;
|
||||
}
|
||||
|
||||
let family_metadata: FamilyMetadata = serde_json::from_reader(family_metadata_file)
|
||||
.context(format!(
|
||||
"failed to parse `family.json` for '{theme_family_slug}'"
|
||||
))?;
|
||||
|
||||
let mut themes = Vec::new();
|
||||
|
||||
for theme_metadata in family_metadata.themes {
|
||||
let theme_file_path = theme_family_dir.path().join(&theme_metadata.file_name);
|
||||
|
||||
let theme_file = match File::open(&theme_file_path) {
|
||||
Ok(file) => file,
|
||||
Err(_) => {
|
||||
println!("Failed to open file at path: {:?}", theme_file_path);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let vscode_theme: VsCodeTheme = serde_json::from_reader(theme_file)
|
||||
.context(format!("failed to parse theme {theme_file_path:?}"))?;
|
||||
|
||||
let converter = VsCodeThemeConverter::new(vscode_theme, theme_metadata);
|
||||
|
||||
let theme = converter.convert()?;
|
||||
|
||||
themes.push(theme);
|
||||
}
|
||||
|
||||
let theme_family = ThemeFamily {
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
name: family_metadata.name.into(),
|
||||
author: family_metadata.author.into(),
|
||||
themes,
|
||||
scales: default_color_scales(),
|
||||
};
|
||||
|
||||
theme_families.push(theme_family);
|
||||
}
|
||||
|
||||
let themes_output_path = PathBuf::from_str(OUT_PATH)?;
|
||||
|
||||
if !themes_output_path.exists() {
|
||||
println!("Creating directory: {:?}", themes_output_path);
|
||||
fs::create_dir_all(&themes_output_path)?;
|
||||
}
|
||||
|
||||
let mut mod_rs_file = File::create(themes_output_path.join(format!("mod.rs")))?;
|
||||
|
||||
let mut theme_modules = Vec::new();
|
||||
|
||||
for theme_family in theme_families {
|
||||
let theme_family_slug = theme_family.name.to_string().to_case(Case::Snake);
|
||||
|
||||
let mut output_file =
|
||||
File::create(themes_output_path.join(format!("{theme_family_slug}.rs")))?;
|
||||
println!(
|
||||
"Creating file: {:?}",
|
||||
themes_output_path.join(format!("{theme_family_slug}.rs"))
|
||||
);
|
||||
|
||||
let theme_module = format!(
|
||||
r#"
|
||||
use gpui::rgba;
|
||||
|
||||
use crate::{{
|
||||
default_color_scales, Appearance, GitStatusColors, PlayerColor, PlayerColors, StatusColors,
|
||||
SyntaxTheme, SystemColors, ThemeColors, ThemeFamily, ThemeStyles, ThemeVariant,
|
||||
}};
|
||||
|
||||
pub fn {theme_family_slug}() -> ThemeFamily {{
|
||||
{theme_family_definition}
|
||||
}}
|
||||
"#,
|
||||
theme_family_definition = format!("{:#?}", ThemeFamilyPrinter::new(theme_family))
|
||||
);
|
||||
|
||||
output_file.write_all(theme_module.as_bytes())?;
|
||||
|
||||
theme_modules.push(theme_family_slug);
|
||||
}
|
||||
|
||||
let themes_vector_contents = format!(
|
||||
r#"
|
||||
use crate::ThemeFamily;
|
||||
|
||||
pub(crate) fn all_imported_themes() -> Vec<ThemeFamily> {{
|
||||
vec![{all_themes}]
|
||||
}}
|
||||
"#,
|
||||
all_themes = theme_modules
|
||||
.iter()
|
||||
.map(|module| format!("{}()", module))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
);
|
||||
|
||||
let mod_rs_contents = format!(
|
||||
r#"
|
||||
{mod_statements}
|
||||
|
||||
{use_statements}
|
||||
|
||||
{themes_vector_contents}
|
||||
"#,
|
||||
mod_statements = theme_modules
|
||||
.iter()
|
||||
.map(|module| format!("mod {module};"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
use_statements = theme_modules
|
||||
.iter()
|
||||
.map(|module| format!("pub use {module}::*;"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
themes_vector_contents = themes_vector_contents
|
||||
);
|
||||
|
||||
mod_rs_file.write_all(mod_rs_contents.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
384
crates/theme_importer/src/theme_printer.rs
Normal file
384
crates/theme_importer/src/theme_printer.rs
Normal file
|
@ -0,0 +1,384 @@
|
|||
use std::fmt::{self, Debug};
|
||||
|
||||
use gpui::{Hsla, Rgba};
|
||||
use theme::{
|
||||
Appearance, GitStatusColors, PlayerColor, PlayerColors, StatusColors, SyntaxTheme,
|
||||
SystemColors, ThemeColors, ThemeFamily, ThemeStyles, ThemeVariant,
|
||||
};
|
||||
|
||||
struct RawSyntaxPrinter<'a>(&'a str);
|
||||
|
||||
impl<'a> Debug for RawSyntaxPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
struct HslaPrinter(Hsla);
|
||||
|
||||
impl Debug for HslaPrinter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", IntoPrinter(&Rgba::from(self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
struct IntoPrinter<'a, D: Debug>(&'a D);
|
||||
|
||||
impl<'a, D: Debug> Debug for IntoPrinter<'a, D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}.into()", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VecPrinter<'a, T>(&'a Vec<T>);
|
||||
|
||||
impl<'a, T: Debug> Debug for VecPrinter<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "vec!{:?}", &self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThemeFamilyPrinter(ThemeFamily);
|
||||
|
||||
impl ThemeFamilyPrinter {
|
||||
pub fn new(theme_family: ThemeFamily) -> Self {
|
||||
Self(theme_family)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for ThemeFamilyPrinter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("ThemeFamily")
|
||||
.field("id", &IntoPrinter(&self.0.id))
|
||||
.field("name", &IntoPrinter(&self.0.name))
|
||||
.field("author", &IntoPrinter(&self.0.author))
|
||||
.field(
|
||||
"themes",
|
||||
&VecPrinter(
|
||||
&self
|
||||
.0
|
||||
.themes
|
||||
.iter()
|
||||
.map(|theme| ThemeVariantPrinter(theme))
|
||||
.collect(),
|
||||
),
|
||||
)
|
||||
.field("scales", &RawSyntaxPrinter("default_color_scales()"))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThemeVariantPrinter<'a>(&'a ThemeVariant);
|
||||
|
||||
impl<'a> Debug for ThemeVariantPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("ThemeVariant")
|
||||
.field("id", &IntoPrinter(&self.0.id))
|
||||
.field("name", &IntoPrinter(&self.0.name))
|
||||
.field("appearance", &AppearancePrinter(self.0.appearance))
|
||||
.field("styles", &ThemeStylesPrinter(&self.0.styles))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AppearancePrinter(Appearance);
|
||||
|
||||
impl Debug for AppearancePrinter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Appearance::{:?}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThemeStylesPrinter<'a>(&'a ThemeStyles);
|
||||
|
||||
impl<'a> Debug for ThemeStylesPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("ThemeStyles")
|
||||
.field("system", &SystemColorsPrinter(&self.0.system))
|
||||
.field("colors", &ThemeColorsPrinter(&self.0.colors))
|
||||
.field("status", &StatusColorsPrinter(&self.0.status))
|
||||
.field("git", &GitStatusColorsPrinter(&self.0.git))
|
||||
.field("player", &PlayerColorsPrinter(&self.0.player))
|
||||
.field("syntax", &SyntaxThemePrinter(&self.0.syntax))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SystemColorsPrinter<'a>(&'a SystemColors);
|
||||
|
||||
impl<'a> Debug for SystemColorsPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SystemColors")
|
||||
.field("transparent", &HslaPrinter(self.0.transparent))
|
||||
.field(
|
||||
"mac_os_traffic_light_red",
|
||||
&HslaPrinter(self.0.mac_os_traffic_light_red),
|
||||
)
|
||||
.field(
|
||||
"mac_os_traffic_light_yellow",
|
||||
&HslaPrinter(self.0.mac_os_traffic_light_yellow),
|
||||
)
|
||||
.field(
|
||||
"mac_os_traffic_light_green",
|
||||
&HslaPrinter(self.0.mac_os_traffic_light_green),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThemeColorsPrinter<'a>(&'a ThemeColors);
|
||||
|
||||
impl<'a> Debug for ThemeColorsPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("ThemeColors")
|
||||
.field("border", &HslaPrinter(self.0.border))
|
||||
.field("border_variant", &HslaPrinter(self.0.border_variant))
|
||||
.field("border_focused", &HslaPrinter(self.0.border_focused))
|
||||
.field("border_disabled", &HslaPrinter(self.0.border_disabled))
|
||||
.field("border_selected", &HslaPrinter(self.0.border_selected))
|
||||
.field(
|
||||
"border_transparent",
|
||||
&HslaPrinter(self.0.border_transparent),
|
||||
)
|
||||
.field(
|
||||
"elevated_surface_background",
|
||||
&HslaPrinter(self.0.elevated_surface_background),
|
||||
)
|
||||
.field(
|
||||
"surface_background",
|
||||
&HslaPrinter(self.0.surface_background),
|
||||
)
|
||||
.field("background", &HslaPrinter(self.0.background))
|
||||
.field(
|
||||
"element_background",
|
||||
&HslaPrinter(self.0.element_background),
|
||||
)
|
||||
.field("element_hover", &HslaPrinter(self.0.element_hover))
|
||||
.field("element_active", &HslaPrinter(self.0.element_active))
|
||||
.field("element_selected", &HslaPrinter(self.0.element_selected))
|
||||
.field("element_disabled", &HslaPrinter(self.0.element_disabled))
|
||||
.field(
|
||||
"element_placeholder",
|
||||
&HslaPrinter(self.0.element_placeholder),
|
||||
)
|
||||
.field(
|
||||
"element_drop_target",
|
||||
&HslaPrinter(self.0.element_drop_target),
|
||||
)
|
||||
.field(
|
||||
"ghost_element_background",
|
||||
&HslaPrinter(self.0.ghost_element_background),
|
||||
)
|
||||
.field(
|
||||
"ghost_element_hover",
|
||||
&HslaPrinter(self.0.ghost_element_hover),
|
||||
)
|
||||
.field(
|
||||
"ghost_element_active",
|
||||
&HslaPrinter(self.0.ghost_element_active),
|
||||
)
|
||||
.field(
|
||||
"ghost_element_selected",
|
||||
&HslaPrinter(self.0.ghost_element_selected),
|
||||
)
|
||||
.field(
|
||||
"ghost_element_disabled",
|
||||
&HslaPrinter(self.0.ghost_element_disabled),
|
||||
)
|
||||
.field("text", &HslaPrinter(self.0.text))
|
||||
.field("text_muted", &HslaPrinter(self.0.text_muted))
|
||||
.field("text_placeholder", &HslaPrinter(self.0.text_placeholder))
|
||||
.field("text_disabled", &HslaPrinter(self.0.text_disabled))
|
||||
.field("text_accent", &HslaPrinter(self.0.text_accent))
|
||||
.field("icon", &HslaPrinter(self.0.icon))
|
||||
.field("icon_muted", &HslaPrinter(self.0.icon_muted))
|
||||
.field("icon_disabled", &HslaPrinter(self.0.icon_disabled))
|
||||
.field("icon_placeholder", &HslaPrinter(self.0.icon_placeholder))
|
||||
.field("icon_accent", &HslaPrinter(self.0.icon_accent))
|
||||
.field(
|
||||
"status_bar_background",
|
||||
&HslaPrinter(self.0.status_bar_background),
|
||||
)
|
||||
.field(
|
||||
"title_bar_background",
|
||||
&HslaPrinter(self.0.title_bar_background),
|
||||
)
|
||||
.field(
|
||||
"toolbar_background",
|
||||
&HslaPrinter(self.0.toolbar_background),
|
||||
)
|
||||
.field(
|
||||
"tab_bar_background",
|
||||
&HslaPrinter(self.0.tab_bar_background),
|
||||
)
|
||||
.field(
|
||||
"tab_inactive_background",
|
||||
&HslaPrinter(self.0.tab_inactive_background),
|
||||
)
|
||||
.field(
|
||||
"tab_active_background",
|
||||
&HslaPrinter(self.0.tab_active_background),
|
||||
)
|
||||
.field("editor_background", &HslaPrinter(self.0.editor_background))
|
||||
.field(
|
||||
"editor_subheader_background",
|
||||
&HslaPrinter(self.0.editor_subheader_background),
|
||||
)
|
||||
.field(
|
||||
"editor_active_line",
|
||||
&HslaPrinter(self.0.editor_active_line_background),
|
||||
)
|
||||
.field(
|
||||
"terminal_background",
|
||||
&HslaPrinter(self.0.terminal_background),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_bright_black",
|
||||
&HslaPrinter(self.0.terminal_ansi_bright_black),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_bright_red",
|
||||
&HslaPrinter(self.0.terminal_ansi_bright_red),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_bright_green",
|
||||
&HslaPrinter(self.0.terminal_ansi_bright_green),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_bright_yellow",
|
||||
&HslaPrinter(self.0.terminal_ansi_bright_yellow),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_bright_blue",
|
||||
&HslaPrinter(self.0.terminal_ansi_bright_blue),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_bright_magenta",
|
||||
&HslaPrinter(self.0.terminal_ansi_bright_magenta),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_bright_cyan",
|
||||
&HslaPrinter(self.0.terminal_ansi_bright_cyan),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_bright_white",
|
||||
&HslaPrinter(self.0.terminal_ansi_bright_white),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_black",
|
||||
&HslaPrinter(self.0.terminal_ansi_black),
|
||||
)
|
||||
.field("terminal_ansi_red", &HslaPrinter(self.0.terminal_ansi_red))
|
||||
.field(
|
||||
"terminal_ansi_green",
|
||||
&HslaPrinter(self.0.terminal_ansi_green),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_yellow",
|
||||
&HslaPrinter(self.0.terminal_ansi_yellow),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_blue",
|
||||
&HslaPrinter(self.0.terminal_ansi_blue),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_magenta",
|
||||
&HslaPrinter(self.0.terminal_ansi_magenta),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_cyan",
|
||||
&HslaPrinter(self.0.terminal_ansi_cyan),
|
||||
)
|
||||
.field(
|
||||
"terminal_ansi_white",
|
||||
&HslaPrinter(self.0.terminal_ansi_white),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StatusColorsPrinter<'a>(&'a StatusColors);
|
||||
|
||||
impl<'a> Debug for StatusColorsPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("StatusColors")
|
||||
.field("conflict", &HslaPrinter(self.0.conflict))
|
||||
.field("created", &HslaPrinter(self.0.created))
|
||||
.field("deleted", &HslaPrinter(self.0.deleted))
|
||||
.field("error", &HslaPrinter(self.0.error))
|
||||
.field("hidden", &HslaPrinter(self.0.hidden))
|
||||
.field("ignored", &HslaPrinter(self.0.ignored))
|
||||
.field("info", &HslaPrinter(self.0.info))
|
||||
.field("modified", &HslaPrinter(self.0.modified))
|
||||
.field("renamed", &HslaPrinter(self.0.renamed))
|
||||
.field("success", &HslaPrinter(self.0.success))
|
||||
.field("warning", &HslaPrinter(self.0.warning))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GitStatusColorsPrinter<'a>(&'a GitStatusColors);
|
||||
|
||||
impl<'a> Debug for GitStatusColorsPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("GitStatusColors")
|
||||
.field("conflict", &HslaPrinter(self.0.conflict))
|
||||
.field("created", &HslaPrinter(self.0.created))
|
||||
.field("deleted", &HslaPrinter(self.0.deleted))
|
||||
.field("ignored", &HslaPrinter(self.0.ignored))
|
||||
.field("modified", &HslaPrinter(self.0.modified))
|
||||
.field("renamed", &HslaPrinter(self.0.renamed))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PlayerColorsPrinter<'a>(&'a PlayerColors);
|
||||
|
||||
impl<'a> Debug for PlayerColorsPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("PlayerColors")
|
||||
.field(&VecPrinter(
|
||||
&self
|
||||
.0
|
||||
.0
|
||||
.iter()
|
||||
.map(|player_color| PlayerColorPrinter(player_color))
|
||||
.collect(),
|
||||
))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PlayerColorPrinter<'a>(&'a PlayerColor);
|
||||
|
||||
impl<'a> Debug for PlayerColorPrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PlayerColor")
|
||||
.field("cursor", &HslaPrinter(self.0.cursor))
|
||||
.field("background", &HslaPrinter(self.0.background))
|
||||
.field("selection", &HslaPrinter(self.0.selection))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SyntaxThemePrinter<'a>(&'a SyntaxTheme);
|
||||
|
||||
impl<'a> Debug for SyntaxThemePrinter<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SyntaxTheme")
|
||||
.field(
|
||||
"highlights",
|
||||
&VecPrinter(
|
||||
&self
|
||||
.0
|
||||
.highlights
|
||||
.iter()
|
||||
.map(|(token, highlight)| {
|
||||
(IntoPrinter(token), HslaPrinter(highlight.color.unwrap()))
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
11
crates/theme_importer/src/util.rs
Normal file
11
crates/theme_importer/src/util.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
use anyhow::Result;
|
||||
|
||||
pub trait Traverse<T, U> {
|
||||
fn traverse(self, f: impl FnOnce(T) -> Result<U>) -> Result<Option<U>>;
|
||||
}
|
||||
|
||||
impl<T, U> Traverse<T, U> for Option<T> {
|
||||
fn traverse(self, f: impl FnOnce(T) -> Result<U>) -> Result<Option<U>> {
|
||||
self.map_or(Ok(None), |value| f(value).map(Some))
|
||||
}
|
||||
}
|
606
crates/theme_importer/src/vscode.rs
Normal file
606
crates/theme_importer/src/vscode.rs
Normal file
|
@ -0,0 +1,606 @@
|
|||
use anyhow::Result;
|
||||
use gpui::{Hsla, Refineable, Rgba};
|
||||
use serde::Deserialize;
|
||||
use theme::{
|
||||
Appearance, GitStatusColors, PlayerColors, StatusColors, SyntaxTheme, SystemColors,
|
||||
ThemeColors, ThemeColorsRefinement, ThemeStyles, ThemeVariant,
|
||||
};
|
||||
|
||||
use crate::util::Traverse;
|
||||
use crate::ThemeMetadata;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct VsCodeTheme {
|
||||
#[serde(rename = "$schema")]
|
||||
pub schema: Option<String>,
|
||||
pub name: Option<String>,
|
||||
pub author: Option<String>,
|
||||
pub maintainers: Option<Vec<String>>,
|
||||
#[serde(rename = "semanticClass")]
|
||||
pub semantic_class: Option<String>,
|
||||
#[serde(rename = "semanticHighlighting")]
|
||||
pub semantic_highlighting: Option<bool>,
|
||||
pub colors: VsCodeColors,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct VsCodeColors {
|
||||
#[serde(rename = "terminal.background")]
|
||||
pub terminal_background: Option<String>,
|
||||
#[serde(rename = "terminal.foreground")]
|
||||
pub terminal_foreground: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBrightBlack")]
|
||||
pub terminal_ansi_bright_black: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBrightRed")]
|
||||
pub terminal_ansi_bright_red: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBrightGreen")]
|
||||
pub terminal_ansi_bright_green: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBrightYellow")]
|
||||
pub terminal_ansi_bright_yellow: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBrightBlue")]
|
||||
pub terminal_ansi_bright_blue: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBrightMagenta")]
|
||||
pub terminal_ansi_bright_magenta: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBrightCyan")]
|
||||
pub terminal_ansi_bright_cyan: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBrightWhite")]
|
||||
pub terminal_ansi_bright_white: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBlack")]
|
||||
pub terminal_ansi_black: Option<String>,
|
||||
#[serde(rename = "terminal.ansiRed")]
|
||||
pub terminal_ansi_red: Option<String>,
|
||||
#[serde(rename = "terminal.ansiGreen")]
|
||||
pub terminal_ansi_green: Option<String>,
|
||||
#[serde(rename = "terminal.ansiYellow")]
|
||||
pub terminal_ansi_yellow: Option<String>,
|
||||
#[serde(rename = "terminal.ansiBlue")]
|
||||
pub terminal_ansi_blue: Option<String>,
|
||||
#[serde(rename = "terminal.ansiMagenta")]
|
||||
pub terminal_ansi_magenta: Option<String>,
|
||||
#[serde(rename = "terminal.ansiCyan")]
|
||||
pub terminal_ansi_cyan: Option<String>,
|
||||
#[serde(rename = "terminal.ansiWhite")]
|
||||
pub terminal_ansi_white: Option<String>,
|
||||
#[serde(rename = "focusBorder")]
|
||||
pub focus_border: Option<String>,
|
||||
pub foreground: Option<String>,
|
||||
#[serde(rename = "selection.background")]
|
||||
pub selection_background: Option<String>,
|
||||
#[serde(rename = "errorForeground")]
|
||||
pub error_foreground: Option<String>,
|
||||
#[serde(rename = "button.background")]
|
||||
pub button_background: Option<String>,
|
||||
#[serde(rename = "button.foreground")]
|
||||
pub button_foreground: Option<String>,
|
||||
#[serde(rename = "button.secondaryBackground")]
|
||||
pub button_secondary_background: Option<String>,
|
||||
#[serde(rename = "button.secondaryForeground")]
|
||||
pub button_secondary_foreground: Option<String>,
|
||||
#[serde(rename = "button.secondaryHoverBackground")]
|
||||
pub button_secondary_hover_background: Option<String>,
|
||||
#[serde(rename = "dropdown.background")]
|
||||
pub dropdown_background: Option<String>,
|
||||
#[serde(rename = "dropdown.border")]
|
||||
pub dropdown_border: Option<String>,
|
||||
#[serde(rename = "dropdown.foreground")]
|
||||
pub dropdown_foreground: Option<String>,
|
||||
#[serde(rename = "input.background")]
|
||||
pub input_background: Option<String>,
|
||||
#[serde(rename = "input.foreground")]
|
||||
pub input_foreground: Option<String>,
|
||||
#[serde(rename = "input.border")]
|
||||
pub input_border: Option<String>,
|
||||
#[serde(rename = "input.placeholderForeground")]
|
||||
pub input_placeholder_foreground: Option<String>,
|
||||
#[serde(rename = "inputOption.activeBorder")]
|
||||
pub input_option_active_border: Option<String>,
|
||||
#[serde(rename = "inputValidation.infoBorder")]
|
||||
pub input_validation_info_border: Option<String>,
|
||||
#[serde(rename = "inputValidation.warningBorder")]
|
||||
pub input_validation_warning_border: Option<String>,
|
||||
#[serde(rename = "inputValidation.errorBorder")]
|
||||
pub input_validation_error_border: Option<String>,
|
||||
#[serde(rename = "badge.foreground")]
|
||||
pub badge_foreground: Option<String>,
|
||||
#[serde(rename = "badge.background")]
|
||||
pub badge_background: Option<String>,
|
||||
#[serde(rename = "progressBar.background")]
|
||||
pub progress_bar_background: Option<String>,
|
||||
#[serde(rename = "list.activeSelectionBackground")]
|
||||
pub list_active_selection_background: Option<String>,
|
||||
#[serde(rename = "list.activeSelectionForeground")]
|
||||
pub list_active_selection_foreground: Option<String>,
|
||||
#[serde(rename = "list.dropBackground")]
|
||||
pub list_drop_background: Option<String>,
|
||||
#[serde(rename = "list.focusBackground")]
|
||||
pub list_focus_background: Option<String>,
|
||||
#[serde(rename = "list.highlightForeground")]
|
||||
pub list_highlight_foreground: Option<String>,
|
||||
#[serde(rename = "list.hoverBackground")]
|
||||
pub list_hover_background: Option<String>,
|
||||
#[serde(rename = "list.inactiveSelectionBackground")]
|
||||
pub list_inactive_selection_background: Option<String>,
|
||||
#[serde(rename = "list.warningForeground")]
|
||||
pub list_warning_foreground: Option<String>,
|
||||
#[serde(rename = "list.errorForeground")]
|
||||
pub list_error_foreground: Option<String>,
|
||||
#[serde(rename = "activityBar.background")]
|
||||
pub activity_bar_background: Option<String>,
|
||||
#[serde(rename = "activityBar.inactiveForeground")]
|
||||
pub activity_bar_inactive_foreground: Option<String>,
|
||||
#[serde(rename = "activityBar.foreground")]
|
||||
pub activity_bar_foreground: Option<String>,
|
||||
#[serde(rename = "activityBar.activeBorder")]
|
||||
pub activity_bar_active_border: Option<String>,
|
||||
#[serde(rename = "activityBar.activeBackground")]
|
||||
pub activity_bar_active_background: Option<String>,
|
||||
#[serde(rename = "activityBarBadge.background")]
|
||||
pub activity_bar_badge_background: Option<String>,
|
||||
#[serde(rename = "activityBarBadge.foreground")]
|
||||
pub activity_bar_badge_foreground: Option<String>,
|
||||
#[serde(rename = "sideBar.background")]
|
||||
pub side_bar_background: Option<String>,
|
||||
#[serde(rename = "sideBarTitle.foreground")]
|
||||
pub side_bar_title_foreground: Option<String>,
|
||||
#[serde(rename = "sideBarSectionHeader.background")]
|
||||
pub side_bar_section_header_background: Option<String>,
|
||||
#[serde(rename = "sideBarSectionHeader.border")]
|
||||
pub side_bar_section_header_border: Option<String>,
|
||||
#[serde(rename = "editorGroup.border")]
|
||||
pub editor_group_border: Option<String>,
|
||||
#[serde(rename = "editorGroup.dropBackground")]
|
||||
pub editor_group_drop_background: Option<String>,
|
||||
#[serde(rename = "editorGroupHeader.tabsBackground")]
|
||||
pub editor_group_header_tabs_background: Option<String>,
|
||||
#[serde(rename = "tab.activeBackground")]
|
||||
pub tab_active_background: Option<String>,
|
||||
#[serde(rename = "tab.activeForeground")]
|
||||
pub tab_active_foreground: Option<String>,
|
||||
#[serde(rename = "tab.border")]
|
||||
pub tab_border: Option<String>,
|
||||
#[serde(rename = "tab.activeBorderTop")]
|
||||
pub tab_active_border_top: Option<String>,
|
||||
#[serde(rename = "tab.inactiveBackground")]
|
||||
pub tab_inactive_background: Option<String>,
|
||||
#[serde(rename = "tab.inactiveForeground")]
|
||||
pub tab_inactive_foreground: Option<String>,
|
||||
#[serde(rename = "editor.foreground")]
|
||||
pub editor_foreground: Option<String>,
|
||||
#[serde(rename = "editor.background")]
|
||||
pub editor_background: Option<String>,
|
||||
#[serde(rename = "editorLineNumber.foreground")]
|
||||
pub editor_line_number_foreground: Option<String>,
|
||||
#[serde(rename = "editor.selectionBackground")]
|
||||
pub editor_selection_background: Option<String>,
|
||||
#[serde(rename = "editor.selectionHighlightBackground")]
|
||||
pub editor_selection_highlight_background: Option<String>,
|
||||
#[serde(rename = "editor.foldBackground")]
|
||||
pub editor_fold_background: Option<String>,
|
||||
#[serde(rename = "editor.wordHighlightBackground")]
|
||||
pub editor_word_highlight_background: Option<String>,
|
||||
#[serde(rename = "editor.wordHighlightStrongBackground")]
|
||||
pub editor_word_highlight_strong_background: Option<String>,
|
||||
#[serde(rename = "editor.findMatchBackground")]
|
||||
pub editor_find_match_background: Option<String>,
|
||||
#[serde(rename = "editor.findMatchHighlightBackground")]
|
||||
pub editor_find_match_highlight_background: Option<String>,
|
||||
#[serde(rename = "editor.findRangeHighlightBackground")]
|
||||
pub editor_find_range_highlight_background: Option<String>,
|
||||
#[serde(rename = "editor.hoverHighlightBackground")]
|
||||
pub editor_hover_highlight_background: Option<String>,
|
||||
#[serde(rename = "editor.lineHighlightBorder")]
|
||||
pub editor_line_highlight_border: Option<String>,
|
||||
#[serde(rename = "editorLink.activeForeground")]
|
||||
pub editor_link_active_foreground: Option<String>,
|
||||
#[serde(rename = "editor.rangeHighlightBackground")]
|
||||
pub editor_range_highlight_background: Option<String>,
|
||||
#[serde(rename = "editor.snippetTabstopHighlightBackground")]
|
||||
pub editor_snippet_tabstop_highlight_background: Option<String>,
|
||||
#[serde(rename = "editor.snippetTabstopHighlightBorder")]
|
||||
pub editor_snippet_tabstop_highlight_border: Option<String>,
|
||||
#[serde(rename = "editor.snippetFinalTabstopHighlightBackground")]
|
||||
pub editor_snippet_final_tabstop_highlight_background: Option<String>,
|
||||
#[serde(rename = "editor.snippetFinalTabstopHighlightBorder")]
|
||||
pub editor_snippet_final_tabstop_highlight_border: Option<String>,
|
||||
#[serde(rename = "editorWhitespace.foreground")]
|
||||
pub editor_whitespace_foreground: Option<String>,
|
||||
#[serde(rename = "editorIndentGuide.background")]
|
||||
pub editor_indent_guide_background: Option<String>,
|
||||
#[serde(rename = "editorIndentGuide.activeBackground")]
|
||||
pub editor_indent_guide_active_background: Option<String>,
|
||||
#[serde(rename = "editorRuler.foreground")]
|
||||
pub editor_ruler_foreground: Option<String>,
|
||||
#[serde(rename = "editorCodeLens.foreground")]
|
||||
pub editor_code_lens_foreground: Option<String>,
|
||||
#[serde(rename = "editorBracketHighlight.foreground1")]
|
||||
pub editor_bracket_highlight_foreground1: Option<String>,
|
||||
#[serde(rename = "editorBracketHighlight.foreground2")]
|
||||
pub editor_bracket_highlight_foreground2: Option<String>,
|
||||
#[serde(rename = "editorBracketHighlight.foreground3")]
|
||||
pub editor_bracket_highlight_foreground3: Option<String>,
|
||||
#[serde(rename = "editorBracketHighlight.foreground4")]
|
||||
pub editor_bracket_highlight_foreground4: Option<String>,
|
||||
#[serde(rename = "editorBracketHighlight.foreground5")]
|
||||
pub editor_bracket_highlight_foreground5: Option<String>,
|
||||
#[serde(rename = "editorBracketHighlight.foreground6")]
|
||||
pub editor_bracket_highlight_foreground6: Option<String>,
|
||||
#[serde(rename = "editorBracketHighlight.unexpectedBracket.foreground")]
|
||||
pub editor_bracket_highlight_unexpected_bracket_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.border")]
|
||||
pub editor_overview_ruler_border: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.selectionHighlightForeground")]
|
||||
pub editor_overview_ruler_selection_highlight_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.wordHighlightForeground")]
|
||||
pub editor_overview_ruler_word_highlight_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.wordHighlightStrongForeground")]
|
||||
pub editor_overview_ruler_word_highlight_strong_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.modifiedForeground")]
|
||||
pub editor_overview_ruler_modified_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.addedForeground")]
|
||||
pub editor_overview_ruler_added_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.deletedForeground")]
|
||||
pub editor_overview_ruler_deleted_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.errorForeground")]
|
||||
pub editor_overview_ruler_error_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.warningForeground")]
|
||||
pub editor_overview_ruler_warning_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.infoForeground")]
|
||||
pub editor_overview_ruler_info_foreground: Option<String>,
|
||||
#[serde(rename = "editorError.foreground")]
|
||||
pub editor_error_foreground: Option<String>,
|
||||
#[serde(rename = "editorWarning.foreground")]
|
||||
pub editor_warning_foreground: Option<String>,
|
||||
#[serde(rename = "editorGutter.modifiedBackground")]
|
||||
pub editor_gutter_modified_background: Option<String>,
|
||||
#[serde(rename = "editorGutter.addedBackground")]
|
||||
pub editor_gutter_added_background: Option<String>,
|
||||
#[serde(rename = "editorGutter.deletedBackground")]
|
||||
pub editor_gutter_deleted_background: Option<String>,
|
||||
#[serde(rename = "gitDecoration.modifiedResourceForeground")]
|
||||
pub git_decoration_modified_resource_foreground: Option<String>,
|
||||
#[serde(rename = "gitDecoration.deletedResourceForeground")]
|
||||
pub git_decoration_deleted_resource_foreground: Option<String>,
|
||||
#[serde(rename = "gitDecoration.untrackedResourceForeground")]
|
||||
pub git_decoration_untracked_resource_foreground: Option<String>,
|
||||
#[serde(rename = "gitDecoration.ignoredResourceForeground")]
|
||||
pub git_decoration_ignored_resource_foreground: Option<String>,
|
||||
#[serde(rename = "gitDecoration.conflictingResourceForeground")]
|
||||
pub git_decoration_conflicting_resource_foreground: Option<String>,
|
||||
#[serde(rename = "diffEditor.insertedTextBackground")]
|
||||
pub diff_editor_inserted_text_background: Option<String>,
|
||||
#[serde(rename = "diffEditor.removedTextBackground")]
|
||||
pub diff_editor_removed_text_background: Option<String>,
|
||||
#[serde(rename = "inlineChat.regionHighlight")]
|
||||
pub inline_chat_region_highlight: Option<String>,
|
||||
#[serde(rename = "editorWidget.background")]
|
||||
pub editor_widget_background: Option<String>,
|
||||
#[serde(rename = "editorSuggestWidget.background")]
|
||||
pub editor_suggest_widget_background: Option<String>,
|
||||
#[serde(rename = "editorSuggestWidget.foreground")]
|
||||
pub editor_suggest_widget_foreground: Option<String>,
|
||||
#[serde(rename = "editorSuggestWidget.selectedBackground")]
|
||||
pub editor_suggest_widget_selected_background: Option<String>,
|
||||
#[serde(rename = "editorHoverWidget.background")]
|
||||
pub editor_hover_widget_background: Option<String>,
|
||||
#[serde(rename = "editorHoverWidget.border")]
|
||||
pub editor_hover_widget_border: Option<String>,
|
||||
#[serde(rename = "editorMarkerNavigation.background")]
|
||||
pub editor_marker_navigation_background: Option<String>,
|
||||
#[serde(rename = "peekView.border")]
|
||||
pub peek_view_border: Option<String>,
|
||||
#[serde(rename = "peekViewEditor.background")]
|
||||
pub peek_view_editor_background: Option<String>,
|
||||
#[serde(rename = "peekViewEditor.matchHighlightBackground")]
|
||||
pub peek_view_editor_match_highlight_background: Option<String>,
|
||||
#[serde(rename = "peekViewResult.background")]
|
||||
pub peek_view_result_background: Option<String>,
|
||||
#[serde(rename = "peekViewResult.fileForeground")]
|
||||
pub peek_view_result_file_foreground: Option<String>,
|
||||
#[serde(rename = "peekViewResult.lineForeground")]
|
||||
pub peek_view_result_line_foreground: Option<String>,
|
||||
#[serde(rename = "peekViewResult.matchHighlightBackground")]
|
||||
pub peek_view_result_match_highlight_background: Option<String>,
|
||||
#[serde(rename = "peekViewResult.selectionBackground")]
|
||||
pub peek_view_result_selection_background: Option<String>,
|
||||
#[serde(rename = "peekViewResult.selectionForeground")]
|
||||
pub peek_view_result_selection_foreground: Option<String>,
|
||||
#[serde(rename = "peekViewTitle.background")]
|
||||
pub peek_view_title_background: Option<String>,
|
||||
#[serde(rename = "peekViewTitleDescription.foreground")]
|
||||
pub peek_view_title_description_foreground: Option<String>,
|
||||
#[serde(rename = "peekViewTitleLabel.foreground")]
|
||||
pub peek_view_title_label_foreground: Option<String>,
|
||||
#[serde(rename = "merge.currentHeaderBackground")]
|
||||
pub merge_current_header_background: Option<String>,
|
||||
#[serde(rename = "merge.incomingHeaderBackground")]
|
||||
pub merge_incoming_header_background: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.currentContentForeground")]
|
||||
pub editor_overview_ruler_current_content_foreground: Option<String>,
|
||||
#[serde(rename = "editorOverviewRuler.incomingContentForeground")]
|
||||
pub editor_overview_ruler_incoming_content_foreground: Option<String>,
|
||||
#[serde(rename = "panel.background")]
|
||||
pub panel_background: Option<String>,
|
||||
#[serde(rename = "panel.border")]
|
||||
pub panel_border: Option<String>,
|
||||
#[serde(rename = "panelTitle.activeBorder")]
|
||||
pub panel_title_active_border: Option<String>,
|
||||
#[serde(rename = "panelTitle.activeForeground")]
|
||||
pub panel_title_active_foreground: Option<String>,
|
||||
#[serde(rename = "panelTitle.inactiveForeground")]
|
||||
pub panel_title_inactive_foreground: Option<String>,
|
||||
#[serde(rename = "statusBar.background")]
|
||||
pub status_bar_background: Option<String>,
|
||||
#[serde(rename = "statusBar.foreground")]
|
||||
pub status_bar_foreground: Option<String>,
|
||||
#[serde(rename = "statusBar.debuggingBackground")]
|
||||
pub status_bar_debugging_background: Option<String>,
|
||||
#[serde(rename = "statusBar.debuggingForeground")]
|
||||
pub status_bar_debugging_foreground: Option<String>,
|
||||
#[serde(rename = "statusBar.noFolderBackground")]
|
||||
pub status_bar_no_folder_background: Option<String>,
|
||||
#[serde(rename = "statusBar.noFolderForeground")]
|
||||
pub status_bar_no_folder_foreground: Option<String>,
|
||||
#[serde(rename = "statusBarItem.prominentBackground")]
|
||||
pub status_bar_item_prominent_background: Option<String>,
|
||||
#[serde(rename = "statusBarItem.prominentHoverBackground")]
|
||||
pub status_bar_item_prominent_hover_background: Option<String>,
|
||||
#[serde(rename = "statusBarItem.remoteForeground")]
|
||||
pub status_bar_item_remote_foreground: Option<String>,
|
||||
#[serde(rename = "statusBarItem.remoteBackground")]
|
||||
pub status_bar_item_remote_background: Option<String>,
|
||||
#[serde(rename = "titleBar.activeBackground")]
|
||||
pub title_bar_active_background: Option<String>,
|
||||
#[serde(rename = "titleBar.activeForeground")]
|
||||
pub title_bar_active_foreground: Option<String>,
|
||||
#[serde(rename = "titleBar.inactiveBackground")]
|
||||
pub title_bar_inactive_background: Option<String>,
|
||||
#[serde(rename = "titleBar.inactiveForeground")]
|
||||
pub title_bar_inactive_foreground: Option<String>,
|
||||
#[serde(rename = "extensionButton.prominentForeground")]
|
||||
pub extension_button_prominent_foreground: Option<String>,
|
||||
#[serde(rename = "extensionButton.prominentBackground")]
|
||||
pub extension_button_prominent_background: Option<String>,
|
||||
#[serde(rename = "extensionButton.prominentHoverBackground")]
|
||||
pub extension_button_prominent_hover_background: Option<String>,
|
||||
#[serde(rename = "pickerGroup.border")]
|
||||
pub picker_group_border: Option<String>,
|
||||
#[serde(rename = "pickerGroup.foreground")]
|
||||
pub picker_group_foreground: Option<String>,
|
||||
#[serde(rename = "debugToolBar.background")]
|
||||
pub debug_tool_bar_background: Option<String>,
|
||||
#[serde(rename = "walkThrough.embeddedEditorBackground")]
|
||||
pub walk_through_embedded_editor_background: Option<String>,
|
||||
#[serde(rename = "settings.headerForeground")]
|
||||
pub settings_header_foreground: Option<String>,
|
||||
#[serde(rename = "settings.modifiedItemIndicator")]
|
||||
pub settings_modified_item_indicator: Option<String>,
|
||||
#[serde(rename = "settings.dropdownBackground")]
|
||||
pub settings_dropdown_background: Option<String>,
|
||||
#[serde(rename = "settings.dropdownForeground")]
|
||||
pub settings_dropdown_foreground: Option<String>,
|
||||
#[serde(rename = "settings.dropdownBorder")]
|
||||
pub settings_dropdown_border: Option<String>,
|
||||
#[serde(rename = "settings.checkboxBackground")]
|
||||
pub settings_checkbox_background: Option<String>,
|
||||
#[serde(rename = "settings.checkboxForeground")]
|
||||
pub settings_checkbox_foreground: Option<String>,
|
||||
#[serde(rename = "settings.checkboxBorder")]
|
||||
pub settings_checkbox_border: Option<String>,
|
||||
#[serde(rename = "settings.textInputBackground")]
|
||||
pub settings_text_input_background: Option<String>,
|
||||
#[serde(rename = "settings.textInputForeground")]
|
||||
pub settings_text_input_foreground: Option<String>,
|
||||
#[serde(rename = "settings.textInputBorder")]
|
||||
pub settings_text_input_border: Option<String>,
|
||||
#[serde(rename = "settings.numberInputBackground")]
|
||||
pub settings_number_input_background: Option<String>,
|
||||
#[serde(rename = "settings.numberInputForeground")]
|
||||
pub settings_number_input_foreground: Option<String>,
|
||||
#[serde(rename = "settings.numberInputBorder")]
|
||||
pub settings_number_input_border: Option<String>,
|
||||
#[serde(rename = "breadcrumb.foreground")]
|
||||
pub breadcrumb_foreground: Option<String>,
|
||||
#[serde(rename = "breadcrumb.background")]
|
||||
pub breadcrumb_background: Option<String>,
|
||||
#[serde(rename = "breadcrumb.focusForeground")]
|
||||
pub breadcrumb_focus_foreground: Option<String>,
|
||||
#[serde(rename = "breadcrumb.activeSelectionForeground")]
|
||||
pub breadcrumb_active_selection_foreground: Option<String>,
|
||||
#[serde(rename = "breadcrumbPicker.background")]
|
||||
pub breadcrumb_picker_background: Option<String>,
|
||||
#[serde(rename = "listFilterWidget.background")]
|
||||
pub list_filter_widget_background: Option<String>,
|
||||
#[serde(rename = "listFilterWidget.outline")]
|
||||
pub list_filter_widget_outline: Option<String>,
|
||||
#[serde(rename = "listFilterWidget.noMatchesOutline")]
|
||||
pub list_filter_widget_no_matches_outline: Option<String>,
|
||||
}
|
||||
|
||||
fn try_parse_color(color: &str) -> Result<Hsla> {
|
||||
Ok(Rgba::try_from(color)?.into())
|
||||
}
|
||||
|
||||
pub struct VsCodeThemeConverter {
|
||||
theme: VsCodeTheme,
|
||||
theme_metadata: ThemeMetadata,
|
||||
}
|
||||
|
||||
impl VsCodeThemeConverter {
|
||||
pub fn new(theme: VsCodeTheme, theme_metadata: ThemeMetadata) -> Self {
|
||||
Self {
|
||||
theme,
|
||||
theme_metadata,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert(self) -> Result<ThemeVariant> {
|
||||
let appearance = self.theme_metadata.appearance.into();
|
||||
|
||||
let mut theme_colors = match appearance {
|
||||
Appearance::Light => ThemeColors::default_light(),
|
||||
Appearance::Dark => ThemeColors::default_dark(),
|
||||
};
|
||||
|
||||
let vscode_colors = &self.theme.colors;
|
||||
|
||||
let theme_colors_refinements = ThemeColorsRefinement {
|
||||
border: vscode_colors
|
||||
.panel_border
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
border_variant: vscode_colors
|
||||
.panel_border
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
border_focused: vscode_colors
|
||||
.panel_border
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
border_disabled: vscode_colors
|
||||
.panel_border
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
border_selected: vscode_colors
|
||||
.panel_border
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
border_transparent: vscode_colors
|
||||
.panel_border
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
elevated_surface_background: vscode_colors
|
||||
.panel_background
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
surface_background: vscode_colors
|
||||
.panel_background
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
background: vscode_colors
|
||||
.editor_background
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
element_background: vscode_colors
|
||||
.button_background
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
text: vscode_colors
|
||||
.foreground
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
tab_active_background: vscode_colors
|
||||
.tab_active_background
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
tab_inactive_background: vscode_colors
|
||||
.tab_inactive_background
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_background: vscode_colors
|
||||
.terminal_background
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_bright_black: vscode_colors
|
||||
.terminal_ansi_bright_black
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_bright_red: vscode_colors
|
||||
.terminal_ansi_bright_red
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_bright_green: vscode_colors
|
||||
.terminal_ansi_bright_green
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_bright_yellow: vscode_colors
|
||||
.terminal_ansi_bright_yellow
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_bright_blue: vscode_colors
|
||||
.terminal_ansi_bright_blue
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_bright_magenta: vscode_colors
|
||||
.terminal_ansi_bright_magenta
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_bright_cyan: vscode_colors
|
||||
.terminal_ansi_bright_cyan
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_bright_white: vscode_colors
|
||||
.terminal_ansi_bright_white
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_black: vscode_colors
|
||||
.terminal_ansi_black
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_red: vscode_colors
|
||||
.terminal_ansi_red
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_green: vscode_colors
|
||||
.terminal_ansi_green
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_yellow: vscode_colors
|
||||
.terminal_ansi_yellow
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_blue: vscode_colors
|
||||
.terminal_ansi_blue
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_magenta: vscode_colors
|
||||
.terminal_ansi_magenta
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_cyan: vscode_colors
|
||||
.terminal_ansi_cyan
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
terminal_ansi_white: vscode_colors
|
||||
.terminal_ansi_white
|
||||
.as_ref()
|
||||
.traverse(|color| try_parse_color(&color))?,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
theme_colors.refine(&theme_colors_refinements);
|
||||
|
||||
Ok(ThemeVariant {
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
name: self.theme_metadata.name.into(),
|
||||
appearance,
|
||||
styles: ThemeStyles {
|
||||
system: SystemColors::default(),
|
||||
colors: theme_colors,
|
||||
status: StatusColors::default(),
|
||||
git: GitStatusColors::default(),
|
||||
player: PlayerColors::default(),
|
||||
syntax: SyntaxTheme::default_dark(),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
// use std::path::PathBuf;
|
||||
|
||||
// #[test]
|
||||
// fn test_deserialize_theme() {
|
||||
// let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
// let root_dir = manifest_dir.parent().unwrap().parent().unwrap();
|
||||
|
||||
// let mut d = root_dir.to_path_buf();
|
||||
// d.push("assets/themes/src/vsc/dracula/dracula.json");
|
||||
|
||||
// let data = std::fs::read_to_string(d).expect("Unable to read file");
|
||||
|
||||
// let result: Theme = serde_json::from_str(&data).unwrap();
|
||||
// println!("{:#?}", result);
|
||||
// }
|
||||
// }
|
Loading…
Add table
Add a link
Reference in a new issue