expand env vars
change mltvqxswxkvqvqkmskynwwuyrkmwltpl
commit c43cc73e6c492706a8384d97a5fa5e0c1fa44f70
author Alpha Chen <alpha@kejadlen.dev>
date
parent slvrzqwo
diff --git a/Cargo.lock b/Cargo.lock
index 501366d..7fd0767 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,6 +17,15 @@ version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
 
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "anstream"
 version = "0.6.21"
@@ -297,6 +306,7 @@ dependencies = [
  "color-eyre",
  "facet",
  "mlua",
+ "regex",
  "thiserror",
  "tracing",
  "tracing-subscriber",
@@ -549,6 +559,35 @@ dependencies = [
  "bitflags",
 ]
 
+[[package]]
+name = "regex"
+version = "1.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
+
 [[package]]
 name = "rustc-demangle"
 version = "0.1.26"
diff --git a/Cargo.toml b/Cargo.toml
index 43c7ced..6ef52d3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,7 @@ color-eyre = "*"
 clap = { version = "*", features = ["derive"] }
 facet = "*"
 mlua = { version = "*", features = ["lua54", "vendored"] }
+regex = "*"
 thiserror = "*"
 tracing = "*"
 tracing-subscriber = "*"
diff --git a/src/main.rs b/src/main.rs
index 7b58005..9ea5be0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,12 +4,14 @@ use color_eyre::{
     eyre::{WrapErr, eyre},
 };
 use mlua::prelude::*;
+use regex::Regex;
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::env;
 use std::fs;
 use std::path::Path;
 use std::rc::Rc;
+use std::sync::LazyLock;
 use thiserror::Error;
 use tracing::{debug, info};
 
@@ -60,16 +62,28 @@ impl From<LuaError> for FrorkError {
     }
 }
 
-fn expand_tilde(path: &str) -> String {
-    if path.starts_with('~') {
+static ENV_VAR_REGEX: LazyLock<Regex> =
+    LazyLock::new(|| Regex::new(r"\$([A-Za-z_][A-Za-z0-9_]*)").unwrap());
+
+fn expand_path(path: &str) -> String {
+    let mut expanded = path.to_string();
+
+    // Expand tilde
+    if expanded.starts_with('~') {
         if let Ok(home) = env::var("HOME") {
-            path.replacen('~', &home, 1)
-        } else {
-            path.to_string()
+            expanded = expanded.replacen('~', &home, 1);
         }
-    } else {
-        path.to_string()
     }
+
+    // Expand environment variables using regex
+    expanded = ENV_VAR_REGEX
+        .replace_all(&expanded, |caps: &regex::Captures| {
+            let var_name = caps.get(1).unwrap().as_str();
+            env::var(var_name).unwrap_or_else(|_| caps.get(0).unwrap().as_str().to_string())
+        })
+        .to_string();
+
+    expanded
 }
 
 #[derive(Debug)]
@@ -149,7 +163,7 @@ impl Symlink {
         let strings: Vec<String> = args_vec
             .into_iter()
             .map(|val| {
-                val.to_string().map(|s| expand_tilde(&s)).map_err(|_| {
+                val.to_string().map(|s| expand_path(&s)).map_err(|_| {
                     FrorkError::InvalidArguments("Arguments must be strings".to_string())
                 })
             })
@@ -225,7 +239,7 @@ impl Directory {
             .to_string()
             .map_err(|_| FrorkError::InvalidArguments("Argument must be a string".to_string()))?;
 
-        let expanded_path = expand_tilde(&path);
+        let expanded_path = expand_path(&path);
 
         Ok(Self {
             path: expanded_path,