use crate::{commands::Result, views::TableStyle};
use derive_more::{Deref, DerefMut};
use serde::{Deserialize, Serialize};
use tabled::{
grid::config::Borders,
settings::{Style, Theme},
};
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct ConfigurationInner {
pub(crate) current_job: Option<usize>,
pub(crate) table_style: TableStyle,
pub(crate) delete_empty_job_after_export: bool,
}
#[derive(Deref, DerefMut)]
pub(crate) struct Config {
#[deref]
#[deref_mut]
config: ConfigurationInner,
original_config: ConfigurationInner,
}
impl Config {
fn app_name<'a>() -> &'a str {
env!("CARGO_PKG_NAME")
}
pub(crate) fn load() -> Result<Config> {
let config: ConfigurationInner = confy::load(Self::app_name(), None)?;
Ok(Self {
original_config: config.clone(),
config: config.clone(),
})
}
pub(crate) fn set_current_job(&mut self, job_id: usize) {
self.config.current_job = Some(job_id);
}
pub(crate) fn calendar_theme(&self) -> Theme {
let mut theme = Theme::from_style(Style::empty());
match self.table_style {
TableStyle::Empty => (),
TableStyle::Markdown => theme.set_borders(MARKDOWN),
TableStyle::Rounded => theme.set_borders(ROUNDED),
}
theme
}
pub(crate) fn app_path() -> Result<std::path::PathBuf> {
Ok(Self::config_path()?
.parent()
.expect("invalid configuration path")
.to_path_buf())
}
pub(crate) fn config_path() -> Result<std::path::PathBuf> {
Ok(confy::get_configuration_file_path(Self::app_name(), None)?.to_path_buf())
}
pub(crate) fn database_path(&self) -> Result<std::path::PathBuf> {
Ok(Self::app_path()?.join("jobber.json"))
}
}
impl Drop for Config {
fn drop(&mut self) {
if self.config != self.original_config {
confy::store(Self::app_name(), None, &self.config)
.expect("failed to store configuration")
}
}
}
const ROUNDED: Borders<char> = Borders {
top: Some('─'),
bottom: Some('─'),
left: Some('│'),
right: Some('│'),
top_left: Some('╭'),
top_right: Some('╮'),
bottom_left: Some('╰'),
bottom_right: Some('╯'),
top_intersection: None,
bottom_intersection: None,
horizontal: None,
vertical: None,
intersection: None,
left_intersection: None,
right_intersection: None,
};
const MARKDOWN: Borders<char> = Borders {
top: None,
bottom: None,
left: Some('|'),
right: Some('|'),
top_left: None,
top_right: None,
bottom_left: None,
bottom_right: None,
top_intersection: None,
bottom_intersection: None,
horizontal: None,
vertical: None,
intersection: None,
left_intersection: None,
right_intersection: None,
};