♻️ refactor(config): improve ConfigRoot to handle different root types

- change ConfigRoot to use RootBase enum for different root types (Crate, Home, Root, None)
- add full_path method to resolve the full path based on RootBase and path
- update tests to use full_path to string conversion for assertions
This commit is contained in:
Jeremiah Russell
2025-10-16 15:29:46 +01:00
committed by Jeremiah Russell
parent 73e9eed539
commit 486bcb1934

View File

@@ -1,32 +1,49 @@
use std::{env, fmt::Display}; use std::{env, fmt::Display, path::PathBuf};
use lazy_regex::{Lazy, Regex, lazy_regex}; use lazy_regex::{Lazy, Regex, lazy_regex};
static ROOT_CONFIG: Lazy<Regex> = lazy_regex!(r"^(?P<class>[hrc]):(?P<path>.+)$"); static ROOT_CONFIG: Lazy<Regex> = lazy_regex!(r"^(?P<class>[hrc]):(?P<path>.+)$");
#[derive(Debug, Default)] #[derive(Debug, Default, Clone)]
pub enum ConfigRoot { pub enum RootBase {
#[default] #[default]
None, None,
Crate(String), Crate,
Home(String), Home,
Root(String), Root,
}
impl Display for RootBase {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RootBase::None => write!(f, ""),
RootBase::Crate => write!(f, "c:"),
RootBase::Home => write!(f, "h:"),
RootBase::Root => write!(f, "r:"),
}
}
}
impl RootBase {
fn path(&self) -> PathBuf {
match self {
RootBase::None => PathBuf::new(),
RootBase::Crate => PathBuf::new(),
RootBase::Home => env::home_dir().unwrap_or_default(),
RootBase::Root => PathBuf::from("/"),
}
}
}
#[derive(Debug, Default, Clone)]
pub struct ConfigRoot {
root: RootBase,
path: String,
} }
impl Display for ConfigRoot { impl Display for ConfigRoot {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { write!(f, "{}{}", self.root, self.path)
ConfigRoot::None => write!(f, ""),
ConfigRoot::Crate(path) => write!(f, "{path}"),
ConfigRoot::Home(path) => {
let pb = path.trim_start_matches("/");
write!(f, "{}/{}", env::home_dir().unwrap().display(), pb)
}
ConfigRoot::Root(path) => {
let pb = path.trim_start_matches("/");
write!(f, "/{pb}")
}
}
} }
} }
@@ -34,7 +51,10 @@ impl ConfigRoot {
pub fn parse(s: &str) -> Self { pub fn parse(s: &str) -> Self {
log::debug!("parsing the string `{s}`"); log::debug!("parsing the string `{s}`");
let Some(captures) = ROOT_CONFIG.captures(s) else { let Some(captures) = ROOT_CONFIG.captures(s) else {
return ConfigRoot::None; return ConfigRoot {
root: RootBase::None,
path: "".to_string(),
};
}; };
log::debug!("found captures `{captures:?}`"); log::debug!("found captures `{captures:?}`");
@@ -45,21 +65,36 @@ impl ConfigRoot {
}); });
log::debug!("set the path to `{path}`"); log::debug!("set the path to `{path}`");
let Some(class) = captures.name("class") else { let class = if let Some(c) = captures.name("class") {
return ConfigRoot::None; c.as_str()
} else {
""
}; };
log::debug!("found the class `{class:?}`"); log::debug!("found the class `{class:?}`");
match class.as_str() { let root = match class {
"h" => ConfigRoot::Home(path), "c" => RootBase::Crate,
"r" => ConfigRoot::Root(path), "h" => RootBase::Home,
"c" => ConfigRoot::Crate(path), "r" => RootBase::Root,
"" => RootBase::None,
_ => unreachable!(), _ => unreachable!(),
} };
}
ConfigRoot { root, path }
} }
enum ConfigRootError {} pub fn set_root_base(&mut self, root: &RootBase) {
self.root = root.to_owned();
}
pub fn set_path(&mut self, path: &str) {
self.path = path.to_string();
}
pub fn full_path(&self) -> PathBuf {
self.root.path().join(&self.path)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@@ -80,7 +115,10 @@ mod tests {
let expected = user_home.join(dir_part).display().to_string(); let expected = user_home.join(dir_part).display().to_string();
assert_eq!(expected, ConfigRoot::parse(&input).to_string()); let output = ConfigRoot::parse(&input);
log::debug!("Output set to: `{output:?}`");
assert_eq!(expected, output.full_path().to_string_lossy().to_string());
} }
#[test] #[test]
@@ -92,7 +130,10 @@ mod tests {
let expected = format!("/{dir_part}"); let expected = format!("/{dir_part}");
assert_eq!(expected, ConfigRoot::parse(&input).to_string()); let output = ConfigRoot::parse(&input);
log::debug!("Output set to: `{output:?}`");
assert_eq!(expected, output.full_path().to_string_lossy().to_string());
} }
#[test] #[test]
@@ -102,7 +143,10 @@ mod tests {
log::debug!("Input set to: `{input}`"); log::debug!("Input set to: `{input}`");
let expected = input[2..].to_string(); let expected = input[2..].to_string();
assert_eq!(expected, ConfigRoot::parse(&input).to_string()); let output = ConfigRoot::parse(&input);
log::debug!("Output set to: `{output:?}`");
assert_eq!(expected, output.full_path().to_string_lossy().to_string());
} }
#[test] #[test]
@@ -113,6 +157,9 @@ mod tests {
let expected = "".to_string(); let expected = "".to_string();
assert_eq!(expected, ConfigRoot::parse(&input).to_string()); let output = ConfigRoot::parse(&input);
log::debug!("Output set to: `{output:?}`");
assert_eq!(expected, output.full_path().to_string_lossy().to_string());
} }
} }