You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

55 lines
1.8 KiB

  1. use crate::error::ShellError;
  2. use once_cell::unsync::Lazy;
  3. use regex::Regex;
  4. use std::env;
  5. const ENV_SET: Lazy<Regex> = Lazy::new(|| Regex::new(r#"(?P<key>\w+)=(?P<value>\w*)"#).unwrap());
  6. const ENV_VARIABLE: Lazy<Regex> = Lazy::new(|| Regex::new(r"(\\\$|\$(?P<env>\w+))").unwrap());
  7. /// Returns `Ok(Some(...))` if a command should be triggered after calling this functions. If it
  8. /// returns `Ok(None)`, do not execute a command.
  9. pub fn preprocess(mut line: String) -> Result<Option<String>, ShellError> {
  10. if let Some(capture) = ENV_SET.captures(&line) {
  11. let key = capture.name("key").unwrap().as_str();
  12. let value = capture
  13. .name("value")
  14. .map_or("".to_string(), |v| v.as_str().to_string());
  15. env::set_var(key, value);
  16. return Ok(None);
  17. }
  18. for capture in ENV_VARIABLE.captures_iter(&line.clone()) {
  19. let variable_name = capture.name("env").unwrap().as_str();
  20. if variable_name.is_empty() {
  21. continue;
  22. }
  23. let value = env::var(variable_name).unwrap_or_default();
  24. line = ENV_VARIABLE.replacen(&line, 1, &value).to_string();
  25. }
  26. Ok(Some(line))
  27. }
  28. #[cfg(test)]
  29. mod tests {
  30. use super::*;
  31. #[test]
  32. fn test_preprocess_env_variable() {
  33. assert_eq!(preprocess("key=value".to_string()), Ok(None));
  34. assert_eq!(env::var("key").unwrap_or_default(), "value".to_string())
  35. }
  36. #[test]
  37. fn test_preprocessing_resolve_env_variable() {
  38. assert_eq!(preprocess("key=value".to_string()), Ok(None));
  39. assert_eq!(preprocess("$key".to_string()), Ok(Some("value".to_string())))
  40. }
  41. #[test]
  42. fn test_preprocessing_resolve_non_existent_env_variable() {
  43. assert_eq!(preprocess("$nonexitent".to_string()), Ok(Some("".to_string())))
  44. }
  45. }