use crate::config::Config;
use crate::instruction_presets::{PresetType, get_instruction_preset_library};
use crate::providers::{Provider, ProviderConfig};
use anyhow::Result;
use clap::Args;
#[derive(Args, Clone, Default, Debug)]
pub struct CommonParams {
#[arg(long, help = "Override default LLM provider", value_parser = available_providers_parser)]
pub provider: Option<String>,
#[arg(long, help = "Override model for this operation")]
pub model: Option<String>,
#[arg(short, long, help = "Custom instructions for this operation")]
pub instructions: Option<String>,
#[arg(
long,
help = "Select an instruction preset (use 'git-iris list-presets' to see available presets for commits and reviews)"
)]
pub preset: Option<String>,
#[arg(
long = "gitmoji",
help = "Enable Gitmoji",
conflicts_with = "no_gitmoji",
action = clap::ArgAction::SetTrue
)]
pub gitmoji_flag: bool,
#[arg(long = "no-gitmoji", help = "Disable Gitmoji", action = clap::ArgAction::SetTrue)]
pub no_gitmoji: bool,
#[arg(skip)]
pub gitmoji: Option<bool>,
#[arg(
short = 'r',
long = "repo",
help = "Repository URL to use instead of local repository"
)]
pub repository_url: Option<String>,
}
impl CommonParams {
#[must_use]
pub fn resolved_gitmoji(&self) -> Option<bool> {
if self.gitmoji_flag {
Some(true)
} else if self.no_gitmoji {
Some(false)
} else {
self.gitmoji }
}
pub fn apply_to_config(&self, config: &mut Config) -> Result<bool> {
let mut changes_made = false;
if let Some(provider_str) = &self.provider {
let provider: Provider = provider_str.parse()?;
let provider_name = provider.name().to_string();
if config.default_provider != provider_name {
if !config.providers.contains_key(&provider_name) {
config.providers.insert(
provider_name.clone(),
ProviderConfig::with_defaults(provider),
);
}
config.default_provider = provider_name;
changes_made = true;
}
}
if let Some(model) = &self.model {
let provider_name = config.default_provider.clone();
if let Some(provider_config) = config.providers.get_mut(&provider_name) {
provider_config.model.clone_from(model);
changes_made = true;
}
}
if let Some(instructions) = &self.instructions {
config.set_temp_instructions(Some(instructions.clone()));
}
if let Some(preset) = &self.preset {
config.set_temp_preset(Some(preset.clone()));
}
if let Some(use_gitmoji) = self.resolved_gitmoji() {
config.gitmoji_override = Some(use_gitmoji);
if config.use_gitmoji != use_gitmoji {
config.use_gitmoji = use_gitmoji;
changes_made = true;
}
}
Ok(changes_made)
}
#[must_use]
pub fn is_valid_preset_for_type(&self, preset_type: PresetType) -> bool {
if let Some(preset_name) = &self.preset {
let library = get_instruction_preset_library();
let valid_presets = library.list_valid_presets_for_command(preset_type);
return valid_presets.iter().any(|(key, _)| *key == preset_name);
}
true }
}
pub fn available_providers_parser(s: &str) -> Result<String, String> {
match s.parse::<Provider>() {
Ok(provider) => Ok(provider.name().to_string()),
Err(_) => Err(format!(
"Invalid provider '{}'. Available providers: {}",
s,
Provider::all_names().join(", ")
)),
}
}