use crate::commands::Command;
use crate::error::{CliError, CliResult};
use std::path::PathBuf;
#[derive(Debug, Clone)]
pub struct TuiConfig {
pub theme: Option<String>,
pub vim_mode: bool,
pub config_file: Option<PathBuf>,
pub provider: Option<String>,
pub model: Option<String>,
}
pub struct TuiCommand {
theme: Option<String>,
vim_mode: bool,
config_file: Option<PathBuf>,
provider: Option<String>,
model: Option<String>,
}
impl TuiCommand {
pub fn new(
theme: Option<String>,
vim_mode: bool,
config_file: Option<PathBuf>,
provider: Option<String>,
model: Option<String>,
) -> Self {
Self {
theme,
vim_mode,
config_file,
provider,
model,
}
}
pub fn get_config(&self) -> TuiConfig {
TuiConfig {
theme: self.theme.clone(),
vim_mode: self.vim_mode,
config_file: self.config_file.clone(),
provider: self.provider.clone(),
model: self.model.clone(),
}
}
}
impl Command for TuiCommand {
fn execute(&self) -> CliResult<()> {
let config = self.get_config();
launch_tui(config)
}
}
fn launch_tui(config: TuiConfig) -> CliResult<()> {
let rt = tokio::runtime::Runtime::new()
.map_err(|e| CliError::Internal(format!("Failed to create runtime: {}", e)))?;
rt.block_on(async {
use ricecoder_tui::App;
let mut tui_config = ricecoder_tui::TuiConfig::default();
if let Some(theme) = config.theme {
tui_config.theme = theme;
}
if config.vim_mode {
tui_config.vim_mode = true;
}
if let Some(provider) = config.provider {
tui_config.provider = Some(provider);
}
if let Some(model) = config.model {
tui_config.model = Some(model);
}
if tui_config.provider.is_some() {
validate_provider_config(&tui_config)?;
}
let mut app = App::with_config(tui_config)
.map_err(|e| CliError::Internal(format!("Failed to initialize TUI: {}", e)))?;
app.run()
.await
.map_err(|e| CliError::Internal(format!("TUI error: {}", e)))
})
}
fn validate_provider_config(config: &ricecoder_tui::TuiConfig) -> CliResult<()> {
let supported_providers = ["openai", "anthropic", "ollama", "google", "zen"];
if let Some(ref provider) = config.provider {
if !supported_providers.contains(&provider.as_str()) {
return Err(CliError::Internal(format!(
"Unsupported provider: {}. Supported providers: {}",
provider,
supported_providers.join(", ")
)));
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tui_command_creation() {
let cmd = TuiCommand::new(
Some("dark".to_string()),
true,
None,
Some("openai".to_string()),
Some("gpt-4".to_string()),
);
let config = cmd.get_config();
assert_eq!(config.theme, Some("dark".to_string()));
assert!(config.vim_mode);
assert_eq!(config.provider, Some("openai".to_string()));
assert_eq!(config.model, Some("gpt-4".to_string()));
}
#[test]
fn test_tui_command_defaults() {
let cmd = TuiCommand::new(None, false, None, None, None);
let config = cmd.get_config();
assert_eq!(config.theme, None);
assert!(!config.vim_mode);
assert_eq!(config.provider, None);
assert_eq!(config.model, None);
}
#[test]
fn test_tui_config_with_provider() {
let cmd = TuiCommand::new(
None,
false,
None,
Some("anthropic".to_string()),
Some("claude-3-opus".to_string()),
);
let config = cmd.get_config();
assert_eq!(config.provider, Some("anthropic".to_string()));
assert_eq!(config.model, Some("claude-3-opus".to_string()));
}
#[test]
fn test_tui_config_with_theme() {
let cmd = TuiCommand::new(Some("monokai".to_string()), false, None, None, None);
let config = cmd.get_config();
assert_eq!(config.theme, Some("monokai".to_string()));
}
#[test]
fn test_tui_config_with_vim_mode() {
let cmd = TuiCommand::new(None, true, None, None, None);
let config = cmd.get_config();
assert!(config.vim_mode);
}
}