Skip to main content

gemini_cli/
config.rs

1use std::io::Write;
2
3pub fn show() -> i32 {
4    let stdout = std::io::stdout();
5    let mut stdout = stdout.lock();
6    show_with_io(&mut stdout)
7}
8
9pub fn show_with_io(stdout: &mut impl Write) -> i32 {
10    let snapshot = crate::runtime::config_snapshot();
11
12    let _ = writeln!(stdout, "GEMINI_CLI_MODEL={}", snapshot.model);
13    let _ = writeln!(stdout, "GEMINI_CLI_REASONING={}", snapshot.reasoning);
14    let _ = writeln!(
15        stdout,
16        "GEMINI_ALLOW_DANGEROUS_ENABLED={}",
17        snapshot.allow_dangerous_enabled_raw
18    );
19
20    if let Some(path) = snapshot.secret_dir {
21        let _ = writeln!(stdout, "GEMINI_SECRET_DIR={}", path.to_string_lossy());
22    } else {
23        let _ = writeln!(stdout, "GEMINI_SECRET_DIR=");
24    }
25
26    if let Some(path) = snapshot.auth_file {
27        let _ = writeln!(stdout, "GEMINI_AUTH_FILE={}", path.to_string_lossy());
28    } else {
29        let _ = writeln!(stdout, "GEMINI_AUTH_FILE=");
30    }
31
32    if let Some(path) = snapshot.secret_cache_dir {
33        let _ = writeln!(stdout, "GEMINI_SECRET_CACHE_DIR={}", path.to_string_lossy());
34    } else {
35        let _ = writeln!(stdout, "GEMINI_SECRET_CACHE_DIR=");
36    }
37
38    let _ = writeln!(
39        stdout,
40        "GEMINI_STARSHIP_ENABLED={}",
41        snapshot.starship_enabled
42    );
43    let _ = writeln!(
44        stdout,
45        "GEMINI_AUTO_REFRESH_ENABLED={}",
46        snapshot.auto_refresh_enabled
47    );
48    let _ = writeln!(
49        stdout,
50        "GEMINI_AUTO_REFRESH_MIN_DAYS={}",
51        snapshot.auto_refresh_min_days
52    );
53
54    0
55}
56
57pub fn set(key: &str, value: &str) -> i32 {
58    let stdout = std::io::stdout();
59    let mut stdout = stdout.lock();
60    let stderr = std::io::stderr();
61    let mut stderr = stderr.lock();
62    set_with_io(key, value, &mut stdout, &mut stderr)
63}
64
65pub fn set_with_io(
66    key: &str,
67    value: &str,
68    stdout: &mut impl Write,
69    stderr: &mut impl Write,
70) -> i32 {
71    match key {
72        "model" | "GEMINI_CLI_MODEL" => {
73            let _ = writeln!(
74                stdout,
75                "export GEMINI_CLI_MODEL={}",
76                quote_posix_single(value)
77            );
78            0
79        }
80        "reasoning" | "reason" | "GEMINI_CLI_REASONING" => {
81            let _ = writeln!(
82                stdout,
83                "export GEMINI_CLI_REASONING={}",
84                quote_posix_single(value)
85            );
86            0
87        }
88        "dangerous" | "allow-dangerous" | "GEMINI_ALLOW_DANGEROUS_ENABLED" => {
89            let lowered = value.trim().to_ascii_lowercase();
90            if lowered != "true" && lowered != "false" {
91                let _ = writeln!(
92                    stderr,
93                    "gemini-cli config: dangerous must be true|false (got: {})",
94                    value
95                );
96                return 64;
97            }
98            let _ = writeln!(stdout, "export GEMINI_ALLOW_DANGEROUS_ENABLED={}", lowered);
99            0
100        }
101        _ => {
102            let _ = writeln!(stderr, "gemini-cli config: unknown key: {key}");
103            let _ = writeln!(stderr, "gemini-cli config: keys: model|reasoning|dangerous");
104            64
105        }
106    }
107}
108
109fn quote_posix_single(raw: &str) -> String {
110    let escaped = raw.replace('\'', "'\"'\"'");
111    format!("'{escaped}'")
112}
113
114#[cfg(test)]
115mod tests {
116    use super::quote_posix_single;
117
118    #[test]
119    fn quote_posix_single_handles_single_quotes_and_empty() {
120        assert_eq!(quote_posix_single(""), "''");
121        assert_eq!(quote_posix_single("abc"), "'abc'");
122        assert_eq!(quote_posix_single("a'b"), "'a'\"'\"'b'");
123    }
124}