rubx 0.1.1

Rubx (Rust Basic Toolbox) is a library for command programs that features a toolbox with a series of basic functionalities.
Documentation
use std::io::{Read, Write};
use std::process::{Command, Stdio};
use std::thread;
use std::time::Duration;

use crate::rux_debug::{dbg_bleb, dbg_erro};
use crate::rux_debug::{dbg_call, dbg_lets, dbg_reav, dbg_step};
use crate::rux_paths;
use crate::RubxError;

pub fn cmd(
  command: &str,
  args: &[impl AsRef<str>],
  dir: Option<impl AsRef<str>>,
  print: Option<bool>,
  throw: Option<bool>,
) -> Result<(i32, String), RubxError> {
  dbg_call!(command, print, throw);
  let mut cmd = Command::new(command);
  let args = dbg_lets!(args
    .iter()
    .map(|arg| {
      let arg = arg.as_ref();
      cmd.arg(arg);
      arg.into()
    })
    .collect::<Vec<&str>>());
  let dir: String = if let Some(dir) = dir {
    dir.as_ref().into()
  } else {
    ".".into()
  };
  dbg_step!(dir);
  cmd.current_dir(&dir);
  let mut child = cmd
    .stdin(Stdio::null())
    .stdout(Stdio::piped())
    .stderr(Stdio::piped())
    .spawn()
    .map_err(|err| dbg_erro!(err, command, args, dir))?;
  let mut output = String::new();
  child
    .stdout
    .take()
    .ok_or("Could not take on the child stdout")
    .map_err(|err| dbg_erro!(err))?
    .read_to_string(&mut output)
    .map_err(|err| dbg_erro!(err))?;
  dbg_step!(output);
  child
    .stderr
    .take()
    .ok_or("Could not take on the child stderr")
    .map_err(|err| dbg_erro!(err))?
    .read_to_string(&mut output)
    .map_err(|err| dbg_erro!(err))?;
  dbg_step!(output);
  let output = output.trim();
  let output = String::from(output);
  dbg_step!(output);
  let result = child
    .wait()
    .map_err(|err| dbg_erro!(err))?
    .code()
    .ok_or("Could not found the exit code")
    .map_err(|err| dbg_erro!(err))?;
  dbg_step!(result);
  let print = if let Some(print) = print { print } else { true };
  dbg_step!(print);
  if print && !output.is_empty() {
    println!("{}", output);
  }
  let throw = if let Some(throw) = throw { throw } else { true };
  dbg_step!(throw);
  if throw && result != 0 {
    return Err(dbg_erro!(
      "Result code from command is different than zero",
      command,
      result
    ));
  }
  Ok((result, output))
}

pub fn sleep(millis: u64) {
  dbg_call!(millis);
  thread::sleep(Duration::from_millis(millis))
}

pub fn pause() -> Result<(), RubxError> {
  dbg_call!();
  let mut stdin = std::io::stdin();
  let mut stdout = std::io::stdout();
  write!(stdout, "Press enter to continue...").map_err(|err| dbg_erro!(err))?;
  stdout.flush()?;
  let mut buffer = [0u8];
  stdin.read(&mut buffer).map_err(|err| dbg_erro!(err))?;
  Ok(())
}

pub fn exe_path() -> Result<String, RubxError> {
  dbg_call!();
  dbg_reav!(Ok(format!(
    "{}",
    std::env::current_exe()
      .map_err(|err| dbg_erro!(err))?
      .display(),
  )))
}

pub fn exe_dir() -> Result<String, RubxError> {
  dbg_call!();
  let exe_path = exe_path().map_err(|err| dbg_bleb!(err))?;
  dbg_reav!(Ok(
    rux_paths::path_parent(&exe_path).map_err(|err| dbg_bleb!(err))?,
  ))
}

pub fn exe_name() -> Result<String, RubxError> {
  dbg_call!();
  let exe_path = exe_path().map_err(|err| dbg_bleb!(err))?;
  dbg_reav!(Ok(rux_paths::path_name(&exe_path).into()))
}

pub fn exe_stem() -> Result<String, RubxError> {
  dbg_call!();
  let exe_path = exe_path().map_err(|err| dbg_bleb!(err))?;
  dbg_reav!(Ok(rux_paths::path_stem(&exe_path).into()))
}

pub fn exe_ext() -> &'static str {
  dbg_call!();
  dbg_reav!(std::env::consts::EXE_EXTENSION)
}

pub fn dot_exe_ext() -> String {
  dbg_call!();
  dbg_reav!(if std::env::consts::EXE_EXTENSION.is_empty() {
    String::default()
  } else {
    format!(".{}", std::env::consts::EXE_EXTENSION)
  })
}

pub fn get_os() -> &'static str {
  dbg_call!();
  dbg_reav!(std::env::consts::OS)
}

pub fn is_lin() -> bool {
  dbg_call!();
  dbg_reav!(std::env::consts::OS == "linux")
}

pub fn is_mac() -> bool {
  dbg_call!();
  dbg_reav!(std::env::consts::OS == "macos")
}

pub fn is_win() -> bool {
  dbg_call!();
  dbg_reav!(std::env::consts::OS == "windows")
}

pub fn thread_id() -> String {
  dbg_call!();
  dbg_reav!(format!("{:?}", thread::current().id()))
}

pub fn thread_display() -> String {
  dbg_call!();
  dbg_reav!(if let Some(name) = thread::current().name() {
    format!("{}", name)
  } else {
    format!("{}", thread_id())
  })
}