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