use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TemplateManifest {
pub id: String,
pub name: String,
#[serde(default)]
pub author: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub category: String,
#[serde(default)]
pub icon: String,
pub detection: Detection,
pub template: TemplateFile,
pub install: InstallConfig,
#[serde(default)]
pub reload: Option<ReloadConfig>,
#[serde(default)]
pub ui: UiConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReloadConfig {
pub signal: String,
pub process_name: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Detection {
#[serde(default)]
pub bundle_ids: Vec<String>,
#[serde(default)]
pub paths: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TemplateFile {
pub file: String,
pub output_name: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InstallConfig {
#[serde(default)]
pub method: String,
#[serde(default)]
pub create_directories: bool,
#[serde(default)]
pub destinations: Vec<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UiConfig {
#[serde(default)]
pub description: String,
#[serde(default)]
pub config_snippet: Option<String>,
#[serde(default)]
pub config_path: Option<String>,
#[serde(default)]
pub help_url: Option<String>,
}
impl TemplateManifest {
pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
serde_json::from_str(json)
}
pub fn load<P: AsRef<std::path::Path>>(path: P) -> anyhow::Result<Self> {
let content = std::fs::read_to_string(path)?;
Ok(Self::from_json(&content)?)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_manifest() {
let json = r#"{
"id": "mksg.kitty",
"name": "Kitty",
"author": "mksg",
"description": "Dynamic color scheme for Kitty terminal",
"category": "terminals",
"icon": "terminal",
"detection": {
"bundleIds": ["net.kovidgoyal.kitty"],
"paths": ["/Applications/kitty.app"]
},
"template": {
"file": "template.conf",
"outputName": "colors-kitty.conf"
},
"install": {
"method": "symlink",
"createDirectories": true,
"destinations": []
},
"ui": {
"description": "Add include line to kitty.conf",
"configSnippet": "include ~/.cache/mksg/wallflow/colors-kitty.conf"
}
}"#;
let manifest = TemplateManifest::from_json(json).unwrap();
assert_eq!(manifest.id, "mksg.kitty");
assert_eq!(manifest.name, "Kitty");
assert_eq!(manifest.detection.bundle_ids, vec!["net.kovidgoyal.kitty"]);
assert_eq!(manifest.template.output_name, "colors-kitty.conf");
}
}