dynamically inject theme names and language properties into schema
This commit is contained in:
parent
035cd37aa8
commit
3e40b5bead
3 changed files with 97 additions and 54 deletions
|
@ -234,6 +234,14 @@ impl LanguageRegistry {
|
|||
.cloned()
|
||||
}
|
||||
|
||||
pub fn language_names(&self) -> Vec<String> {
|
||||
self.languages
|
||||
.read()
|
||||
.iter()
|
||||
.map(|language| language.name().to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn select_language(&self, path: impl AsRef<Path>) -> Option<Arc<Language>> {
|
||||
let path = path.as_ref();
|
||||
let filename = path.file_name().and_then(|name| name.to_str());
|
||||
|
|
|
@ -2,10 +2,14 @@ use anyhow::Result;
|
|||
use gpui::font_cache::{FamilyId, FontCache};
|
||||
use schemars::{
|
||||
gen::{SchemaGenerator, SchemaSettings},
|
||||
schema::{
|
||||
InstanceType, ObjectValidation, Schema, SchemaObject, SingleOrVec, SubschemaValidation,
|
||||
},
|
||||
JsonSchema,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::{collections::HashMap, fmt::Display, sync::Arc};
|
||||
use serde_json::Value;
|
||||
use std::{collections::HashMap, fmt::Display, os::unix::fs::chroot, sync::Arc};
|
||||
use theme::{Theme, ThemeRegistry};
|
||||
use util::ResultExt as _;
|
||||
|
||||
|
@ -36,53 +40,6 @@ pub enum SoftWrap {
|
|||
PreferredLineLength,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
pub enum ThemeNames {
|
||||
Dark,
|
||||
Light,
|
||||
}
|
||||
|
||||
impl Display for ThemeNames {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ThemeNames::Dark => write!(f, "Dark"),
|
||||
ThemeNames::Light => write!(f, "Light"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||
pub struct LanguageOverrides {
|
||||
C: Option<LanguageOverride>,
|
||||
JSON: Option<LanguageOverride>,
|
||||
Markdown: Option<LanguageOverride>,
|
||||
PlainText: Option<LanguageOverride>,
|
||||
Rust: Option<LanguageOverride>,
|
||||
TSX: Option<LanguageOverride>,
|
||||
TypeScript: Option<LanguageOverride>,
|
||||
}
|
||||
|
||||
impl IntoIterator for LanguageOverrides {
|
||||
type Item = (String, LanguageOverride);
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
vec![
|
||||
("C", self.C),
|
||||
("JSON", self.JSON),
|
||||
("Markdown", self.Markdown),
|
||||
("PlainText", self.PlainText),
|
||||
("Rust", self.Rust),
|
||||
("TSX", self.TSX),
|
||||
("TypeScript", self.TypeScript),
|
||||
]
|
||||
.into_iter()
|
||||
.filter_map(|(name, language_override)| language_override.map(|lo| (name.to_owned(), lo)))
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, JsonSchema)]
|
||||
pub struct SettingsFileContent {
|
||||
#[serde(default)]
|
||||
|
@ -94,9 +51,9 @@ pub struct SettingsFileContent {
|
|||
#[serde(flatten)]
|
||||
pub editor: LanguageOverride,
|
||||
#[serde(default)]
|
||||
pub language_overrides: LanguageOverrides,
|
||||
pub language_overrides: HashMap<Arc<str>, LanguageOverride>,
|
||||
#[serde(default)]
|
||||
pub theme: Option<ThemeNames>,
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
|
@ -117,13 +74,88 @@ impl Settings {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn file_json_schema() -> serde_json::Value {
|
||||
pub fn file_json_schema(
|
||||
theme_names: Vec<String>,
|
||||
language_names: Vec<String>,
|
||||
) -> serde_json::Value {
|
||||
let settings = SchemaSettings::draft07().with(|settings| {
|
||||
settings.option_nullable = true;
|
||||
settings.option_add_null_type = false;
|
||||
});
|
||||
let generator = SchemaGenerator::new(settings);
|
||||
serde_json::to_value(generator.into_root_schema_for::<SettingsFileContent>()).unwrap()
|
||||
let mut root_schema = generator.into_root_schema_for::<SettingsFileContent>();
|
||||
|
||||
// Construct theme names reference type
|
||||
let theme_names = theme_names
|
||||
.into_iter()
|
||||
.map(|name| Value::String(name))
|
||||
.collect();
|
||||
let theme_names_schema = Schema::Object(SchemaObject {
|
||||
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
|
||||
enum_values: Some(theme_names),
|
||||
..Default::default()
|
||||
});
|
||||
root_schema
|
||||
.definitions
|
||||
.insert("ThemeName".to_owned(), theme_names_schema);
|
||||
|
||||
// Construct language overrides reference type
|
||||
let language_override_schema_reference = Schema::Object(SchemaObject {
|
||||
reference: Some("#/definitions/LanguageOverride".to_owned()),
|
||||
..Default::default()
|
||||
});
|
||||
let language_overrides_properties = language_names
|
||||
.into_iter()
|
||||
.map(|name| {
|
||||
(
|
||||
name,
|
||||
Schema::Object(SchemaObject {
|
||||
subschemas: Some(Box::new(SubschemaValidation {
|
||||
all_of: Some(vec![language_override_schema_reference.clone()]),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
}),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let language_overrides_schema = Schema::Object(SchemaObject {
|
||||
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Object))),
|
||||
object: Some(Box::new(ObjectValidation {
|
||||
properties: language_overrides_properties,
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
});
|
||||
root_schema
|
||||
.definitions
|
||||
.insert("LanguageOverrides".to_owned(), language_overrides_schema);
|
||||
|
||||
// Modify theme property to use new theme reference type
|
||||
let settings_file_schema = root_schema.schema.object.as_mut().unwrap();
|
||||
let language_overrides_schema_reference = Schema::Object(SchemaObject {
|
||||
reference: Some("#/definitions/ThemeName".to_owned()),
|
||||
..Default::default()
|
||||
});
|
||||
settings_file_schema.properties.insert(
|
||||
"theme".to_owned(),
|
||||
Schema::Object(SchemaObject {
|
||||
subschemas: Some(Box::new(SubschemaValidation {
|
||||
all_of: Some(vec![language_overrides_schema_reference]),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
}),
|
||||
);
|
||||
|
||||
// Modify language_overrides property to use LanguageOverrides reference
|
||||
settings_file_schema.properties.insert(
|
||||
"language_overrides".to_owned(),
|
||||
Schema::Object(SchemaObject {
|
||||
reference: Some("#/definitions/LanguageOverrides".to_owned()),
|
||||
..Default::default()
|
||||
}),
|
||||
);
|
||||
serde_json::to_value(root_schema).unwrap()
|
||||
}
|
||||
|
||||
pub fn with_overrides(
|
||||
|
|
|
@ -137,13 +137,16 @@ pub fn build_workspace(
|
|||
let mut workspace = Workspace::new(&workspace_params, cx);
|
||||
let project = workspace.project().clone();
|
||||
|
||||
let theme_names = app_state.themes.list().collect();
|
||||
let language_names = app_state.languages.language_names();
|
||||
|
||||
project.update(cx, |project, _| {
|
||||
project.set_language_server_settings(serde_json::json!({
|
||||
"json": {
|
||||
"schemas": [
|
||||
{
|
||||
"fileMatch": "**/.zed/settings.json",
|
||||
"schema": Settings::file_json_schema(),
|
||||
"schema": Settings::file_json_schema(theme_names, language_names),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue