|
|
@ -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,
|
|
|
|