Skip to main content

tatara_lisp_script/stdlib/
os.rs

1//! OS introspection — the few knobs scripts actually need.
2//!
3//!   (os-platform)    → "linux" | "macos" | "windows" | "other"
4//!   (os-arch)        → "x86_64" | "aarch64" | ...
5//!   (hostname)       → machine hostname string
6//!   (username)       → $USER / $USERNAME / system user
7//!   (user-home)      → $HOME expanded
8
9use std::sync::Arc;
10
11use tatara_lisp_eval::{Arity, EvalError, Interpreter, Value};
12
13use crate::script_ctx::ScriptCtx;
14
15pub fn install(interp: &mut Interpreter<ScriptCtx>) {
16    interp.register_fn(
17        "os-platform",
18        Arity::Exact(0),
19        |_args: &[Value], _ctx: &mut ScriptCtx, _sp| {
20            let p = if cfg!(target_os = "linux") {
21                "linux"
22            } else if cfg!(target_os = "macos") {
23                "macos"
24            } else if cfg!(target_os = "windows") {
25                "windows"
26            } else {
27                "other"
28            };
29            Ok(Value::Str(Arc::from(p)))
30        },
31    );
32
33    interp.register_fn(
34        "os-arch",
35        Arity::Exact(0),
36        |_args: &[Value], _ctx: &mut ScriptCtx, _sp| {
37            Ok(Value::Str(Arc::from(std::env::consts::ARCH)))
38        },
39    );
40
41    interp.register_fn(
42        "hostname",
43        Arity::Exact(0),
44        |_args: &[Value], _ctx: &mut ScriptCtx, sp| {
45            // Read /etc/hostname on unix-like; fall back to HOSTNAME env.
46            if let Ok(h) = std::fs::read_to_string("/etc/hostname") {
47                return Ok(Value::Str(Arc::from(h.trim())));
48            }
49            if let Ok(h) = std::env::var("HOSTNAME") {
50                return Ok(Value::Str(Arc::from(h.as_str())));
51            }
52            Err(EvalError::native_fn(
53                "hostname",
54                "could not determine hostname",
55                sp,
56            ))
57        },
58    );
59
60    interp.register_fn(
61        "username",
62        Arity::Exact(0),
63        |_args: &[Value], _ctx: &mut ScriptCtx, sp| {
64            for k in ["USER", "USERNAME", "LOGNAME"] {
65                if let Ok(u) = std::env::var(k) {
66                    return Ok(Value::Str(Arc::from(u.as_str())));
67                }
68            }
69            Err(EvalError::native_fn(
70                "username",
71                "USER/USERNAME/LOGNAME all unset",
72                sp,
73            ))
74        },
75    );
76
77    interp.register_fn(
78        "user-home",
79        Arity::Exact(0),
80        |_args: &[Value], _ctx: &mut ScriptCtx, sp| {
81            std::env::var("HOME")
82                .map(|h| Value::Str(Arc::from(h.as_str())))
83                .map_err(|_| EvalError::native_fn("user-home", "HOME not set", sp))
84        },
85    );
86}