systemprompt_cli/
cli_settings.rs1use std::io::IsTerminal;
12
13use crate::env_overrides::EnvOverrides;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum OutputFormat {
17 Table,
18 Json,
19 Yaml,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
23pub enum VerbosityLevel {
24 Quiet,
25 Normal,
26 Verbose,
27 Debug,
28}
29
30impl VerbosityLevel {
31 pub const fn as_tracing_filter(&self) -> Option<&'static str> {
32 match self {
33 Self::Quiet => Some("error"),
34 Self::Normal => None,
35 Self::Verbose => Some("debug"),
36 Self::Debug => Some("trace"),
37 }
38 }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub enum ColorMode {
43 Auto,
44 Always,
45 Never,
46}
47
48#[derive(Debug, Clone)]
49pub struct CliConfig {
50 pub output_format: OutputFormat,
51 pub verbosity: VerbosityLevel,
52 pub color_mode: ColorMode,
53 pub interactive: bool,
54 pub assume_terminal: bool,
55 pub profile_override: Option<String>,
56}
57
58impl Default for CliConfig {
59 fn default() -> Self {
60 Self {
61 output_format: OutputFormat::Table,
62 verbosity: VerbosityLevel::Normal,
63 color_mode: ColorMode::Auto,
64 interactive: true,
65 assume_terminal: false,
66 profile_override: None,
67 }
68 }
69}
70
71impl CliConfig {
72 #[must_use]
73 pub fn new() -> Self {
74 Self::default()
75 }
76
77 #[must_use]
78 pub fn resolve(env: &EnvOverrides) -> Self {
79 let mut config = Self::default();
80 config.apply_env(env);
81 config
82 }
83
84 pub const fn with_output_format(mut self, format: OutputFormat) -> Self {
85 self.output_format = format;
86 self
87 }
88
89 pub const fn with_verbosity(mut self, level: VerbosityLevel) -> Self {
90 self.verbosity = level;
91 self
92 }
93
94 pub const fn with_color_mode(mut self, mode: ColorMode) -> Self {
95 self.color_mode = mode;
96 self
97 }
98
99 pub const fn with_interactive(mut self, interactive: bool) -> Self {
100 self.interactive = interactive;
101 self
102 }
103
104 pub const fn with_assume_terminal(mut self, assume: bool) -> Self {
111 self.assume_terminal = assume;
112 self
113 }
114
115 pub fn with_profile_override(mut self, profile: Option<String>) -> Self {
116 self.profile_override = profile;
117 self
118 }
119
120 fn apply_env(&mut self, env: &EnvOverrides) {
121 if let Some(format) = &env.output_format {
122 self.output_format = match format.to_lowercase().as_str() {
123 "json" => OutputFormat::Json,
124 "yaml" => OutputFormat::Yaml,
125 "table" => OutputFormat::Table,
126 _ => self.output_format,
127 };
128 }
129
130 if let Some(level) = &env.log_level {
131 self.verbosity = match level.to_lowercase().as_str() {
132 "quiet" => VerbosityLevel::Quiet,
133 "normal" => VerbosityLevel::Normal,
134 "verbose" => VerbosityLevel::Verbose,
135 "debug" => VerbosityLevel::Debug,
136 _ => self.verbosity,
137 };
138 }
139
140 if env.no_color {
141 self.color_mode = ColorMode::Never;
142 }
143
144 if env.non_interactive {
145 self.interactive = false;
146 }
147 }
148
149 pub fn should_use_color(&self) -> bool {
150 match self.color_mode {
151 ColorMode::Always => true,
152 ColorMode::Never => false,
153 ColorMode::Auto => std::io::stdout().is_terminal(),
154 }
155 }
156
157 pub fn is_json_output(&self) -> bool {
158 self.output_format == OutputFormat::Json
159 }
160
161 pub fn should_show_verbose(&self) -> bool {
162 self.verbosity >= VerbosityLevel::Verbose
163 }
164
165 pub fn is_interactive(&self) -> bool {
166 self.interactive
167 && (self.assume_terminal
168 || (std::io::stdin().is_terminal() && std::io::stdout().is_terminal()))
169 }
170
171 pub const fn output_format(&self) -> OutputFormat {
172 self.output_format
173 }
174}