hyper-scripter 0.3.3

The script managing tool for script lovers
Documentation
use std::fs::canonicalize;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use std::process::ExitStatus;
use std::process::{Command, Stdio};
use std::sync::{Mutex, MutexGuard};

lazy_static::lazy_static! {
    static ref LOCK: Mutex<()> = Mutex::new(());
}
#[cfg(not(debug_assertions))]
const EXE: &'static str = "../target/release/hs";
#[cfg(debug_assertions)]
const EXE: &'static str = "../target/debug/hs";

pub fn get_exe_abs() -> String {
    canonicalize(EXE)
        .unwrap()
        .to_string_lossy()
        .as_ref()
        .to_owned()
}

const HOME: &str = "./.hyper_scripter";

pub fn get_home() -> PathBuf {
    canonicalize(HOME).unwrap()
}

pub fn setup<'a>() -> MutexGuard<'a, ()> {
    let guard = LOCK.lock().unwrap_or_else(|err| err.into_inner());
    let _ = env_logger::try_init();
    match std::fs::remove_dir_all(HOME) {
        Ok(_) => (),
        Err(e) => {
            if e.kind() != std::io::ErrorKind::NotFound {
                panic!("重整測試用資料夾失敗了……")
            }
        }
    }
    let _ = std::fs::remove_dir_all(".tmp");
    std::fs::create_dir(HOME).unwrap();
    run("alias e edit --fast").unwrap();

    guard
}
fn join_path(p: &[&str]) -> PathBuf {
    let mut file = get_home();
    for p in p.iter() {
        file = file.join(p);
    }
    file
}

pub fn read(p: &[&str]) -> String {
    let file = join_path(p);
    let s = std::fs::read(file).unwrap();
    let s: &str = std::str::from_utf8(&s).unwrap();
    s.to_owned()
}
pub fn check_exist(p: &[&str]) -> bool {
    let file = join_path(p);
    file.exists()
}
pub fn run(args: &str) -> Result<String, ExitStatus> {
    let home = get_home();
    run_with_home(&*home.to_string_lossy(), args)
}
pub fn run_with_home(home: &str, args: &str) -> Result<String, ExitStatus> {
    let mut full_args = vec!["-H", home];
    let args_vec: Vec<&str> = if args.find("|").is_some() {
        let (first, second) = args.split_once("|").unwrap();
        let mut v: Vec<_> = first.split(" ").filter(|s| s.len() > 0).collect();
        v.push(second.trim());
        v
    } else {
        args.split(" ").collect()
    };
    full_args.extend(&args_vec);

    let mut cmd = Command::new(EXE);
    let mut child = cmd
        .args(&full_args)
        .stdout(Stdio::piped())
        .stderr(Stdio::inherit())
        .spawn()
        .unwrap();
    let stdout = child.stdout.as_mut().unwrap();
    let mut out_str = vec![];
    let reader = BufReader::new(stdout);
    reader
        .lines()
        .filter_map(|line| line.ok())
        .for_each(|line| {
            println!("{}", line);
            out_str.push(line);
        });

    let status = child.wait().unwrap();
    let res = if status.success() {
        Ok(out_str.join("\n"))
    } else {
        Err(status)
    };
    log::trace!("執行 {:?} 完畢,結果為 {:?}", args_vec, res);
    res
}

pub fn assert_ls_len(expect: usize) {
    let ls_res = run("ls -f all --grouping none --plain --name").unwrap();
    let ls_vec = ls_res
        .split(" ")
        .filter(|s| s.len() > 0)
        .collect::<Vec<_>>();
    assert_eq!(expect, ls_vec.len(), "ls 結果為 {:?}", ls_vec);
}