use crate::output::create_output_directory;
use crate::settings::Settings;
use crate::{input::load_model, log};
use ::log::info;
use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use include_dir::{include_dir, Dir, DirEntry};
use std::fs;
use std::path::{Path, PathBuf};
use tempfile::TempDir;
pub const EXAMPLES_DIR: Dir = include_dir!("examples");
#[derive(Parser)]
#[command(version, about)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
Run {
#[arg(help = "Path to the model directory")]
model_dir: PathBuf,
},
Example {
#[command(subcommand)]
subcommand: ExampleSubcommands,
},
}
#[derive(Subcommand)]
pub enum ExampleSubcommands {
List,
Run {
name: String,
},
}
pub fn handle_run_command(model_dir: &Path) -> Result<()> {
let settings = Settings::from_path(model_dir).context("Failed to load settings.")?;
let output_path =
create_output_directory(model_dir).context("Failed to create output directory.")?;
log::init(settings.log_level.as_deref(), &output_path)
.context("Failed to initialize logging.")?;
info!("Output directory created: {}", output_path.display());
let (model, assets) = load_model(model_dir).context("Failed to load model.")?;
info!("Model loaded successfully.");
crate::simulation::run(model, assets);
Ok(())
}
pub fn handle_example_run_command(name: &str) -> Result<()> {
let sub_dir = EXAMPLES_DIR.get_dir(name).context("Directory not found.")?;
let temp_dir = TempDir::new().context("Failed to create temporary directory.")?;
for entry in sub_dir.entries() {
match entry {
DirEntry::Dir(_) => panic!("Subdirectories in examples not supported"),
DirEntry::File(f) => {
let file_name = f.path().file_name().unwrap();
let file_path = temp_dir.path().join(file_name);
fs::write(&file_path, f.contents())?;
}
}
}
handle_run_command(temp_dir.path())
}
pub fn handle_example_list_command() -> Result<()> {
for entry in EXAMPLES_DIR.dirs() {
println!("{}", entry.path().display());
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::{Path, PathBuf};
fn get_model_dir() -> PathBuf {
Path::new(file!())
.parent()
.unwrap()
.parent()
.unwrap()
.join("examples")
.join("simple")
}
#[test]
fn test_handle_run_command() {
handle_run_command(&get_model_dir()).unwrap();
assert_eq!(
handle_run_command(&get_model_dir())
.unwrap_err()
.chain()
.next()
.unwrap()
.to_string(),
"Failed to initialize logging."
);
}
}