use clap::{Parser, Subcommand};
use mmd_mpl::MPLCompiler;
use std::path::Path;
#[derive(Parser)]
#[command(name = "mpl")]
#[command(about = "MPL - Rule-based Domain-Specific Language for MMD poses and animations")]
#[command(version)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
#[command(short_flag = 'c')]
Compile {
input: String,
#[arg(short, long)]
output: Option<String>,
},
#[command(short_flag = 'r')]
ReverseCompile {
input: String,
#[arg(short, long)]
output: Option<String>,
},
}
fn main() {
let cli = Cli::parse();
let compiler = MPLCompiler::new();
match cli.command {
Commands::Compile { input, output } => {
compile(&compiler, &input, output);
}
Commands::ReverseCompile { input, output } => {
reverse_compile(&compiler, &input, output);
}
}
}
fn compile(compiler: &MPLCompiler, input: &str, output: Option<String>) {
let mpl_script = match std::fs::read_to_string(input) {
Ok(content) => content,
Err(e) => {
eprintln!("Error reading input file '{}': {}", input, e);
std::process::exit(1);
}
};
let vmd_bytes = match compiler.compile(&mpl_script) {
Ok(bytes) => bytes,
Err(e) => {
eprintln!("Compilation error: {}", e);
std::process::exit(1);
}
};
let output_path = output.unwrap_or_else(|| {
let input_path = Path::new(input);
let stem = input_path.file_stem().unwrap_or_default();
format!("{}.vmd", stem.to_string_lossy())
});
if let Err(e) = std::fs::write(&output_path, &vmd_bytes) {
eprintln!("Error writing output file '{}': {}", output_path, e);
std::process::exit(1);
}
println!("Successfully compiled '{}' to '{}'", input, output_path);
}
fn reverse_compile(compiler: &MPLCompiler, input: &str, output: Option<String>) {
let input_data = match std::fs::read(input) {
Ok(data) => data,
Err(e) => {
eprintln!("Error reading input file '{}': {}", input, e);
std::process::exit(1);
}
};
let input_path = Path::new(input);
let extension = input_path
.extension()
.and_then(|ext| ext.to_str())
.unwrap_or("")
.to_lowercase();
let mpl_script = match extension.as_str() {
"vmd" => match compiler.from_vmd(&input_data) {
Ok(script) => script,
Err(e) => {
eprintln!("Error reverse compiling VMD: {}", e);
std::process::exit(1);
}
},
"vpd" => match compiler.from_vpd(&input_data) {
Ok(script) => script,
Err(e) => {
eprintln!("Error reverse compiling VPD: {}", e);
std::process::exit(1);
}
},
_ => {
eprintln!(
"Unknown file extension '{}'. Please use .vmd or .vpd files.",
extension
);
std::process::exit(1);
}
};
let output_path = output.unwrap_or_else(|| {
let input_path = Path::new(input);
let stem = input_path.file_stem().unwrap_or_default();
format!("{}.mpl", stem.to_string_lossy())
});
if let Err(e) = std::fs::write(&output_path, mpl_script) {
eprintln!("Error writing output file '{}': {}", output_path, e);
std::process::exit(1);
}
println!("Successfully reversed '{}' to '{}'", input, output_path);
}