150 lines
3.5 KiB
Rust
150 lines
3.5 KiB
Rust
use config::builder::DefaultState;
|
|
use config::ConfigError;
|
|
use config::{Config, ConfigBuilder};
|
|
use serde::Deserialize;
|
|
use std::collections::HashMap;
|
|
use std::convert::TryInto;
|
|
use std::path::Path;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct Color(f64, f64, f64, f64);
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct ColorScheme {
|
|
base: Color,
|
|
border: Color,
|
|
highlight: Color,
|
|
|
|
divider: Color,
|
|
|
|
text: Color,
|
|
text_highlight: Color,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct Theme {
|
|
color_scheme: ColorScheme,
|
|
font: (String, i32),
|
|
border: f64,
|
|
divider: f64,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub enum Matcher {
|
|
Prefix,
|
|
Fuse,
|
|
Flex,
|
|
Skim,
|
|
}
|
|
|
|
impl Matcher {
|
|
pub fn init(&self) -> Box<dyn super::shared::Matcher> {
|
|
match self {
|
|
Matcher::Prefix => super::matcher::PrefixMatcher::new(),
|
|
Matcher::Fuse => super::matcher::FuseMatcher::new(),
|
|
Matcher::Flex => super::matcher::FlxMatcher::new(),
|
|
Matcher::Skim => super::matcher::SkimMatcher::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub enum Source {
|
|
Apps,
|
|
Shell,
|
|
Windows,
|
|
Test,
|
|
}
|
|
|
|
impl Source {
|
|
pub fn init(&self) -> Box<dyn super::shared::Source> {
|
|
match self {
|
|
Source::Apps => super::sources::Apps::new(),
|
|
Source::Shell => super::sources::ShellHost::new(),
|
|
Source::Windows => super::sources::Window::new(),
|
|
Source::Test => super::sources::TestSource::new("ts1"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct SourceConfig<T> {
|
|
matcher: Matcher,
|
|
source: T,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct Sources {
|
|
primary: SourceConfig<Source>,
|
|
additional: SourceConfig<Vec<Source>>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
#[serde(rename_all = "lowercase", remote = "log::Level")]
|
|
enum LogLevelDef {
|
|
Error,
|
|
Warn,
|
|
Info,
|
|
Debug,
|
|
Trace,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct Settings {
|
|
#[serde(with = "LogLevelDef")]
|
|
log_level: log::Level,
|
|
completions: HashMap<String, String>,
|
|
sources: Sources,
|
|
theme: Theme,
|
|
}
|
|
|
|
impl Settings {
|
|
pub fn parse() -> Result<Self, ConfigError> {
|
|
let mut config: ConfigBuilder<DefaultState> = Config::builder();
|
|
|
|
let xdg_path_expanded = shellexpand::tilde("~/.config/roftl/config.toml");
|
|
let xdg_config_path = Path::new(xdg_path_expanded.as_ref());
|
|
let cwd_config_path = Path::new("default.toml");
|
|
|
|
if xdg_config_path.exists() {
|
|
config = config.add_source(config::File::from(xdg_config_path));
|
|
}
|
|
|
|
if cwd_config_path.exists() {
|
|
config = config.add_source(config::File::from(cwd_config_path));
|
|
}
|
|
|
|
config = config.add_source(
|
|
config::Environment::with_prefix("roftl")
|
|
.ignore_empty(true)
|
|
.separator("_"),
|
|
);
|
|
|
|
config.build()?.try_deserialize()
|
|
}
|
|
|
|
pub fn primary_matcher(&self) -> Box<dyn super::shared::Matcher> {
|
|
self.sources.primary.matcher.init()
|
|
}
|
|
|
|
pub fn primary_source(&self) -> Box<dyn super::shared::Source> {
|
|
self.sources.primary.source.init()
|
|
}
|
|
|
|
pub fn matcher(&self) -> Box<dyn super::shared::Matcher> {
|
|
self.sources.additional.matcher.init()
|
|
}
|
|
|
|
pub fn sources(&self) -> Vec<Box<dyn super::shared::Source>> {
|
|
self.sources
|
|
.additional
|
|
.source
|
|
.iter()
|
|
.map(|s| s.init())
|
|
.collect()
|
|
}
|
|
|
|
pub fn completions(&self) -> HashMap<String, String> {
|
|
self.completions.clone()
|
|
}
|
|
}
|