Skip to main content

systemprompt_cli/
cli_settings.rs

1use std::env;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum OutputFormat {
5    Table,
6    Json,
7    Yaml,
8}
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
11pub enum VerbosityLevel {
12    Quiet,
13    Normal,
14    Verbose,
15    Debug,
16}
17
18impl VerbosityLevel {
19    pub const fn as_tracing_filter(&self) -> Option<&'static str> {
20        match self {
21            Self::Quiet => Some("error"),
22            Self::Normal => None,
23            Self::Verbose => Some("debug"),
24            Self::Debug => Some("trace"),
25        }
26    }
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum ColorMode {
31    Auto,
32    Always,
33    Never,
34}
35
36#[derive(Debug, Clone)]
37pub struct CliConfig {
38    pub output_format: OutputFormat,
39    pub verbosity: VerbosityLevel,
40    pub color_mode: ColorMode,
41    pub interactive: bool,
42    pub profile_override: Option<String>,
43}
44
45impl Default for CliConfig {
46    fn default() -> Self {
47        Self {
48            output_format: OutputFormat::Table,
49            verbosity: VerbosityLevel::Normal,
50            color_mode: ColorMode::Auto,
51            interactive: true,
52            profile_override: None,
53        }
54    }
55}
56
57impl CliConfig {
58    pub fn new() -> Self {
59        let mut config = Self::default();
60        config.apply_environment_variables();
61        config
62    }
63
64    pub const fn with_output_format(mut self, format: OutputFormat) -> Self {
65        self.output_format = format;
66        self
67    }
68
69    pub const fn with_verbosity(mut self, level: VerbosityLevel) -> Self {
70        self.verbosity = level;
71        self
72    }
73
74    pub const fn with_color_mode(mut self, mode: ColorMode) -> Self {
75        self.color_mode = mode;
76        self
77    }
78
79    pub const fn with_interactive(mut self, interactive: bool) -> Self {
80        self.interactive = interactive;
81        self
82    }
83
84    pub fn with_profile_override(mut self, profile: Option<String>) -> Self {
85        self.profile_override = profile;
86        self
87    }
88
89    fn apply_environment_variables(&mut self) {
90        if let Ok(format) = env::var("SYSTEMPROMPT_OUTPUT_FORMAT") {
91            self.output_format = match format.to_lowercase().as_str() {
92                "json" => OutputFormat::Json,
93                "yaml" => OutputFormat::Yaml,
94                "table" => OutputFormat::Table,
95                _ => self.output_format,
96            };
97        }
98
99        if let Ok(level) = env::var("SYSTEMPROMPT_LOG_LEVEL") {
100            self.verbosity = match level.to_lowercase().as_str() {
101                "quiet" => VerbosityLevel::Quiet,
102                "normal" => VerbosityLevel::Normal,
103                "verbose" => VerbosityLevel::Verbose,
104                "debug" => VerbosityLevel::Debug,
105                _ => self.verbosity,
106            };
107        }
108
109        if env::var("SYSTEMPROMPT_NO_COLOR").is_ok() || env::var("NO_COLOR").is_ok() {
110            self.color_mode = ColorMode::Never;
111        }
112
113        if env::var("SYSTEMPROMPT_NON_INTERACTIVE").is_ok() {
114            self.interactive = false;
115        }
116    }
117
118    pub fn should_use_color(&self) -> bool {
119        match self.color_mode {
120            ColorMode::Always => true,
121            ColorMode::Never => false,
122            ColorMode::Auto => atty::is(atty::Stream::Stdout),
123        }
124    }
125
126    pub fn is_json_output(&self) -> bool {
127        self.output_format == OutputFormat::Json
128    }
129
130    pub fn should_show_verbose(&self) -> bool {
131        self.verbosity >= VerbosityLevel::Verbose
132    }
133
134    pub fn is_interactive(&self) -> bool {
135        self.interactive && atty::is(atty::Stream::Stdin) && atty::is(atty::Stream::Stdout)
136    }
137
138    pub const fn output_format(&self) -> OutputFormat {
139        self.output_format
140    }
141}
142
143thread_local! {
144    static CLI_CONFIG: std::cell::RefCell<CliConfig> = std::cell::RefCell::new(CliConfig::new());
145}
146
147pub fn set_global_config(config: CliConfig) {
148    CLI_CONFIG.with(|c| {
149        *c.borrow_mut() = config;
150    });
151}
152
153pub fn get_global_config() -> CliConfig {
154    CLI_CONFIG.with(|c| c.borrow().clone())
155}