use clap::Subcommand;
use clap::{Parser, ValueEnum};
use plottery_project::{export_plottery_home, LibSource, Project};
use std::path::PathBuf;
#[derive(Debug, Clone, ValueEnum, PartialEq)]
enum RenderType {
Svg,
Png,
}
fn parse_lib_source(value: &str) -> LibSource {
match value {
"cratesio" => LibSource::CratesIO,
"home" => LibSource::PlotteryHome,
path => LibSource::Path {
path: PathBuf::from(path),
},
}
}
#[derive(Debug, Clone, Subcommand)]
enum Command {
New {
#[arg(help = "Directory where the project will be created")]
path: String,
#[arg(help = "Name of the project")]
name: String,
#[arg(
value_name = "cratesio|home|PATH",
short = 'l',
help = "Plottery library source [default: cratesio]",
long_help = "Plottery library source\n cratesio [default] Use the published crate from crates.io\n home Use local source from PLOTTERY_HOME env var\n PATH Use local source from a custom path"
)]
lib: Option<String>,
},
Render {
#[arg(help = "Output format (svg or png)")]
format: RenderType,
#[arg(help = "Path to the .plottery project file")]
project_path: String,
#[arg(help = "Output file path")]
out_path: String,
},
Build {
#[arg(help = "Path to the .plottery project file")]
project_path: String,
},
SetHome {
#[arg(help = "Path to the plottery workspace directory")]
path: String,
},
}
#[derive(Parser, Debug)]
#[command(about="CLI helper to create and manager plottery projects", long_about = None)]
struct Args {
#[command(subcommand)]
command: Command,
}
pub fn main() {
let args = Args::parse();
match args.command {
Command::New { name, path, lib } => {
let lib_source = match lib {
Some(value) => parse_lib_source(&value),
None => LibSource::CratesIO,
};
let project = Project::new(PathBuf::from(path), &name);
if project.exists() {
println!(
"Project already exists at '{}'",
project
.dir
.to_str()
.expect("Failed to convert project directory path to string")
);
return;
}
let result = project.generate_to_disk(lib_source, true);
if let Err(error) = result {
println!("Failed to create project: {}", error);
return;
}
println!(
"Created project at '{}'",
project
.dir
.to_str()
.expect("Failed to convert project directory path to string")
);
}
Command::Build { project_path } => {
let project_path_buf = PathBuf::from(project_path);
if project_path_buf.is_dir() {
println!(
"Path '{}' is a directory. Use the '.plottery' file.",
project_path_buf.to_str().unwrap()
);
return;
}
let project = Project::load_from_file(project_path_buf).unwrap();
if !project.exists() {
println!("No project found at '{}'", project.dir.to_str().unwrap());
return;
}
project.build(true).unwrap();
}
Command::Render {
format,
project_path,
out_path,
} => {
let project_path_buf = PathBuf::from(project_path);
if project_path_buf.is_dir() {
println!(
"Path '{}' is a directory. Use the '.plottery' file.",
project_path_buf.to_str().unwrap()
);
return;
}
let project = Project::load_from_file(project_path_buf).unwrap();
if !project.exists() {
println!("No project found at '{}'", project.dir.to_str().unwrap());
return;
}
let release = true;
project.build(release).unwrap();
let params = project
.run_get_params(release)
.expect("Failed to get params");
let out_path_buf = PathBuf::from(out_path);
match format {
RenderType::Svg => {
project.write_svg(out_path_buf, release, ¶ms).unwrap();
}
RenderType::Png => {
project.write_png(out_path_buf, release, ¶ms).unwrap();
}
}
}
Command::SetHome { path } => {
let path_buf = PathBuf::from(&path);
if !path_buf.exists() {
println!("Error: Path does not exist: {}", path);
return;
}
if !path_buf.is_dir() {
println!("Error: Path is not a directory: {}", path);
return;
}
let absolute_path = path_buf.canonicalize().unwrap_or(path_buf);
let absolute_path_str = absolute_path.to_string_lossy();
match export_plottery_home(&absolute_path_str) {
Ok(()) => {
println!("PLOTTERY_HOME has been set to: {}", absolute_path_str);
println!("This setting will persist across terminal sessions.");
}
Err(e) => {
println!("Failed to set PLOTTERY_HOME: {}", e);
}
}
}
}
}