use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SkillSpec {
pub product: String,
pub slug: String,
pub tagline: String,
pub version: String,
pub rules: Vec<Rule>,
pub commands: Vec<CmdHint>,
pub sibling: Option<Sibling>,
pub bootstrap: Vec<BootstrapStep>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BootstrapStep {
pub cmd: String,
pub purpose: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Rule {
pub text: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CmdHint {
pub invocation: String,
pub purpose: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Sibling {
pub product: String,
pub bin: String,
pub pitch: String,
}
impl SkillSpec {
pub fn new(
product: impl Into<String>,
slug: impl Into<String>,
tagline: impl Into<String>,
version: impl Into<String>,
) -> Self {
Self {
product: product.into(),
slug: slug.into(),
tagline: tagline.into(),
version: version.into(),
rules: Vec::new(),
commands: Vec::new(),
sibling: None,
bootstrap: Vec::new(),
}
}
pub fn rule(mut self, text: impl Into<String>) -> Self {
self.rules.push(Rule { text: text.into() });
self
}
pub fn command(mut self, invocation: impl Into<String>, purpose: impl Into<String>) -> Self {
self.commands.push(CmdHint {
invocation: invocation.into(),
purpose: purpose.into(),
});
self
}
pub fn sibling(
mut self,
product: impl Into<String>,
bin: impl Into<String>,
pitch: impl Into<String>,
) -> Self {
self.sibling = Some(Sibling {
product: product.into(),
bin: bin.into(),
pitch: pitch.into(),
});
self
}
pub fn bootstrap_step(mut self, cmd: impl Into<String>, purpose: impl Into<String>) -> Self {
self.bootstrap.push(BootstrapStep {
cmd: cmd.into(),
purpose: purpose.into(),
});
self
}
pub fn to_json(&self) -> String {
serde_json::to_string(self).unwrap_or_default()
}
pub fn from_json(s: &str) -> Option<Self> {
serde_json::from_str(s).ok()
}
}