mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 01:18:21 +00:00
smarter config loading giving more diagnostics to the user about whats going wrong (#589)
This commit is contained in:
parent
52bf018515
commit
7d4b79606c
4 changed files with 63 additions and 46 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
51
src/keys.rs
51
src/keys.rs
|
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
11
src/main.rs
11
src/main.rs
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue