Skip to content

Commit 8ac5df7

Browse files
authored
fix: expand tilde out into home directory
1 parent bf55b41 commit 8ac5df7

File tree

1 file changed

+50
-2
lines changed

1 file changed

+50
-2
lines changed

src/config.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use anyhow::{Context, Result};
22
use serde::Deserialize;
3-
use std::{fs, path::PathBuf};
3+
use std::{env, fs, path::PathBuf};
44

55
/// Represents global application settings loaded from cmdy.toml.
66
#[derive(Debug, Deserialize)]
@@ -22,6 +22,17 @@ impl Default for AppConfig {
2222
}
2323
}
2424

25+
fn expand_tilde(path: &PathBuf) -> PathBuf {
26+
if let Some(path_str) = path.to_str() {
27+
if path_str.starts_with("~/") {
28+
if let Ok(home) = env::var("HOME") {
29+
return PathBuf::from(home).join(&path_str[2..]);
30+
}
31+
}
32+
}
33+
path.clone()
34+
}
35+
2536
/// Loads the application configuration from a TOML file.
2637
/// Checks ~/.config/cmdy/cmdy.toml (macOS) or $XDG_CONFIG_HOME/cmdy/cmdy.toml, falling back to defaults.
2738
pub fn load_app_config() -> Result<AppConfig> {
@@ -42,7 +53,10 @@ pub fn load_app_config() -> Result<AppConfig> {
4253
let content = fs::read_to_string(&config_path)
4354
.with_context(|| format!("Failed to read config file: {}", config_path.display()))?;
4455
match toml::from_str::<AppConfig>(&content) {
45-
Ok(cfg) => return Ok(cfg),
56+
Ok(mut cfg) => {
57+
cfg.directories = cfg.directories.iter().map(expand_tilde).collect();
58+
return Ok(cfg);
59+
}
4660
Err(e) => eprintln!(
4761
"Warning: Failed to parse config file {}: {}. Using defaults.",
4862
config_path.display(),
@@ -235,4 +249,38 @@ directories = ["one", "two"]
235249
assert!(result.is_err(), "Expected I/O error, got {:?}", result);
236250
Ok(())
237251
}
252+
253+
#[test]
254+
/// load_app_config expands ~ in directory paths
255+
fn test_load_app_config_tilde_expansion() -> Result<()> {
256+
let _guard = ENV_LOCK.lock().unwrap();
257+
let tmp = tempdir()?;
258+
unsafe {
259+
env::set_var("HOME", tmp.path());
260+
}
261+
let (_config_dir, config_file) = if cfg!(target_os = "macos") {
262+
let base = tmp.path().join(".config").join("cmdy");
263+
fs::create_dir_all(&base)?;
264+
let file = base.join("cmdy.toml");
265+
(base, file)
266+
} else {
267+
unsafe {
268+
env::set_var("XDG_CONFIG_HOME", tmp.path());
269+
}
270+
let base = tmp.path().join("cmdy");
271+
fs::create_dir_all(&base)?;
272+
let file = base.join("cmdy.toml");
273+
(base, file)
274+
};
275+
let content = r#"
276+
filter_command = "fzf"
277+
directories = ["~/test/path", "/absolute/path"]
278+
"#;
279+
fs::write(&config_file, content)?;
280+
let cfg = load_app_config()?;
281+
assert_eq!(cfg.directories.len(), 2);
282+
assert_eq!(cfg.directories[0], tmp.path().join("test/path"));
283+
assert_eq!(cfg.directories[1], PathBuf::from("/absolute/path"));
284+
Ok(())
285+
}
238286
}

0 commit comments

Comments
 (0)