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