You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.0 KiB

// Copyright (C) 2021-2022 Tassilo Horn <tsdh@gnu.org>
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <https://www.gnu.org/licenses/>.
/// Config file loading stuff.
use directories::ProjectDirs;
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::fs::{DirBuilder, OpenOptions};
use std::io::{Read, Write};
use std::path::Path;
pub fn get_config_file_path(project: &str) -> Box<Path> {
let proj_dirs = ProjectDirs::from("", "", project).expect("");
let user_config_dir = proj_dirs.config_dir();
if !user_config_dir.exists() {
let sys_path = format!("/etc/xdg/{}/config.toml", project);
let sys_config_file = Path::new(sys_path.as_str());
if sys_config_file.exists() {
return sys_config_file.into();
}
DirBuilder::new()
.recursive(true)
.create(user_config_dir)
.unwrap();
}
user_config_dir.join("config.toml").into_boxed_path()
}
pub fn save_config<T>(project: &str, cfg: T)
where
T: Serialize,
{
let path = get_config_file_path(project);
let content =
toml::to_string_pretty::<T>(&cfg).expect("Cannot serialize config.");
let mut file = OpenOptions::new()
.read(false)
.write(true)
.create(true)
.open(path)
.unwrap();
file.write_all(content.as_str().as_bytes()).unwrap();
}
pub fn load_config<T>(project: &str) -> T
where
T: Serialize + DeserializeOwned + Default,
{
let path = get_config_file_path(project);
if !path.exists() {
save_config(project, T::default());
// Tell the user that a fresh default config has been created.
std::process::Command::new("swaynag")
.arg("--background")
.arg("00FF44")
.arg("--text")
.arg("0000CC")
.arg("--message")
.arg(
if project == "swayr" {
"Welcome to swayr! ".to_owned()
+ "I've created a fresh config for use with wofi for you in "
+ &path.to_string_lossy()
+ ". Adapt it to your needs."
} else {
"Welcome to swayrbar! ".to_owned()
+ "I've created a fresh config for for you in "
+ &path.to_string_lossy()
+ ". Adapt it to your needs."
},
)
.arg("--type")
.arg("warning")
.arg("--dismiss-button")
.arg("Thanks!")
.spawn()
.ok();
log::debug!("Created new config in {}.", path.to_string_lossy());
}
load_config_file(&path)
}
pub fn load_config_file<T>(config_file: &Path) -> T
where
T: Serialize + DeserializeOwned + Default,
{
if !config_file.exists() {
panic!(
"Config file {} does not exist.",
config_file.to_string_lossy()
);
} else {
log::debug!("Loading config from {}.", config_file.to_string_lossy());
}
let mut file = OpenOptions::new()
.read(true)
.write(false)
.create(false)
.open(config_file)
.unwrap();
let mut buf: String = String::new();
file.read_to_string(&mut buf).unwrap();
match toml::from_str::<T>(&buf) {
Ok(cfg) => cfg,
Err(err) => {
log::error!("Invalid config: {}", err);
log::error!("Using default configuration.");
T::default()
}
}
}