use case_clause::case;
use std::{
env,
fs::File,
io::{ErrorKind, Write},
path::Path,
process::Command,
};
use clap::{Arg, ArgMatches, Command as ClapCommand};
fn env_to_matches(env_args: Vec<String>) -> ArgMatches {
ClapCommand::new("cargo")
.version("0.1.0")
.author("GueLaKais <koroyeldiores@gmail.com>")
.about("Creates a new Rust package with ROS package.xml")
.arg(
Arg::new("package_name")
.required(true)
.help("Name of the package to create")
.index(1),
).arg(
Arg::new("vcs")
.long("vcs")
.help("Initialize a new repository for the given version control system, overriding a global configuration. [possible values: git, hg, pijul, fossil, none]")
.value_name("VCS").value_parser(["git", "hg", "pijul", "fossil", "none"])
).arg(
Arg::new("edition")
.long("edition")
.help(
"Edition to set for the crate generated [possible values: 2015, 2018, 2021, 2024]"
)
.value_name("YEAR")
.value_parser(["2015", "2018", "2021", "2024"])
)
.arg(
Arg::new("bin")
.long("bin")
.help("Use a binary (application) template [default]")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("lib")
.long("lib")
.help("Use a library template")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("mail")
.long("mail")
.default_value("you@email.com")
.help("Adds the E-mail Address of the maintainer"),
)
.arg(
Arg::new("maintainer")
.long("maintainer")
.default_value("user")
.help("The name of the maintainer"),
)
.arg(
Arg::new("license")
.long("license")
.default_value("TODO: License declaration")
.help("Declares the used License of this Package"),
)
.arg(
Arg::new("format")
.long("format")
.default_value("3")
.help("Declares the ROS package format"),
)
.arg(
Arg::new("description")
.long("description")
.default_value("TODO: Package description")
.help("Package Description"),
)
.get_matches_from(
case!(
env_args.iter().any(|arg| arg == "ros-new")=> env_args.iter().take(1).chain(env_args.iter().skip(2)).cloned().collect(),
true => env_args
)
)
}
fn main() -> Result<(), Box<ErrorKind>> {
let matches: ArgMatches = env_to_matches(env::args().collect());
let arguments = [matches
.get_one::<String>("package_name")
.ok_or(ErrorKind::NotFound)?
.clone()]
.to_vec()
.into_iter()
.chain(
["format", "description", "mail", "maintainer", "license"]
.iter()
.map(|argument| matches.get_one::<String>(argument).unwrap().clone()),
)
.collect::<Vec<String>>();
Command::new("cargo")
.arg("new")
.args(
matches
.get_one::<String>("edition")
.into_iter()
.flat_map(|e| ["--edition", e]),
)
.args(
matches
.get_one::<String>("vcs")
.into_iter()
.flat_map(|v| ["--vcs", v]),
)
.arg(if matches.get_flag("lib") {
"--lib"
} else {
"--bin"
})
.arg(&arguments[0])
.status()
.map_err(|err| err.kind())?;
File::create(Path::new(&arguments[0]).join("package.xml"))
.map_err(|err| err.kind())?
.write_all(
[
r#"<?xml version="1.0"?>"#,
r#"<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>"#,
&format!(r#"<package format="{}">"#,arguments[1]),
&format!(" <name>{}</name>",arguments[0]),
" <version>0.1.0</version>",
&format!(" <description>{}</description>",arguments[2]),
&format!(r#" <maintainer email="{}">{}</maintainer>"#,arguments[3],arguments[4]),
&format!(" <license>{}</license>",arguments[5]),
" <export>",
" <build_type>ament_cargo</build_type>",
" </export>",
"</package>",
]
.join("\n")
.as_bytes(),
)
.map_err(|err| err.kind())?;
println!(
"Created ROS Rust package `{}` with package.xml",
arguments[0]
);
Ok(())
}