1use 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 }