use {
super::*,
crate::{
display::ColsConf,
errors::ProgramError,
skin::SkinEntry,
path::{Glob, SpecialHandling},
},
crossterm::style::Attribute,
ahash::AHashMap,
fnv::FnvHashMap,
serde::Deserialize,
std::{
fs, io,
path::{Path, PathBuf},
},
};
macro_rules! overwrite {
($dst: ident, $prop: ident, $src: ident) => {
if $src.$prop.is_some() {
$dst.$prop = $src.$prop.take();
}
};
}
macro_rules! overwrite_map {
($dst: ident, $prop: ident, $src: ident) => {
for (k, v) in $src.$prop {
$dst.$prop.insert(k, v);
}
};
}
#[derive(Default, Clone, Debug, Deserialize)]
pub struct Conf {
#[serde(skip)]
pub files: Vec<PathBuf>,
#[serde(alias="default-flags")]
pub default_flags: Option<String>,
#[serde(alias="date-time-format")]
pub date_time_format: Option<String>,
#[serde(default)]
pub verbs: Vec<VerbConf>,
pub skin: Option<AHashMap<String, SkinEntry>>,
#[serde(default, alias="special-paths")]
pub special_paths: AHashMap<Glob, SpecialHandling>,
#[serde(alias="search-modes")]
pub search_modes: Option<FnvHashMap<String, String>>,
#[serde(alias="disable-mouse-capture")]
pub disable_mouse_capture: Option<bool>,
#[serde(alias="cols-order")]
pub cols_order: Option<ColsConf>,
#[serde(alias="show-selection-mark")]
pub show_selection_mark: Option<bool>,
#[serde(default, alias="ext-colors")]
pub ext_colors: AHashMap<String, String>,
#[serde(alias="syntax-theme")]
pub syntax_theme: Option<String>,
#[serde(alias="true-colors")]
pub true_colors: Option<bool>,
#[serde(alias="icon-theme")]
pub icon_theme: Option<String>,
pub modal: Option<bool>,
pub max_panels_count: Option<usize>,
}
impl Conf {
pub fn default_location() -> PathBuf {
let hjson_file = super::dir().join("conf.hjson");
if !hjson_file.exists() {
let toml_file = super::dir().join("conf.toml");
if toml_file.exists() {
return toml_file;
}
}
hjson_file
}
pub fn from_default_location() -> Result<Conf, ProgramError> {
let conf_filepath = Conf::default_location();
if !conf_filepath.exists() {
Conf::write_sample(&conf_filepath)?;
println!(
"New Configuration file written in {}{:?}{}.",
Attribute::Bold,
&conf_filepath,
Attribute::Reset,
);
println!("You should have a look at it.");
}
let mut conf = Conf::default();
match conf.read_file(conf_filepath) {
Err(e) => Err(e),
_ => Ok(conf),
}
}
pub fn write_sample(filepath: &Path) -> Result<(), io::Error> {
fs::create_dir_all(filepath.parent().unwrap())?;
fs::write(filepath, DEFAULT_CONF_FILE)?;
Ok(())
}
pub fn read_file(&mut self, path: PathBuf) -> Result<(), ProgramError> {
let mut conf: Conf = SerdeFormat::read_file(&path)?;
overwrite!(self, default_flags, conf);
overwrite!(self, date_time_format, conf);
overwrite!(self, icon_theme, conf);
overwrite!(self, syntax_theme, conf);
overwrite!(self, disable_mouse_capture, conf);
overwrite!(self, true_colors, conf);
overwrite!(self, show_selection_mark, conf);
overwrite!(self, cols_order, conf);
overwrite!(self, skin, conf);
overwrite!(self, search_modes, conf);
overwrite!(self, max_panels_count, conf);
overwrite!(self, modal, conf);
self.verbs.append(&mut conf.verbs);
overwrite_map!(self, special_paths, conf);
overwrite_map!(self, ext_colors, conf);
self.files.push(path);
Ok(())
}
}