use std::path::{Path, PathBuf};
use crate::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SkillDocument {
pub name: &'static str,
pub title: &'static str,
pub body: &'static str,
}
macro_rules! document {
($name:literal, $title:literal) => {
SkillDocument {
name: $name,
title: $title,
body: include_str!(concat!("../skill/", $name)),
}
};
}
pub const DOCUMENTS: &[SkillDocument] = &[
document!("SKILL.md", "How to drive xtalforge"),
document!("mcp.md", "MCP client setup"),
document!("prompts/build-mof.md", "Prompt: build a MOF"),
document!("prompts/porosity-report.md", "Prompt: porosity report"),
document!(
"prompts/prepare-deposited-cif.md",
"Prompt: prepare a deposited CIF"
),
document!("references/api.md", "Reference: API and surfaces"),
document!("references/calculations.md", "Reference: calculations"),
document!("references/carbon.md", "Reference: carbon builders"),
document!("references/diagnostics.md", "Reference: diagnostics"),
document!("references/mof.md", "Reference: MOF builder"),
document!("references/polymer.md", "Reference: polymers"),
document!("references/porosity.md", "Reference: porosity"),
document!("references/prepare.md", "Reference: preparation"),
document!(
"references/workspace.md",
"Reference: documents and history"
),
];
#[must_use]
pub fn find(name: &str) -> Option<&'static SkillDocument> {
let wanted = name.trim().trim_start_matches('/');
DOCUMENTS.iter().find(|document| {
document.name == wanted
|| document
.name
.strip_suffix(".md")
.is_some_and(|stem| stem == wanted)
})
}
#[must_use]
pub fn default_directory() -> PathBuf {
if let Some(base) = std::env::var_os("XDG_DATA_HOME")
&& !base.is_empty()
{
return PathBuf::from(base).join("xtalforge").join("skill");
}
if let Some(home) = std::env::var_os("HOME")
&& !home.is_empty()
{
return PathBuf::from(home)
.join(".local")
.join("share")
.join("xtalforge")
.join("skill");
}
PathBuf::from("xtalforge-skill")
}
pub fn install(directory: &Path) -> Result<Vec<PathBuf>, Error> {
let mut written = Vec::with_capacity(DOCUMENTS.len());
for document in DOCUMENTS {
let path = directory.join(document.name);
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.map_err(|error| Error::Io(format!("{}: {error}", parent.display())))?;
}
std::fs::write(&path, document.body)
.map_err(|error| Error::Io(format!("{}: {error}", path.display())))?;
written.push(path);
}
Ok(written)
}