diff --git a/Cargo.lock b/Cargo.lock index eb2228a45..68b627e46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1542,6 +1542,7 @@ dependencies = [ "libc", "parking_lot", "ratatui", + "regex", "tokio", ] diff --git a/cspell.json b/cspell.json index 2eb6645ea..b19e1b92e 100644 --- a/cspell.json +++ b/cspell.json @@ -1 +1 @@ -{"version":"0.2","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","backstack","natsort","natsort"],"language":"en"} \ No newline at end of file +{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","backstack","natsort","natsort","USERPROFILE"],"language":"en","version":"0.2"} diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 57b327eb0..85f147f19 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -10,4 +10,5 @@ futures = "^0" libc = "^0" parking_lot = "^0" ratatui = { version = "^0" } +regex = "^1" tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "time", "fs" ] } diff --git a/shared/src/fns.rs b/shared/src/fns.rs index 2ac3234de..061253dea 100644 --- a/shared/src/fns.rs +++ b/shared/src/fns.rs @@ -5,12 +5,32 @@ use tokio::fs; use crate::Url; pub fn expand_path(p: impl AsRef) -> PathBuf { - let p = p.as_ref(); + // ${HOME} or $HOME + #[cfg(unix)] + let re = regex::Regex::new(r"\$(?:\{([^}]+)\}|([a-zA-Z\d_]+))").unwrap(); + + // %USERPROFILE% + #[cfg(windows)] + let re = regex::Regex::new(r"%([^%]+)%").unwrap(); + + let s = p.as_ref().to_string_lossy(); + let s = re.replace_all(&s, |caps: ®ex::Captures| { + let name = caps.get(2).or_else(|| caps.get(1)).unwrap(); + env::var(name.as_str()).unwrap_or_else(|_| caps.get(0).unwrap().as_str().to_owned()) + }); + + let p = Path::new(s.as_ref()); if let Ok(p) = p.strip_prefix("~") { + #[cfg(unix)] if let Some(home) = env::var_os("HOME") { - return PathBuf::from_iter([&home, p.as_os_str()]); + return Path::new(&home).join(p); + } + #[cfg(windows)] + if let Some(home) = env::var_os("USERPROFILE") { + return Path::new(&home).join(p); } } + if p.is_absolute() { return p.to_path_buf(); } @@ -48,7 +68,7 @@ pub fn short_path<'a>(p: &'a Path, base: &Path) -> ShortPath<'a> { } pub fn readable_path(p: &Path) -> String { - if let Ok(home) = env::var("HOME") { + if let Some(home) = env::var_os("HOME") { if let Ok(p) = p.strip_prefix(home) { return format!("~/{}", p.display()); }