ricecoder_cli/commands/
config.rs

1// Configuration management
2// Adapted from automation/src/infrastructure/storage/config.rs
3
4use super::Command;
5use crate::error::{CliError, CliResult};
6use crate::output::OutputStyle;
7use std::collections::HashMap;
8use std::path::PathBuf;
9
10/// Manage configuration
11pub struct ConfigCommand {
12    pub action: ConfigAction,
13}
14
15#[derive(Debug, Clone)]
16pub enum ConfigAction {
17    List,
18    Get(String),
19    Set(String, String),
20}
21
22impl ConfigCommand {
23    pub fn new(action: ConfigAction) -> Self {
24        Self { action }
25    }
26
27    /// Get the configuration directory path
28    fn get_config_dir() -> CliResult<PathBuf> {
29        // Try to get from environment first
30        if let Ok(path) = std::env::var("RICECODER_HOME") {
31            return Ok(PathBuf::from(path));
32        }
33
34        // Fall back to home directory
35        if let Some(home) = dirs::home_dir() {
36            return Ok(home.join(".ricecoder"));
37        }
38
39        Err(CliError::Config(
40            "Could not determine configuration directory".to_string(),
41        ))
42    }
43
44    /// Load configuration from file
45    fn load_config() -> CliResult<HashMap<String, String>> {
46        let mut config = HashMap::new();
47
48        // Default configuration values
49        config.insert("provider.default".to_string(), "openai".to_string());
50        config.insert("storage.mode".to_string(), "merged".to_string());
51        config.insert("chat.history".to_string(), "true".to_string());
52        config.insert("output.colors".to_string(), "auto".to_string());
53
54        // TODO: Load from config file if it exists
55        // config_dir/ricecoder.toml
56
57        Ok(config)
58    }
59
60    /// List all configuration values
61    fn list_config(&self) -> CliResult<()> {
62        let style = OutputStyle::default();
63        let config = Self::load_config()?;
64
65        println!("{}", style.header("RiceCoder Configuration"));
66        println!();
67
68        let mut keys: Vec<_> = config.keys().collect();
69        keys.sort();
70
71        for key in keys {
72            let value = &config[key];
73            println!("  {} = {}", style.code(key), value);
74        }
75
76        println!();
77        let config_dir = Self::get_config_dir()?;
78        println!(
79            "{}",
80            style.info(&format!("Config directory: {}", config_dir.display()))
81        );
82
83        Ok(())
84    }
85
86    /// Get a specific configuration value
87    fn get_config(&self, key: &str) -> CliResult<()> {
88        let style = OutputStyle::default();
89        let config = Self::load_config()?;
90
91        match config.get(key) {
92            Some(value) => {
93                println!("{} = {}", style.code(key), value);
94                Ok(())
95            }
96            None => {
97                println!(
98                    "{}",
99                    style.warning(&format!("Configuration key not found: {}", key))
100                );
101                println!(
102                    "{}",
103                    style.info("Run 'rice config' to see all available keys")
104                );
105                Ok(())
106            }
107        }
108    }
109
110    /// Set a configuration value
111    fn set_config(&self, key: &str, value: &str) -> CliResult<()> {
112        let style = OutputStyle::default();
113
114        // TODO: Validate key format
115        // TODO: Write to config file
116
117        println!("{}", style.success(&format!("Set {} = {}", key, value)));
118        println!(
119            "{}",
120            style.info("Configuration changes will take effect on next run")
121        );
122
123        Ok(())
124    }
125}
126
127impl Command for ConfigCommand {
128    fn execute(&self) -> CliResult<()> {
129        match &self.action {
130            ConfigAction::List => self.list_config(),
131            ConfigAction::Get(key) => self.get_config(key),
132            ConfigAction::Set(key, value) => self.set_config(key, value),
133        }
134    }
135}