Skip to main content

custom_utils/util_args/
mod.rs

1use anyhow::Context;
2use std::path::PathBuf;
3
4/// arg_value("--check", "-c")
5pub fn arg_value(long: &str, short: &str) -> Option<String> {
6    assert!(long.starts_with("--"));
7    assert!(short.starts_with('-'));
8    let mut is_val = false;
9    for arg in std::env::args() {
10        if is_val {
11            return Some(arg);
12        }
13        is_val = arg == long || arg == short;
14    }
15    None
16}
17
18/// exist_arg("--check", "-c")
19pub fn exist_arg(long: &str, short: &str) -> bool {
20    assert!(long.starts_with("--"));
21    assert!(short.starts_with('-'));
22    for arg in std::env::args() {
23        if arg == long || arg == short {
24            return true;
25        }
26    }
27    false
28}
29
30pub fn command() -> Option<String> {
31    for (index, arg) in std::env::args().enumerate() {
32        if index == 1 {
33            return Some(arg);
34        }
35    }
36    None
37}
38
39/// Gets the current system user's home directory.
40pub fn get_user_home() -> anyhow::Result<PathBuf> {
41    home::home_dir().context("Failed to get user home directory")
42}
43
44/// Expands path, supporting '~' for the user's home directory.
45pub fn expand_path(path: &str) -> anyhow::Result<PathBuf> {
46    if let Some(stripped) = path.strip_prefix('~') {
47        let home = get_user_home()?;
48        // Remove leading separator if present to avoid join issues
49        let suffix = stripped.trim_start_matches(['/', '\\']);
50        return Ok(home.join(suffix));
51    }
52
53    if path == "." || path == "./" || path == ".\\" {
54        return std::env::current_dir().context("Failed to get current directory");
55    }
56
57    if let Some(stripped) = path.strip_prefix("./").or_else(|| path.strip_prefix(".\\")) {
58        let current_dir = std::env::current_dir().context("Failed to get current directory")?;
59        let suffix = stripped.trim_start_matches(['/', '\\']);
60        return Ok(current_dir.join(suffix));
61    }
62
63    let expanded = shellexpand::tilde(path);
64    Ok(PathBuf::from(expanded.into_owned()))
65}
66
67/// $HOME/.config/app
68pub fn workspace(workspace: &Option<String>, app: &str) -> anyhow::Result<PathBuf> {
69    let workspace = if let Some(workspace) = workspace {
70        expand_path(workspace)?
71    } else {
72        get_user_home()?.join(".config").join(app)
73    };
74    log::debug!("{}", workspace.display());
75    Ok(workspace)
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use std::env;
82
83    #[test]
84    fn test_get_user_home() {
85        let home = get_user_home();
86        assert!(home.is_ok());
87    }
88
89    #[test]
90    fn test_expand_path_tilde() {
91        let home = get_user_home().unwrap();
92        let expanded = expand_path("~").unwrap();
93        assert_eq!(expanded, home);
94    }
95
96    #[test]
97    fn test_expand_path_dot() {
98        let cwd = std::env::current_dir().unwrap();
99        let expanded = expand_path("./test").unwrap();
100        assert_eq!(expanded, cwd.join("test"));
101    }
102
103    #[test]
104    fn test_expand_path_dot_only() {
105        let cwd = std::env::current_dir().unwrap();
106        assert_eq!(expand_path(".").unwrap(), cwd);
107    }
108}