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.

66 lines
2.2 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. // check if the input line has `key=value` syntax. if so, set an env variable with `key` as key
  11. // and `value` as value
  12. if let Some(capture) = ENV_SET.captures(&line) {
  13. let key = capture.name("key").unwrap().as_str();
  14. let value = capture
  15. .name("value")
  16. .map_or("".to_string(), |v| v.as_str().to_string());
  17. env::set_var(key, value);
  18. return Ok(None);
  19. }
  20. // resolve env variables. if the input line contains `$key` and a env variable with the name
  21. // `key` exists too, resolve `$key` to the variable value. if `key` env variable does not exist,
  22. // simply resolve it with an empty string
  23. for capture in ENV_VARIABLE.captures_iter(&line.clone()) {
  24. let variable_name = capture.name("env").unwrap().as_str();
  25. if variable_name.is_empty() {
  26. continue;
  27. }
  28. let value = env::var(variable_name).unwrap_or_default();
  29. line = ENV_VARIABLE.replacen(&line, 1, &value).to_string();
  30. }
  31. Ok(Some(line))
  32. }
  33. #[cfg(test)]
  34. mod tests {
  35. use super::*;
  36. #[test]
  37. fn test_preprocess_env_variable() {
  38. assert_eq!(preprocess("key=value".to_string()), Ok(None));
  39. assert_eq!(env::var("key").unwrap_or_default(), "value".to_string())
  40. }
  41. #[test]
  42. fn test_preprocessing_resolve_env_variable() {
  43. assert_eq!(preprocess("key=value".to_string()), Ok(None));
  44. assert_eq!(
  45. preprocess("$key".to_string()),
  46. Ok(Some("value".to_string()))
  47. )
  48. }
  49. #[test]
  50. fn test_preprocessing_resolve_non_existent_env_variable() {
  51. assert_eq!(
  52. preprocess("$nonexitent".to_string()),
  53. Ok(Some("".to_string()))
  54. )
  55. }
  56. }