Repository: TabbyML/tabby
File: crates/tabby-common/src/config.rs (Rust)

Code before:
    path::repositories_dir,
    terminal::{HeaderFormat, InfoMessage},
};

#[derive(Serialize, Deserialize, Default, Debug, Clone)]
pub struct Config {
    #[serde(default)]
    pub repositories: Vec<RepositoryConfig>,

    #[serde(default)]
    pub server: ServerConfig,

    #[serde(default)]
    pub model: ModelConfigGroup,

    #[serde(default)]
    pub completion: CompletionConfig,

    #[serde(default)]
    pub answer: AnswerConfig,
}

impl Config {
    pub fn load() -> Result<Self> {
        let cfg_path = crate::path::config_file();
        if !cfg_path.as_path().exists() {
            debug!(
                "Config file {} not found, apply default configuration",
                cfg_path.display()
            );
            return Ok(Default::default());
        }
        let mut cfg: Self = serdeconv::from_toml_file(cfg_path.as_path())
            .context(format!("Config file '{}' is not valid", cfg_path.display()))?;

        if let Err(e) = cfg.validate_dirs() {
            cfg = Default::default();
            InfoMessage::new(
                "Parsing config failed",
                HeaderFormat::BoldRed,
                &[
                    &format!(
                        "Warning: Could not parse the Tabby configuration at {}",
                        crate::path::config_file().as_path().to_string_lossy()
                    ),
                    &format!("Reason: {e}"),
                    "Falling back to default config, please resolve the errors and restart Tabby",
                ],
            )
            .print();
        }

Review comment (bug):
```suggestion
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
#[serde(transparent)]
pub struct AdditionalLanguages(pub Vec<languages::Language>);
impl AdditionalLanguages {
    pub fn lang(&self) -> &Vec<languages::Language> {
        &self.0
    }

    pub fn lang_mut(&mut self) -> &mut Vec<languages::Language> {
        &mut self.0
    }
}
```

just for example

Code after:
    languages,
    path::repositories_dir,
    terminal::{HeaderFormat, InfoMessage},
};

#[derive(Serialize, Deserialize, Default, Debug, Clone)]
pub struct Config {
    #[serde(default)]
    pub repositories: Vec<RepositoryConfig>,

    #[serde(default)]
    pub server: ServerConfig,

    #[serde(default)]
    pub model: ModelConfigGroup,

    #[serde(default)]
    pub completion: CompletionConfig,

    #[serde(default)]
    pub answer: AnswerConfig,

    #[serde(default)]
    pub additional_languages: Vec<languages::Language>,
}

impl Config {
    pub fn load() -> Result<Self> {
        let cfg_path = crate::path::config_file();
        if !cfg_path.as_path().exists() {
            debug!(
                "Config file {} not found, apply default configuration",
                cfg_path.display()
            );
            return Ok(Default::default());
        }
        let mut cfg: Self = serdeconv::from_toml_file(cfg_path.as_path())
            .context(format!("Config file '{}' is not valid", cfg_path.display()))?;

        if let Err(e) = cfg.validate_dirs() {
            cfg = Default::default();
            InfoMessage::new(
                "Parsing config failed",
                HeaderFormat::BoldRed,
                &[
                    &format!(
                        "Warning: Could not parse the Tabby configuration at {}",
                        crate::path::config_file().as_path().to_string_lossy()
                    ),
                    &format!("Reason: {e}"),
                    "Falling back to default config, please resolve the errors and restart Tabby",