use serde::Deserialize;
use std::collections::HashMap;
use std::process::Command;
use thiserror::Error;
pub struct Justfile {
justfile: JustfileDump,
}
#[derive(Deserialize, Debug)]
struct JustfileDump {
recipes: HashMap<String, JustfileRecipe>,
}
#[derive(Deserialize, Debug)]
struct JustfileRecipe {
attributes: Vec<HashMap<String, String>>,
name: String,
}
#[derive(Error, Debug)]
pub enum JustfileError {
#[error("Error in calling just executable: {0}")]
SpawnError(#[from] std::io::Error),
#[error("Invalid characters in justfile: {0}")]
Utf8Error(#[from] std::string::FromUtf8Error),
#[error("justfile version mismatch: {0}")]
JsonError(#[from] serde_json::error::Error),
}
impl Justfile {
pub fn parse() -> Result<Self, JustfileError> {
let output = Command::new("just")
.args(["--dump", "--dump-format", "json"])
.output()?;
let jsonstr = String::from_utf8(output.stdout)?;
let justfile = serde_json::from_str(&jsonstr)?;
let just = Justfile { justfile };
Ok(just)
}
pub fn group_recipes(&self, group: &str) -> Vec<String> {
let recipes = self.justfile.recipes.values().filter(|recipe| {
recipe
.attributes
.iter()
.any(|attr| attr.get("group").map(|g| g == group).unwrap_or(false))
});
recipes.map(|recipe| recipe.name.clone()).collect()
}
}