1use std::fmt::{Display, Formatter};
2
3use crossterm::event::{KeyCode, KeyEvent, KeyEventState, KeyModifiers};
4use mlua::{FromLua, IntoLua};
5use ratatui::style::{Modifier, Style};
6use serde::{ser::SerializeMap, Deserialize, Serialize};
7
8use super::{
9 key_settings::KeySettings,
10 register_color_settings_macro::{get_style, set_style},
11 register_key_settings_macro::{key_event_to_lua, lua_to_key_event},
12};
13
14#[derive(Debug, Clone, PartialEq)]
15pub enum SettingsValue {
16 Bool(bool),
17 Int(i64),
18 Float(f64),
19 String(String),
20 Style(Style),
21 Key(KeyEvent),
22}
23
24impl From<bool> for SettingsValue {
25 fn from(value: bool) -> Self {
26 SettingsValue::Bool(value)
27 }
28}
29
30impl From<i64> for SettingsValue {
31 fn from(value: i64) -> Self {
32 SettingsValue::Int(value)
33 }
34}
35
36impl From<f64> for SettingsValue {
37 fn from(value: f64) -> Self {
38 SettingsValue::Float(value)
39 }
40}
41
42impl From<String> for SettingsValue {
43 fn from(value: String) -> Self {
44 SettingsValue::String(value)
45 }
46}
47
48impl From<&str> for SettingsValue {
49 fn from(value: &str) -> Self {
50 SettingsValue::String(value.to_string())
51 }
52}
53
54impl From<Style> for SettingsValue {
55 fn from(value: Style) -> Self {
56 SettingsValue::Style(value)
57 }
58}
59
60impl From<KeyEvent> for SettingsValue {
61 fn from(value: KeyEvent) -> Self {
62 SettingsValue::Key(value)
63 }
64}
65
66impl Display for SettingsValue {
67 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
68 match self {
69 SettingsValue::Bool(value) => write!(f, "{}", value),
70 SettingsValue::Int(value) => write!(f, "{}", value),
71 SettingsValue::Float(value) => write!(f, "{}", value),
72 SettingsValue::String(value) => write!(f, "{}", value),
73 SettingsValue::Style(value) => {
74 write!(
75 f,
76 "{{fg:{},",
77 value.fg.map_or("None".to_string(), |c| c.to_string())
78 )?;
79 write!(
80 f,
81 "bg:{},",
82 value.bg.map_or("None".to_string(), |c| c.to_string())
83 )?;
84 write!(
85 f,
86 "underline:{},",
87 value
88 .underline_color
89 .map_or("None".to_string(), |c| c.to_string())
90 )?;
91 write!(f, "add_modifier:{},", value.add_modifier.bits())?;
92 write!(f, "sub_modifier:{}}}", value.sub_modifier.bits())?;
93 Ok(())
94 }
95 SettingsValue::Key(value) => {
96 write!(f, "{{code:{},", KeySettings::key_code_to_string(value.code))?;
97 write!(f, "modifiers:{},", value.modifiers.bits())?;
98 write!(
99 f,
100 "kind:{},",
101 KeySettings::key_event_kind_to_string(value.kind)
102 )?;
103 write!(f, "state:{}}}", value.state.bits())?;
104 Ok(())
105 }
106 }
107 }
108}
109
110impl Serialize for SettingsValue {
111 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 where
113 S: serde::Serializer,
114 {
115 match self {
116 SettingsValue::Bool(value) => serializer.serialize_bool(*value),
117 SettingsValue::Int(value) => serializer.serialize_i64(*value),
118 SettingsValue::Float(value) => serializer.serialize_f64(*value),
119 SettingsValue::String(value) => serializer.serialize_str(value),
120 SettingsValue::Style(value) => {
121 let len = 2
122 + value.fg.is_some() as usize
123 + value.bg.is_some() as usize
124 + value.underline_color.is_some() as usize;
125 let mut map = serializer.serialize_map(Some(len))?;
126 if let Some(fg) = value.fg {
127 map.serialize_key("fg")?;
128 map.serialize_value(&fg.to_string())?;
129 }
130 if let Some(bg) = value.bg {
131 map.serialize_key("bg")?;
132 map.serialize_value(&bg.to_string())?;
133 }
134 if let Some(underline) = value.underline_color {
135 map.serialize_key("underline")?;
136 map.serialize_value(&underline.to_string())?;
137 }
138 map.serialize_key("add_modifier")?;
139 map.serialize_value(&value.add_modifier.bits())?;
140 map.serialize_key("sub_modifier")?;
141 map.serialize_value(&value.sub_modifier.bits())?;
142 map.end()
143 }
144 SettingsValue::Key(value) => {
145 let mut map = serializer.serialize_map(Some(4))?;
146 map.serialize_key("code")?;
147 map.serialize_value(&KeySettings::key_code_to_string(value.code))?;
148 map.serialize_key("modifiers")?;
149 map.serialize_value(&value.modifiers.bits())?;
150 map.serialize_key("kind")?;
151 map.serialize_value(&KeySettings::key_event_kind_to_string(value.kind))?;
152 map.serialize_key("state")?;
153 map.serialize_value(&value.state.bits())?;
154 map.end()
155 }
156 }
157 }
158}
159
160struct SettingsValueVisitor;
161
162impl SettingsValueVisitor {
163 fn visit_bool<E>(self, value: bool) -> Result<SettingsValue, E> {
164 Ok(SettingsValue::Bool(value))
165 }
166
167 fn visit_i64<E>(self, value: i64) -> Result<SettingsValue, E> {
168 Ok(SettingsValue::Int(value))
169 }
170
171 fn visit_f64<E>(self, value: f64) -> Result<SettingsValue, E> {
172 Ok(SettingsValue::Float(value))
173 }
174
175 fn visit_str<E>(self, value: &str) -> Result<SettingsValue, E> {
176 Ok(SettingsValue::String(value.to_string()))
177 }
178
179 fn visit_style<E>(self, style: Style) -> Result<SettingsValue, E> {
180 Ok(SettingsValue::Style(style))
181 }
182
183 fn visit_key<E>(self, value: KeyEvent) -> Result<SettingsValue, E> {
184 Ok(SettingsValue::Key(value))
185 }
186}
187
188impl<'de> serde::de::Visitor<'de> for SettingsValueVisitor {
189 type Value = SettingsValue;
190
191 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
192 formatter.write_str("a boolean, integer, number, string, style, or key event")
193 }
194
195 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
196 self.visit_bool(value)
197 }
198
199 fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
200 where
201 E: serde::de::Error,
202 {
203 self.visit_i64(v.into())
204 }
205
206 fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
207 where
208 E: serde::de::Error,
209 {
210 self.visit_i64(v.into())
211 }
212
213 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
214 where
215 E: serde::de::Error,
216 {
217 self.visit_i64(v.into())
218 }
219
220 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
221 self.visit_i64(value)
222 }
223
224 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
225 where
226 E: serde::de::Error,
227 {
228 self.visit_i64(v.into())
229 }
230
231 fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
232 where
233 E: serde::de::Error,
234 {
235 self.visit_i64(v.into())
236 }
237
238 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
239 where
240 E: serde::de::Error,
241 {
242 self.visit_i64(v.into())
243 }
244
245 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
246 where
247 E: serde::de::Error,
248 {
249 if let Ok(value) = i64::try_from(v) {
250 self.visit_i64(value)
251 } else {
252 Err(E::custom("u64 value is too large to fit in an i64"))
253 }
254 }
255
256 fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
257 where
258 E: serde::de::Error,
259 {
260 self.visit_f64(v.into())
261 }
262
263 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> {
264 self.visit_f64(value)
265 }
266
267 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> {
268 self.visit_str(value)
269 }
270
271 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
272 where
273 A: serde::de::MapAccess<'de>,
274 {
275 let mut style = Style::default();
276 let mut key_event = KeyEvent::new(KeyCode::Null, KeyModifiers::NONE);
277 #[derive(Debug, PartialEq)]
278 enum MapKind {
279 Unknown,
280 Style,
281 Key,
282 }
283 let mut map_kind = MapKind::Unknown;
284 while let Some(key) = map.next_key()? {
285 if map_kind == MapKind::Unknown {
286 match key {
287 "fg" | "bg" | "underline" | "add_modifier" | "sub_modifier" => {
288 map_kind = MapKind::Style;
289 }
290 "code" | "modifiers" | "kind" | "state" => {
291 map_kind = MapKind::Key;
292 }
293 _ => break,
294 }
295 }
296
297 match map_kind {
298 MapKind::Unknown => break,
299 MapKind::Style => match key {
300 "fg" => {
301 let value = map.next_value()?;
302 style.fg = Some(value);
303 }
304 "bg" => {
305 let value = map.next_value()?;
306 style.bg = Some(value);
307 }
308 "underline" => {
309 let value = map.next_value()?;
310 style.underline_color = Some(value);
311 }
312 "add_modifier" => {
313 let value = map.next_value()?;
314 style.add_modifier = Modifier::from_bits(value).ok_or_else(|| {
315 serde::de::Error::custom("Invalid style add modifier")
316 })?;
317 }
318 "sub_modifier" => {
319 let value = map.next_value()?;
320 style.sub_modifier = Modifier::from_bits(value).ok_or_else(|| {
321 serde::de::Error::custom("Invalid style sub modifier")
322 })?;
323 }
324 _ => {
325 map_kind = MapKind::Unknown;
326 break;
327 }
328 },
329 MapKind::Key => match key {
330 "code" => {
331 let value = map.next_value::<String>()?;
332 key_event.code = KeySettings::string_to_key_code(&value)
333 .map_err(serde::de::Error::custom)?;
334 }
335 "modifiers" => {
336 let value = map.next_value()?;
337 key_event.modifiers = KeyModifiers::from_bits(value)
338 .ok_or_else(|| serde::de::Error::custom("Invalid key modifiers"))?;
339 }
340 "kind" => {
341 let value = map.next_value::<String>()?;
342 key_event.kind = KeySettings::string_to_key_event_kind(&value)
343 .map_err(serde::de::Error::custom)?;
344 }
345 "state" => {
346 let value = map.next_value()?;
347 key_event.state = KeyEventState::from_bits(value)
348 .ok_or_else(|| serde::de::Error::custom("Invalid key event state"))?;
349 }
350 _ => {
351 map_kind = MapKind::Unknown;
352 break;
353 }
354 },
355 }
356 }
357 match map_kind {
358 MapKind::Unknown => Err(serde::de::Error::custom(
359 "Invalid table, expected style or key event",
360 )),
361 MapKind::Style => self.visit_style(style),
362 MapKind::Key => self.visit_key(key_event),
363 }
364 }
365}
366
367impl<'de> Deserialize<'de> for SettingsValue {
368 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
369 where
370 D: serde::Deserializer<'de>,
371 {
372 deserializer.deserialize_any(SettingsValueVisitor)
373 }
374}
375
376impl IntoLua for SettingsValue {
377 fn into_lua(self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
378 match self {
379 SettingsValue::Bool(value) => value.into_lua(lua),
380 SettingsValue::Int(value) => value.into_lua(lua),
381 SettingsValue::Float(value) => value.into_lua(lua),
382 SettingsValue::String(value) => value.into_lua(lua),
383 SettingsValue::Style(value) => Ok(mlua::Value::Table(get_style(lua, &value)?)),
384 SettingsValue::Key(value) => Ok(mlua::Value::Table(key_event_to_lua(lua, &value)?)),
385 }
386 }
387}
388
389impl FromLua for SettingsValue {
390 fn from_lua(value: mlua::Value, _lua: &mlua::Lua) -> mlua::Result<Self> {
391 match value {
392 mlua::Value::Boolean(value) => Ok(SettingsValue::Bool(value)),
393 mlua::Value::Integer(value) => Ok(SettingsValue::Int(value)),
394 mlua::Value::Number(value) => Ok(SettingsValue::Float(value)),
395 mlua::Value::String(value) => Ok(SettingsValue::String(value.to_str()?.to_string())),
396 mlua::Value::Table(value) => {
397 if value.contains_key("fg")?
398 || value.contains_key("bg")?
399 || value.contains_key("underline")?
400 || value.contains_key("add_modifier")?
401 || value.contains_key("sub_modifier")?
402 {
403 let mut style = Style::default();
404 set_style(_lua, &mut style, value)?;
405 Ok(SettingsValue::Style(style))
406 } else if value.contains_key("code")?
407 || value.contains_key("modifiers")?
408 || value.contains_key("kind")?
409 || value.contains_key("state")?
410 {
411 let key_event = lua_to_key_event(_lua, &value)?;
412 Ok(SettingsValue::Key(key_event))
413 } else {
414 Err(mlua::Error::RuntimeError(
415 "Invalid table, expected style or key event".to_string(),
416 ))
417 }
418 }
419 _ => Err(mlua::Error::RuntimeError(
420 "Expected boolean, integer, number, string, style or key event".to_string(),
421 )),
422 }
423 }
424}