use crate::detection::ProjectType;
use crate::editor::state::Platform;
use crate::error::Result;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub enum OptionValue {
Bool(bool),
Enum {
selected: String,
variants: Vec<String>,
},
String(String),
Int(i32),
}
impl OptionValue {
pub fn as_bool(&self) -> bool {
matches!(self, OptionValue::Bool(true))
}
pub fn toggle_bool(&mut self) {
if let OptionValue::Bool(v) = self {
*v = !*v;
}
}
pub fn cycle_enum(&mut self) {
if let OptionValue::Enum { selected, variants } = self {
let idx = variants.iter().position(|v| v == selected).unwrap_or(0);
let next_idx = (idx + 1) % variants.len();
*selected = variants[next_idx].clone();
}
}
}
#[derive(Debug, Clone)]
pub struct OptionMeta {
pub id: String,
pub display_name: String,
pub description: String,
pub default_value: OptionValue,
pub depends_on: Option<String>, }
#[derive(Debug, Clone)]
pub struct FeatureMeta {
pub id: String,
pub display_name: String,
pub description: String,
pub options: Vec<OptionMeta>,
}
#[derive(Debug, Clone)]
pub struct PresetConfig {
pub preset_id: String,
pub values: HashMap<String, OptionValue>,
}
impl PresetConfig {
pub fn new(preset_id: String) -> Self {
Self {
preset_id,
values: HashMap::new(),
}
}
pub fn get(&self, option_id: &str) -> Option<&OptionValue> {
self.values.get(option_id)
}
pub fn get_bool(&self, option_id: &str) -> bool {
self.values
.get(option_id)
.map(|v| v.as_bool())
.unwrap_or(false)
}
pub fn get_string(&self, option_id: &str) -> Option<String> {
self.values.get(option_id).and_then(|v| {
if let OptionValue::String(s) = v {
Some(s.clone())
} else {
None
}
})
}
pub fn get_enum(&self, option_id: &str) -> Option<String> {
self.values.get(option_id).and_then(|v| {
if let OptionValue::Enum { selected, .. } = v {
Some(selected.clone())
} else {
None
}
})
}
pub fn set(&mut self, option_id: String, value: OptionValue) {
self.values.insert(option_id, value);
}
pub fn toggle(&mut self, option_id: &str) {
if let Some(value) = self.values.get_mut(option_id) {
match value {
OptionValue::Bool(b) => *b = !*b,
OptionValue::Enum { .. } => value.cycle_enum(),
_ => {}
}
}
}
}
pub trait EditorPreset: Send + Sync {
fn preset_id(&self) -> &'static str;
fn preset_name(&self) -> &'static str;
fn preset_description(&self) -> &'static str;
fn features(&self) -> Vec<FeatureMeta>;
fn generate(&self, config: &PresetConfig, platform: Platform, language_version: &str)
-> Result<String>;
fn matches_project(&self, project_type: &ProjectType, working_dir: &std::path::Path) -> bool;
fn default_config(&self, detected: bool) -> PresetConfig;
}