gravel_core/
config.rs

1//! For an explanation of the config, see `config.yml` in the crate's root.
2
3use abi_stable::{std_types::RString, traits::IntoReprC};
4use gravel_ffi::config::__private_api::{ConfigLayer, create_figment};
5use gravel_ffi::{FrontendMessage, PluginConfigAdapter};
6use nameof::name_of;
7use serde::Deserialize;
8
9pub const DEFAULT_CONFIG: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../config.yml"));
10
11pub struct ConfigManager {
12	root: Config,
13	config_sources: Vec<ConfigLayer>,
14}
15
16impl ConfigManager {
17	pub fn new(config_sources: Vec<ConfigLayer>) -> Self {
18		let root = match create_figment(&config_sources).extract() {
19			Ok(root) => root,
20			Err(err) => {
21				log::error!("error in config: {err}");
22				std::process::exit(1);
23			}
24		};
25
26		Self { config_sources, root }
27	}
28
29	pub fn root(&self) -> &Config {
30		&self.root
31	}
32
33	pub fn adapt_provider(&self, index: usize) -> PluginConfigAdapter<'_> {
34		self.adapt(format!("{}.{index}", name_of!(providers in Config)))
35	}
36
37	pub fn adapt_frontend(&self) -> PluginConfigAdapter<'_> {
38		self.adapt(name_of!(frontend in Config))
39	}
40
41	fn adapt(&self, key: impl Into<RString>) -> PluginConfigAdapter<'_> {
42		PluginConfigAdapter::from(key.into(), self.config_sources.as_slice().into_c())
43	}
44}
45
46#[derive(Debug, Deserialize)]
47pub struct Config {
48	pub single_instance: Option<String>,
49	pub external_plugins: ExternalPluginPolicy,
50	pub hotkeys: Vec<Hotkey>,
51	pub frontend: Frontend,
52	pub providers: Vec<Provider>,
53}
54
55#[derive(Debug, Deserialize)]
56#[serde(rename_all = "snake_case")]
57pub enum ExternalPluginPolicy {
58	Disabled,
59	All,
60	Whitelist(Vec<String>),
61}
62
63#[derive(Debug, Deserialize)]
64pub struct Hotkey {
65	pub binding: String,
66	pub action: HotkeyAction,
67}
68
69#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
70#[serde(rename_all = "snake_case")]
71pub enum HotkeyAction {
72	ShowHide,
73	Show,
74	Hide,
75	ShowWith(String),
76}
77
78impl From<&HotkeyAction> for FrontendMessage {
79	fn from(value: &HotkeyAction) -> Self {
80		match value {
81			HotkeyAction::ShowHide => Self::ShowOrHide,
82			HotkeyAction::Show => Self::Show,
83			HotkeyAction::Hide => Self::Hide,
84			HotkeyAction::ShowWith(query) => Self::ShowWithQuery(query.clone().into_c()),
85		}
86	}
87}
88
89#[derive(Debug, Deserialize)]
90pub struct Frontend {
91	pub plugin: String,
92}
93
94#[derive(Debug, Deserialize)]
95pub struct Provider {
96	pub plugin: String,
97	pub keyword: Option<String>,
98	// Technically expected here but is deserialized differently, see [`gravel_ffi::PluginConfigAdapter`]
99	//pub config: Any,
100}