use std::collections::HashMap;
use crate::core::builtin_providers::find_builtin_provider;
use crate::core::config::data::Config;
use crate::ui::builtin_themes::find_builtin_theme;
use super::error::SettingError;
use super::SetContext;
pub fn mutate_config<F>(f: F) -> Result<(), SettingError>
where
F: FnOnce(&mut Config) -> Result<(), Box<dyn std::error::Error>>,
{
Config::mutate(f).map_err(|e| SettingError::ConfigError(e.to_string()))
}
pub fn mutate_config_with_message<F>(f: F, message: String) -> Result<String, SettingError>
where
F: FnOnce(&mut Config) -> Result<(), Box<dyn std::error::Error>>,
{
mutate_config(f)?;
Ok(message)
}
pub fn parse_provider_model_value(
args: &[String],
ctx: &SetContext<'_>,
hint: &'static str,
example: &'static str,
) -> Result<(String, String, String), SettingError> {
if args.len() < 3 {
return Err(SettingError::MissingArgs { hint, example });
}
let provider = validate_provider(ctx.config, &args[0])?;
let model = args[1].clone();
let value = args[2..].join(" ");
Ok((provider, model, value))
}
pub fn parse_provider_model(
args: Option<&str>,
ctx: &SetContext<'_>,
hint: &'static str,
example: &'static str,
) -> Result<(String, String), SettingError> {
let value = args.ok_or(SettingError::MissingArgs { hint, example })?;
let parts: Vec<&str> = value.splitn(2, ' ').collect();
if parts.len() < 2 {
return Err(SettingError::MissingArgs { hint, example });
}
let provider = validate_provider(ctx.config, parts[0])?;
let model = parts[1].to_string();
Ok((provider, model))
}
pub fn parse_provider_value(
args: &[String],
ctx: &SetContext<'_>,
hint: &'static str,
example: &'static str,
) -> Result<(String, String), SettingError> {
if args.len() < 2 {
return Err(SettingError::MissingArgs { hint, example });
}
let provider = validate_provider(ctx.config, &args[0])?;
let value = args[1..].join(" ");
Ok((provider, value))
}
pub fn success_set(setting: &str, value: &str) -> String {
format!("✅ Set {setting} to: {value}")
}
pub fn success_unset(setting: &str) -> String {
format!("✅ Unset {setting}")
}
pub fn success_set_provider_value(setting: &str, provider: &str, value: &str) -> String {
format!("✅ Set {setting} for provider '{provider}' to: {value}")
}
pub fn success_unset_provider_value(setting: &str, provider: &str) -> String {
format!("✅ Unset {setting} for provider: {provider}")
}
pub fn success_set_provider_model_value(
setting: &str,
provider: &str,
model: &str,
value: &str,
) -> String {
format!("✅ Set {setting} for '{provider}:{model}' to: {value}")
}
pub fn success_unset_provider_model_value(setting: &str, provider: &str, model: &str) -> String {
format!("✅ Unset {setting} for '{provider}:{model}'")
}
pub fn format_provider_model_map(
name: &str,
map: &HashMap<String, HashMap<String, String>>,
) -> String {
if map.is_empty() {
format!(" {name}: (none set)")
} else {
let mut output = format!(" {name}:\n");
let mut providers: Vec<_> = map.iter().collect();
providers.sort_by_key(|(k, _)| *k);
for (provider, models) in providers {
let mut model_entries: Vec<_> = models.iter().collect();
model_entries.sort_by_key(|(k, _)| *k);
for (model, value) in model_entries {
output.push_str(&format!(" {provider}:{model}: {value}\n"));
}
}
output.pop();
output
}
}
pub fn parse_bool(input: &str) -> Option<bool> {
match input.to_lowercase().as_str() {
"on" | "true" | "yes" | "1" => Some(true),
"off" | "false" | "no" | "0" => Some(false),
_ => None,
}
}
pub fn format_bool(value: bool) -> &'static str {
if value {
"on"
} else {
"off"
}
}
pub fn validate_provider(config: &Config, input: &str) -> Result<String, SettingError> {
if let Some(provider) = find_builtin_provider(input) {
return Ok(provider.id);
}
if let Some(provider) = config.get_custom_provider(input) {
return Ok(provider.id.clone());
}
Err(SettingError::UnknownProvider {
input: input.to_string(),
})
}
pub fn validate_theme(config: &Config, input: &str) -> Result<String, SettingError> {
if let Some(theme) = find_builtin_theme(input) {
return Ok(theme.id);
}
if let Some(theme) = config.get_custom_theme(input) {
return Ok(theme.id.clone());
}
Err(SettingError::UnknownTheme {
input: input.to_string(),
})
}