use std::ffi::OsStr;
use std::fs;
use std::io::ErrorKind;
use std::{error::Error, process::Command};
const GITIGNORE: &str = "
# Eric Wastl wishes for users not to share their puzzle input
/inputs/*
/input_examples/*
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
";
pub fn init() -> Result<(), Box<dyn Error>> {
cmd("cargo", &["init"]);
cmd("cargo", &["add", "aors"]);
fs::remove_file("src/main.rs")?;
fs::remove_file(".gitignore")?;
mkdir("inputs");
mkdir("input_examples");
mkdir("answers");
mkdir("src/bin/helpers");
touch(
"src/bin/helpers/mod.rs",
"",
"failed to create helpers module",
);
touch(".gitignore", GITIGNORE, "failed to create .gitignore");
touch("src/main.rs", "fn main() {}", "failed to create main.rs");
Ok(())
}
fn cmd<I, S>(cmd: &str, args: I)
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
let cmd = Command::new(cmd)
.args(args)
.spawn()
.expect("failed to run command");
cmd.wait_with_output().expect("failed to run command");
}
fn mkdir(path: &str) {
if let Err(a) = fs::create_dir_all(path) {
if a.kind() != ErrorKind::AlreadyExists {
eprintln!("\x1b[31m{}\x1b[0m", a);
}
}
}
fn touch(path: &str, contents: &str, error_msg: &str) {
if let Err(_) = fs::File::open(path) {
fs::write(path, contents).expect(error_msg);
}
}