doge_runtime/stdlib/env.rs
1//! `env` — command-line arguments and environment variables. The script's
2//! arguments are captured once at startup (`set_script_args`, called from the
3//! generated `main` and the interpreter's CLI path) into a process-global slot;
4//! `env.args()` reads them back and `env.get(name)` reads the OS environment.
5
6use std::sync::OnceLock;
7
8use crate::error::DogeResult;
9use crate::stdlib::str_arg;
10use crate::value::Value;
11
12/// The script's command-line arguments (excluding the program name), set once at
13/// startup. Unset until `set_script_args` runs, which reads back as no arguments.
14static SCRIPT_ARGS: OnceLock<Vec<String>> = OnceLock::new();
15
16/// Record the script's command-line arguments. Called once at program startup
17/// (compiled `main` or the interpreter's file runner); any later call is ignored,
18/// so the arguments a script sees are fixed for its whole run.
19pub fn set_script_args(args: Vec<String>) {
20 let _ = SCRIPT_ARGS.set(args);
21}
22
23/// `env.args()` — the script's command-line arguments as a List of Str, excluding
24/// the program name. Empty when the script was given none.
25pub fn env_args() -> DogeResult {
26 let args = SCRIPT_ARGS
27 .get()
28 .map(|args| args.iter().map(Value::str).collect())
29 .unwrap_or_default();
30 Ok(Value::list(args))
31}
32
33/// `env.get(name)` — the value of environment variable `name` as a Str, or `none`
34/// when it is unset or not valid text.
35pub fn env_get(name: &Value) -> DogeResult {
36 let name = str_arg("env", "get", name)?;
37 match std::env::var(name) {
38 Ok(value) => Ok(Value::str(value)),
39 Err(_) => Ok(Value::None),
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn args_default_to_empty() {
49 // No `set_script_args` runs in this test binary, so the slot is unset.
50 match env_args().unwrap() {
51 Value::List(items) => assert!(items.borrow().is_empty()),
52 _ => panic!("expected a list"),
53 }
54 }
55
56 #[test]
57 fn get_of_an_unset_variable_is_none() {
58 let unset = Value::str("DOGE_SURELY_UNSET_VARIABLE_KABOSU");
59 assert!(matches!(env_get(&unset).unwrap(), Value::None));
60 }
61}