cargo-dev 0.0.2

Alias shell commands (think NPM scripts for cargo)
use clap::Parser;
use serde::Deserialize;
use std::{
    collections::HashMap,
    env, fs,
    io::{BufRead, BufReader},
    process::{Command, Stdio},
};

#[derive(Deserialize)]
struct Cargotoml {
    dev: HashMap<String, String>,
}

#[derive(Parser)]
#[structopt(name = "cargo-dev", bin_name = "cargo dev")]
struct Cli {
    #[clap(default_value = "dev")]
    cmd: String,

    #[clap(value_delimiter = ' ')]
    args: Vec<String>,
}

fn main() {
    let cli = Cli::parse();

    let expanded_cmd = get_cmd(&cli.cmd);

    println!("> {}: {}", cli.cmd, expanded_cmd);
    exec(&expanded_cmd);
}

fn exec(exec_cmd: &str) {
    let mut cmd = Command::new("bash")
        .args(vec!["-c", exec_cmd])
        .env_clear()
        .stdout(Stdio::piped())
        .spawn()
        .expect("CMD to run");

    {
        let stdout = cmd.stdout.as_mut().unwrap();
        let stdout_reader = BufReader::new(stdout);
        let stdout_lines = stdout_reader.lines();

        for line in stdout_lines {
            println!("{}", line.unwrap());
        }
    }

    cmd.wait().unwrap();
}

fn get_cmd(name: &String) -> String {
    let cmd_toml_str = fs::read_to_string(format!(
        "{}/Cargo.toml",
        env::var("CARGO_MANIFEST_DIR").unwrap_or("./".to_string())
    ))
    .unwrap();

    let cmd_toml: Cargotoml = toml::from_str(&cmd_toml_str[..]).expect("ASD");

    let cargo_commands = cmd_toml.dev;
    let specific_command = cargo_commands.get(name).expect("ASD");

    specific_command.to_string()
}