ricecoder_cli/commands/
tui.rs1use crate::commands::Command;
4use crate::error::{CliError, CliResult};
5use std::path::PathBuf;
6
7#[derive(Debug, Clone)]
9pub struct TuiConfig {
10 pub theme: Option<String>,
12 pub vim_mode: bool,
14 pub config_file: Option<PathBuf>,
16 pub provider: Option<String>,
18 pub model: Option<String>,
20}
21
22pub struct TuiCommand {
24 theme: Option<String>,
25 vim_mode: bool,
26 config_file: Option<PathBuf>,
27 provider: Option<String>,
28 model: Option<String>,
29}
30
31impl TuiCommand {
32 pub fn new(
34 theme: Option<String>,
35 vim_mode: bool,
36 config_file: Option<PathBuf>,
37 provider: Option<String>,
38 model: Option<String>,
39 ) -> Self {
40 Self {
41 theme,
42 vim_mode,
43 config_file,
44 provider,
45 model,
46 }
47 }
48
49 pub fn get_config(&self) -> TuiConfig {
51 TuiConfig {
52 theme: self.theme.clone(),
53 vim_mode: self.vim_mode,
54 config_file: self.config_file.clone(),
55 provider: self.provider.clone(),
56 model: self.model.clone(),
57 }
58 }
59}
60
61impl Command for TuiCommand {
62 fn execute(&self) -> CliResult<()> {
63 let config = self.get_config();
65
66 launch_tui(config)
68 }
69}
70
71fn launch_tui(config: TuiConfig) -> CliResult<()> {
73 let rt = tokio::runtime::Runtime::new()
75 .map_err(|e| CliError::Internal(format!("Failed to create runtime: {}", e)))?;
76
77 rt.block_on(async {
78 use ricecoder_tui::App;
80
81 let mut tui_config = ricecoder_tui::TuiConfig::default();
83
84 if let Some(theme) = config.theme {
86 tui_config.theme = theme;
87 }
88
89 if config.vim_mode {
91 tui_config.vim_mode = true;
92 }
93
94 if let Some(provider) = config.provider {
96 tui_config.provider = Some(provider);
97 }
98 if let Some(model) = config.model {
99 tui_config.model = Some(model);
100 }
101
102 if tui_config.provider.is_some() {
104 validate_provider_config(&tui_config)?;
105 }
106
107 let mut app = App::with_config(tui_config)
109 .map_err(|e| CliError::Internal(format!("Failed to initialize TUI: {}", e)))?;
110
111 app.run()
112 .await
113 .map_err(|e| CliError::Internal(format!("TUI error: {}", e)))
114 })
115}
116
117fn validate_provider_config(config: &ricecoder_tui::TuiConfig) -> CliResult<()> {
119 let supported_providers = ["openai", "anthropic", "ollama", "google", "zen"];
120
121 if let Some(ref provider) = config.provider {
122 if !supported_providers.contains(&provider.as_str()) {
123 return Err(CliError::Internal(format!(
124 "Unsupported provider: {}. Supported providers: {}",
125 provider,
126 supported_providers.join(", ")
127 )));
128 }
129 }
130
131 Ok(())
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn test_tui_command_creation() {
140 let cmd = TuiCommand::new(
141 Some("dark".to_string()),
142 true,
143 None,
144 Some("openai".to_string()),
145 Some("gpt-4".to_string()),
146 );
147
148 let config = cmd.get_config();
149 assert_eq!(config.theme, Some("dark".to_string()));
150 assert!(config.vim_mode);
151 assert_eq!(config.provider, Some("openai".to_string()));
152 assert_eq!(config.model, Some("gpt-4".to_string()));
153 }
154
155 #[test]
156 fn test_tui_command_defaults() {
157 let cmd = TuiCommand::new(None, false, None, None, None);
158 let config = cmd.get_config();
159
160 assert_eq!(config.theme, None);
161 assert!(!config.vim_mode);
162 assert_eq!(config.provider, None);
163 assert_eq!(config.model, None);
164 }
165
166 #[test]
167 fn test_tui_config_with_provider() {
168 let cmd = TuiCommand::new(
169 None,
170 false,
171 None,
172 Some("anthropic".to_string()),
173 Some("claude-3-opus".to_string()),
174 );
175
176 let config = cmd.get_config();
177 assert_eq!(config.provider, Some("anthropic".to_string()));
178 assert_eq!(config.model, Some("claude-3-opus".to_string()));
179 }
180
181 #[test]
182 fn test_tui_config_with_theme() {
183 let cmd = TuiCommand::new(Some("monokai".to_string()), false, None, None, None);
184
185 let config = cmd.get_config();
186 assert_eq!(config.theme, Some("monokai".to_string()));
187 }
188
189 #[test]
190 fn test_tui_config_with_vim_mode() {
191 let cmd = TuiCommand::new(None, true, None, None, None);
192
193 let config = cmd.get_config();
194 assert!(config.vim_mode);
195 }
196}