use std::fs;
use std::path::{Path, PathBuf};
#[must_use]
pub fn resolve_under_root(base: &Path, path: &str) -> PathBuf {
base.join(path)
}
#[must_use]
pub fn rel_path_is_directory(root: &Path, path: &Path) -> bool {
fs::metadata(root.join(path))
.map(|m| m.is_dir())
.unwrap_or(false)
}
#[must_use]
pub fn path_to_slash_string(path: &Path) -> String {
path.to_string_lossy().replace('\\', "/")
}
#[must_use]
pub fn normalize_snapshot_rel_path_str(path: &str) -> String {
let mut s = path.trim();
s = s.strip_prefix("./").unwrap_or(s);
if let Some(rest) = s.strip_prefix(".\\") {
s = rest;
}
s.replace('\\', "/")
}
#[must_use]
pub fn snapshot_rel_path_buf(path_str: &str) -> PathBuf {
PathBuf::from(normalize_snapshot_rel_path_str(path_str))
}
#[must_use]
pub fn shorten_path_for_title(path: &str) -> String {
const TAIL: usize = 3;
let normalized = path.trim().replace('\\', "/");
let parts: Vec<&str> = normalized.split('/').filter(|s| !s.is_empty()).collect();
if parts.len() <= TAIL {
return normalized;
}
let tail = parts[parts.len() - TAIL..].join("/");
format!(".../{tail}")
}
#[must_use]
pub fn path_has_extension(path: &str, exts: &[&str]) -> bool {
std::path::Path::new(path)
.extension()
.is_some_and(|ext| exts.iter().any(|e| ext.eq_ignore_ascii_case(e)))
}
#[macro_export]
macro_rules! define_path_ext_predicate {
(
$(#[$meta:meta])*
$vis:vis fn $name:ident($path:ident: &str) -> bool {
$($ext:literal),+ $(,)?
}
) => {
$(#[$meta])*
$vis fn $name(path: &str) -> bool {
$crate::utils::path_has_extension(path, &[$($ext),+])
}
};
}
#[cfg(test)]
mod tests {
use super::shorten_path_for_title;
#[test]
fn shorten_path_for_title_short_unchanged() {
assert_eq!(shorten_path_for_title("a/b"), "a/b");
assert_eq!(shorten_path_for_title("a/b/c"), "a/b/c");
assert_eq!(shorten_path_for_title("file.rs"), "file.rs");
}
#[test]
fn shorten_path_for_title_long_keeps_last_three() {
assert_eq!(shorten_path_for_title("a/b/c/d"), ".../b/c/d");
assert_eq!(
shorten_path_for_title("/usr/local/bin/tool"),
".../local/bin/tool"
);
}
#[test]
fn shorten_path_for_title_normalizes_backslashes() {
assert_eq!(shorten_path_for_title(r"a\b\c\d"), ".../b/c/d");
}
}