smarter config loading giving more diagnostics to the user about whats going wrong (#589)

This commit is contained in:
Stephan Dilly 2021-03-14 00:25:30 +01:00 committed by GitHub
parent 52bf018515
commit 7d4b79606c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 46 deletions

View file

@ -23,7 +23,7 @@ use crossbeam_channel::Sender;
use crossterm::event::{Event, KeyEvent}; use crossterm::event::{Event, KeyEvent};
use std::{ use std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
path::{Path, PathBuf}, path::Path,
rc::Rc, rc::Rc,
}; };
use tui::{ use tui::{
@ -74,11 +74,12 @@ impl App {
pub fn new( pub fn new(
sender: &Sender<AsyncNotification>, sender: &Sender<AsyncNotification>,
input: Input, input: Input,
theme_path: PathBuf, theme: Theme,
key_config: KeyConfig,
) -> Self { ) -> Self {
let queue = Queue::default(); let queue = Queue::default();
let theme = Rc::new(Theme::init(theme_path)); let theme = Rc::new(theme);
let key_config = Rc::new(KeyConfig::init()); let key_config = Rc::new(key_config);
Self { Self {
input, input,

View file

@ -5,12 +5,12 @@ use crate::get_app_config_path;
use anyhow::Result; use anyhow::Result;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use ron::{ use ron::{
de::from_bytes, self,
ser::{to_string_pretty, PrettyConfig}, ser::{to_string_pretty, PrettyConfig},
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
fs::File, fs::{self, File},
io::{Read, Write}, io::{Read, Write},
path::PathBuf, path::PathBuf,
rc::Rc, rc::Rc,
@ -127,15 +127,14 @@ impl Default for KeyConfig {
} }
impl KeyConfig { impl KeyConfig {
fn save(&self) -> Result<()> { fn save(&self, file: PathBuf) -> Result<()> {
let config_file = Self::get_config_file()?; let mut file = File::create(file)?;
let mut file = File::create(config_file)?;
let data = to_string_pretty(self, PrettyConfig::default())?; let data = to_string_pretty(self, PrettyConfig::default())?;
file.write_all(data.as_bytes())?; file.write_all(data.as_bytes())?;
Ok(()) Ok(())
} }
fn get_config_file() -> Result<PathBuf> { pub fn get_config_file() -> Result<PathBuf> {
let app_home = get_app_config_path()?; let app_home = get_app_config_path()?;
Ok(app_home.join("key_config.ron")) Ok(app_home.join("key_config.ron"))
} }
@ -144,31 +143,31 @@ impl KeyConfig {
let mut f = File::open(config_file)?; let mut f = File::open(config_file)?;
let mut buffer = Vec::new(); let mut buffer = Vec::new();
f.read_to_end(&mut buffer)?; f.read_to_end(&mut buffer)?;
Ok(from_bytes(&buffer)?) Ok(ron::de::from_bytes(&buffer)?)
} }
fn init_internal() -> Result<Self> { pub fn init(file: PathBuf) -> Result<Self> {
let file = Self::get_config_file()?;
if file.exists() { if file.exists() {
Ok(Self::read_file(file)?) match Self::read_file(file.clone()) {
} else { Err(e) => {
let def = Self::default(); let config_path = file.clone();
if def.save().is_err() { let config_path_old =
log::warn!( format!("{}.old", file.to_string_lossy());
"failed to store default key config to disk." fs::rename(
) config_path.clone(),
} config_path_old.clone(),
Ok(def) )?;
}
}
pub fn init() -> Self { Self::default().save(file)?;
match Self::init_internal() {
Ok(v) => v, Err(anyhow::anyhow!("{}\n Old file was renamed to {:?}.\n Defaults loaded and saved as {:?}",
Err(e) => { e,config_path_old,config_path.to_string_lossy()))
log::error!("failed loading key binding: {}", e); }
Self::default() Ok(res) => Ok(res),
} }
} else {
Self::default().save(file)?;
Ok(Self::default())
} }
} }

View file

@ -43,6 +43,7 @@ use crossterm::{
ExecutableCommand, ExecutableCommand,
}; };
use input::{Input, InputEvent, InputState}; use input::{Input, InputEvent, InputState};
use keys::KeyConfig;
use profiler::Profiler; use profiler::Profiler;
use scopeguard::defer; use scopeguard::defer;
use scopetime::scope_time; use scopetime::scope_time;
@ -61,6 +62,7 @@ use tui::{
backend::{Backend, CrosstermBackend}, backend::{Backend, CrosstermBackend},
Terminal, Terminal,
}; };
use ui::style::Theme;
static TICK_INTERVAL: Duration = Duration::from_secs(5); static TICK_INTERVAL: Duration = Duration::from_secs(5);
static SPINNER_INTERVAL: Duration = Duration::from_millis(80); static SPINNER_INTERVAL: Duration = Duration::from_millis(80);
@ -88,6 +90,13 @@ fn main() -> Result<()> {
return Ok(()); return Ok(());
} }
let key_config = KeyConfig::init(KeyConfig::get_config_file()?)
.map_err(|e| eprintln!("KeyConfig loading error: {}", e))
.unwrap_or_default();
let theme = Theme::init(cliargs.theme)
.map_err(|e| eprintln!("Theme loading error: {}", e))
.unwrap_or_default();
setup_terminal()?; setup_terminal()?;
defer! { defer! {
shutdown_terminal().expect("shutdown failed"); shutdown_terminal().expect("shutdown failed");
@ -105,7 +114,7 @@ fn main() -> Result<()> {
let ticker = tick(TICK_INTERVAL); let ticker = tick(TICK_INTERVAL);
let spinner_ticker = tick(SPINNER_INTERVAL); let spinner_ticker = tick(SPINNER_INTERVAL);
let mut app = App::new(&tx_git, input, cliargs.theme); let mut app = App::new(&tx_git, input, theme, key_config);
let mut spinner = Spinner::default(); let mut spinner = Spinner::default();
let mut first_update = true; let mut first_update = true;

View file

@ -9,7 +9,7 @@ use ron::{
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
fs::File, fs::{self, File},
io::{Read, Write}, io::{Read, Write},
path::PathBuf, path::PathBuf,
rc::Rc, rc::Rc,
@ -250,21 +250,29 @@ impl Theme {
Ok(from_bytes(&buffer)?) Ok(from_bytes(&buffer)?)
} }
fn init_internal(theme: PathBuf) -> Result<Self> { pub fn init(file: PathBuf) -> Result<Self> {
if theme.exists() { if file.exists() {
Ok(Self::read_file(theme)?) match Self::read_file(file.clone()) {
} else { Err(e) => {
// This will only be called when theme.ron doesn't already exists let config_path = file.clone();
let def = Self::default(); let config_path_old =
if def.save(theme).is_err() { format!("{}.old", file.to_string_lossy());
log::warn!("failed to store default theme to disk.") fs::rename(
} config_path.clone(),
Ok(def) config_path_old.clone(),
} )?;
}
pub fn init(theme_path: PathBuf) -> Self { Self::default().save(file)?;
Self::init_internal(theme_path).unwrap_or_default()
Err(anyhow::anyhow!("{}\n Old file was renamed to {:?}.\n Defaults loaded and saved as {:?}",
e,config_path_old,config_path.to_string_lossy()))
}
Ok(res) => Ok(res),
}
} else {
Self::default().save(file)?;
Ok(Self::default())
}
} }
} }