use std::{
env::{current_dir, current_exe},
path::{Path, PathBuf, MAIN_SEPARATOR},
sync::{Arc, LazyLock},
};
use path_clean::PathClean;
static CWD: LazyLock<Arc<Path>> = LazyLock::new(create_cwd);
static EXE: LazyLock<Arc<Path>> = LazyLock::new(create_exe);
fn create_cwd() -> Arc<Path> {
let mut cwd = current_dir()
.expect("failed to find current working directory")
.to_str()
.expect("current working directory is not valid UTF-8")
.to_string();
if !cwd.ends_with(MAIN_SEPARATOR) {
cwd.push(MAIN_SEPARATOR);
}
dunce::canonicalize(cwd)
.expect("failed to canonicalize current working directory")
.into()
}
fn create_exe() -> Arc<Path> {
let exe = current_exe()
.expect("failed to find current executable")
.to_str()
.expect("current executable is not valid UTF-8")
.to_string();
dunce::canonicalize(exe)
.expect("failed to canonicalize current executable")
.into()
}
#[must_use]
pub fn get_current_dir() -> Arc<Path> {
Arc::clone(&CWD)
}
#[must_use]
pub fn get_current_exe() -> Arc<Path> {
Arc::clone(&EXE)
}
pub fn diff_path(path: impl AsRef<Path>, base: impl AsRef<Path>) -> Option<PathBuf> {
pathdiff::diff_paths(path, base)
}
pub fn clean_path(path: impl AsRef<Path>) -> PathBuf {
path.as_ref().clean()
}
pub fn clean_path_and_make_absolute(path: impl AsRef<Path>) -> PathBuf {
let path = path.as_ref();
if path.is_relative() {
CWD.join(path).clean()
} else {
path.clean()
}
}