From 2a33d0bddd004a5aaf7bb21a7935470f9410376a Mon Sep 17 00:00:00 2001 From: hexclover <47456195+hexclover@users.noreply.github.com> Date: Mon, 1 Jan 2024 20:17:09 +0800 Subject: [PATCH 1/2] When calculating path, apply tilde expansion before adding prefix --- src/types/dir.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/types/dir.rs b/src/types/dir.rs index 52fd8b9..4f089b3 100644 --- a/src/types/dir.rs +++ b/src/types/dir.rs @@ -72,6 +72,16 @@ fn config_home() -> Result { home } +fn expand_tilde(path: &String) -> std::path::PathBuf { + let parsed_path = std::path::Path::new(path); + if let Ok(stripped_path) = parsed_path.strip_prefix("~") { + let home = config_home().unwrap_or("/".to_string()); + std::path::Path::new(&home).join(stripped_path) + } else { + parsed_path.into() + } +} + macro_rules! define_calculate_path { ($ty:ident, $xdg_env:expr, $xdg_fallback:expr) => { impl $ty { @@ -85,25 +95,22 @@ macro_rules! define_calculate_path { &self, config_file_path: &P, ) -> std::path::PathBuf { + let expanded_path = expand_tilde(&self.path); + let path = match self.prefix { - DirPrefix::Default => self.path.as_str().into(), - DirPrefix::Cwd => std::path::Path::new(".").join(self.path.as_str()), + DirPrefix::Default => expanded_path.into(), + DirPrefix::Cwd => std::path::Path::new(".").join(expanded_path), DirPrefix::Relative => match config_file_path.as_ref().parent() { - Some(parent) => parent.join(self.path.as_str()), - None => std::path::Path::new(".").join(self.path.as_str()), + Some(parent) => parent.join(expanded_path), + None => std::path::Path::new(".").join(expanded_path), }, DirPrefix::Xdg => std::path::PathBuf::from( std::env::var($xdg_env).unwrap_or_else(|_| $xdg_fallback.into()), ) - .join(self.path.as_str()), + .join(expanded_path), }; - if let Ok(stripped_path) = path.strip_prefix("~") { - let home = config_home().unwrap_or("/".to_string()); - std::path::Path::new(&home).join(stripped_path) - } else { - path - } + path } } }; From 56a1498141bc1892208b41692bd92891004980de Mon Sep 17 00:00:00 2001 From: hexclover <47456195+hexclover@users.noreply.github.com> Date: Mon, 1 Jan 2024 20:26:38 +0800 Subject: [PATCH 2/2] Implement different 'default' prefix behavior for different directives --- src/types/dir.rs | 70 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/types/dir.rs b/src/types/dir.rs index 4f089b3..ed9081b 100644 --- a/src/types/dir.rs +++ b/src/types/dir.rs @@ -42,6 +42,13 @@ pub enum DirPrefix { Relative, } +pub enum PrefixBehavior { + Config, + Cwd, + Xdg, + Relative, +} + parse_enum! { DirPrefix, (Default, "default"), @@ -72,6 +79,20 @@ fn config_home() -> Result { home } +/// Given a relative path to a config file, this function returns +/// the complete file name to load. +/// +/// This is a simplified version of `FcConfigGetFilename` from the Fontconfig +/// library. +fn config_get_file_name(p: &std::path::PathBuf) -> std::path::PathBuf { + #[cfg(target_os = "windows")] + { + // TODO: get config file path properly for Windows + return p.clone(); + } + std::path::Path::new("/etc/fonts").join(p) +} + fn expand_tilde(path: &String) -> std::path::PathBuf { let parsed_path = std::path::Path::new(path); if let Ok(stripped_path) = parsed_path.strip_prefix("~") { @@ -83,12 +104,22 @@ fn expand_tilde(path: &String) -> std::path::PathBuf { } macro_rules! define_calculate_path { - ($ty:ident, $xdg_env:expr, $xdg_fallback:expr) => { + ($ty:ident, $xdg_env:expr, $xdg_fallback:expr, $default_prefix_behavior:expr) => { impl $ty { /// Environment variable name which used `xdg` prefix pub const XDG_ENV: &'static str = $xdg_env; /// Fallback path when `XDG_ENV` is not exists pub const XDG_FALLBACK_PATH: &'static str = $xdg_fallback; + const DEFAULT_PREFIX_BEHAVIOR: PrefixBehavior = $default_prefix_behavior; + + fn get_prefix_behavior(prefix: DirPrefix) -> PrefixBehavior { + match prefix { + DirPrefix::Default => Self::DEFAULT_PREFIX_BEHAVIOR, + DirPrefix::Cwd => PrefixBehavior::Cwd, + DirPrefix::Xdg => PrefixBehavior::Xdg, + DirPrefix::Relative => PrefixBehavior::Relative + } + } /// Calculate actual path pub fn calculate_path + ?Sized>( @@ -97,26 +128,33 @@ macro_rules! define_calculate_path { ) -> std::path::PathBuf { let expanded_path = expand_tilde(&self.path); - let path = match self.prefix { - DirPrefix::Default => expanded_path.into(), - DirPrefix::Cwd => std::path::Path::new(".").join(expanded_path), - DirPrefix::Relative => match config_file_path.as_ref().parent() { + if expanded_path.is_absolute() { + return expanded_path; + } + + let prefix = Self::get_prefix_behavior(self.prefix); + + match prefix { + PrefixBehavior::Config => config_get_file_name(&expanded_path), + PrefixBehavior::Cwd => std::path::Path::new(".").join(expanded_path), + PrefixBehavior::Relative => match config_file_path.as_ref().parent() { Some(parent) => parent.join(expanded_path), None => std::path::Path::new(".").join(expanded_path), }, - DirPrefix::Xdg => std::path::PathBuf::from( - std::env::var($xdg_env).unwrap_or_else(|_| $xdg_fallback.into()), - ) - .join(expanded_path), - }; - - path + PrefixBehavior::Xdg => { + let xdg_path = std::env::var($xdg_env) + .unwrap_or_else(|_| + $xdg_fallback.into() + ); + expand_tilde(&xdg_path).join(expanded_path) + } + } } } }; } -define_calculate_path!(Dir, "XDG_DATA_HOME", "~/.local/share"); -define_calculate_path!(CacheDir, "XDG_CACHE_HOME", "~/.cache"); -define_calculate_path!(Include, "XDG_CONFIG_HOME", "~/.config"); -define_calculate_path!(RemapDir, "XDG_CONFIG_HOME", "~/.config"); +define_calculate_path!(Dir, "XDG_DATA_HOME", "~/.local/share", PrefixBehavior::Cwd); +define_calculate_path!(CacheDir, "XDG_CACHE_HOME", "~/.cache", PrefixBehavior::Cwd); +define_calculate_path!(Include, "XDG_CONFIG_HOME", "~/.config", PrefixBehavior::Config); +define_calculate_path!(RemapDir, "XDG_CONFIG_HOME", "~/.config", PrefixBehavior::Cwd);