tidy up config loading and merging

pull/9545/head
Dipsy 10 months ago
parent 1b5605abd5
commit bcc5e38f59

@ -436,7 +436,7 @@ impl Application {
fn refresh_config(&mut self) { fn refresh_config(&mut self) {
let mut refresh_config = || -> Result<(), Error> { let mut refresh_config = || -> Result<(), Error> {
let default_config = Config::load_default() let default_config = Config::load()
.map_err(|err| anyhow::anyhow!("Failed to load config: {}", err))?; .map_err(|err| anyhow::anyhow!("Failed to load config: {}", err))?;
self.refresh_language_config()?; self.refresh_language_config()?;
self.refresh_theme(&default_config)?; self.refresh_theme(&default_config)?;

@ -4,6 +4,7 @@ use helix_loader::merge_toml_values;
use helix_view::document::Mode; use helix_view::document::Mode;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf;
use std::fmt::Display; use std::fmt::Display;
use std::fs; use std::fs;
use std::io::Error as IOError; use std::io::Error as IOError;
@ -58,46 +59,60 @@ impl Display for ConfigLoadError {
} }
} }
impl Config { impl ConfigRaw {
pub fn load( fn load(file: PathBuf) -> Result<Self, ConfigLoadError> {
mut global: ConfigRaw, mut workspace: Option<ConfigRaw>, let source = fs::read_to_string(file).map_err(ConfigLoadError::Error)?;
) -> Result<Config, ConfigLoadError> { toml::from_str(&source).map_err(ConfigLoadError::BadConfig)
// Create merged keymap
let mut keys = keymap::default();
[Some(&mut global), workspace.as_mut()].into_iter()
.flatten().filter_map(|c| c.keys.take())
.for_each(|k| merge_keys(&mut keys, k));
// Create config
let config = Config {
workspace_config: global.workspace_config.unwrap_or(false),
theme: workspace.as_mut().and_then(|c| c.theme.take()).or(global.theme),
keys,
editor: match (global.editor, workspace.and_then(|c| c.editor)) {
(None, None) => Ok(helix_view::editor::Config::default()),
(None, Some(editor)) | (Some(editor), None) => editor.try_into(),
(Some(glob), Some(work)) => merge_toml_values(glob, work, 3).try_into(),
}.map_err(ConfigLoadError::BadConfig)?,
};
Ok(config)
} }
}
impl TryFrom<ConfigRaw> for Config {
type Error = ConfigLoadError;
fn try_from(config: ConfigRaw) -> Result<Self, Self::Error> {
Ok(Self {
workspace_config: config.workspace_config.unwrap_or_default(),
theme: config.theme,
keys: match config.keys {
Some(keys) => merge_keys(keymap::default(), keys),
None => keymap::default(),
},
editor: config.editor
.map(|e| e.try_into()).transpose()
.map_err(ConfigLoadError::BadConfig)?
.unwrap_or_default(),
})
}
}
pub fn load_default() -> Result<Config, ConfigLoadError> { impl Config {
pub fn load() -> Result<Config, ConfigLoadError> {
// Load and parse global config returning all errors // Load and parse global config returning all errors
let global: ConfigRaw = fs::read_to_string(helix_loader::config_file()) let global: Config = ConfigRaw::load(helix_loader::config_file())?.try_into()?;
.map_err(ConfigLoadError::Error)
.and_then(|c| toml::from_str(&c).map_err(ConfigLoadError::BadConfig))?; if global.workspace_config {
global.merge(ConfigRaw::load(helix_loader::workspace_config_file())?)
// Load and parse workspace config if enabled ignoring IO errors } else {
let workspace = global.workspace_config.unwrap_or(false) Ok(global)
.then(|| helix_loader::workspace_config_file()) }
.and_then(|f| fs::read_to_string(f).ok()) }
.map(|c| toml::from_str(&c).map_err(ConfigLoadError::BadConfig))
.transpose()?; fn merge(self, other: ConfigRaw) -> Result<Self, ConfigLoadError> {
Ok(Config {
// Create merged config workspace_config: other.workspace_config.unwrap_or(self.workspace_config),
Config::load(global, workspace) theme: other.theme.or(self.theme),
keys: match other.keys {
Some(keys) => merge_keys(self.keys, keys),
None => self.keys,
},
editor: match other.editor {
None => self.editor,
Some(editor) => merge_toml_values(
toml::Value::try_from(self.editor).unwrap(),
editor, 3
).try_into().map_err(ConfigLoadError::BadConfig)?,
}
})
} }
} }
@ -107,7 +122,8 @@ mod tests {
impl Config { impl Config {
fn load_test(file: &str) -> Config { fn load_test(file: &str) -> Config {
Config::load(toml::from_str(file).unwrap(), None).unwrap() let raw: ConfigRaw = toml::from_str(file).unwrap();
raw.try_into().unwrap()
} }
} }
@ -126,9 +142,8 @@ mod tests {
A-F12 = "move_next_word_end" A-F12 = "move_next_word_end"
"#; "#;
let mut keys = keymap::default(); let keys = merge_keys(
merge_keys( keymap::default(),
&mut keys,
hashmap! { hashmap! {
Mode::Insert => keymap!({ "Insert mode" Mode::Insert => keymap!({ "Insert mode"
"y" => move_line_down, "y" => move_line_down,

@ -130,7 +130,7 @@ FLAGS:
helix_stdx::env::set_current_working_dir(path)?; helix_stdx::env::set_current_working_dir(path)?;
} }
let config = match Config::load_default() { let config = match Config::load() {
Ok(config) => config, Ok(config) => config,
Err(ConfigLoadError::Error(err)) if err.kind() == std::io::ErrorKind::NotFound => { Err(ConfigLoadError::Error(err)) if err.kind() == std::io::ErrorKind::NotFound => {
Config::default() Config::default()

Loading…
Cancel
Save