hyprshell_core_lib/config/
structs.rs

1use serde::{Deserialize, Serialize};
2use smart_default::SmartDefault;
3use std::fmt::Display;
4
5#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
6#[serde(default, deny_unknown_fields)]
7pub struct Config {
8    #[default = true]
9    pub layerrules: bool,
10    #[default = "ctrl+shift+alt, h"]
11    pub kill_bind: String,
12    #[default(None)]
13    pub launcher: Option<Launcher>,
14    #[default(Some(Windows::default()))]
15    pub windows: Option<Windows>,
16}
17
18#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
19#[serde(default, deny_unknown_fields)]
20pub struct Launcher {
21    #[default(None)]
22    pub default_terminal: Option<Box<str>>,
23    #[default = 650]
24    pub width: u32,
25    #[default = 5]
26    pub max_items: u8,
27    #[default = true]
28    pub show_when_empty: bool,
29    #[default = 250]
30    pub animate_launch_ms: u64,
31    #[default(Plugins{
32        applications: Some(ApplicationsPluginConfig::default()),
33        terminal: Some(EmptyConfig::default()),
34        shell: None,
35        websearch: Some(WebSearchConfig::default()),
36        calc: Some(EmptyConfig::default()),
37    })]
38    pub plugins: Plugins,
39}
40
41// no default for this, if some elements are missing, they should be None.
42// if no config for plugins is provided, use the default value from the launcher.
43#[derive(Debug, Clone, Deserialize, Serialize)]
44#[serde(deny_unknown_fields)]
45pub struct Plugins {
46    pub applications: Option<ApplicationsPluginConfig>,
47    pub terminal: Option<EmptyConfig>,
48    pub shell: Option<EmptyConfig>,
49    pub websearch: Option<WebSearchConfig>,
50    pub calc: Option<EmptyConfig>,
51}
52
53#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
54#[serde(default, deny_unknown_fields)]
55pub struct EmptyConfig {}
56
57#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
58#[serde(default, deny_unknown_fields)]
59pub struct ApplicationsPluginConfig {
60    #[default = 4]
61    pub run_cache_weeks: u8,
62    #[default = true]
63    pub show_execs: bool,
64    #[default = false]
65    pub show_actions_submenu: bool,
66}
67
68#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
69#[serde(default, deny_unknown_fields)]
70pub struct WebSearchConfig {
71    #[default(vec![SearchEngine {
72        url: "https://www.google.com/search?q={}".into(),
73        name: "Google".into(),
74        key: 'g',
75    }])]
76    pub engines: Vec<SearchEngine>,
77}
78
79#[derive(Debug, Clone, Deserialize, Serialize)]
80#[serde(deny_unknown_fields)]
81pub struct SearchEngine {
82    pub url: String,
83    pub name: String,
84    pub key: char,
85}
86
87#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
88#[serde(default, deny_unknown_fields)]
89pub struct Windows {
90    #[default = 8.5]
91    pub scale: f64,
92    #[default = 5]
93    pub workspaces_per_row: u8,
94    #[default = true]
95    pub strip_html_from_workspace_title: bool,
96    pub overview: Option<Overview>,
97    pub switch: Option<Switch>,
98}
99
100#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
101#[serde(default, deny_unknown_fields)]
102pub struct Overview {
103    pub open: OpenOverview,
104    pub navigate: Navigate,
105    pub other: OtherOverview,
106}
107
108#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
109#[serde(default, deny_unknown_fields)]
110pub struct OtherOverview {
111    #[default(Vec::new())]
112    pub filter_by: Vec<FilterBy>,
113    #[default = false]
114    pub hide_filtered: bool,
115}
116
117#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
118#[serde(default, deny_unknown_fields)]
119pub struct OpenOverview {
120    #[default = "super"]
121    pub key: KeyMaybeMod,
122    #[default(Mod::Super)]
123    pub modifier: Mod,
124}
125
126#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
127#[serde(default, deny_unknown_fields)]
128pub struct Navigate {
129    #[default = "tab"]
130    pub forward: String,
131    #[default(Reverse::Mod(Mod::Shift))]
132    pub reverse: Reverse,
133}
134
135#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
136#[serde(default, deny_unknown_fields)]
137pub struct Switch {
138    pub open: OpenSwitch,
139    pub navigate: Navigate,
140    pub other: OtherSwitch,
141}
142
143#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
144#[serde(default, deny_unknown_fields)]
145pub struct OpenSwitch {
146    #[default(Mod::Super)]
147    pub modifier: Mod,
148}
149
150#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
151#[serde(default, deny_unknown_fields)]
152pub struct OtherSwitch {
153    #[default(Vec::new())]
154    pub filter_by: Vec<FilterBy>,
155    #[default = true]
156    pub hide_filtered: bool,
157}
158
159#[derive(Debug, Clone, Copy, Deserialize, Serialize, Eq, PartialEq)]
160#[serde(rename_all = "snake_case")]
161pub enum FilterBy {
162    SameClass,
163    CurrentWorkspace,
164    CurrentMonitor,
165}
166
167#[derive(Debug, Clone, Deserialize, Serialize)]
168#[serde(rename_all = "snake_case")]
169pub enum Reverse {
170    Key(String),
171    Mod(Mod),
172}
173#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
174#[serde(rename_all = "snake_case")]
175pub enum Mod {
176    Alt,
177    Ctrl,
178    Super,
179    Shift,
180}
181
182impl Display for Mod {
183    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184        match self {
185            Mod::Alt => write!(f, "alt"),
186            Mod::Ctrl => write!(f, "ctrl"),
187            Mod::Super => write!(f, "super"),
188            Mod::Shift => write!(f, "shift"),
189        }
190    }
191}
192
193#[derive(Debug, Clone, Deserialize, Serialize)]
194pub struct KeyMaybeMod(String);
195impl From<&str> for KeyMaybeMod {
196    fn from(s: &str) -> Self {
197        Self(s.to_string())
198    }
199}
200
201// https://wiki.hyprland.org/Configuring/Variables/#variable-types
202// SHIFT CAPS CTRL/CONTROL ALT MOD2 MOD3 SUPER/WIN/LOGO/MOD4 MOD5
203impl KeyMaybeMod {
204    pub fn to_key(&self) -> String {
205        match &*self.0.to_ascii_lowercase() {
206            "alt" => "alt_l".to_string(),
207            "ctrl" => "ctrl_l".to_string(),
208            "super" => "super_l".to_string(),
209            "shift" => "shift_l".to_string(),
210            a => a.to_string(),
211        }
212    }
213}
214
215impl Mod {
216    pub fn mod_to_keys(&self) -> [&'static str; 2] {
217        match self {
218            Mod::Alt => ["alt_l", "alt_r"],
219            Mod::Ctrl => ["control_l", "control_r"], // WHY is this not ctrl_l and ctrl_r?
220            Mod::Super => ["super_l", "super_r"],
221            Mod::Shift => ["shift_l", "shift_r"],
222        }
223    }
224}