lean_ctx/core/config/
shell_approval.rs1use serde::{Deserialize, Serialize};
9
10use super::Config;
11
12#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
19#[serde(rename_all = "kebab-case")]
20pub enum ShellApproval {
21 #[default]
22 Ask,
23 Off,
24}
25
26impl ShellApproval {
27 pub fn from_env() -> Option<Self> {
29 std::env::var("LEAN_CTX_SHELL_APPROVAL").ok().and_then(|v| {
30 match v.trim().to_lowercase().as_str() {
31 "ask" | "on" | "1" | "true" | "yes" => Some(Self::Ask),
32 "off" | "0" | "false" | "no" => Some(Self::Off),
33 _ => None,
34 }
35 })
36 }
37
38 pub fn effective(config: &Config) -> Self {
40 Self::from_env().unwrap_or(config.shell_approval)
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn asks_by_default_and_parses_the_env_spellings() {
50 assert_eq!(ShellApproval::default(), ShellApproval::Ask);
51 let _lock = crate::core::data_dir::test_env_lock();
52 for (raw, want) in [
53 ("ask", Some(ShellApproval::Ask)),
54 ("OFF", Some(ShellApproval::Off)),
55 ("0", Some(ShellApproval::Off)),
56 ("maybe", None),
57 ] {
58 crate::test_env::set_var("LEAN_CTX_SHELL_APPROVAL", raw);
59 assert_eq!(ShellApproval::from_env(), want, "{raw}");
60 }
61 crate::test_env::remove_var("LEAN_CTX_SHELL_APPROVAL");
62 }
63
64 #[test]
65 fn the_config_key_reads_kebab_case() {
66 let cfg: Config = toml::from_str("shell_approval = \"off\"").unwrap();
67 assert_eq!(cfg.shell_approval, ShellApproval::Off);
68 }
69}