diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index f93a8656f..b4153b062 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -269,7 +269,7 @@ impl Application { } fn refresh_config(&mut self) { - let config = Config::load(helix_loader::config_file()).unwrap(); + let config = Config::load(helix_loader::config_file()).unwrap_or_default(); // Just an example to start; Some config properties like "theme" are a bit more involved and require a reload if let Some(theme) = config.theme.clone() { let true_color = self.true_color(); diff --git a/helix-term/src/config.rs b/helix-term/src/config.rs index 71d4b0255..f665e72cb 100644 --- a/helix-term/src/config.rs +++ b/helix-term/src/config.rs @@ -1,7 +1,8 @@ use crate::keymap::{merge_keys, Keymaps}; -use anyhow::{Error, Result}; use serde::Deserialize; +use std::io::Error as IOError; use std::path::PathBuf; +use toml::de::Error as TomlError; #[derive(Debug, Default, Clone, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] @@ -15,6 +16,12 @@ pub struct Config { pub editor: helix_view::editor::Config, } +#[derive(Debug)] +pub enum ConfigLoadError { + BadConfig(TomlError), + Error(IOError), +} + #[derive(Debug, Default, Clone, PartialEq, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields)] pub struct LspConfig { @@ -22,22 +29,18 @@ pub struct LspConfig { } impl Config { - pub fn load(config_path: PathBuf) -> Result { + pub fn load(config_path: PathBuf) -> Result { match std::fs::read_to_string(config_path) { - Ok(config) => Ok(toml::from_str(&config) + Ok(config) => toml::from_str(&config) .map(merge_keys) - .unwrap_or_else(|err| { - eprintln!("Bad config: {}", err); - eprintln!("Press to continue with default config"); - use std::io::Read; - // This waits for an enter press. - let _ = std::io::stdin().read(&mut []); - Config::default() - })), - Err(err) if err.kind() == std::io::ErrorKind::NotFound => Result::Ok(Config::default()), - Err(err) => Err(err.into()), + .map_err(ConfigLoadError::BadConfig), + Err(err) => Err(ConfigLoadError::Error(err)), } } + + pub fn load_default() -> Result { + Config::load(helix_loader::config_file()) + } } #[cfg(test)] diff --git a/helix-term/src/main.rs b/helix-term/src/main.rs index 14da7d8b0..75a02f852 100644 --- a/helix-term/src/main.rs +++ b/helix-term/src/main.rs @@ -1,7 +1,7 @@ -use anyhow::{Context, Result}; +use anyhow::{Context, Result, Error}; use helix_term::application::Application; use helix_term::args::Args; -use helix_term::config::Config; +use helix_term::config::{Config, ConfigLoadError}; use std::path::PathBuf; fn setup_logging(logpath: PathBuf, verbosity: u64) -> Result<()> { @@ -117,7 +117,25 @@ FLAGS: std::fs::create_dir_all(&conf_dir).ok(); } - let config = Config::load(helix_loader::config_file())?; + let config = match Config::load_default() { + Ok(config) => config, + Err(err) => { + match err { + ConfigLoadError::BadConfig(err) => { + eprintln!("Bad config: {}", err); + eprintln!("Press to continue with default config"); + use std::io::Read; + // This waits for an enter press. + let _ = std::io::stdin().read(&mut []); + Config::default() + } + ConfigLoadError::Error(err) if err.kind() == std::io::ErrorKind::NotFound => { + Config::default() + } + ConfigLoadError::Error(err) => return Err(Error::new(err)), + } + } + }; setup_logging(logpath, args.verbosity).context("failed to initialize logging")?;