tatara_lisp_script/stdlib/
log.rs1use std::sync::Arc;
13
14use tatara_lisp_eval::{Arity, Interpreter, Value};
15
16use crate::script_ctx::ScriptCtx;
17use crate::stdlib::env::str_arg;
18
19const LEVEL_DEBUG: u8 = 0;
20const LEVEL_INFO: u8 = 1;
21const LEVEL_WARN: u8 = 2;
22const LEVEL_ERROR: u8 = 3;
23
24pub fn install(interp: &mut Interpreter<ScriptCtx>) {
25 for (name, lvl, label) in [
26 ("log-debug", LEVEL_DEBUG, "DEBUG"),
27 ("log-info", LEVEL_INFO, "INFO"),
28 ("log-warn", LEVEL_WARN, "WARN"),
29 ("log-error", LEVEL_ERROR, "ERROR"),
30 ] {
31 interp.register_fn(
32 name,
33 Arity::Exact(1),
34 move |args: &[Value], _ctx: &mut ScriptCtx, sp| {
35 let msg = str_arg(&args[0], name, sp)?;
36 if lvl >= current_level() {
37 eprintln!("[{}] {} {}", now_hms(), label, msg);
38 }
39 Ok(Value::Nil)
40 },
41 );
42 }
43}
44
45fn current_level() -> u8 {
46 match std::env::var("TATARA_LOG")
47 .ok()
48 .as_deref()
49 .unwrap_or("info")
50 {
51 "debug" => LEVEL_DEBUG,
52 "warn" => LEVEL_WARN,
53 "error" => LEVEL_ERROR,
54 _ => LEVEL_INFO,
55 }
56}
57
58fn now_hms() -> String {
59 let secs = std::time::SystemTime::now()
62 .duration_since(std::time::UNIX_EPOCH)
63 .map(|d| d.as_secs())
64 .unwrap_or(0);
65 let h = (secs / 3600) % 24;
66 let m = (secs / 60) % 60;
67 let s = secs % 60;
68 Arc::<str>::from(format!("{h:02}:{m:02}:{s:02}")).to_string()
69}